📄 loop_serpent.c
字号:
ILINTRANS(r0,r4,r3,r2,r1); I4(r0,r4,r3,r2,r1); KEYMIX(r0,r2,r3,r1,r4,48); /* round 21 */ ILINTRANS(r0,r2,r3,r1,r4); I3(r0,r2,r3,r1,r4); KEYMIX(r3,r2,r1,r0,r4,44); /* round 22 */ ILINTRANS(r3,r2,r1,r0,r4); I2(r3,r2,r1,r0,r4); KEYMIX(r2,r4,r1,r0,r3,40); /* round 23 */ ILINTRANS(r2,r4,r1,r0,r3); I1(r2,r4,r1,r0,r3); KEYMIX(r3,r2,r0,r1,r4,36); /* round 24 */ ILINTRANS(r3,r2,r0,r1,r4); I0(r3,r2,r0,r1,r4); KEYMIX(r3,r4,r2,r1,r0,32); /* round 25 */ ILINTRANS(r3,r4,r2,r1,r0); I7(r3,r4,r2,r1,r0); KEYMIX(r1,r3,r4,r0,r2,28); /* round 26 */ ILINTRANS(r1,r3,r4,r0,r2); I6(r1,r3,r4,r0,r2); KEYMIX(r3,r4,r2,r0,r1,24); /* round 27 */ ILINTRANS(r3,r4,r2,r0,r1); I5(r3,r4,r2,r0,r1); KEYMIX(r4,r1,r0,r2,r3,20); /* round 28 */ ILINTRANS(r4,r1,r0,r2,r3); I4(r4,r1,r0,r2,r3); KEYMIX(r4,r2,r0,r3,r1,16); /* round 29 */ ILINTRANS(r4,r2,r0,r3,r1); I3(r4,r2,r0,r3,r1); KEYMIX(r0,r2,r3,r4,r1,12); /* round 30 */ ILINTRANS(r0,r2,r3,r4,r1); I2(r0,r2,r3,r4,r1); KEYMIX(r2,r1,r3,r4,r0,8); /* round 31 */ ILINTRANS(r2,r1,r3,r4,r0); I1(r2,r1,r3,r4,r0); KEYMIX(r0,r2,r4,r3,r1,4); /* round 32 */ ILINTRANS(r0,r2,r4,r3,r1); I0(r0,r2,r4,r3,r1); KEYMIX(r0,r1,r2,r3,r4,0); if (wrongByteOrder) { /* incorrect byte order */ out_blk[3] = io_swap_be(r0); out_blk[2] = io_swap_be(r1); out_blk[1] = io_swap_be(r2); out_blk[0] = io_swap_be(r3); } else { /* correct byte order */ out_blk[0] = io_swap_le(r0); out_blk[1] = io_swap_le(r1); out_blk[2] = io_swap_le(r2); out_blk[3] = io_swap_le(r3); }};#if LINUX_VERSION_CODE >= 0x20600typedef sector_t TransferSector_t;# define LoopInfo_t struct loop_info64#elsetypedef int TransferSector_t;# define LoopInfo_t struct loop_info#endif#if !defined(LOOP_MULTI_KEY_SETUP)# define LOOP_MULTI_KEY_SETUP 0x4C4D#endif#if !defined(LOOP_MULTI_KEY_SETUP_V3)# define LOOP_MULTI_KEY_SETUP_V3 0x4C4E#endifextern void loop_compute_sector_iv(TransferSector_t, u_int32_t *);extern void loop_compute_md5_iv_v3(TransferSector_t, u_int32_t *, u_int32_t *);typedef struct { u32 k[140];} serpent_context;typedef struct { serpent_context *keyPtr[64]; unsigned keyMask; u_int32_t partialMD5[4];} SerpentMultiKey;static SerpentMultiKey *allocMultiKey(void){ SerpentMultiKey *m; serpent_context *a; int x, n; m = (SerpentMultiKey *) kmalloc(sizeof(SerpentMultiKey), GFP_KERNEL); if(!m) return 0; memset(m, 0, sizeof(SerpentMultiKey)); n = PAGE_SIZE / sizeof(serpent_context); if(!n) n = 1; a = (serpent_context *) kmalloc(sizeof(serpent_context) * n, GFP_KERNEL); if(!a) { kfree(m); return 0; } x = 0; while((x < 64) && n) { m->keyPtr[x] = a; a++; x++; n--; } return m;}static void clearAndFreeMultiKey(SerpentMultiKey *m){ serpent_context *a; int x, n; n = PAGE_SIZE / sizeof(serpent_context); if(!n) n = 1; x = 0; while(x < 64) { a = m->keyPtr[x]; if(!a) break; memset(a, 0, sizeof(serpent_context) * n); kfree(a); x += n; } memset(m, 0, sizeof(SerpentMultiKey)); kfree(m);}static int multiKeySetup(struct loop_device *lo, unsigned char *k, int version3){ SerpentMultiKey *m; serpent_context *a; int x, y, n; union { u_int32_t w[16]; unsigned char b[64]; } un; /* lo->lo_init[0] == 0 or 1 means correct byte order serpent */ /* lo->lo_init[0] == 2 means inverted byte order serpent */ int wrongByteOrder = (lo->lo_init[0] == 2); extern void md5_transform_CPUbyteorder_C(u_int32_t *, u_int32_t const *);#if LINUX_VERSION_CODE >= 0x20200 if(lo->lo_key_owner != current->uid && !capable(CAP_SYS_ADMIN)) return -EPERM;#endif m = (SerpentMultiKey *)lo->key_data; if(!m) return -ENXIO; n = PAGE_SIZE / sizeof(serpent_context); if(!n) n = 1; x = 0; while(x < 64) { if(!m->keyPtr[x]) { a = (serpent_context *) kmalloc(sizeof(serpent_context) * n, GFP_KERNEL); if(!a) return -ENOMEM; y = x; while((y < (x + n)) && (y < 64)) { m->keyPtr[y] = a; a++; y++; } } if(copy_from_user(&un.b[0], k, 32)) return -EFAULT; serpent_set_key(&m->keyPtr[x]->k[0], &un.b[0], lo->lo_encrypt_key_size, wrongByteOrder); k += 32; x++; } m->partialMD5[0] = 0x67452301; m->partialMD5[1] = 0xefcdab89; m->partialMD5[2] = 0x98badcfe; m->partialMD5[3] = 0x10325476; if(version3) { /* only first 128 bits of iv-key is used */ if(copy_from_user(&un.b[0], k, 16)) return -EFAULT;#if defined(__BIG_ENDIAN) un.w[0] = cpu_to_le32(un.w[0]); un.w[1] = cpu_to_le32(un.w[1]); un.w[2] = cpu_to_le32(un.w[2]); un.w[3] = cpu_to_le32(un.w[3]);#endif memset(&un.b[16], 0, 48); md5_transform_CPUbyteorder_C(&m->partialMD5[0], &un.w[0]); lo->lo_flags |= 0x080000; /* multi-key-v3 (info exported to user space) */ } m->keyMask = 0x3F; /* range 0...63 */ lo->lo_flags |= 0x100000; /* multi-key (info exported to user space) */ memset(&un.b[0], 0, 32); return 0;}static int transfer_serpent(struct loop_device *lo, int cmd, char *raw_buf, char *loop_buf, int size, TransferSector_t devSect){ serpent_context *a; SerpentMultiKey *m; int x; unsigned y; u_int32_t iv[8]; /* lo->lo_init[0] == 0 or 1 means correct byte order serpent */ /* lo->lo_init[0] == 2 means inverted byte order serpent */ int wrongByteOrder = (lo->lo_init[0] == 2); if(!size || (size & 511)) { return -EINVAL; } m = (SerpentMultiKey *)lo->key_data; y = m->keyMask; if(cmd == READ) { while(size) { a = m->keyPtr[((unsigned)devSect) & y]; if(y) { memcpy(&iv[0], raw_buf, 16); raw_buf += 16; loop_buf += 16; } else { loop_compute_sector_iv(devSect, &iv[0]); } x = 15; do { memcpy(&iv[4], raw_buf, 16); serpent_decrypt(&a->k[0], raw_buf, loop_buf, wrongByteOrder); *((u_int32_t *)(&loop_buf[ 0])) ^= iv[0]; *((u_int32_t *)(&loop_buf[ 4])) ^= iv[1]; *((u_int32_t *)(&loop_buf[ 8])) ^= iv[2]; *((u_int32_t *)(&loop_buf[12])) ^= iv[3]; if(y && !x) { raw_buf -= 496; loop_buf -= 496; memcpy(&iv[4], &m->partialMD5[0], 16); loop_compute_md5_iv_v3(devSect, &iv[4], (u_int32_t *)(&loop_buf[16])); } else { raw_buf += 16; loop_buf += 16; memcpy(&iv[0], raw_buf, 16); } serpent_decrypt(&a->k[0], raw_buf, loop_buf, wrongByteOrder); *((u_int32_t *)(&loop_buf[ 0])) ^= iv[4]; *((u_int32_t *)(&loop_buf[ 4])) ^= iv[5]; *((u_int32_t *)(&loop_buf[ 8])) ^= iv[6]; *((u_int32_t *)(&loop_buf[12])) ^= iv[7]; if(y && !x) { raw_buf += 512; loop_buf += 512; } else { raw_buf += 16; loop_buf += 16; } } while(--x >= 0);#if LINUX_VERSION_CODE >= 0x20600 cond_resched();#elif LINUX_VERSION_CODE >= 0x20400 if(current->need_resched) {set_current_state(TASK_RUNNING);schedule();}#else if(current->need_resched) {current->state=TASK_RUNNING;schedule();}#endif size -= 512; devSect++; } } else { while(size) { a = m->keyPtr[((unsigned)devSect) & y]; if(y) {#if LINUX_VERSION_CODE < 0x20400 /* on 2.2 and older kernels, real raw_buf may be doing */ /* writes at any time, so this needs to be stack buffer */ u_int32_t tmp_raw_buf[128]; char *TMP_RAW_BUF = (char *)(&tmp_raw_buf[0]);#else /* on 2.4 and later kernels, real raw_buf is not doing */ /* any writes now so it can be used as temp buffer */# define TMP_RAW_BUF raw_buf#endif memcpy(TMP_RAW_BUF, loop_buf, 512); memcpy(&iv[0], &m->partialMD5[0], 16); loop_compute_md5_iv_v3(devSect, &iv[0], (u_int32_t *)(&TMP_RAW_BUF[16])); x = 15; do { iv[0] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 0])); iv[1] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 4])); iv[2] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 8])); iv[3] ^= *((u_int32_t *)(&TMP_RAW_BUF[12])); serpent_encrypt(&a->k[0], (unsigned char *)(&iv[0]), raw_buf, wrongByteOrder); memcpy(&iv[0], raw_buf, 16); raw_buf += 16;#if LINUX_VERSION_CODE < 0x20400 TMP_RAW_BUF += 16;#endif iv[0] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 0])); iv[1] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 4])); iv[2] ^= *((u_int32_t *)(&TMP_RAW_BUF[ 8])); iv[3] ^= *((u_int32_t *)(&TMP_RAW_BUF[12])); serpent_encrypt(&a->k[0], (unsigned char *)(&iv[0]), raw_buf, wrongByteOrder); memcpy(&iv[0], raw_buf, 16); raw_buf += 16;#if LINUX_VERSION_CODE < 0x20400 TMP_RAW_BUF += 16;#endif } while(--x >= 0); loop_buf += 512; } else { loop_compute_sector_iv(devSect, &iv[0]); x = 15; do { iv[0] ^= *((u_int32_t *)(&loop_buf[ 0])); iv[1] ^= *((u_int32_t *)(&loop_buf[ 4])); iv[2] ^= *((u_int32_t *)(&loop_buf[ 8])); iv[3] ^= *((u_int32_t *)(&loop_buf[12])); serpent_encrypt(&a->k[0], (unsigned char *)(&iv[0]), raw_buf, wrongByteOrder); memcpy(&iv[0], raw_buf, 16); loop_buf += 16; raw_buf += 16; iv[0] ^= *((u_int32_t *)(&loop_buf[ 0])); iv[1] ^= *((u_int32_t *)(&loop_buf[ 4])); iv[2] ^= *((u_int32_t *)(&loop_buf[ 8])); iv[3] ^= *((u_int32_t *)(&loop_buf[12])); serpent_encrypt(&a->k[0], (unsigned char *)(&iv[0]), raw_buf, wrongByteOrder); memcpy(&iv[0], raw_buf, 16); loop_buf += 16; raw_buf += 16; } while(--x >= 0); }#if LINUX_VERSION_CODE >= 0x20600 cond_resched();#elif LINUX_VERSION_CODE >= 0x20400 if(current->need_resched) {set_current_state(TASK_RUNNING);schedule();}#else if(current->need_resched) {current->state=TASK_RUNNING;schedule();}#endif size -= 512; devSect++; } } return(0);}static int keySetup_serpent(struct loop_device *lo, LoopInfo_t *info){ SerpentMultiKey *m; /* lo->lo_init[0] == 0 or 1 means correct byte order serpent */ /* lo->lo_init[0] == 2 means inverted byte order serpent */ int wrongByteOrder = (info->lo_init[0] == 2); lo->key_data = m = allocMultiKey(); if(!m) return(-ENOMEM); serpent_set_key(&m->keyPtr[0]->k[0], &info->lo_encrypt_key[0], info->lo_encrypt_key_size, wrongByteOrder); memset(&info->lo_encrypt_key[0], 0, sizeof(info->lo_encrypt_key)); return(0);}static int keyClean_serpent(struct loop_device *lo){ if(lo->key_data) { clearAndFreeMultiKey((SerpentMultiKey *)lo->key_data); lo->key_data = 0; } return(0);}static int handleIoctl_serpent(struct loop_device *lo, int cmd, unsigned long arg){ int err; switch (cmd) { case LOOP_MULTI_KEY_SETUP: err = multiKeySetup(lo, (unsigned char *)arg, 0); break; case LOOP_MULTI_KEY_SETUP_V3: err = multiKeySetup(lo, (unsigned char *)arg, 1); break; default: err = -EINVAL; } return err;}#if LINUX_VERSION_CODE < 0x20600static void lock_serpent(struct loop_device *lo){ MOD_INC_USE_COUNT;}static void unlock_serpent(struct loop_device *lo){ MOD_DEC_USE_COUNT;}#endifstatic struct loop_func_table funcs_serpent = { number: 7, /* 7 == LO_CRYPT_SERPENT */ transfer: (void *) transfer_serpent, init: (void *) keySetup_serpent, release: keyClean_serpent,#if LINUX_VERSION_CODE >= 0x20600 owner: THIS_MODULE,#else lock: lock_serpent, unlock: unlock_serpent,#endif ioctl: (void *) handleIoctl_serpent}; #if LINUX_VERSION_CODE >= 0x20600# define loop_serpent_init __init loop_serpent_initfn# define loop_serpent_exit loop_serpent_exitfn#else# define loop_serpent_init init_module# define loop_serpent_exit cleanup_module#endifint loop_serpent_init(void){ if (loop_register_transfer(&funcs_serpent)) { printk(KERN_WARNING "loop: unable to register serpent transfer\n"); return -EIO; } printk(KERN_INFO "loop: registered serpent encryption\n"); return 0;}void loop_serpent_exit(void){ if (loop_unregister_transfer(funcs_serpent.number)) { printk(KERN_WARNING "loop: unable to unregister serpent transfer\n"); return; } printk(KERN_INFO "loop: unregistered serpent encryption\n");}#if LINUX_VERSION_CODE >= 0x20600module_init(loop_serpent_initfn);module_exit(loop_serpent_exitfn);#endif#if defined(MODULE_LICENSE)MODULE_LICENSE("GPL");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -