18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * CTR: Counter mode 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _CRYPTO_CTR_H 98c2ecf20Sopenharmony_ci#define _CRYPTO_CTR_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 128c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 138c2ecf20Sopenharmony_ci#include <linux/string.h> 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define CTR_RFC3686_NONCE_SIZE 4 178c2ecf20Sopenharmony_ci#define CTR_RFC3686_IV_SIZE 8 188c2ecf20Sopenharmony_ci#define CTR_RFC3686_BLOCK_SIZE 16 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic inline int crypto_ctr_encrypt_walk(struct skcipher_request *req, 218c2ecf20Sopenharmony_ci void (*fn)(struct crypto_skcipher *, 228c2ecf20Sopenharmony_ci const u8 *, u8 *)) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 258c2ecf20Sopenharmony_ci int blocksize = crypto_skcipher_chunksize(tfm); 268c2ecf20Sopenharmony_ci u8 buf[MAX_CIPHER_BLOCKSIZE]; 278c2ecf20Sopenharmony_ci struct skcipher_walk walk; 288c2ecf20Sopenharmony_ci int err; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci /* avoid integer division due to variable blocksize parameter */ 318c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!is_power_of_2(blocksize))) 328c2ecf20Sopenharmony_ci return -EINVAL; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci while (walk.nbytes > 0) { 378c2ecf20Sopenharmony_ci u8 *dst = walk.dst.virt.addr; 388c2ecf20Sopenharmony_ci u8 *src = walk.src.virt.addr; 398c2ecf20Sopenharmony_ci int nbytes = walk.nbytes; 408c2ecf20Sopenharmony_ci int tail = 0; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (nbytes < walk.total) { 438c2ecf20Sopenharmony_ci tail = walk.nbytes & (blocksize - 1); 448c2ecf20Sopenharmony_ci nbytes -= tail; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci do { 488c2ecf20Sopenharmony_ci int bsize = min(nbytes, blocksize); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci fn(tfm, walk.iv, buf); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci crypto_xor_cpy(dst, src, buf, bsize); 538c2ecf20Sopenharmony_ci crypto_inc(walk.iv, blocksize); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci dst += bsize; 568c2ecf20Sopenharmony_ci src += bsize; 578c2ecf20Sopenharmony_ci nbytes -= bsize; 588c2ecf20Sopenharmony_ci } while (nbytes > 0); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, tail); 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci return err; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#endif /* _CRYPTO_CTR_H */ 66