Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/*
* make tea CFLAGS="-std=gnu99"
*
* ./tea "hello there how r You" -d "FOF5;?9#LDQ2'MAI\LT286+]\$63@Q;JG"
*
* XXTEA Encoder/decoder test program
* (C) Michel Pollet <buserror@gmail.com>
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#define DEBUG
//#define TEST
#ifdef DEBUG
#define D(_w) _w
#else
#define D(_w)
#endif
#ifdef TEST
#define T(_w) _w
#else
#define T(_w)
#endif
/* Lifted from teh Wikipedia page */
#define MX (z>>5^y<<2) + (y>>3^z<<4) ^ (sum^y) + (k[p&3^e]^z);
static void btea(uint32_t* v, uint8_t n, uint32_t* k) {
uint32_t z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9;
long p, q ;
q = 6 + 52/n;
while (q-- > 0) {
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++) y = v[p+1], z = v[p] += MX;
y = v[0];
z = v[n-1] += MX;
}
}
static void debtea(uint32_t* v, uint8_t n, uint32_t* k) {
uint32_t z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9;
long p, q ;
q = 6 + 52/n;
sum = q*DELTA ;
while (sum != 0) {
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX;
z = v[n-1];
y = v[0] -= MX;
sum -= DELTA;
}
}
/*
* This is a uuencode/decode -like format
*/
static uint8_t uuencode(uint8_t * s, uint8_t l, uint8_t *d) {
if (l > 63) {
D(printf("%s: len > 63, truncating\n", __func__);)
l = 63;
}
// d[0] = ' ' + 1 + l; // encode the length as one char
uint8_t bl = (l + 2) / 3;
for (uint8_t bi = 0; bi < bl; bi++, s += 3, d += 4) {
d[0] = ' ' + (s[0] >> 2);
d[1] = ' ' + (((s[0] & 0x3) << 4) | (s[1] >> 4));
d[2] = ' ' + (((s[1] & 0xf) << 2) | (s[2] >> 6));
d[3] = ' ' + (s[2] & 0x3f);
// debug
T(d[4] = 0; printf("%02x:%02x:%02x %s\n", s[0], s[1], s[2], d);)
}
*d = 0;
return (bl * 4); // + 1;
}
static uint8_t uudecode(uint8_t * s, uint8_t l, uint8_t *d) {
if (l & 0x3) {
D(printf("%s: %d not a multiple of 4, padding\n", __func__, l);)
l = (l + 3) & ~3;
}
uint8_t bl = l / 4;
for (uint8_t bi = 0; bi < bl; bi++, s += 4, d += 3) {
d[0] = ((s[0] - ' ') << 2) | ((s[1] - ' ') >> 4);
d[1] = ((s[1] - ' ') << 4) | ((s[2] - ' ') >> 2);
d[2] = ((s[2] - ' ') << 6) | ((s[3] - ' '));
T(printf("%02x:%02x:%02x %-4.4s\n", d[0],d[1],d[2], s);)
}
*d = 0;
return bl * 3;
}
int
main(int argc, const char *argv[])
{
char key[32] = "This is a test key";
bool encode = true;
uint8_t padded[256];
uint8_t buf_encode[256];
uint8_t buf_uuencode[256];
#ifdef TEST /* uuencode/decode self test */
printf("uuencode test\n");
uuencode(key, strlen(key), padded);
printf("uudecode test\n");
uudecode(padded, strlen(padded), buf_uuencode);
//padded[strlen(key)] = 0;
printf("decoded: '%s' -- should be '%s'\n", buf_uuencode, key);
#endif
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-d")) {
encode = false;
continue;
} else if (!strcmp(argv[i], "-e")) {
encode = true;
continue;
} else if (!strcmp(argv[i], "-k") && i < argc -1) {
memset(key, 0, sizeof(key));
strncpy(key, argv[i], sizeof(key)-1);
} else if (argv[i][0] == '-') {
printf("%s invalid argument %s\n", argv[0], argv[i]);
exit(1);
}
memset(padded, 0, sizeof(padded));
memset(buf_encode, 0, sizeof(buf_encode));
memset(buf_uuencode, 0, sizeof(buf_uuencode));
if (!encode) {
D(printf("decode: '%s' l:%d\n", argv[i], strlen(argv[i]));)
strncpy(buf_uuencode, argv[i], sizeof(buf_uuencode)-1);
}
if (encode) {
int l = strlen(argv[i]);
// todo, check size overflow
memcpy(padded, argv[i], l);
int b = (l + 3) / 4;
D(printf("encode %d to %d blocks\n", l, b);)
if (b < 2) {
printf("Not enough blocks (min 2) padding\n");
b = 2;
}
btea((uint32_t*)padded, b, (uint32_t*)key);
int dl = uuencode(padded, b * 4, buf_uuencode);
printf("E:%03d '%s'\n", dl, buf_uuencode);
}
/* now re-decode it */
int dl = uudecode(buf_uuencode, strlen(buf_uuencode), buf_encode);
D(printf("decode uu:%d to %d, %d blocks\n", strlen(buf_uuencode),
dl, dl / 4);)
if (dl < 2) dl = 2;
debtea((uint32_t*)buf_encode, dl / 4, (uint32_t*)key);
printf("D:%03d '%s'\n", dl, buf_encode);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment