11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Cryptographic API. 31da177e4SLinus Torvalds * 4fb4f10edSAaron Grothe * TEA, XTEA, and XETA crypto alogrithms 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * The TEA and Xtended TEA algorithms were developed by David Wheeler 71da177e4SLinus Torvalds * and Roger Needham at the Computer Laboratory of Cambridge University. 81da177e4SLinus Torvalds * 9fb4f10edSAaron Grothe * Due to the order of evaluation in XTEA many people have incorrectly 10fb4f10edSAaron Grothe * implemented it. XETA (XTEA in the wrong order), exists for 11fb4f10edSAaron Grothe * compatibility with these implementations. 12fb4f10edSAaron Grothe * 131da177e4SLinus Torvalds * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 161da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 171da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 181da177e4SLinus Torvalds * (at your option) any later version. 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds #include <linux/init.h> 231da177e4SLinus Torvalds #include <linux/module.h> 241da177e4SLinus Torvalds #include <linux/mm.h> 2506ace7a9SHerbert Xu #include <asm/byteorder.h> 261da177e4SLinus Torvalds #include <asm/scatterlist.h> 271da177e4SLinus Torvalds #include <linux/crypto.h> 2806ace7a9SHerbert Xu #include <linux/types.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #define TEA_KEY_SIZE 16 311da177e4SLinus Torvalds #define TEA_BLOCK_SIZE 8 321da177e4SLinus Torvalds #define TEA_ROUNDS 32 331da177e4SLinus Torvalds #define TEA_DELTA 0x9e3779b9 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds #define XTEA_KEY_SIZE 16 361da177e4SLinus Torvalds #define XTEA_BLOCK_SIZE 8 371da177e4SLinus Torvalds #define XTEA_ROUNDS 32 381da177e4SLinus Torvalds #define XTEA_DELTA 0x9e3779b9 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds struct tea_ctx { 411da177e4SLinus Torvalds u32 KEY[4]; 421da177e4SLinus Torvalds }; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds struct xtea_ctx { 451da177e4SLinus Torvalds u32 KEY[4]; 461da177e4SLinus Torvalds }; 471da177e4SLinus Torvalds 486c2bb98bSHerbert Xu static int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key, 49560c06aeSHerbert Xu unsigned int key_len) 501da177e4SLinus Torvalds { 516c2bb98bSHerbert Xu struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 5206ace7a9SHerbert Xu const __le32 *key = (const __le32 *)in_key; 531da177e4SLinus Torvalds 5406ace7a9SHerbert Xu ctx->KEY[0] = le32_to_cpu(key[0]); 5506ace7a9SHerbert Xu ctx->KEY[1] = le32_to_cpu(key[1]); 5606ace7a9SHerbert Xu ctx->KEY[2] = le32_to_cpu(key[2]); 5706ace7a9SHerbert Xu ctx->KEY[3] = le32_to_cpu(key[3]); 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds return 0; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds 636c2bb98bSHerbert Xu static void tea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 641da177e4SLinus Torvalds { 651da177e4SLinus Torvalds u32 y, z, n, sum = 0; 661da177e4SLinus Torvalds u32 k0, k1, k2, k3; 676c2bb98bSHerbert Xu struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 6806ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 6906ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 701da177e4SLinus Torvalds 7106ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 7206ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds k0 = ctx->KEY[0]; 751da177e4SLinus Torvalds k1 = ctx->KEY[1]; 761da177e4SLinus Torvalds k2 = ctx->KEY[2]; 771da177e4SLinus Torvalds k3 = ctx->KEY[3]; 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds n = TEA_ROUNDS; 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds while (n-- > 0) { 821da177e4SLinus Torvalds sum += TEA_DELTA; 831da177e4SLinus Torvalds y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 841da177e4SLinus Torvalds z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 8706ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 8806ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds 916c2bb98bSHerbert Xu static void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 921da177e4SLinus Torvalds { 931da177e4SLinus Torvalds u32 y, z, n, sum; 941da177e4SLinus Torvalds u32 k0, k1, k2, k3; 956c2bb98bSHerbert Xu struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 9606ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 9706ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 981da177e4SLinus Torvalds 9906ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 10006ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 1011da177e4SLinus Torvalds 1021da177e4SLinus Torvalds k0 = ctx->KEY[0]; 1031da177e4SLinus Torvalds k1 = ctx->KEY[1]; 1041da177e4SLinus Torvalds k2 = ctx->KEY[2]; 1051da177e4SLinus Torvalds k3 = ctx->KEY[3]; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds sum = TEA_DELTA << 5; 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds n = TEA_ROUNDS; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds while (n-- > 0) { 1121da177e4SLinus Torvalds z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 1131da177e4SLinus Torvalds y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 1141da177e4SLinus Torvalds sum -= TEA_DELTA; 1151da177e4SLinus Torvalds } 1161da177e4SLinus Torvalds 11706ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 11806ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1216c2bb98bSHerbert Xu static int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key, 122560c06aeSHerbert Xu unsigned int key_len) 1231da177e4SLinus Torvalds { 1246c2bb98bSHerbert Xu struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 12506ace7a9SHerbert Xu const __le32 *key = (const __le32 *)in_key; 1261da177e4SLinus Torvalds 12706ace7a9SHerbert Xu ctx->KEY[0] = le32_to_cpu(key[0]); 12806ace7a9SHerbert Xu ctx->KEY[1] = le32_to_cpu(key[1]); 12906ace7a9SHerbert Xu ctx->KEY[2] = le32_to_cpu(key[2]); 13006ace7a9SHerbert Xu ctx->KEY[3] = le32_to_cpu(key[3]); 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds return 0; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds 1366c2bb98bSHerbert Xu static void xtea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 1371da177e4SLinus Torvalds { 1381da177e4SLinus Torvalds u32 y, z, sum = 0; 1391da177e4SLinus Torvalds u32 limit = XTEA_DELTA * XTEA_ROUNDS; 1406c2bb98bSHerbert Xu struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 14106ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 14206ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 1431da177e4SLinus Torvalds 14406ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 14506ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds while (sum != limit) { 148fb4f10edSAaron Grothe y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); 149fb4f10edSAaron Grothe sum += XTEA_DELTA; 150fb4f10edSAaron Grothe z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); 151fb4f10edSAaron Grothe } 152fb4f10edSAaron Grothe 15306ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 15406ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 155fb4f10edSAaron Grothe } 156fb4f10edSAaron Grothe 1576c2bb98bSHerbert Xu static void xtea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 158fb4f10edSAaron Grothe { 159fb4f10edSAaron Grothe u32 y, z, sum; 1606c2bb98bSHerbert Xu struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 16106ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 16206ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 163fb4f10edSAaron Grothe 16406ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 16506ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 166fb4f10edSAaron Grothe 167fb4f10edSAaron Grothe sum = XTEA_DELTA * XTEA_ROUNDS; 168fb4f10edSAaron Grothe 169fb4f10edSAaron Grothe while (sum) { 170fb4f10edSAaron Grothe z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]); 171fb4f10edSAaron Grothe sum -= XTEA_DELTA; 172fb4f10edSAaron Grothe y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]); 173fb4f10edSAaron Grothe } 174fb4f10edSAaron Grothe 17506ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 17606ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 177fb4f10edSAaron Grothe } 178fb4f10edSAaron Grothe 179fb4f10edSAaron Grothe 1806c2bb98bSHerbert Xu static void xeta_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 181fb4f10edSAaron Grothe { 182fb4f10edSAaron Grothe u32 y, z, sum = 0; 183fb4f10edSAaron Grothe u32 limit = XTEA_DELTA * XTEA_ROUNDS; 1846c2bb98bSHerbert Xu struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 18506ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 18606ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 187fb4f10edSAaron Grothe 18806ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 18906ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 190fb4f10edSAaron Grothe 191fb4f10edSAaron Grothe while (sum != limit) { 1921da177e4SLinus Torvalds y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 1931da177e4SLinus Torvalds sum += XTEA_DELTA; 1941da177e4SLinus Torvalds z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 19706ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 19806ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 1991da177e4SLinus Torvalds } 2001da177e4SLinus Torvalds 2016c2bb98bSHerbert Xu static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 2021da177e4SLinus Torvalds { 2031da177e4SLinus Torvalds u32 y, z, sum; 2046c2bb98bSHerbert Xu struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 20506ace7a9SHerbert Xu const __le32 *in = (const __le32 *)src; 20606ace7a9SHerbert Xu __le32 *out = (__le32 *)dst; 2071da177e4SLinus Torvalds 20806ace7a9SHerbert Xu y = le32_to_cpu(in[0]); 20906ace7a9SHerbert Xu z = le32_to_cpu(in[1]); 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds sum = XTEA_DELTA * XTEA_ROUNDS; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds while (sum) { 2141da177e4SLinus Torvalds z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3]; 2151da177e4SLinus Torvalds sum -= XTEA_DELTA; 2161da177e4SLinus Torvalds y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; 2171da177e4SLinus Torvalds } 2181da177e4SLinus Torvalds 21906ace7a9SHerbert Xu out[0] = cpu_to_le32(y); 22006ace7a9SHerbert Xu out[1] = cpu_to_le32(z); 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds static struct crypto_alg tea_alg = { 2241da177e4SLinus Torvalds .cra_name = "tea", 2251da177e4SLinus Torvalds .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2261da177e4SLinus Torvalds .cra_blocksize = TEA_BLOCK_SIZE, 2271da177e4SLinus Torvalds .cra_ctxsize = sizeof (struct tea_ctx), 228a429d260SHerbert Xu .cra_alignmask = 3, 2291da177e4SLinus Torvalds .cra_module = THIS_MODULE, 2301da177e4SLinus Torvalds .cra_list = LIST_HEAD_INIT(tea_alg.cra_list), 2311da177e4SLinus Torvalds .cra_u = { .cipher = { 2321da177e4SLinus Torvalds .cia_min_keysize = TEA_KEY_SIZE, 2331da177e4SLinus Torvalds .cia_max_keysize = TEA_KEY_SIZE, 2341da177e4SLinus Torvalds .cia_setkey = tea_setkey, 2351da177e4SLinus Torvalds .cia_encrypt = tea_encrypt, 2361da177e4SLinus Torvalds .cia_decrypt = tea_decrypt } } 2371da177e4SLinus Torvalds }; 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds static struct crypto_alg xtea_alg = { 2401da177e4SLinus Torvalds .cra_name = "xtea", 2411da177e4SLinus Torvalds .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2421da177e4SLinus Torvalds .cra_blocksize = XTEA_BLOCK_SIZE, 2431da177e4SLinus Torvalds .cra_ctxsize = sizeof (struct xtea_ctx), 244a429d260SHerbert Xu .cra_alignmask = 3, 2451da177e4SLinus Torvalds .cra_module = THIS_MODULE, 2461da177e4SLinus Torvalds .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), 2471da177e4SLinus Torvalds .cra_u = { .cipher = { 2481da177e4SLinus Torvalds .cia_min_keysize = XTEA_KEY_SIZE, 2491da177e4SLinus Torvalds .cia_max_keysize = XTEA_KEY_SIZE, 2501da177e4SLinus Torvalds .cia_setkey = xtea_setkey, 2511da177e4SLinus Torvalds .cia_encrypt = xtea_encrypt, 2521da177e4SLinus Torvalds .cia_decrypt = xtea_decrypt } } 2531da177e4SLinus Torvalds }; 2541da177e4SLinus Torvalds 255fb4f10edSAaron Grothe static struct crypto_alg xeta_alg = { 256fb4f10edSAaron Grothe .cra_name = "xeta", 257fb4f10edSAaron Grothe .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 258fb4f10edSAaron Grothe .cra_blocksize = XTEA_BLOCK_SIZE, 259fb4f10edSAaron Grothe .cra_ctxsize = sizeof (struct xtea_ctx), 260a429d260SHerbert Xu .cra_alignmask = 3, 261fb4f10edSAaron Grothe .cra_module = THIS_MODULE, 262fb4f10edSAaron Grothe .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), 263fb4f10edSAaron Grothe .cra_u = { .cipher = { 264fb4f10edSAaron Grothe .cia_min_keysize = XTEA_KEY_SIZE, 265fb4f10edSAaron Grothe .cia_max_keysize = XTEA_KEY_SIZE, 266fb4f10edSAaron Grothe .cia_setkey = xtea_setkey, 267fb4f10edSAaron Grothe .cia_encrypt = xeta_encrypt, 268fb4f10edSAaron Grothe .cia_decrypt = xeta_decrypt } } 269fb4f10edSAaron Grothe }; 270fb4f10edSAaron Grothe 2711da177e4SLinus Torvalds static int __init init(void) 2721da177e4SLinus Torvalds { 2731da177e4SLinus Torvalds int ret = 0; 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds ret = crypto_register_alg(&tea_alg); 2761da177e4SLinus Torvalds if (ret < 0) 2771da177e4SLinus Torvalds goto out; 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds ret = crypto_register_alg(&xtea_alg); 2801da177e4SLinus Torvalds if (ret < 0) { 2811da177e4SLinus Torvalds crypto_unregister_alg(&tea_alg); 2821da177e4SLinus Torvalds goto out; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 285fb4f10edSAaron Grothe ret = crypto_register_alg(&xeta_alg); 286fb4f10edSAaron Grothe if (ret < 0) { 287fb4f10edSAaron Grothe crypto_unregister_alg(&tea_alg); 288fb4f10edSAaron Grothe crypto_unregister_alg(&xtea_alg); 289fb4f10edSAaron Grothe goto out; 290fb4f10edSAaron Grothe } 291fb4f10edSAaron Grothe 2921da177e4SLinus Torvalds out: 2931da177e4SLinus Torvalds return ret; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds static void __exit fini(void) 2971da177e4SLinus Torvalds { 2981da177e4SLinus Torvalds crypto_unregister_alg(&tea_alg); 2991da177e4SLinus Torvalds crypto_unregister_alg(&xtea_alg); 300fb4f10edSAaron Grothe crypto_unregister_alg(&xeta_alg); 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds MODULE_ALIAS("xtea"); 304fb4f10edSAaron Grothe MODULE_ALIAS("xeta"); 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds module_init(init); 3071da177e4SLinus Torvalds module_exit(fini); 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 310fb4f10edSAaron Grothe MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms"); 311