static unsigned int __glue_cbc_decrypt_128bit(const struct common_glue_ctx *gctx, struct blkcipher_desc *desc, struct blkcipher_walk *walk) { void *ctx = crypto_blkcipher_ctx(desc->tfm); const unsigned int bsize = 128 / 8; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 last_iv; unsigned int num_blocks, func_bytes; unsigned int i; /* Start of the last block. */ src += nbytes / bsize - 1; dst += nbytes / bsize - 1; last_iv = *src; for (i = 0; i < gctx->num_funcs; i++) { num_blocks = gctx->funcs[i].num_blocks; func_bytes = bsize * num_blocks; /* Process multi-block batch */ if (nbytes >= func_bytes) { do { nbytes -= func_bytes - bsize; src -= num_blocks - 1; dst -= num_blocks - 1; gctx->funcs[i].fn_u.cbc(ctx, dst, src); nbytes -= bsize; if (nbytes < bsize) goto done; u128_xor(dst, dst, src - 1); src -= 1; dst -= 1; } while (nbytes >= func_bytes); if (nbytes < bsize) goto done; } } done: u128_xor(dst, dst, (u128 *)walk->iv); *(u128 *)walk->iv = last_iv; return nbytes; }
void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src) { u128 ivs[2]; ivs[0] = src[0]; ivs[1] = src[1]; twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); u128_xor(&dst[1], &dst[1], &ivs[0]); u128_xor(&dst[2], &dst[2], &ivs[1]); }
void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src, le128 *iv, common_glue_func_t fn) { le128 ivblk = *iv; /* generate next IV */ le128_gf128mul_x_ble(iv, &ivblk); /* CC <- T xor C */ u128_xor(dst, src, (u128 *)&ivblk); /* PP <- D(Key2,CC) */ fn(ctx, (u8 *)dst, (u8 *)dst); /* P <- T xor PP */ u128_xor(dst, dst, (u128 *)&ivblk); }
static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv) { be128 ctrblk; le128_to_be128(&ctrblk, iv); le128_inc(iv); __cast6_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); u128_xor(dst, src, (u128 *)&ctrblk); }
static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra, u8 res[16]) { u8 p1[16], p2[16]; int err; memset(p1, 0, 16); /* p1 = pres || preq || _rat || _iat */ swap56(pres, p1); swap56(preq, p1 + 7); p1[14] = _rat; p1[15] = _iat; memset(p2, 0, 16); /* p2 = padding || ia || ra */ baswap((bdaddr_t *) (p2 + 4), ia); baswap((bdaddr_t *) (p2 + 10), ra); /* res = r XOR p1 */ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); /* res = e(k, res) */ err = smp_e(tfm, k, res); if (err) { BT_ERR("Encrypt data error"); return err; } /* res = res XOR p2 */ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); /* res = e(k, res) */ err = smp_e(tfm, k, res); if (err) BT_ERR("Encrypt data error"); return err; }
static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra, u8 res[16]) { u8 p1[16], p2[16]; int err; memset(p1, 0, 16); swap56(pres, p1); swap56(preq, p1 + 7); p1[14] = _rat; p1[15] = _iat; memset(p2, 0, 16); baswap((bdaddr_t *) (p2 + 4), ia); baswap((bdaddr_t *) (p2 + 10), ra); u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); err = smp_e(tfm, k, res); if (err) { BT_ERR("Encrypt data error"); return err; } u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); err = smp_e(tfm, k, res); if (err) BT_ERR("Encrypt data error"); return err; }
static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra, u8 res[16]) { u8 p1[16], p2[16]; int err; memset(p1, 0, 16); /* p1 = pres || preq || _rat || _iat */ p1[0] = _iat; p1[1] = _rat; memcpy(p1 + 2, preq, 7); memcpy(p1 + 9, pres, 7); /* p2 = padding || ia || ra */ memcpy(p2, ra, 6); memcpy(p2 + 6, ia, 6); memset(p2 + 12, 0, 4); /* res = r XOR p1 */ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); /* res = e(k, res) */ err = smp_e(tfm, k, res); if (err) { BT_ERR("Encrypt data error"); return err; } /* res = res XOR p2 */ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); /* res = e(k, res) */ err = smp_e(tfm, k, res); if (err) BT_ERR("Encrypt data error"); return err; }
void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv) { be128 ctrblk; if (dst != src) *dst = *src; u128_to_be128(&ctrblk, iv); u128_inc(iv); twofish_enc_blk(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk); u128_xor(dst, dst, (u128 *)&ctrblk); }
static void twofish_dec_blk_cbc_xway(void *ctx, u128 *dst, const u128 *src) { u128 ivs[TWOFISH_PARALLEL_BLOCKS - 1]; unsigned int j; for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++) ivs[j] = src[j]; twofish_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); for (j = 0; j < TWOFISH_PARALLEL_BLOCKS - 1; j++) u128_xor(dst + (j + 1), dst + (j + 1), ivs + j); }
static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src) { u128 ivs[SERPENT_PARALLEL_BLOCKS - 1]; unsigned int j; for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) ivs[j] = src[j]; serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src); for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++) u128_xor(dst + (j + 1), dst + (j + 1), ivs + j); }
static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); unsigned int bsize = TF_BLOCK_SIZE; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 *iv = (u128 *)walk->iv; do { u128_xor(dst, src, iv); twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); iv = dst; src += 1; dst += 1; nbytes -= bsize; } while (nbytes >= bsize); u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv); return nbytes; }
static unsigned int __glue_cbc_encrypt_128bit(const common_glue_func_t fn, struct blkcipher_desc *desc, struct blkcipher_walk *walk) { void *ctx = crypto_blkcipher_ctx(desc->tfm); const unsigned int bsize = 128 / 8; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 *iv = (u128 *)walk->iv; do { u128_xor(dst, src, iv); fn(ctx, (u8 *)dst, (u8 *)dst); iv = dst; src += 1; dst += 1; nbytes -= bsize; } while (nbytes >= bsize); *(u128 *)walk->iv = *iv; return nbytes; }
static unsigned int __ctr_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); unsigned int bsize = TF_BLOCK_SIZE; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 ctrblk; be128 ctrblocks[3]; be128_to_u128(&ctrblk, (be128 *)walk->iv); /* Process three block batch */ if (nbytes >= bsize * 3) { do { if (dst != src) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; } /* create ctrblks for parallel encrypt */ u128_to_be128(&ctrblocks[0], &ctrblk); u128_inc(&ctrblk); u128_to_be128(&ctrblocks[1], &ctrblk); u128_inc(&ctrblk); u128_to_be128(&ctrblocks[2], &ctrblk); u128_inc(&ctrblk); twofish_enc_blk_xor_3way(ctx, (u8 *)dst, (u8 *)ctrblocks); src += 3; dst += 3; nbytes -= bsize * 3; } while (nbytes >= bsize * 3); if (nbytes < bsize) goto done; } /* Handle leftovers */ do { if (dst != src) *dst = *src; u128_to_be128(&ctrblocks[0], &ctrblk); u128_inc(&ctrblk); twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks); u128_xor(dst, dst, (u128 *)ctrblocks); src += 1; dst += 1; nbytes -= bsize; } while (nbytes >= bsize); done: u128_to_be128((be128 *)walk->iv, &ctrblk); return nbytes; }
static unsigned int __cbc_decrypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); unsigned int bsize = TF_BLOCK_SIZE; unsigned int nbytes = walk->nbytes; u128 *src = (u128 *)walk->src.virt.addr; u128 *dst = (u128 *)walk->dst.virt.addr; u128 ivs[3 - 1]; u128 last_iv; /* Start of the last block. */ src += nbytes / bsize - 1; dst += nbytes / bsize - 1; last_iv = *src; /* Process three block batch */ if (nbytes >= bsize * 3) { do { nbytes -= bsize * (3 - 1); src -= 3 - 1; dst -= 3 - 1; ivs[0] = src[0]; ivs[1] = src[1]; twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src); u128_xor(dst + 1, dst + 1, ivs + 0); u128_xor(dst + 2, dst + 2, ivs + 1); nbytes -= bsize; if (nbytes < bsize) goto done; u128_xor(dst, dst, src - 1); src -= 1; dst -= 1; } while (nbytes >= bsize * 3); if (nbytes < bsize) goto done; } /* Handle leftovers */ for (;;) { twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src); nbytes -= bsize; if (nbytes < bsize) break; u128_xor(dst, dst, src - 1); src -= 1; dst -= 1; } done: u128_xor(dst, dst, (u128 *)walk->iv); *(u128 *)walk->iv = last_iv; return nbytes; }