int crypto_stream_xor(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *n, const unsigned char *k) { #define PTR_ALIGN(ptr, mask) ((void *)((((long)(ptr)) + (mask)) & ~((long)(mask)))) const unsigned long align = 4096; char ctxbuf[sizeof(struct blowfish_ctx) + align]; struct blowfish_ctx *ctx = PTR_ALIGN(ctxbuf, align - 1); uint64_t iv; uint64_t block; blowfish_init(ctx, k, CRYPTO_KEYBYTES); iv = __builtin_bswap64(*(uint64_t *)n); /* be => le */ while (likely(inlen >= BLOCKSIZE)) { block = __builtin_bswap64(iv++); /* le => be */ blowfish_enc_blk(ctx, out, &block); if (unlikely(in)) { *(uint64_t *)out ^= *(uint64_t *)in; in += BLOCKSIZE; } out += BLOCKSIZE; inlen -= BLOCKSIZE; } if (unlikely(inlen > 0)) { /* handle remaining bytes */ unsigned int i; block = __builtin_bswap64(iv); /* le => be */ blowfish_enc_blk(ctx, &block, &block); if (in) { for (i = 0; i < inlen; i++) out[i] = in[i] ^ ((uint8_t*)&block)[i]; } else { for (i = 0; i < inlen; i++) out[i] = ((uint8_t*)&block)[i]; } } return 0; }
static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk) { u8 *ctrblk = walk->iv; u8 keystream[BF_BLOCK_SIZE]; u8 *src = walk->src.virt.addr; u8 *dst = walk->dst.virt.addr; unsigned int nbytes = walk->nbytes; blowfish_enc_blk(ctx, keystream, ctrblk); crypto_xor(keystream, src, nbytes); memcpy(dst, keystream, nbytes); crypto_inc(ctrblk, BF_BLOCK_SIZE); }
static unsigned int __cbc_encrypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk) { struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); unsigned int bsize = BF_BLOCK_SIZE; unsigned int nbytes = walk->nbytes; u64 *src = (u64 *)walk->src.virt.addr; u64 *dst = (u64 *)walk->dst.virt.addr; u64 *iv = (u64 *)walk->iv; do { *dst = *src ^ *iv; blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst); iv = dst; src += 1; dst += 1; nbytes -= bsize; } while (nbytes >= bsize); *(u64 *)walk->iv = *iv; return nbytes; }
static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) { blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src); }