|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+#include <stdint.h>
|
|
|
2
|
+
|
|
|
3
|
+#define LENGTH_OF_BLOCK 8
|
|
|
4
|
+
|
|
|
5
|
+void xxtea_Encrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4]);
|
|
|
6
|
+void xxtea_Decrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4]);
|
|
|
7
|
+
|
|
|
8
|
+/* The data packets are encrypted using the xxtea algorithm. */
|
|
|
9
|
+void Encrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t key[4])
|
|
|
10
|
+{
|
|
|
11
|
+ /* This function assumes that the dataLength is a multiple of the length of the
|
|
|
12
|
+ * salt (8)
|
|
|
13
|
+ *
|
|
|
14
|
+ * The data is encrypted using cipher block chaining:
|
|
|
15
|
+ * (https://upload.wikimedia.org/wikipedia/commons/8/80/CBC_encryption.svg)
|
|
|
16
|
+ */
|
|
|
17
|
+
|
|
|
18
|
+ uint8_t i;
|
|
|
19
|
+ uint8_t * previousCipherBlock = (uint8_t*) &salt;
|
|
|
20
|
+ uint8_t * currentPlaintextBlock = (uint8_t*) data;
|
|
|
21
|
+
|
|
|
22
|
+ for (i = 0; i < dataLength/LENGTH_OF_BLOCK; i++)
|
|
|
23
|
+ {
|
|
|
24
|
+ /* XOR of current plain text block and previous cipher block */
|
|
|
25
|
+ //for (j = 0; j < LENGTH_OF_BLOCK; j++)
|
|
|
26
|
+ //{
|
|
|
27
|
+ // currentPlaintextBlock[j] ^= previousCipherBlock[j];
|
|
|
28
|
+ //}
|
|
|
29
|
+ *((uint64_t*) currentPlaintextBlock) ^= *((uint64_t*) previousCipherBlock);
|
|
|
30
|
+
|
|
|
31
|
+ /* Encrypt the block */
|
|
|
32
|
+ xxtea_Encrypt((uint32_t*) currentPlaintextBlock, LENGTH_OF_BLOCK, key);
|
|
|
33
|
+
|
|
|
34
|
+ /* Setup for next block */
|
|
|
35
|
+ previousCipherBlock = currentPlaintextBlock;
|
|
|
36
|
+ currentPlaintextBlock += LENGTH_OF_BLOCK;
|
|
|
37
|
+ }
|
|
|
38
|
+
|
|
|
39
|
+}
|
|
|
40
|
+
|
|
|
41
|
+
|
|
|
42
|
+void Decrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t key[4])
|
|
|
43
|
+{
|
|
|
44
|
+ /* This function assumes that the dataLength is a multiple of the length of the
|
|
|
45
|
+ * salt (8)
|
|
|
46
|
+ *
|
|
|
47
|
+ * The data is encrypted using cipher block chaining:
|
|
|
48
|
+ * (https://upload.wikimedia.org/wikipedia/commons/2/2a/CBC_decryption.svg)
|
|
|
49
|
+ */
|
|
|
50
|
+
|
|
|
51
|
+ /* The data is decrypted from back to front as front to back cannot be done in
|
|
|
52
|
+ * place
|
|
|
53
|
+ */
|
|
|
54
|
+ uint8_t i;
|
|
|
55
|
+ uint8_t * previousCipherBlock = (uint8_t*) data + dataLength - 2 * LENGTH_OF_BLOCK;
|
|
|
56
|
+ uint8_t * currentCipherBlock = (uint8_t*) data + dataLength - LENGTH_OF_BLOCK;
|
|
|
57
|
+
|
|
|
58
|
+ for (i = dataLength/LENGTH_OF_BLOCK; i > 0; i--)
|
|
|
59
|
+ {
|
|
|
60
|
+ /* Decrypt the block */
|
|
|
61
|
+ xxtea_Decrypt((uint32_t*) currentCipherBlock, LENGTH_OF_BLOCK, key);
|
|
|
62
|
+
|
|
|
63
|
+ /* XOR of the decrypted block with cipher block in front of it */
|
|
|
64
|
+ *((uint64_t*) currentCipherBlock) ^= *((uint64_t*) previousCipherBlock);
|
|
|
65
|
+
|
|
|
66
|
+ /* Setup for next block */
|
|
|
67
|
+ currentCipherBlock = previousCipherBlock;
|
|
|
68
|
+ if (previousCipherBlock != (uint8_t*) data)
|
|
|
69
|
+ {
|
|
|
70
|
+ previousCipherBlock -= LENGTH_OF_BLOCK;
|
|
|
71
|
+ }
|
|
|
72
|
+ else
|
|
|
73
|
+ {
|
|
|
74
|
+ previousCipherBlock = (uint8_t*) &salt;
|
|
|
75
|
+ }
|
|
|
76
|
+ }
|
|
|
77
|
+}
|
|
|
78
|
+
|
|
|
79
|
+void xxtea_Encrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4])
|
|
|
80
|
+{
|
|
|
81
|
+ uint32_t sum = 0, z, y, e;
|
|
|
82
|
+ uint8_t i = 6 + 52/(dataLength/4), r;
|
|
|
83
|
+ const int16_t n = dataLength / 4 - 1;
|
|
|
84
|
+
|
|
|
85
|
+ z = data[n]; // left neighbour for the first round
|
|
|
86
|
+ do {
|
|
|
87
|
+ // cycle
|
|
|
88
|
+ sum += 0x9e3779b9ul;
|
|
|
89
|
+ e = (sum >> 2) & 3;
|
|
|
90
|
+ for (r = 0; r <= n; r++) {
|
|
|
91
|
+ // round
|
|
|
92
|
+ y = data[(r+1) % (n + 1)]; // right neighbour
|
|
|
93
|
+ data[r] += ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum^y) + (key[(r^e) & 3] ^ z));
|
|
|
94
|
+ z = data[r]; // left neighbour for the next round
|
|
|
95
|
+ }
|
|
|
96
|
+ } while (--i);
|
|
|
97
|
+}
|
|
|
98
|
+
|
|
|
99
|
+void xxtea_Decrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4])
|
|
|
100
|
+{
|
|
|
101
|
+ uint32_t sum, z, y, e;
|
|
|
102
|
+ int16_t i = 6 + 52/(dataLength/4), r;
|
|
|
103
|
+ const int16_t n = dataLength / 4;
|
|
|
104
|
+
|
|
|
105
|
+ sum = (uint32_t) ((uint64_t) (6 + 52/(dataLength/4)) * 0x9e3779b9ul);
|
|
|
106
|
+ y = data[0];
|
|
|
107
|
+ do {
|
|
|
108
|
+ // cycle
|
|
|
109
|
+ e = sum >> 2;
|
|
|
110
|
+ for (r = n-1; r >= 0; --r) {
|
|
|
111
|
+ // round
|
|
|
112
|
+ z = data[(r+n-1) % n];
|
|
|
113
|
+ data[r] -= ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum^y) + (key[(r^e) & 3] ^ z));
|
|
|
114
|
+ y = data[r];
|
|
|
115
|
+ }
|
|
|
116
|
+ sum -= 0x9e3779b9;
|
|
|
117
|
+ } while (--i);
|
|
|
118
|
+}
|