18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Shared glue code for 128bit block ciphers 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by: 88c2ecf20Sopenharmony_ci * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> 98c2ecf20Sopenharmony_ci * CTR part based on code (crypto/ctr.c) by: 108c2ecf20Sopenharmony_ci * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <crypto/b128ops.h> 158c2ecf20Sopenharmony_ci#include <crypto/gf128mul.h> 168c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 178c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 188c2ecf20Sopenharmony_ci#include <crypto/xts.h> 198c2ecf20Sopenharmony_ci#include <asm/crypto/glue_helper.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ciint glue_ecb_req_128bit(const struct common_glue_ctx *gctx, 228c2ecf20Sopenharmony_ci struct skcipher_request *req) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 258c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 268c2ecf20Sopenharmony_ci struct skcipher_walk walk; 278c2ecf20Sopenharmony_ci bool fpu_enabled = false; 288c2ecf20Sopenharmony_ci unsigned int nbytes; 298c2ecf20Sopenharmony_ci int err; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes)) { 348c2ecf20Sopenharmony_ci const u8 *src = walk.src.virt.addr; 358c2ecf20Sopenharmony_ci u8 *dst = walk.dst.virt.addr; 368c2ecf20Sopenharmony_ci unsigned int func_bytes; 378c2ecf20Sopenharmony_ci unsigned int i; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, 408c2ecf20Sopenharmony_ci &walk, fpu_enabled, nbytes); 418c2ecf20Sopenharmony_ci for (i = 0; i < gctx->num_funcs; i++) { 428c2ecf20Sopenharmony_ci func_bytes = bsize * gctx->funcs[i].num_blocks; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (nbytes < func_bytes) 458c2ecf20Sopenharmony_ci continue; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* Process multi-block batch */ 488c2ecf20Sopenharmony_ci do { 498c2ecf20Sopenharmony_ci gctx->funcs[i].fn_u.ecb(ctx, dst, src); 508c2ecf20Sopenharmony_ci src += func_bytes; 518c2ecf20Sopenharmony_ci dst += func_bytes; 528c2ecf20Sopenharmony_ci nbytes -= func_bytes; 538c2ecf20Sopenharmony_ci } while (nbytes >= func_bytes); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (nbytes < bsize) 568c2ecf20Sopenharmony_ci break; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci glue_fpu_end(fpu_enabled); 628c2ecf20Sopenharmony_ci return err; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_ecb_req_128bit); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciint glue_cbc_encrypt_req_128bit(const common_glue_func_t fn, 678c2ecf20Sopenharmony_ci struct skcipher_request *req) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 708c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 718c2ecf20Sopenharmony_ci struct skcipher_walk walk; 728c2ecf20Sopenharmony_ci unsigned int nbytes; 738c2ecf20Sopenharmony_ci int err; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes)) { 788c2ecf20Sopenharmony_ci const u128 *src = (u128 *)walk.src.virt.addr; 798c2ecf20Sopenharmony_ci u128 *dst = (u128 *)walk.dst.virt.addr; 808c2ecf20Sopenharmony_ci u128 *iv = (u128 *)walk.iv; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci do { 838c2ecf20Sopenharmony_ci u128_xor(dst, src, iv); 848c2ecf20Sopenharmony_ci fn(ctx, (u8 *)dst, (u8 *)dst); 858c2ecf20Sopenharmony_ci iv = dst; 868c2ecf20Sopenharmony_ci src++; 878c2ecf20Sopenharmony_ci dst++; 888c2ecf20Sopenharmony_ci nbytes -= bsize; 898c2ecf20Sopenharmony_ci } while (nbytes >= bsize); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci *(u128 *)walk.iv = *iv; 928c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci return err; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_cbc_encrypt_req_128bit); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ciint glue_cbc_decrypt_req_128bit(const struct common_glue_ctx *gctx, 998c2ecf20Sopenharmony_ci struct skcipher_request *req) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 1028c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 1038c2ecf20Sopenharmony_ci struct skcipher_walk walk; 1048c2ecf20Sopenharmony_ci bool fpu_enabled = false; 1058c2ecf20Sopenharmony_ci unsigned int nbytes; 1068c2ecf20Sopenharmony_ci int err; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes)) { 1118c2ecf20Sopenharmony_ci const u128 *src = walk.src.virt.addr; 1128c2ecf20Sopenharmony_ci u128 *dst = walk.dst.virt.addr; 1138c2ecf20Sopenharmony_ci unsigned int func_bytes, num_blocks; 1148c2ecf20Sopenharmony_ci unsigned int i; 1158c2ecf20Sopenharmony_ci u128 last_iv; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, 1188c2ecf20Sopenharmony_ci &walk, fpu_enabled, nbytes); 1198c2ecf20Sopenharmony_ci /* Start of the last block. */ 1208c2ecf20Sopenharmony_ci src += nbytes / bsize - 1; 1218c2ecf20Sopenharmony_ci dst += nbytes / bsize - 1; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci last_iv = *src; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci for (i = 0; i < gctx->num_funcs; i++) { 1268c2ecf20Sopenharmony_ci num_blocks = gctx->funcs[i].num_blocks; 1278c2ecf20Sopenharmony_ci func_bytes = bsize * num_blocks; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (nbytes < func_bytes) 1308c2ecf20Sopenharmony_ci continue; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Process multi-block batch */ 1338c2ecf20Sopenharmony_ci do { 1348c2ecf20Sopenharmony_ci src -= num_blocks - 1; 1358c2ecf20Sopenharmony_ci dst -= num_blocks - 1; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci gctx->funcs[i].fn_u.cbc(ctx, (u8 *)dst, 1388c2ecf20Sopenharmony_ci (const u8 *)src); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci nbytes -= func_bytes; 1418c2ecf20Sopenharmony_ci if (nbytes < bsize) 1428c2ecf20Sopenharmony_ci goto done; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci u128_xor(dst, dst, --src); 1458c2ecf20Sopenharmony_ci dst--; 1468c2ecf20Sopenharmony_ci } while (nbytes >= func_bytes); 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_cidone: 1498c2ecf20Sopenharmony_ci u128_xor(dst, dst, (u128 *)walk.iv); 1508c2ecf20Sopenharmony_ci *(u128 *)walk.iv = last_iv; 1518c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci glue_fpu_end(fpu_enabled); 1558c2ecf20Sopenharmony_ci return err; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_cbc_decrypt_req_128bit); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciint glue_ctr_req_128bit(const struct common_glue_ctx *gctx, 1608c2ecf20Sopenharmony_ci struct skcipher_request *req) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 1638c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 1648c2ecf20Sopenharmony_ci struct skcipher_walk walk; 1658c2ecf20Sopenharmony_ci bool fpu_enabled = false; 1668c2ecf20Sopenharmony_ci unsigned int nbytes; 1678c2ecf20Sopenharmony_ci int err; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes) >= bsize) { 1728c2ecf20Sopenharmony_ci const u128 *src = walk.src.virt.addr; 1738c2ecf20Sopenharmony_ci u128 *dst = walk.dst.virt.addr; 1748c2ecf20Sopenharmony_ci unsigned int func_bytes, num_blocks; 1758c2ecf20Sopenharmony_ci unsigned int i; 1768c2ecf20Sopenharmony_ci le128 ctrblk; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, 1798c2ecf20Sopenharmony_ci &walk, fpu_enabled, nbytes); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci be128_to_le128(&ctrblk, (be128 *)walk.iv); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci for (i = 0; i < gctx->num_funcs; i++) { 1848c2ecf20Sopenharmony_ci num_blocks = gctx->funcs[i].num_blocks; 1858c2ecf20Sopenharmony_ci func_bytes = bsize * num_blocks; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (nbytes < func_bytes) 1888c2ecf20Sopenharmony_ci continue; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* Process multi-block batch */ 1918c2ecf20Sopenharmony_ci do { 1928c2ecf20Sopenharmony_ci gctx->funcs[i].fn_u.ctr(ctx, (u8 *)dst, 1938c2ecf20Sopenharmony_ci (const u8 *)src, 1948c2ecf20Sopenharmony_ci &ctrblk); 1958c2ecf20Sopenharmony_ci src += num_blocks; 1968c2ecf20Sopenharmony_ci dst += num_blocks; 1978c2ecf20Sopenharmony_ci nbytes -= func_bytes; 1988c2ecf20Sopenharmony_ci } while (nbytes >= func_bytes); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (nbytes < bsize) 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci le128_to_be128((be128 *)walk.iv, &ctrblk); 2058c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci glue_fpu_end(fpu_enabled); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci if (nbytes) { 2118c2ecf20Sopenharmony_ci le128 ctrblk; 2128c2ecf20Sopenharmony_ci u128 tmp; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci be128_to_le128(&ctrblk, (be128 *)walk.iv); 2158c2ecf20Sopenharmony_ci memcpy(&tmp, walk.src.virt.addr, nbytes); 2168c2ecf20Sopenharmony_ci gctx->funcs[gctx->num_funcs - 1].fn_u.ctr(ctx, (u8 *)&tmp, 2178c2ecf20Sopenharmony_ci (const u8 *)&tmp, 2188c2ecf20Sopenharmony_ci &ctrblk); 2198c2ecf20Sopenharmony_ci memcpy(walk.dst.virt.addr, &tmp, nbytes); 2208c2ecf20Sopenharmony_ci le128_to_be128((be128 *)walk.iv, &ctrblk); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, 0); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci return err; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_ctr_req_128bit); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic unsigned int __glue_xts_req_128bit(const struct common_glue_ctx *gctx, 2308c2ecf20Sopenharmony_ci void *ctx, 2318c2ecf20Sopenharmony_ci struct skcipher_walk *walk) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 2348c2ecf20Sopenharmony_ci unsigned int nbytes = walk->nbytes; 2358c2ecf20Sopenharmony_ci u128 *src = walk->src.virt.addr; 2368c2ecf20Sopenharmony_ci u128 *dst = walk->dst.virt.addr; 2378c2ecf20Sopenharmony_ci unsigned int num_blocks, func_bytes; 2388c2ecf20Sopenharmony_ci unsigned int i; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Process multi-block batch */ 2418c2ecf20Sopenharmony_ci for (i = 0; i < gctx->num_funcs; i++) { 2428c2ecf20Sopenharmony_ci num_blocks = gctx->funcs[i].num_blocks; 2438c2ecf20Sopenharmony_ci func_bytes = bsize * num_blocks; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci if (nbytes >= func_bytes) { 2468c2ecf20Sopenharmony_ci do { 2478c2ecf20Sopenharmony_ci gctx->funcs[i].fn_u.xts(ctx, (u8 *)dst, 2488c2ecf20Sopenharmony_ci (const u8 *)src, 2498c2ecf20Sopenharmony_ci walk->iv); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci src += num_blocks; 2528c2ecf20Sopenharmony_ci dst += num_blocks; 2538c2ecf20Sopenharmony_ci nbytes -= func_bytes; 2548c2ecf20Sopenharmony_ci } while (nbytes >= func_bytes); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (nbytes < bsize) 2578c2ecf20Sopenharmony_ci goto done; 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cidone: 2628c2ecf20Sopenharmony_ci return nbytes; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciint glue_xts_req_128bit(const struct common_glue_ctx *gctx, 2668c2ecf20Sopenharmony_ci struct skcipher_request *req, 2678c2ecf20Sopenharmony_ci common_glue_func_t tweak_fn, void *tweak_ctx, 2688c2ecf20Sopenharmony_ci void *crypt_ctx, bool decrypt) 2698c2ecf20Sopenharmony_ci{ 2708c2ecf20Sopenharmony_ci const bool cts = (req->cryptlen % XTS_BLOCK_SIZE); 2718c2ecf20Sopenharmony_ci const unsigned int bsize = 128 / 8; 2728c2ecf20Sopenharmony_ci struct skcipher_request subreq; 2738c2ecf20Sopenharmony_ci struct skcipher_walk walk; 2748c2ecf20Sopenharmony_ci bool fpu_enabled = false; 2758c2ecf20Sopenharmony_ci unsigned int nbytes, tail; 2768c2ecf20Sopenharmony_ci int err; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (req->cryptlen < XTS_BLOCK_SIZE) 2798c2ecf20Sopenharmony_ci return -EINVAL; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (unlikely(cts)) { 2828c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci tail = req->cryptlen % XTS_BLOCK_SIZE + XTS_BLOCK_SIZE; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&subreq, tfm); 2878c2ecf20Sopenharmony_ci skcipher_request_set_callback(&subreq, 2888c2ecf20Sopenharmony_ci crypto_skcipher_get_flags(tfm), 2898c2ecf20Sopenharmony_ci NULL, NULL); 2908c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&subreq, req->src, req->dst, 2918c2ecf20Sopenharmony_ci req->cryptlen - tail, req->iv); 2928c2ecf20Sopenharmony_ci req = &subreq; 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 2968c2ecf20Sopenharmony_ci nbytes = walk.nbytes; 2978c2ecf20Sopenharmony_ci if (err) 2988c2ecf20Sopenharmony_ci return err; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* set minimum length to bsize, for tweak_fn */ 3018c2ecf20Sopenharmony_ci fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit, 3028c2ecf20Sopenharmony_ci &walk, fpu_enabled, 3038c2ecf20Sopenharmony_ci nbytes < bsize ? bsize : nbytes); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* calculate first value of T */ 3068c2ecf20Sopenharmony_ci tweak_fn(tweak_ctx, walk.iv, walk.iv); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci while (nbytes) { 3098c2ecf20Sopenharmony_ci nbytes = __glue_xts_req_128bit(gctx, crypt_ctx, &walk); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 3128c2ecf20Sopenharmony_ci nbytes = walk.nbytes; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (unlikely(cts)) { 3168c2ecf20Sopenharmony_ci u8 *next_tweak, *final_tweak = req->iv; 3178c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 3188c2ecf20Sopenharmony_ci struct scatterlist s[2], d[2]; 3198c2ecf20Sopenharmony_ci le128 b[2]; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci dst = src = scatterwalk_ffwd(s, req->src, req->cryptlen); 3228c2ecf20Sopenharmony_ci if (req->dst != req->src) 3238c2ecf20Sopenharmony_ci dst = scatterwalk_ffwd(d, req->dst, req->cryptlen); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (decrypt) { 3268c2ecf20Sopenharmony_ci next_tweak = memcpy(b, req->iv, XTS_BLOCK_SIZE); 3278c2ecf20Sopenharmony_ci gf128mul_x_ble(b, b); 3288c2ecf20Sopenharmony_ci } else { 3298c2ecf20Sopenharmony_ci next_tweak = req->iv; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&subreq, src, dst, XTS_BLOCK_SIZE, 3338c2ecf20Sopenharmony_ci next_tweak); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false) ?: 3368c2ecf20Sopenharmony_ci skcipher_walk_done(&walk, 3378c2ecf20Sopenharmony_ci __glue_xts_req_128bit(gctx, crypt_ctx, &walk)); 3388c2ecf20Sopenharmony_ci if (err) 3398c2ecf20Sopenharmony_ci goto out; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(b, dst, 0, XTS_BLOCK_SIZE, 0); 3428c2ecf20Sopenharmony_ci memcpy(b + 1, b, tail - XTS_BLOCK_SIZE); 3438c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(b, src, XTS_BLOCK_SIZE, 3448c2ecf20Sopenharmony_ci tail - XTS_BLOCK_SIZE, 0); 3458c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(b, dst, 0, tail, 1); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&subreq, dst, dst, XTS_BLOCK_SIZE, 3488c2ecf20Sopenharmony_ci final_tweak); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false) ?: 3518c2ecf20Sopenharmony_ci skcipher_walk_done(&walk, 3528c2ecf20Sopenharmony_ci __glue_xts_req_128bit(gctx, crypt_ctx, &walk)); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ciout: 3568c2ecf20Sopenharmony_ci glue_fpu_end(fpu_enabled); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return err; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_xts_req_128bit); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_civoid glue_xts_crypt_128bit_one(const void *ctx, u8 *dst, const u8 *src, 3638c2ecf20Sopenharmony_ci le128 *iv, common_glue_func_t fn) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci le128 ivblk = *iv; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /* generate next IV */ 3688c2ecf20Sopenharmony_ci gf128mul_x_ble(iv, &ivblk); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* CC <- T xor C */ 3718c2ecf20Sopenharmony_ci u128_xor((u128 *)dst, (const u128 *)src, (u128 *)&ivblk); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* PP <- D(Key2,CC) */ 3748c2ecf20Sopenharmony_ci fn(ctx, dst, dst); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* P <- T xor PP */ 3778c2ecf20Sopenharmony_ci u128_xor((u128 *)dst, (u128 *)dst, (u128 *)&ivblk); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(glue_xts_crypt_128bit_one); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 382