linux/crypto/tea.c
<<
>>
Prefs
   1/* 
   2 * Cryptographic API.
   3 *
   4 * TEA, XTEA, and XETA crypto alogrithms
   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 * Due to the order of evaluation in XTEA many people have incorrectly
  10 * implemented it.  XETA (XTEA in the wrong order), exists for
  11 * compatibility with these implementations.
  12 *
  13 * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.com
  14 *
  15 * This program is free software; you can redistribute it and/or modify
  16 * it under the terms of the GNU General Public License as published by
  17 * the Free Software Foundation; either version 2 of the License, or
  18 * (at your option) any later version.
  19 *
  20 */
  21
  22#include <linux/init.h>
  23#include <linux/module.h>
  24#include <linux/mm.h>
  25#include <asm/byteorder.h>
  26#include <asm/scatterlist.h>
  27#include <linux/crypto.h>
  28#include <linux/types.h>
  29
  30#define TEA_KEY_SIZE            16
  31#define TEA_BLOCK_SIZE          8
  32#define TEA_ROUNDS              32
  33#define TEA_DELTA               0x9e3779b9
  34
  35#define XTEA_KEY_SIZE           16
  36#define XTEA_BLOCK_SIZE         8
  37#define XTEA_ROUNDS             32
  38#define XTEA_DELTA              0x9e3779b9
  39
  40struct tea_ctx {
  41        u32 KEY[4];
  42};
  43
  44struct xtea_ctx {
  45        u32 KEY[4];
  46};
  47
  48static int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key,
  49                      unsigned int key_len, u32 *flags)
  50{
  51        struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
  52        const __le32 *key = (const __le32 *)in_key;
  53        
  54        if (key_len != 16)
  55        {
  56                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
  57                return -EINVAL;
  58        }
  59
  60        ctx->KEY[0] = le32_to_cpu(key[0]);
  61        ctx->KEY[1] = le32_to_cpu(key[1]);
  62        ctx->KEY[2] = le32_to_cpu(key[2]);
  63        ctx->KEY[3] = le32_to_cpu(key[3]);
  64
  65        return 0; 
  66
  67}
  68
  69static void tea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  70{
  71        u32 y, z, n, sum = 0;
  72        u32 k0, k1, k2, k3;
  73        struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
  74        const __le32 *in = (const __le32 *)src;
  75        __le32 *out = (__le32 *)dst;
  76
  77        y = le32_to_cpu(in[0]);
  78        z = le32_to_cpu(in[1]);
  79
  80        k0 = ctx->KEY[0];
  81        k1 = ctx->KEY[1];
  82        k2 = ctx->KEY[2];
  83        k3 = ctx->KEY[3];
  84
  85        n = TEA_ROUNDS;
  86
  87        while (n-- > 0) {
  88                sum += TEA_DELTA;
  89                y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
  90                z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
  91        }
  92        
  93        out[0] = cpu_to_le32(y);
  94        out[1] = cpu_to_le32(z);
  95}
  96
  97static void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  98{
  99        u32 y, z, n, sum;
 100        u32 k0, k1, k2, k3;
 101        struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 102        const __le32 *in = (const __le32 *)src;
 103        __le32 *out = (__le32 *)dst;
 104
 105        y = le32_to_cpu(in[0]);
 106        z = le32_to_cpu(in[1]);
 107
 108        k0 = ctx->KEY[0];
 109        k1 = ctx->KEY[1];
 110        k2 = ctx->KEY[2];
 111        k3 = ctx->KEY[3];
 112
 113        sum = TEA_DELTA << 5;
 114
 115        n = TEA_ROUNDS;
 116
 117        while (n-- > 0) {
 118                z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
 119                y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
 120                sum -= TEA_DELTA;
 121        }
 122        
 123        out[0] = cpu_to_le32(y);
 124        out[1] = cpu_to_le32(z);
 125}
 126
 127static int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key,
 128                       unsigned int key_len, u32 *flags)
 129{
 130        struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 131        const __le32 *key = (const __le32 *)in_key;
 132        
 133        if (key_len != 16)
 134        {
 135                *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 136                return -EINVAL;
 137        }
 138
 139        ctx->KEY[0] = le32_to_cpu(key[0]);
 140        ctx->KEY[1] = le32_to_cpu(key[1]);
 141        ctx->KEY[2] = le32_to_cpu(key[2]);
 142        ctx->KEY[3] = le32_to_cpu(key[3]);
 143
 144        return 0; 
 145
 146}
 147
 148static void xtea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 149{
 150        u32 y, z, sum = 0;
 151        u32 limit = XTEA_DELTA * XTEA_ROUNDS;
 152        struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 153        const __le32 *in = (const __le32 *)src;
 154        __le32 *out = (__le32 *)dst;
 155
 156        y = le32_to_cpu(in[0]);
 157        z = le32_to_cpu(in[1]);
 158
 159        while (sum != limit) {
 160                y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); 
 161                sum += XTEA_DELTA;
 162                z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); 
 163        }
 164        
 165        out[0] = cpu_to_le32(y);
 166        out[1] = cpu_to_le32(z);
 167}
 168
 169static void xtea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 170{
 171        u32 y, z, sum;
 172        struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 173        const __le32 *in = (const __le32 *)src;
 174        __le32 *out = (__le32 *)dst;
 175
 176        y = le32_to_cpu(in[0]);
 177        z = le32_to_cpu(in[1]);
 178
 179        sum = XTEA_DELTA * XTEA_ROUNDS;
 180
 181        while (sum) {
 182                z -= ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 & 3]);
 183                sum -= XTEA_DELTA;
 184                y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]);
 185        }
 186        
 187        out[0] = cpu_to_le32(y);
 188        out[1] = cpu_to_le32(z);
 189}
 190
 191
 192static void xeta_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 193{
 194        u32 y, z, sum = 0;
 195        u32 limit = XTEA_DELTA * XTEA_ROUNDS;
 196        struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 197        const __le32 *in = (const __le32 *)src;
 198        __le32 *out = (__le32 *)dst;
 199
 200        y = le32_to_cpu(in[0]);
 201        z = le32_to_cpu(in[1]);
 202
 203        while (sum != limit) {
 204                y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
 205                sum += XTEA_DELTA;
 206                z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
 207        }
 208        
 209        out[0] = cpu_to_le32(y);
 210        out[1] = cpu_to_le32(z);
 211}
 212
 213static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 214{
 215        u32 y, z, sum;
 216        struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 217        const __le32 *in = (const __le32 *)src;
 218        __le32 *out = (__le32 *)dst;
 219
 220        y = le32_to_cpu(in[0]);
 221        z = le32_to_cpu(in[1]);
 222
 223        sum = XTEA_DELTA * XTEA_ROUNDS;
 224
 225        while (sum) {
 226                z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
 227                sum -= XTEA_DELTA;
 228                y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
 229        }
 230        
 231        out[0] = cpu_to_le32(y);
 232        out[1] = cpu_to_le32(z);
 233}
 234
 235static struct crypto_alg tea_alg = {
 236        .cra_name               =       "tea",
 237        .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
 238        .cra_blocksize          =       TEA_BLOCK_SIZE,
 239        .cra_ctxsize            =       sizeof (struct tea_ctx),
 240        .cra_alignmask          =       3,
 241        .cra_module             =       THIS_MODULE,
 242        .cra_list               =       LIST_HEAD_INIT(tea_alg.cra_list),
 243        .cra_u                  =       { .cipher = {
 244        .cia_min_keysize        =       TEA_KEY_SIZE,
 245        .cia_max_keysize        =       TEA_KEY_SIZE,
 246        .cia_setkey             =       tea_setkey,
 247        .cia_encrypt            =       tea_encrypt,
 248        .cia_decrypt            =       tea_decrypt } }
 249};
 250
 251static struct crypto_alg xtea_alg = {
 252        .cra_name               =       "xtea",
 253        .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
 254        .cra_blocksize          =       XTEA_BLOCK_SIZE,
 255        .cra_ctxsize            =       sizeof (struct xtea_ctx),
 256        .cra_alignmask          =       3,
 257        .cra_module             =       THIS_MODULE,
 258        .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
 259        .cra_u                  =       { .cipher = {
 260        .cia_min_keysize        =       XTEA_KEY_SIZE,
 261        .cia_max_keysize        =       XTEA_KEY_SIZE,
 262        .cia_setkey             =       xtea_setkey,
 263        .cia_encrypt            =       xtea_encrypt,
 264        .cia_decrypt            =       xtea_decrypt } }
 265};
 266
 267static struct crypto_alg xeta_alg = {
 268        .cra_name               =       "xeta",
 269        .cra_flags              =       CRYPTO_ALG_TYPE_CIPHER,
 270        .cra_blocksize          =       XTEA_BLOCK_SIZE,
 271        .cra_ctxsize            =       sizeof (struct xtea_ctx),
 272        .cra_alignmask          =       3,
 273        .cra_module             =       THIS_MODULE,
 274        .cra_list               =       LIST_HEAD_INIT(xtea_alg.cra_list),
 275        .cra_u                  =       { .cipher = {
 276        .cia_min_keysize        =       XTEA_KEY_SIZE,
 277        .cia_max_keysize        =       XTEA_KEY_SIZE,
 278        .cia_setkey             =       xtea_setkey,
 279        .cia_encrypt            =       xeta_encrypt,
 280        .cia_decrypt            =       xeta_decrypt } }
 281};
 282
 283static int __init init(void)
 284{
 285        int ret = 0;
 286        
 287        ret = crypto_register_alg(&tea_alg);
 288        if (ret < 0)
 289                goto out;
 290
 291        ret = crypto_register_alg(&xtea_alg);
 292        if (ret < 0) {
 293                crypto_unregister_alg(&tea_alg);
 294                goto out;
 295        }
 296
 297        ret = crypto_register_alg(&xeta_alg);
 298        if (ret < 0) {
 299                crypto_unregister_alg(&tea_alg);
 300                crypto_unregister_alg(&xtea_alg);
 301                goto out;
 302        }
 303
 304out:    
 305        return ret;
 306}
 307
 308static void __exit fini(void)
 309{
 310        crypto_unregister_alg(&tea_alg);
 311        crypto_unregister_alg(&xtea_alg);
 312        crypto_unregister_alg(&xeta_alg);
 313}
 314
 315MODULE_ALIAS("xtea");
 316MODULE_ALIAS("xeta");
 317
 318module_init(init);
 319module_exit(fini);
 320
 321MODULE_LICENSE("GPL");
 322MODULE_DESCRIPTION("TEA, XTEA & XETA Cryptographic Algorithms");
 323
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.