📄 bc_alg.c
字号:
/******************************************************************* * Copyright (c) 1994-1998 Jetico, Inc., Finland * All rights reserved. * * File: driver/bc_alg.c * * Description: algorithm wrapper for module building * * Scope: BestCrypt algorithms drivers * * Platforms: Linux * * Author: Nail R. Kaipov * * Created: 10-Nov-1998 * * Revision: * *******************************************************************/#include "../bc_cfg.h"#include <linux/module.h>#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))#include <linux/vermagic.h>MODULE_LICENSE("Jetico, Inc.");MODULE_INFO(vermagic, VERMAGIC_STRING);#ifdef _NEED_THIS_MODULEstruct module __this_module__attribute__((section(".gnu.linkonce.this_module"))) = { .name = __stringify(KBUILD_MODNAME), .init = init_module,#ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module,#endif};static const char __module_depends[]__attribute_used____attribute__((section(".modinfo"))) ="depends=";#endif#elseEXPORT_NO_SYMBOLS;#endif#include <linux/mm.h>#include <linux/slab.h>#include <asm/uaccess.h>#include "bc_types.h"#include "../bc_mgr.h" /* algorithm manager defines */#include "algorithm.h" /* algorithm defines */#define POOL_SIZE_BYTES 512#define TABLE_LENGTH 32typedef struct { unsigned char *key_extended; unsigned char *pool; int lock;} KEY_ELEMENT;static KEY_ELEMENT KeyTable[ TABLE_LENGTH ];/*-- keys management -------------------------------------------*/static void shred (u_char **ptr, u_int len){ if (!ptr || !*ptr) return; memset(*ptr, 0, len); kfree(*ptr); *ptr = NULL;}int test_key (KEY_HANDLE kh){ if (kh < 0 || kh >= TABLE_LENGTH) return -EINVAL; if (!KeyTable[kh].key_extended) return -EINVAL; return 0;}int lock_key (KEY_HANDLE kh, int lock){ int error; error = test_key(kh); if (error) return error; if (lock) KeyTable[kh].lock++; else KeyTable[kh].lock--; return 0;}int free_key (KEY_HANDLE kh) { int err; err = test_key(kh); if (err) return err; KeyTable[kh].lock--; if (KeyTable[kh].lock > 0) return 0; shred(&(KeyTable[kh].key_extended), KEY_LENGTH_EXTENDED/8); shred(&(KeyTable[kh].pool), POOL_SIZE_BYTES); memset(&(KeyTable[kh]), 0, sizeof(KEY_ELEMENT));#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) module_put(THIS_MODULE);#else MOD_DEC_USE_COUNT;#endif return 0;}int make_key(u_char *key, u_int keylen, u_char *pool, KEY_HANDLE *return_key)/* NOTE!!! key and pool are in user memory space. */{ KEY_HANDLE kh = -1; int error = 0; //, i; u_char *key_tmp = NULL; if (keylen != KEY_LENGTH) return -EINVAL; keylen = (keylen+7) >> 3; /* convert to bytes */ for (kh = 0; kh < TABLE_LENGTH; kh++) if (!KeyTable[kh].key_extended) break; if (kh >= TABLE_LENGTH || KeyTable[kh].key_extended || KeyTable[kh].pool) return -EBUSY; error = -ENOMEM; KeyTable[kh].key_extended = kmalloc(KEY_LENGTH_EXTENDED/8, GFP_KERNEL); key_tmp = kmalloc(keylen, GFP_KERNEL); KeyTable[kh].pool = kmalloc(POOL_SIZE_BYTES, GFP_KERNEL); if (!KeyTable[kh].key_extended || !key_tmp || !KeyTable[kh].pool) goto error_out; error = copy_from_user(KeyTable[kh].pool, pool, POOL_SIZE_BYTES); if (error) goto error_out; error = copy_from_user(key_tmp, key, keylen); if (error) goto error_out; KeyExtend(key_tmp, (DWORD *)KeyTable[kh].key_extended); shred(&key_tmp, keylen); KeyTable[kh].lock = 1; *return_key = kh;#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) try_module_get(THIS_MODULE);#else MOD_INC_USE_COUNT;#endif return 0; error_out: shred(&(KeyTable[kh].key_extended), KEY_LENGTH_EXTENDED/8); shred(&(KeyTable[kh].pool), POOL_SIZE_BYTES); shred(&key_tmp, keylen); return error; }/*-- encryption/decryption helpers -----------------------------*/inline void transform_iv (DWORD *iv, DWORD *pool, int ver){ unsigned int i; if (0 == ver) { i = (iv[0] & 0x3F) << 1; iv[0] ^= pool[i]; iv[1] ^= pool[i+1]; } else { i = __le32_to_cpu(iv[0]); i = (i & 0x3F) << 1; iv[0] ^= pool[i]; iv[1] ^= pool[i+1]; } }inline void increment_iv(WORD *iv, int ver) { u64 iv64, *piv64; if (0 == ver) { iv[0]++; iv[3] = iv[2] = iv[1] = iv[0]; } else { piv64 = (u64 *)iv; iv64 = __le64_to_cpu(*piv64); iv64++; *piv64 = __cpu_to_le64(iv64); }}inline void transform_buf (DWORD *pool, DWORD *src, DWORD *dst, DWORD len){ while (len--) *dst++ = *src++ ^ *pool++;}/*-- encryption/decryption main --------------------------------*/int encrypt (KEY_HANDLE kh, u_char *iv, u_char *src, u_char *dst, u_int len){ int err, ver = 1; WORD *s, ivector[4], ivectorS[4]; DWORD i, offset, size, *pool; if (!len) return 0; if (len & (BLOCK_LENGTH-1)) return -EINVAL; err = test_key(kh); if (err) return err; pool = (DWORD *)KeyTable[kh].pool; s = (WORD *)iv; for (i = 0; i < 4; i++) ivector[i] = ivectorS[i] = s[i]; if (s[0] == s[3] && s[0] == s[1] && s[0] == s[2]) // check for 64-bit IV ver = 0; for (offset = 0; ; offset += 512) { transform_iv((DWORD *)ivector, pool, ver); size = len > 512 ? 512 : len; len -= size; transform_buf(pool, (DWORD *)(&src[offset]), (DWORD *)(&dst[offset]), size >> 2); Encrypt((DWORD *)ivector, (DWORD *)KeyTable[kh].key_extended, (DWORD *)(&dst[offset]), (DWORD *)(&dst[offset]), size); if (!len) break; /* We need to update IVector every 512 bytes */ increment_iv(ivectorS, ver); for(i = 0; i < 4; i++) ivector[i] = ivectorS[i]; } return 0;}int decrypt (KEY_HANDLE kh, u_char *iv, u_char *src, u_char *dst, u_int len){ int err, ver = 1; WORD *s, ivector[4], ivectorS[4]; DWORD i, offset, size, *pool; if (!len) return 0; if (len & (BLOCK_LENGTH-1)) return -EINVAL; err = test_key(kh); if (err) return err; pool = (DWORD *)KeyTable[kh].pool; s = (WORD *)iv; for (i = 0; i < 4; i++) ivector[i] = ivectorS[i] = s[i]; if (s[0] == s[3] && s[0] == s[1] && s[0] == s[2]) // check for 64-bit IV ver = 0; for (offset = 0; ; offset += 512) { transform_iv((DWORD *)ivector, pool, ver); size = len > 512 ? 512 : len; len -= size; Decrypt((DWORD *)ivector, (DWORD *)KeyTable[kh].key_extended, (DWORD *)(&src[offset]), (DWORD *)(&dst[offset]), size); transform_buf(pool, (DWORD *)(&dst[offset]), (DWORD *)(&dst[offset]), size >> 2); if (!len) break; /* We need to update IVector every 512 bytes */ increment_iv(ivectorS, ver); for(i = 0; i < 4; i++) ivector[i] = ivectorS[i]; } return 0;}/*-- modularization --------------------------------------------*/static struct bc_algorithm algo;int init_module (void){ int i; for (i = 0; i < TABLE_LENGTH; i++) memset(&KeyTable[i], 0x00, sizeof(KEY_ELEMENT)); algo.id = ALGORITHM_ID; algo.name = DISPLAY_NAME; algo.keylen = KEY_LENGTH; algo.make_key = make_key; algo.test_key = test_key; algo.free_key = free_key; algo.lock_key = lock_key; algo.encrypt = encrypt; algo.decrypt = decrypt; i = register_bc_algo(&algo); return i;}void cleanup_module (void) { int i; for (i = 0; i < TABLE_LENGTH; i++) { if (KeyTable[i].key_extended) { memset(KeyTable[i].key_extended, 0, KEY_LENGTH_EXTENDED/8); kfree (KeyTable[i].key_extended); } if (KeyTable[i].pool) { memset(KeyTable[i].pool, 0, POOL_SIZE_BYTES); kfree (KeyTable[i].pool); } memset(&KeyTable[i], 0, sizeof(KEY_ELEMENT)); } i = unregister_bc_algo(ALGORITHM_ID); return;}char bc_alg_c[]="$Id: bc_alg.c,v 1.9 2006/03/07 05:40:24 nail Rel-1.6-3 $";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -