• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  A 32-bit implementation of the XTEA algorithm
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 
8 #include "common.h"
9 
10 #if defined(MBEDTLS_XTEA_C)
11 
12 #include "mbedtls/xtea.h"
13 #include "mbedtls/platform_util.h"
14 
15 #include <string.h>
16 
17 #include "mbedtls/platform.h"
18 
19 #if !defined(MBEDTLS_XTEA_ALT)
20 
mbedtls_xtea_init(mbedtls_xtea_context * ctx)21 void mbedtls_xtea_init(mbedtls_xtea_context *ctx)
22 {
23     memset(ctx, 0, sizeof(mbedtls_xtea_context));
24 }
25 
mbedtls_xtea_free(mbedtls_xtea_context * ctx)26 void mbedtls_xtea_free(mbedtls_xtea_context *ctx)
27 {
28     if (ctx == NULL) {
29         return;
30     }
31 
32     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_xtea_context));
33 }
34 
35 /*
36  * XTEA key schedule
37  */
mbedtls_xtea_setup(mbedtls_xtea_context * ctx,const unsigned char key[16])38 void mbedtls_xtea_setup(mbedtls_xtea_context *ctx, const unsigned char key[16])
39 {
40     int i;
41 
42     memset(ctx, 0, sizeof(mbedtls_xtea_context));
43 
44     for (i = 0; i < 4; i++) {
45         ctx->k[i] = MBEDTLS_GET_UINT32_BE(key, i << 2);
46     }
47 }
48 
49 /*
50  * XTEA encrypt function
51  */
mbedtls_xtea_crypt_ecb(mbedtls_xtea_context * ctx,int mode,const unsigned char input[8],unsigned char output[8])52 int mbedtls_xtea_crypt_ecb(mbedtls_xtea_context *ctx, int mode,
53                            const unsigned char input[8], unsigned char output[8])
54 {
55     uint32_t *k, v0, v1, i;
56 
57     k = ctx->k;
58 
59     v0 = MBEDTLS_GET_UINT32_BE(input, 0);
60     v1 = MBEDTLS_GET_UINT32_BE(input, 4);
61 
62     if (mode == MBEDTLS_XTEA_ENCRYPT) {
63         uint32_t sum = 0, delta = 0x9E3779B9;
64 
65         for (i = 0; i < 32; i++) {
66             v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
67             sum += delta;
68             v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
69         }
70     } else { /* MBEDTLS_XTEA_DECRYPT */
71         uint32_t delta = 0x9E3779B9, sum = delta * 32;
72 
73         for (i = 0; i < 32; i++) {
74             v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
75             sum -= delta;
76             v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
77         }
78     }
79 
80     MBEDTLS_PUT_UINT32_BE(v0, output, 0);
81     MBEDTLS_PUT_UINT32_BE(v1, output, 4);
82 
83     return 0;
84 }
85 
86 #if defined(MBEDTLS_CIPHER_MODE_CBC)
87 /*
88  * XTEA-CBC buffer encryption/decryption
89  */
mbedtls_xtea_crypt_cbc(mbedtls_xtea_context * ctx,int mode,size_t length,unsigned char iv[8],const unsigned char * input,unsigned char * output)90 int mbedtls_xtea_crypt_cbc(mbedtls_xtea_context *ctx, int mode, size_t length,
91                            unsigned char iv[8], const unsigned char *input,
92                            unsigned char *output)
93 {
94     int i;
95     unsigned char temp[8];
96 
97     if (length % 8) {
98         return MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH;
99     }
100 
101     if (mode == MBEDTLS_XTEA_DECRYPT) {
102         while (length > 0) {
103             memcpy(temp, input, 8);
104             mbedtls_xtea_crypt_ecb(ctx, mode, input, output);
105 
106             for (i = 0; i < 8; i++) {
107                 output[i] = (unsigned char) (output[i] ^ iv[i]);
108             }
109 
110             memcpy(iv, temp, 8);
111 
112             input  += 8;
113             output += 8;
114             length -= 8;
115         }
116     } else {
117         while (length > 0) {
118             for (i = 0; i < 8; i++) {
119                 output[i] = (unsigned char) (input[i] ^ iv[i]);
120             }
121 
122             mbedtls_xtea_crypt_ecb(ctx, mode, output, output);
123             memcpy(iv, output, 8);
124 
125             input  += 8;
126             output += 8;
127             length -= 8;
128         }
129     }
130 
131     return 0;
132 }
133 #endif /* MBEDTLS_CIPHER_MODE_CBC */
134 #endif /* !MBEDTLS_XTEA_ALT */
135 
136 #if defined(MBEDTLS_SELF_TEST)
137 
138 /*
139  * XTEA tests vectors (non-official)
140  */
141 
142 static const unsigned char xtea_test_key[6][16] =
143 {
144     { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
145       0x0c, 0x0d, 0x0e, 0x0f },
146     { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
147       0x0c, 0x0d, 0x0e, 0x0f },
148     { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
149       0x0c, 0x0d, 0x0e, 0x0f },
150     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151       0x00, 0x00, 0x00, 0x00 },
152     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153       0x00, 0x00, 0x00, 0x00 },
154     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155       0x00, 0x00, 0x00, 0x00 }
156 };
157 
158 static const unsigned char xtea_test_pt[6][8] =
159 {
160     { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
161     { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
162     { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
163     { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
164     { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
165     { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
166 };
167 
168 static const unsigned char xtea_test_ct[6][8] =
169 {
170     { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
171     { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
172     { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
173     { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
174     { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
175     { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
176 };
177 
178 /*
179  * Checkup routine
180  */
mbedtls_xtea_self_test(int verbose)181 int mbedtls_xtea_self_test(int verbose)
182 {
183     int i, ret = 0;
184     unsigned char buf[8];
185     mbedtls_xtea_context ctx;
186 
187     mbedtls_xtea_init(&ctx);
188     for (i = 0; i < 6; i++) {
189         if (verbose != 0) {
190             mbedtls_printf("  XTEA test #%d: ", i + 1);
191         }
192 
193         memcpy(buf, xtea_test_pt[i], 8);
194 
195         mbedtls_xtea_setup(&ctx, xtea_test_key[i]);
196         mbedtls_xtea_crypt_ecb(&ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf);
197 
198         if (memcmp(buf, xtea_test_ct[i], 8) != 0) {
199             if (verbose != 0) {
200                 mbedtls_printf("failed\n");
201             }
202 
203             ret = 1;
204             goto exit;
205         }
206 
207         if (verbose != 0) {
208             mbedtls_printf("passed\n");
209         }
210     }
211 
212     if (verbose != 0) {
213         mbedtls_printf("\n");
214     }
215 
216 exit:
217     mbedtls_xtea_free(&ctx);
218 
219     return ret;
220 }
221 
222 #endif /* MBEDTLS_SELF_TEST */
223 
224 #endif /* MBEDTLS_XTEA_C */
225