at v2.6.13-rc4 248 lines 5.0 kB view raw
1/* 2 * Cryptographic API. 3 * 4 * TEA and Xtended TEA Algorithms 5 * 6 * The TEA and Xtended TEA algorithms were developed by David Wheeler 7 * and Roger Needham at the Computer Laboratory of Cambridge University. 8 * 9 * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 */ 17 18#include <linux/init.h> 19#include <linux/module.h> 20#include <linux/mm.h> 21#include <asm/scatterlist.h> 22#include <linux/crypto.h> 23 24#define TEA_KEY_SIZE 16 25#define TEA_BLOCK_SIZE 8 26#define TEA_ROUNDS 32 27#define TEA_DELTA 0x9e3779b9 28 29#define XTEA_KEY_SIZE 16 30#define XTEA_BLOCK_SIZE 8 31#define XTEA_ROUNDS 32 32#define XTEA_DELTA 0x9e3779b9 33 34#define u32_in(x) le32_to_cpu(*(const __le32 *)(x)) 35#define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from)) 36 37struct tea_ctx { 38 u32 KEY[4]; 39}; 40 41struct xtea_ctx { 42 u32 KEY[4]; 43}; 44 45static int tea_setkey(void *ctx_arg, const u8 *in_key, 46 unsigned int key_len, u32 *flags) 47{ 48 49 struct tea_ctx *ctx = ctx_arg; 50 51 if (key_len != 16) 52 { 53 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 54 return -EINVAL; 55 } 56 57 ctx->KEY[0] = u32_in (in_key); 58 ctx->KEY[1] = u32_in (in_key + 4); 59 ctx->KEY[2] = u32_in (in_key + 8); 60 ctx->KEY[3] = u32_in (in_key + 12); 61 62 return 0; 63 64} 65 66static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) 67{ 68 u32 y, z, n, sum = 0; 69 u32 k0, k1, k2, k3; 70 71 struct tea_ctx *ctx = ctx_arg; 72 73 y = u32_in (src); 74 z = u32_in (src + 4); 75 76 k0 = ctx->KEY[0]; 77 k1 = ctx->KEY[1]; 78 k2 = ctx->KEY[2]; 79 k3 = ctx->KEY[3]; 80 81 n = TEA_ROUNDS; 82 83 while (n-- > 0) { 84 sum += TEA_DELTA; 85 y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 86 z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 87 } 88 89 u32_out (dst, y); 90 u32_out (dst + 4, z); 91} 92 93static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) 94{ 95 u32 y, z, n, sum; 96 u32 k0, k1, k2, k3; 97 98 struct tea_ctx *ctx = ctx_arg; 99 100 y = u32_in (src); 101 z = u32_in (src + 4); 102 103 k0 = ctx->KEY[0]; 104 k1 = ctx->KEY[1]; 105 k2 = ctx->KEY[2]; 106 k3 = ctx->KEY[3]; 107 108 sum = TEA_DELTA << 5; 109 110 n = TEA_ROUNDS; 111 112 while (n-- > 0) { 113 z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); 114 y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1); 115 sum -= TEA_DELTA; 116 } 117 118 u32_out (dst, y); 119 u32_out (dst + 4, z); 120 121} 122 123static int xtea_setkey(void *ctx_arg, const u8 *in_key, 124 unsigned int key_len, u32 *flags) 125{ 126 127 struct xtea_ctx *ctx = ctx_arg; 128 129 if (key_len != 16) 130 { 131 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 132 return -EINVAL; 133 } 134 135 ctx->KEY[0] = u32_in (in_key); 136 ctx->KEY[1] = u32_in (in_key + 4); 137 ctx->KEY[2] = u32_in (in_key + 8); 138 ctx->KEY[3] = u32_in (in_key + 12); 139 140 return 0; 141 142} 143 144static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) 145{ 146 147 u32 y, z, sum = 0; 148 u32 limit = XTEA_DELTA * XTEA_ROUNDS; 149 150 struct xtea_ctx *ctx = ctx_arg; 151 152 y = u32_in (src); 153 z = u32_in (src + 4); 154 155 while (sum != limit) { 156 y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 157 sum += XTEA_DELTA; 158 z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 159 } 160 161 u32_out (dst, y); 162 u32_out (dst + 4, z); 163 164} 165 166static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) 167{ 168 169 u32 y, z, sum; 170 struct tea_ctx *ctx = ctx_arg; 171 172 y = u32_in (src); 173 z = u32_in (src + 4); 174 175 sum = XTEA_DELTA * XTEA_ROUNDS; 176 177 while (sum) { 178 z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3]; 179 sum -= XTEA_DELTA; 180 y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; 181 } 182 183 u32_out (dst, y); 184 u32_out (dst + 4, z); 185 186} 187 188static struct crypto_alg tea_alg = { 189 .cra_name = "tea", 190 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 191 .cra_blocksize = TEA_BLOCK_SIZE, 192 .cra_ctxsize = sizeof (struct tea_ctx), 193 .cra_module = THIS_MODULE, 194 .cra_list = LIST_HEAD_INIT(tea_alg.cra_list), 195 .cra_u = { .cipher = { 196 .cia_min_keysize = TEA_KEY_SIZE, 197 .cia_max_keysize = TEA_KEY_SIZE, 198 .cia_setkey = tea_setkey, 199 .cia_encrypt = tea_encrypt, 200 .cia_decrypt = tea_decrypt } } 201}; 202 203static struct crypto_alg xtea_alg = { 204 .cra_name = "xtea", 205 .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 206 .cra_blocksize = XTEA_BLOCK_SIZE, 207 .cra_ctxsize = sizeof (struct xtea_ctx), 208 .cra_module = THIS_MODULE, 209 .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), 210 .cra_u = { .cipher = { 211 .cia_min_keysize = XTEA_KEY_SIZE, 212 .cia_max_keysize = XTEA_KEY_SIZE, 213 .cia_setkey = xtea_setkey, 214 .cia_encrypt = xtea_encrypt, 215 .cia_decrypt = xtea_decrypt } } 216}; 217 218static int __init init(void) 219{ 220 int ret = 0; 221 222 ret = crypto_register_alg(&tea_alg); 223 if (ret < 0) 224 goto out; 225 226 ret = crypto_register_alg(&xtea_alg); 227 if (ret < 0) { 228 crypto_unregister_alg(&tea_alg); 229 goto out; 230 } 231 232out: 233 return ret; 234} 235 236static void __exit fini(void) 237{ 238 crypto_unregister_alg(&tea_alg); 239 crypto_unregister_alg(&xtea_alg); 240} 241 242MODULE_ALIAS("xtea"); 243 244module_init(init); 245module_exit(fini); 246 247MODULE_LICENSE("GPL"); 248MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");