RHEL4/crypto/tea.c
<<
>>
Prefs
   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 u32 *)(x))
  35#define u32_out(to, from) (*(u32 *)(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");
 249