18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Cryptographic API. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * TEA, XTEA, and XETA crypto alogrithms 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * The TEA and Xtended TEA algorithms were developed by David Wheeler 88c2ecf20Sopenharmony_ci * and Roger Needham at the Computer Laboratory of Cambridge University. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Due to the order of evaluation in XTEA many people have incorrectly 118c2ecf20Sopenharmony_ci * implemented it. XETA (XTEA in the wrong order), exists for 128c2ecf20Sopenharmony_ci * compatibility with these implementations. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/mm.h> 208c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 218c2ecf20Sopenharmony_ci#include <linux/crypto.h> 228c2ecf20Sopenharmony_ci#include <linux/types.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define TEA_KEY_SIZE 16 258c2ecf20Sopenharmony_ci#define TEA_BLOCK_SIZE 8 268c2ecf20Sopenharmony_ci#define TEA_ROUNDS 32 278c2ecf20Sopenharmony_ci#define TEA_DELTA 0x9e3779b9 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define XTEA_KEY_SIZE 16 308c2ecf20Sopenharmony_ci#define XTEA_BLOCK_SIZE 8 318c2ecf20Sopenharmony_ci#define XTEA_ROUNDS 32 328c2ecf20Sopenharmony_ci#define XTEA_DELTA 0x9e3779b9 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistruct tea_ctx { 358c2ecf20Sopenharmony_ci u32 KEY[4]; 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct xtea_ctx { 398c2ecf20Sopenharmony_ci u32 KEY[4]; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key, 438c2ecf20Sopenharmony_ci unsigned int key_len) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 468c2ecf20Sopenharmony_ci const __le32 *key = (const __le32 *)in_key; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ctx->KEY[0] = le32_to_cpu(key[0]); 498c2ecf20Sopenharmony_ci ctx->KEY[1] = le32_to_cpu(key[1]); 508c2ecf20Sopenharmony_ci ctx->KEY[2] = le32_to_cpu(key[2]); 518c2ecf20Sopenharmony_ci ctx->KEY[3] = le32_to_cpu(key[3]); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return 0; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void tea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci u32 y, z, n, sum = 0; 608c2ecf20Sopenharmony_ci u32 k0, k1, k2, k3; 618c2ecf20Sopenharmony_ci struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 628c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 638c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 668c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci k0 = ctx->KEY[0]; 698c2ecf20Sopenharmony_ci k1 = ctx->KEY[1]; 708c2ecf20Sopenharmony_ci k2 = ctx->KEY[2]; 718c2ecf20Sopenharmony_ci k3 = ctx->KEY[3]; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci n = TEA_ROUNDS; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci while (n-- > 0) { 768c2ecf20Sopenharmony_ci sum += TEA_DELTA; 778c2ecf20Sopenharmony_ci y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 788c2ecf20Sopenharmony_ci z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 828c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci u32 y, z, n, sum; 888c2ecf20Sopenharmony_ci u32 k0, k1, k2, k3; 898c2ecf20Sopenharmony_ci struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 908c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 918c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 948c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci k0 = ctx->KEY[0]; 978c2ecf20Sopenharmony_ci k1 = ctx->KEY[1]; 988c2ecf20Sopenharmony_ci k2 = ctx->KEY[2]; 998c2ecf20Sopenharmony_ci k3 = ctx->KEY[3]; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci sum = TEA_DELTA << 5; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci n = TEA_ROUNDS; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci while (n-- > 0) { 1068c2ecf20Sopenharmony_ci z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 1078c2ecf20Sopenharmony_ci y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 1088c2ecf20Sopenharmony_ci sum -= TEA_DELTA; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 1128c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key, 1168c2ecf20Sopenharmony_ci unsigned int key_len) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 1198c2ecf20Sopenharmony_ci const __le32 *key = (const __le32 *)in_key; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci ctx->KEY[0] = le32_to_cpu(key[0]); 1228c2ecf20Sopenharmony_ci ctx->KEY[1] = le32_to_cpu(key[1]); 1238c2ecf20Sopenharmony_ci ctx->KEY[2] = le32_to_cpu(key[2]); 1248c2ecf20Sopenharmony_ci ctx->KEY[3] = le32_to_cpu(key[3]); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic void xtea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci u32 y, z, sum = 0; 1338c2ecf20Sopenharmony_ci u32 limit = XTEA_DELTA * XTEA_ROUNDS; 1348c2ecf20Sopenharmony_ci struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 1358c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 1368c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 1398c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci while (sum != limit) { 1428c2ecf20Sopenharmony_ci y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); 1438c2ecf20Sopenharmony_ci sum += XTEA_DELTA; 1448c2ecf20Sopenharmony_ci z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 1488c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic void xtea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci u32 y, z, sum; 1548c2ecf20Sopenharmony_ci struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 1558c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 1568c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 1598c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci sum = XTEA_DELTA * XTEA_ROUNDS; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci while (sum) { 1648c2ecf20Sopenharmony_ci z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]); 1658c2ecf20Sopenharmony_ci sum -= XTEA_DELTA; 1668c2ecf20Sopenharmony_ci y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 1708c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic void xeta_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci u32 y, z, sum = 0; 1778c2ecf20Sopenharmony_ci u32 limit = XTEA_DELTA * XTEA_ROUNDS; 1788c2ecf20Sopenharmony_ci struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); 1798c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 1808c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 1838c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci while (sum != limit) { 1868c2ecf20Sopenharmony_ci y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 1878c2ecf20Sopenharmony_ci sum += XTEA_DELTA; 1888c2ecf20Sopenharmony_ci z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 1928c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci u32 y, z, sum; 1988c2ecf20Sopenharmony_ci struct tea_ctx *ctx = crypto_tfm_ctx(tfm); 1998c2ecf20Sopenharmony_ci const __le32 *in = (const __le32 *)src; 2008c2ecf20Sopenharmony_ci __le32 *out = (__le32 *)dst; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci y = le32_to_cpu(in[0]); 2038c2ecf20Sopenharmony_ci z = le32_to_cpu(in[1]); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci sum = XTEA_DELTA * XTEA_ROUNDS; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci while (sum) { 2088c2ecf20Sopenharmony_ci z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3]; 2098c2ecf20Sopenharmony_ci sum -= XTEA_DELTA; 2108c2ecf20Sopenharmony_ci y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci out[0] = cpu_to_le32(y); 2148c2ecf20Sopenharmony_ci out[1] = cpu_to_le32(z); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic struct crypto_alg tea_algs[3] = { { 2188c2ecf20Sopenharmony_ci .cra_name = "tea", 2198c2ecf20Sopenharmony_ci .cra_driver_name = "tea-generic", 2208c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2218c2ecf20Sopenharmony_ci .cra_blocksize = TEA_BLOCK_SIZE, 2228c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof (struct tea_ctx), 2238c2ecf20Sopenharmony_ci .cra_alignmask = 3, 2248c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 2258c2ecf20Sopenharmony_ci .cra_u = { .cipher = { 2268c2ecf20Sopenharmony_ci .cia_min_keysize = TEA_KEY_SIZE, 2278c2ecf20Sopenharmony_ci .cia_max_keysize = TEA_KEY_SIZE, 2288c2ecf20Sopenharmony_ci .cia_setkey = tea_setkey, 2298c2ecf20Sopenharmony_ci .cia_encrypt = tea_encrypt, 2308c2ecf20Sopenharmony_ci .cia_decrypt = tea_decrypt } } 2318c2ecf20Sopenharmony_ci}, { 2328c2ecf20Sopenharmony_ci .cra_name = "xtea", 2338c2ecf20Sopenharmony_ci .cra_driver_name = "xtea-generic", 2348c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2358c2ecf20Sopenharmony_ci .cra_blocksize = XTEA_BLOCK_SIZE, 2368c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof (struct xtea_ctx), 2378c2ecf20Sopenharmony_ci .cra_alignmask = 3, 2388c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 2398c2ecf20Sopenharmony_ci .cra_u = { .cipher = { 2408c2ecf20Sopenharmony_ci .cia_min_keysize = XTEA_KEY_SIZE, 2418c2ecf20Sopenharmony_ci .cia_max_keysize = XTEA_KEY_SIZE, 2428c2ecf20Sopenharmony_ci .cia_setkey = xtea_setkey, 2438c2ecf20Sopenharmony_ci .cia_encrypt = xtea_encrypt, 2448c2ecf20Sopenharmony_ci .cia_decrypt = xtea_decrypt } } 2458c2ecf20Sopenharmony_ci}, { 2468c2ecf20Sopenharmony_ci .cra_name = "xeta", 2478c2ecf20Sopenharmony_ci .cra_driver_name = "xeta-generic", 2488c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2498c2ecf20Sopenharmony_ci .cra_blocksize = XTEA_BLOCK_SIZE, 2508c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof (struct xtea_ctx), 2518c2ecf20Sopenharmony_ci .cra_alignmask = 3, 2528c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 2538c2ecf20Sopenharmony_ci .cra_u = { .cipher = { 2548c2ecf20Sopenharmony_ci .cia_min_keysize = XTEA_KEY_SIZE, 2558c2ecf20Sopenharmony_ci .cia_max_keysize = XTEA_KEY_SIZE, 2568c2ecf20Sopenharmony_ci .cia_setkey = xtea_setkey, 2578c2ecf20Sopenharmony_ci .cia_encrypt = xeta_encrypt, 2588c2ecf20Sopenharmony_ci .cia_decrypt = xeta_decrypt } } 2598c2ecf20Sopenharmony_ci} }; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic int __init tea_mod_init(void) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci return crypto_register_algs(tea_algs, ARRAY_SIZE(tea_algs)); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic void __exit tea_mod_fini(void) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci crypto_unregister_algs(tea_algs, ARRAY_SIZE(tea_algs)); 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("tea"); 2728c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("xtea"); 2738c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("xeta"); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cisubsys_initcall(tea_mod_init); 2768c2ecf20Sopenharmony_cimodule_exit(tea_mod_fini); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2798c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms"); 280