⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loop_twofish.c

📁 Fast and transparent file system and swap encryption package for linux. No source code changes to li
💻 C
📖 第 1 页 / 共 2 页
字号:
{    TwofishMultiKey *m;    fish2_key *a;    int x, n;    m = (TwofishMultiKey *) kmalloc(sizeof(TwofishMultiKey), GFP_KERNEL);    if(!m) return 0;    memset(m, 0, sizeof(TwofishMultiKey));    n = PAGE_SIZE / sizeof(fish2_key);    if(!n) n = 1;    a = (fish2_key *) kmalloc(sizeof(fish2_key) * 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(TwofishMultiKey *m){    fish2_key *a;    int x, n;    n = PAGE_SIZE / sizeof(fish2_key);    if(!n) n = 1;    x = 0;    while(x < 64) {        a = m->keyPtr[x];        if(!a) break;        memset(a, 0, sizeof(fish2_key) * n);        kfree(a);        x += n;    }    memset(m, 0, sizeof(TwofishMultiKey));    kfree(m);}static int multiKeySetup(struct loop_device *lo, unsigned char *k, int version3){    TwofishMultiKey *m;    fish2_key *a;    int x, y, n;    union {        u_int32_t     w[16];        unsigned char b[64];    } un;    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 = (TwofishMultiKey *)lo->key_data;    if(!m) return -ENXIO;    n = PAGE_SIZE / sizeof(fish2_key);    if(!n) n = 1;    x = 0;    while(x < 64) {        if(!m->keyPtr[x]) {            a = (fish2_key *) kmalloc(sizeof(fish2_key) * 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;        a = m->keyPtr[x];        memset(a, 0, sizeof(fish2_key));        a->keyLen = lo->lo_encrypt_key_size << 3;        memcpy(a->key, &un.b[0], lo->lo_encrypt_key_size);        init_key(a);        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;}#if defined(__BIG_ENDIAN)/* twofish specific -- returns ivout[] data in CPU byte order */static void twofish_compute_md5_iv_v3(TransferSector_t devSect, u_int32_t *ivout, u_int32_t *data){    int         x, y, e;    u_int32_t   buf[16];    extern void md5_transform_CPUbyteorder(u_int32_t *, u_int32_t const *);    y = 7;    e = 16;    do {        if (!y) {            e = 12;            /* md5_transform_CPUbyteorder wants data in CPU byte order */            /* devSect is already in CPU byte order -- no need to convert */            if(sizeof(TransferSector_t) == 8) {                /* use only 56 bits of sector number */                buf[12] = devSect;                buf[13] = (((u_int64_t)devSect >> 32) & 0xFFFFFF) | 0x80000000;            } else {                /* 32 bits of sector number + 24 zero bits */                buf[12] = devSect;                buf[13] = 0x80000000;            }            /* 4024 bits == 31 * 128 bit plaintext blocks + 56 bits of sector number */            buf[14] = 4024;            buf[15] = 0;        }        x = 0;        do {            buf[x    ] = cpu_to_le32(data[0]);            buf[x + 1] = cpu_to_le32(data[1]);            buf[x + 2] = cpu_to_le32(data[2]);            buf[x + 3] = cpu_to_le32(data[3]);            x += 4;            data += 4;        } while (x < e);        md5_transform_CPUbyteorder(&ivout[0], &buf[0]);    } while (--y >= 0);    /* caller wants ivout[] data in CPU byte order -- no conversion needed here */}#else/* on little endian boxes loop_compute_md5_iv_v3() returns ivout[] data in little  *//* endian byte order which happens to be same as CPU byte order, so we use that */extern void loop_compute_md5_iv_v3(TransferSector_t, u_int32_t *, u_int32_t *);#define twofish_compute_md5_iv_v3(a,b,c) loop_compute_md5_iv_v3((a),(b),(c))#endif#define roundE_m(x0,x1,x2,x3,rnd) \      t0 = f32_sbox( x0, key->sbox_full ) ; \      t1 = f32_sbox( ROL(x1,8), key->sbox_full ); \      x2 ^= t0 + t1 + key->subKeys[2*rnd+8]; \      x3 = ROL(x3,1); \      x3 ^= t0 + 2*t1 + key->subKeys[2*rnd+9]; \      x2 = ROR(x2,1);static void blockEncrypt_CBC(fish2_key *key,BYTE *src,BYTE *dst,DWORD iv0,DWORD iv1,DWORD iv2,DWORD iv3){ DWORD xx0,xx1,xx2,xx3,t0,t1;  int len;  for (len=512;len>=16;len-=16)  {     xx0=Bswap(((DWORD *)src)[0]) ^ key->subKeys[0] ^ iv0;    xx1=Bswap(((DWORD *)src)[1]) ^ key->subKeys[1] ^ iv1;    xx2=Bswap(((DWORD *)src)[2]) ^ key->subKeys[2] ^ iv2;    xx3=Bswap(((DWORD *)src)[3]) ^ key->subKeys[3] ^ iv3;        src+=16;    roundE_m(xx0,xx1,xx2,xx3,0);    roundE_m(xx2,xx3,xx0,xx1,1);    roundE_m(xx0,xx1,xx2,xx3,2);    roundE_m(xx2,xx3,xx0,xx1,3);    roundE_m(xx0,xx1,xx2,xx3,4);    roundE_m(xx2,xx3,xx0,xx1,5);    roundE_m(xx0,xx1,xx2,xx3,6);    roundE_m(xx2,xx3,xx0,xx1,7);    roundE_m(xx0,xx1,xx2,xx3,8);    roundE_m(xx2,xx3,xx0,xx1,9);    roundE_m(xx0,xx1,xx2,xx3,10);    roundE_m(xx2,xx3,xx0,xx1,11);    roundE_m(xx0,xx1,xx2,xx3,12);    roundE_m(xx2,xx3,xx0,xx1,13);    roundE_m(xx0,xx1,xx2,xx3,14);    roundE_m(xx2,xx3,xx0,xx1,15);        iv0=xx2 ^ key->subKeys[4];    iv1=xx3 ^ key->subKeys[5];    iv2=xx0 ^ key->subKeys[6];    iv3=xx1 ^ key->subKeys[7];        ((DWORD *)dst)[0] = Bswap(iv0);    ((DWORD *)dst)[1] = Bswap(iv1);    ((DWORD *)dst)[2] = Bswap(iv2);    ((DWORD *)dst)[3] = Bswap(iv3);    dst+=16;  }}#define roundD_m(x0,x1,x2,x3,rnd) \      t0 = f32_sbox( x0, key->sbox_full); \      t1 = f32_sbox( ROL(x1,8),key->sbox_full); \      x2 = ROL(x2,1); \      x3 ^= t0 + 2*t1 + key->subKeys[rnd*2+9]; \      x3 = ROR(x3,1); \      x2 ^= t0 + t1 + key->subKeys[rnd*2+8];static void blockDecrypt_CBC(fish2_key *key,BYTE *src,BYTE *dst,int len,DWORD iv0,DWORD iv1,DWORD iv2,DWORD iv3){ DWORD xx0,xx1,xx2,xx3,t0,t1,lx0,lx1,lx2,lx3;  for (;len>=16;len-=16)  {     lx0=iv0;iv0=Bswap(((DWORD *)src)[0]);xx0=iv0 ^ key->subKeys[4];    lx1=iv1;iv1=Bswap(((DWORD *)src)[1]);xx1=iv1 ^ key->subKeys[5];    lx2=iv2;iv2=Bswap(((DWORD *)src)[2]);xx2=iv2 ^ key->subKeys[6];    lx3=iv3;iv3=Bswap(((DWORD *)src)[3]);xx3=iv3 ^ key->subKeys[7];    src+=16;        roundD_m(xx0,xx1,xx2,xx3,15);    roundD_m(xx2,xx3,xx0,xx1,14);    roundD_m(xx0,xx1,xx2,xx3,13);    roundD_m(xx2,xx3,xx0,xx1,12);    roundD_m(xx0,xx1,xx2,xx3,11);    roundD_m(xx2,xx3,xx0,xx1,10);    roundD_m(xx0,xx1,xx2,xx3,9);    roundD_m(xx2,xx3,xx0,xx1,8);    roundD_m(xx0,xx1,xx2,xx3,7);    roundD_m(xx2,xx3,xx0,xx1,6);    roundD_m(xx0,xx1,xx2,xx3,5);    roundD_m(xx2,xx3,xx0,xx1,4);    roundD_m(xx0,xx1,xx2,xx3,3);    roundD_m(xx2,xx3,xx0,xx1,2);    roundD_m(xx0,xx1,xx2,xx3,1);    roundD_m(xx2,xx3,xx0,xx1,0);    ((DWORD *)dst)[0] = Bswap(xx2 ^ key->subKeys[0] ^ lx0);    ((DWORD *)dst)[1] = Bswap(xx3 ^ key->subKeys[1] ^ lx1);    ((DWORD *)dst)[2] = Bswap(xx0 ^ key->subKeys[2] ^ lx2);    ((DWORD *)dst)[3] = Bswap(xx1 ^ key->subKeys[3] ^ lx3);    dst+=16;  }}static int transfer_fish2(struct loop_device *lo, int cmd, char *raw_buf,                  char *loop_buf, int size, TransferSector_t devSect){    TwofishMultiKey *m;    fish2_key *a;    u_int32_t iv[4];    int sectInc = 1;    unsigned y;    if (lo->lo_init[0] == 1) sectInc = devSect = 0; /* "-o loinit=1" means SuSE compatible */    if (size & 0x1FF) return -1;    m = (TwofishMultiKey *)lo->key_data;    y = m->keyMask;    if (cmd == READ) {        while(size > 0) {            a = m->keyPtr[((unsigned)devSect) & y];            if(y) {                iv[0] = Bswap(((u_int32_t *)raw_buf)[0]);                iv[1] = Bswap(((u_int32_t *)raw_buf)[1]);                iv[2] = Bswap(((u_int32_t *)raw_buf)[2]);                iv[3] = Bswap(((u_int32_t *)raw_buf)[3]);                blockDecrypt_CBC(a, raw_buf+16, loop_buf+16, 496, iv[0], iv[1], iv[2], iv[3]);                memcpy(&iv[0], &m->partialMD5[0], 16);                twofish_compute_md5_iv_v3(devSect, &iv[0], (u_int32_t *)(&loop_buf[16]));                blockDecrypt_CBC(a, raw_buf, loop_buf, 16, iv[0], iv[1], iv[2], iv[3]);            } else {                if(sizeof(TransferSector_t) == 8) {                    blockDecrypt_CBC(a, raw_buf, loop_buf, 512, devSect, (__u64)devSect>>32, 0, 0);                } else {                    blockDecrypt_CBC(a, raw_buf, loop_buf, 512, devSect, 0, 0, 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            raw_buf += 512;            loop_buf += 512;            size -= 512;            devSect += sectInc;        }    } else {        while(size > 0) {            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);                twofish_compute_md5_iv_v3(devSect, &iv[0], (u_int32_t *)(&TMP_RAW_BUF[16]));                blockEncrypt_CBC(a, TMP_RAW_BUF, raw_buf, iv[0], iv[1], iv[2], iv[3]);            } else {                if(sizeof(TransferSector_t) == 8) {                    blockEncrypt_CBC(a, loop_buf, raw_buf, devSect, (__u64)devSect>>32, 0, 0);                } else {                    blockEncrypt_CBC(a, loop_buf, raw_buf, devSect, 0, 0, 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            raw_buf += 512;            loop_buf += 512;            size -= 512;            devSect += sectInc;        }    }    return 0;}static int fish2_init(struct loop_device *lo, LoopInfo_t *info){    TwofishMultiKey *m;    fish2_key *a;      if (info->lo_encrypt_key_size<16 || info->lo_encrypt_key_size>32)        return -EINVAL;    lo->key_data = m = allocMultiKey();    if(!m) return(-ENOMEM);    a = m->keyPtr[0];      memset(a, 0, sizeof(fish2_key));    a->keyLen = info->lo_encrypt_key_size << 3;    memcpy(a->key, info->lo_encrypt_key, info->lo_encrypt_key_size);    init_key(a);    memset(&info->lo_encrypt_key[0], 0, sizeof(info->lo_encrypt_key));    return 0;}static int fish2_release(struct loop_device *lo){    if(lo->key_data) {        clearAndFreeMultiKey((TwofishMultiKey *)lo->key_data);        lo->key_data = 0;    }    return(0);}static int handleIoctl_fish2(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 fish2_lock(struct loop_device *lo){    MOD_INC_USE_COUNT;}static void fish2_unlock(struct loop_device *lo){    MOD_DEC_USE_COUNT;}   #endifstatic struct loop_func_table fish2_funcs = {  number: 3, /* 3 == LO_CRYPT_FISH2 */  transfer: (void *) transfer_fish2,  init: (void *) fish2_init,  release: fish2_release,#if LINUX_VERSION_CODE >= 0x20600  owner: THIS_MODULE,#else  lock: fish2_lock,  unlock: fish2_unlock,#endif  ioctl: (void *) handleIoctl_fish2};#if LINUX_VERSION_CODE >= 0x20600# define loop_twofish_init  __init loop_twofish_initfn# define loop_twofish_exit  loop_twofish_exitfn#else# define loop_twofish_init  init_module# define loop_twofish_exit  cleanup_module#endifint loop_twofish_init(void){   if (loop_register_transfer(&fish2_funcs)) {    printk(KERN_WARNING "loop: unable to register twofish transfer\n");    return -EIO;  }  printk(KERN_INFO "loop: registered twofish encryption\n");  return 0;}void loop_twofish_exit(void){   if (loop_unregister_transfer(fish2_funcs.number)) {    printk(KERN_WARNING "loop: unable to unregister twofish transfer\n");    return;  }  printk(KERN_INFO "loop: unregistered twofish encryption\n");}#if LINUX_VERSION_CODE >= 0x20600module_init(loop_twofish_initfn);module_exit(loop_twofish_exitfn);#endif#if defined(MODULE_LICENSE)MODULE_LICENSE("GPL");#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -