18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Adiantum length-preserving encryption mode 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2018 Google LLC 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * Adiantum is a tweakable, length-preserving encryption mode designed for fast 108c2ecf20Sopenharmony_ci * and secure disk encryption, especially on CPUs without dedicated crypto 118c2ecf20Sopenharmony_ci * instructions. Adiantum encrypts each sector using the XChaCha12 stream 128c2ecf20Sopenharmony_ci * cipher, two passes of an ε-almost-∆-universal (ε-∆U) hash function based on 138c2ecf20Sopenharmony_ci * NH and Poly1305, and an invocation of the AES-256 block cipher on a single 148c2ecf20Sopenharmony_ci * 16-byte block. See the paper for details: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Adiantum: length-preserving encryption for entry-level processors 178c2ecf20Sopenharmony_ci * (https://eprint.iacr.org/2018/720.pdf) 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * For flexibility, this implementation also allows other ciphers: 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * - Stream cipher: XChaCha12 or XChaCha20 228c2ecf20Sopenharmony_ci * - Block cipher: any with a 128-bit block size and 256-bit key 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * This implementation doesn't currently allow other ε-∆U hash functions, i.e. 258c2ecf20Sopenharmony_ci * HPolyC is not supported. This is because Adiantum is ~20% faster than HPolyC 268c2ecf20Sopenharmony_ci * but still provably as secure, and also the ε-∆U hash function of HBSH is 278c2ecf20Sopenharmony_ci * formally defined to take two inputs (tweak, message) which makes it difficult 288c2ecf20Sopenharmony_ci * to wrap with the crypto_shash API. Rather, some details need to be handled 298c2ecf20Sopenharmony_ci * here. Nevertheless, if needed in the future, support for other ε-∆U hash 308c2ecf20Sopenharmony_ci * functions could be added here. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <crypto/b128ops.h> 348c2ecf20Sopenharmony_ci#include <crypto/chacha.h> 358c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 368c2ecf20Sopenharmony_ci#include <crypto/internal/poly1305.h> 378c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 388c2ecf20Sopenharmony_ci#include <crypto/nhpoly1305.h> 398c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 408c2ecf20Sopenharmony_ci#include <linux/module.h> 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * Size of right-hand part of input data, in bytes; also the size of the block 448c2ecf20Sopenharmony_ci * cipher's block size and the hash function's output. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci#define BLOCKCIPHER_BLOCK_SIZE 16 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* Size of the block cipher key (K_E) in bytes */ 498c2ecf20Sopenharmony_ci#define BLOCKCIPHER_KEY_SIZE 32 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* Size of the hash key (K_H) in bytes */ 528c2ecf20Sopenharmony_ci#define HASH_KEY_SIZE (POLY1305_BLOCK_SIZE + NHPOLY1305_KEY_SIZE) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* 558c2ecf20Sopenharmony_ci * The specification allows variable-length tweaks, but Linux's crypto API 568c2ecf20Sopenharmony_ci * currently only allows algorithms to support a single length. The "natural" 578c2ecf20Sopenharmony_ci * tweak length for Adiantum is 16, since that fits into one Poly1305 block for 588c2ecf20Sopenharmony_ci * the best performance. But longer tweaks are useful for fscrypt, to avoid 598c2ecf20Sopenharmony_ci * needing to derive per-file keys. So instead we use two blocks, or 32 bytes. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci#define TWEAK_SIZE 32 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistruct adiantum_instance_ctx { 648c2ecf20Sopenharmony_ci struct crypto_skcipher_spawn streamcipher_spawn; 658c2ecf20Sopenharmony_ci struct crypto_cipher_spawn blockcipher_spawn; 668c2ecf20Sopenharmony_ci struct crypto_shash_spawn hash_spawn; 678c2ecf20Sopenharmony_ci}; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistruct adiantum_tfm_ctx { 708c2ecf20Sopenharmony_ci struct crypto_skcipher *streamcipher; 718c2ecf20Sopenharmony_ci struct crypto_cipher *blockcipher; 728c2ecf20Sopenharmony_ci struct crypto_shash *hash; 738c2ecf20Sopenharmony_ci struct poly1305_core_key header_hash_key; 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct adiantum_request_ctx { 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * Buffer for right-hand part of data, i.e. 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * P_L => P_M => C_M => C_R when encrypting, or 828c2ecf20Sopenharmony_ci * C_R => C_M => P_M => P_L when decrypting. 838c2ecf20Sopenharmony_ci * 848c2ecf20Sopenharmony_ci * Also used to build the IV for the stream cipher. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci union { 878c2ecf20Sopenharmony_ci u8 bytes[XCHACHA_IV_SIZE]; 888c2ecf20Sopenharmony_ci __le32 words[XCHACHA_IV_SIZE / sizeof(__le32)]; 898c2ecf20Sopenharmony_ci le128 bignum; /* interpret as element of Z/(2^{128}Z) */ 908c2ecf20Sopenharmony_ci } rbuf; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci bool enc; /* true if encrypting, false if decrypting */ 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * The result of the Poly1305 ε-∆U hash function applied to 968c2ecf20Sopenharmony_ci * (bulk length, tweak) 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci le128 header_hash; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Sub-requests, must be last */ 1018c2ecf20Sopenharmony_ci union { 1028c2ecf20Sopenharmony_ci struct shash_desc hash_desc; 1038c2ecf20Sopenharmony_ci struct skcipher_request streamcipher_req; 1048c2ecf20Sopenharmony_ci } u; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* 1088c2ecf20Sopenharmony_ci * Given the XChaCha stream key K_S, derive the block cipher key K_E and the 1098c2ecf20Sopenharmony_ci * hash key K_H as follows: 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * K_E || K_H || ... = XChaCha(key=K_S, nonce=1||0^191) 1128c2ecf20Sopenharmony_ci * 1138c2ecf20Sopenharmony_ci * Note that this denotes using bits from the XChaCha keystream, which here we 1148c2ecf20Sopenharmony_ci * get indirectly by encrypting a buffer containing all 0's. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_cistatic int adiantum_setkey(struct crypto_skcipher *tfm, const u8 *key, 1178c2ecf20Sopenharmony_ci unsigned int keylen) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 1208c2ecf20Sopenharmony_ci struct { 1218c2ecf20Sopenharmony_ci u8 iv[XCHACHA_IV_SIZE]; 1228c2ecf20Sopenharmony_ci u8 derived_keys[BLOCKCIPHER_KEY_SIZE + HASH_KEY_SIZE]; 1238c2ecf20Sopenharmony_ci struct scatterlist sg; 1248c2ecf20Sopenharmony_ci struct crypto_wait wait; 1258c2ecf20Sopenharmony_ci struct skcipher_request req; /* must be last */ 1268c2ecf20Sopenharmony_ci } *data; 1278c2ecf20Sopenharmony_ci u8 *keyp; 1288c2ecf20Sopenharmony_ci int err; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Set the stream cipher key (K_S) */ 1318c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(tctx->streamcipher, CRYPTO_TFM_REQ_MASK); 1328c2ecf20Sopenharmony_ci crypto_skcipher_set_flags(tctx->streamcipher, 1338c2ecf20Sopenharmony_ci crypto_skcipher_get_flags(tfm) & 1348c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 1358c2ecf20Sopenharmony_ci err = crypto_skcipher_setkey(tctx->streamcipher, key, keylen); 1368c2ecf20Sopenharmony_ci if (err) 1378c2ecf20Sopenharmony_ci return err; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* Derive the subkeys */ 1408c2ecf20Sopenharmony_ci data = kzalloc(sizeof(*data) + 1418c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(tctx->streamcipher), GFP_KERNEL); 1428c2ecf20Sopenharmony_ci if (!data) 1438c2ecf20Sopenharmony_ci return -ENOMEM; 1448c2ecf20Sopenharmony_ci data->iv[0] = 1; 1458c2ecf20Sopenharmony_ci sg_init_one(&data->sg, data->derived_keys, sizeof(data->derived_keys)); 1468c2ecf20Sopenharmony_ci crypto_init_wait(&data->wait); 1478c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&data->req, tctx->streamcipher); 1488c2ecf20Sopenharmony_ci skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP | 1498c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG, 1508c2ecf20Sopenharmony_ci crypto_req_done, &data->wait); 1518c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&data->req, &data->sg, &data->sg, 1528c2ecf20Sopenharmony_ci sizeof(data->derived_keys), data->iv); 1538c2ecf20Sopenharmony_ci err = crypto_wait_req(crypto_skcipher_encrypt(&data->req), &data->wait); 1548c2ecf20Sopenharmony_ci if (err) 1558c2ecf20Sopenharmony_ci goto out; 1568c2ecf20Sopenharmony_ci keyp = data->derived_keys; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Set the block cipher key (K_E) */ 1598c2ecf20Sopenharmony_ci crypto_cipher_clear_flags(tctx->blockcipher, CRYPTO_TFM_REQ_MASK); 1608c2ecf20Sopenharmony_ci crypto_cipher_set_flags(tctx->blockcipher, 1618c2ecf20Sopenharmony_ci crypto_skcipher_get_flags(tfm) & 1628c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 1638c2ecf20Sopenharmony_ci err = crypto_cipher_setkey(tctx->blockcipher, keyp, 1648c2ecf20Sopenharmony_ci BLOCKCIPHER_KEY_SIZE); 1658c2ecf20Sopenharmony_ci if (err) 1668c2ecf20Sopenharmony_ci goto out; 1678c2ecf20Sopenharmony_ci keyp += BLOCKCIPHER_KEY_SIZE; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Set the hash key (K_H) */ 1708c2ecf20Sopenharmony_ci poly1305_core_setkey(&tctx->header_hash_key, keyp); 1718c2ecf20Sopenharmony_ci keyp += POLY1305_BLOCK_SIZE; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci crypto_shash_clear_flags(tctx->hash, CRYPTO_TFM_REQ_MASK); 1748c2ecf20Sopenharmony_ci crypto_shash_set_flags(tctx->hash, crypto_skcipher_get_flags(tfm) & 1758c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 1768c2ecf20Sopenharmony_ci err = crypto_shash_setkey(tctx->hash, keyp, NHPOLY1305_KEY_SIZE); 1778c2ecf20Sopenharmony_ci keyp += NHPOLY1305_KEY_SIZE; 1788c2ecf20Sopenharmony_ci WARN_ON(keyp != &data->derived_keys[ARRAY_SIZE(data->derived_keys)]); 1798c2ecf20Sopenharmony_ciout: 1808c2ecf20Sopenharmony_ci kfree_sensitive(data); 1818c2ecf20Sopenharmony_ci return err; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* Addition in Z/(2^{128}Z) */ 1858c2ecf20Sopenharmony_cistatic inline void le128_add(le128 *r, const le128 *v1, const le128 *v2) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci u64 x = le64_to_cpu(v1->b); 1888c2ecf20Sopenharmony_ci u64 y = le64_to_cpu(v2->b); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci r->b = cpu_to_le64(x + y); 1918c2ecf20Sopenharmony_ci r->a = cpu_to_le64(le64_to_cpu(v1->a) + le64_to_cpu(v2->a) + 1928c2ecf20Sopenharmony_ci (x + y < x)); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* Subtraction in Z/(2^{128}Z) */ 1968c2ecf20Sopenharmony_cistatic inline void le128_sub(le128 *r, const le128 *v1, const le128 *v2) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci u64 x = le64_to_cpu(v1->b); 1998c2ecf20Sopenharmony_ci u64 y = le64_to_cpu(v2->b); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci r->b = cpu_to_le64(x - y); 2028c2ecf20Sopenharmony_ci r->a = cpu_to_le64(le64_to_cpu(v1->a) - le64_to_cpu(v2->a) - 2038c2ecf20Sopenharmony_ci (x - y > x)); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci/* 2078c2ecf20Sopenharmony_ci * Apply the Poly1305 ε-∆U hash function to (bulk length, tweak) and save the 2088c2ecf20Sopenharmony_ci * result to rctx->header_hash. This is the calculation 2098c2ecf20Sopenharmony_ci * 2108c2ecf20Sopenharmony_ci * H_T ← Poly1305_{K_T}(bin_{128}(|L|) || T) 2118c2ecf20Sopenharmony_ci * 2128c2ecf20Sopenharmony_ci * from the procedure in section 6.4 of the Adiantum paper. The resulting value 2138c2ecf20Sopenharmony_ci * is reused in both the first and second hash steps. Specifically, it's added 2148c2ecf20Sopenharmony_ci * to the result of an independently keyed ε-∆U hash function (for equal length 2158c2ecf20Sopenharmony_ci * inputs only) taken over the left-hand part (the "bulk") of the message, to 2168c2ecf20Sopenharmony_ci * give the overall Adiantum hash of the (tweak, left-hand part) pair. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_cistatic void adiantum_hash_header(struct skcipher_request *req) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2218c2ecf20Sopenharmony_ci const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 2228c2ecf20Sopenharmony_ci struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); 2238c2ecf20Sopenharmony_ci const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; 2248c2ecf20Sopenharmony_ci struct { 2258c2ecf20Sopenharmony_ci __le64 message_bits; 2268c2ecf20Sopenharmony_ci __le64 padding; 2278c2ecf20Sopenharmony_ci } header = { 2288c2ecf20Sopenharmony_ci .message_bits = cpu_to_le64((u64)bulk_len * 8) 2298c2ecf20Sopenharmony_ci }; 2308c2ecf20Sopenharmony_ci struct poly1305_state state; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci poly1305_core_init(&state); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(header) % POLY1305_BLOCK_SIZE != 0); 2358c2ecf20Sopenharmony_ci poly1305_core_blocks(&state, &tctx->header_hash_key, 2368c2ecf20Sopenharmony_ci &header, sizeof(header) / POLY1305_BLOCK_SIZE, 1); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci BUILD_BUG_ON(TWEAK_SIZE % POLY1305_BLOCK_SIZE != 0); 2398c2ecf20Sopenharmony_ci poly1305_core_blocks(&state, &tctx->header_hash_key, req->iv, 2408c2ecf20Sopenharmony_ci TWEAK_SIZE / POLY1305_BLOCK_SIZE, 1); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci poly1305_core_emit(&state, NULL, &rctx->header_hash); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/* Hash the left-hand part (the "bulk") of the message using NHPoly1305 */ 2468c2ecf20Sopenharmony_cistatic int adiantum_hash_message(struct skcipher_request *req, 2478c2ecf20Sopenharmony_ci struct scatterlist *sgl, le128 *digest) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2508c2ecf20Sopenharmony_ci const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 2518c2ecf20Sopenharmony_ci struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); 2528c2ecf20Sopenharmony_ci const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; 2538c2ecf20Sopenharmony_ci struct shash_desc *hash_desc = &rctx->u.hash_desc; 2548c2ecf20Sopenharmony_ci struct sg_mapping_iter miter; 2558c2ecf20Sopenharmony_ci unsigned int i, n; 2568c2ecf20Sopenharmony_ci int err; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci hash_desc->tfm = tctx->hash; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci err = crypto_shash_init(hash_desc); 2618c2ecf20Sopenharmony_ci if (err) 2628c2ecf20Sopenharmony_ci return err; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci sg_miter_start(&miter, sgl, sg_nents(sgl), 2658c2ecf20Sopenharmony_ci SG_MITER_FROM_SG | SG_MITER_ATOMIC); 2668c2ecf20Sopenharmony_ci for (i = 0; i < bulk_len; i += n) { 2678c2ecf20Sopenharmony_ci sg_miter_next(&miter); 2688c2ecf20Sopenharmony_ci n = min_t(unsigned int, miter.length, bulk_len - i); 2698c2ecf20Sopenharmony_ci err = crypto_shash_update(hash_desc, miter.addr, n); 2708c2ecf20Sopenharmony_ci if (err) 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci sg_miter_stop(&miter); 2748c2ecf20Sopenharmony_ci if (err) 2758c2ecf20Sopenharmony_ci return err; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci return crypto_shash_final(hash_desc, (u8 *)digest); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci/* Continue Adiantum encryption/decryption after the stream cipher step */ 2818c2ecf20Sopenharmony_cistatic int adiantum_finish(struct skcipher_request *req) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2848c2ecf20Sopenharmony_ci const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 2858c2ecf20Sopenharmony_ci struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); 2868c2ecf20Sopenharmony_ci const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; 2878c2ecf20Sopenharmony_ci le128 digest; 2888c2ecf20Sopenharmony_ci int err; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* If decrypting, decrypt C_M with the block cipher to get P_M */ 2918c2ecf20Sopenharmony_ci if (!rctx->enc) 2928c2ecf20Sopenharmony_ci crypto_cipher_decrypt_one(tctx->blockcipher, rctx->rbuf.bytes, 2938c2ecf20Sopenharmony_ci rctx->rbuf.bytes); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* 2968c2ecf20Sopenharmony_ci * Second hash step 2978c2ecf20Sopenharmony_ci * enc: C_R = C_M - H_{K_H}(T, C_L) 2988c2ecf20Sopenharmony_ci * dec: P_R = P_M - H_{K_H}(T, P_L) 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_ci err = adiantum_hash_message(req, req->dst, &digest); 3018c2ecf20Sopenharmony_ci if (err) 3028c2ecf20Sopenharmony_ci return err; 3038c2ecf20Sopenharmony_ci le128_add(&digest, &digest, &rctx->header_hash); 3048c2ecf20Sopenharmony_ci le128_sub(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); 3058c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->dst, 3068c2ecf20Sopenharmony_ci bulk_len, BLOCKCIPHER_BLOCK_SIZE, 1); 3078c2ecf20Sopenharmony_ci return 0; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic void adiantum_streamcipher_done(struct crypto_async_request *areq, 3118c2ecf20Sopenharmony_ci int err) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct skcipher_request *req = areq->data; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (!err) 3168c2ecf20Sopenharmony_ci err = adiantum_finish(req); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci skcipher_request_complete(req, err); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic int adiantum_crypt(struct skcipher_request *req, bool enc) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 3248c2ecf20Sopenharmony_ci const struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 3258c2ecf20Sopenharmony_ci struct adiantum_request_ctx *rctx = skcipher_request_ctx(req); 3268c2ecf20Sopenharmony_ci const unsigned int bulk_len = req->cryptlen - BLOCKCIPHER_BLOCK_SIZE; 3278c2ecf20Sopenharmony_ci unsigned int stream_len; 3288c2ecf20Sopenharmony_ci le128 digest; 3298c2ecf20Sopenharmony_ci int err; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (req->cryptlen < BLOCKCIPHER_BLOCK_SIZE) 3328c2ecf20Sopenharmony_ci return -EINVAL; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci rctx->enc = enc; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * First hash step 3388c2ecf20Sopenharmony_ci * enc: P_M = P_R + H_{K_H}(T, P_L) 3398c2ecf20Sopenharmony_ci * dec: C_M = C_R + H_{K_H}(T, C_L) 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci adiantum_hash_header(req); 3428c2ecf20Sopenharmony_ci err = adiantum_hash_message(req, req->src, &digest); 3438c2ecf20Sopenharmony_ci if (err) 3448c2ecf20Sopenharmony_ci return err; 3458c2ecf20Sopenharmony_ci le128_add(&digest, &digest, &rctx->header_hash); 3468c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(&rctx->rbuf.bignum, req->src, 3478c2ecf20Sopenharmony_ci bulk_len, BLOCKCIPHER_BLOCK_SIZE, 0); 3488c2ecf20Sopenharmony_ci le128_add(&rctx->rbuf.bignum, &rctx->rbuf.bignum, &digest); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* If encrypting, encrypt P_M with the block cipher to get C_M */ 3518c2ecf20Sopenharmony_ci if (enc) 3528c2ecf20Sopenharmony_ci crypto_cipher_encrypt_one(tctx->blockcipher, rctx->rbuf.bytes, 3538c2ecf20Sopenharmony_ci rctx->rbuf.bytes); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* Initialize the rest of the XChaCha IV (first part is C_M) */ 3568c2ecf20Sopenharmony_ci BUILD_BUG_ON(BLOCKCIPHER_BLOCK_SIZE != 16); 3578c2ecf20Sopenharmony_ci BUILD_BUG_ON(XCHACHA_IV_SIZE != 32); /* nonce || stream position */ 3588c2ecf20Sopenharmony_ci rctx->rbuf.words[4] = cpu_to_le32(1); 3598c2ecf20Sopenharmony_ci rctx->rbuf.words[5] = 0; 3608c2ecf20Sopenharmony_ci rctx->rbuf.words[6] = 0; 3618c2ecf20Sopenharmony_ci rctx->rbuf.words[7] = 0; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci /* 3648c2ecf20Sopenharmony_ci * XChaCha needs to be done on all the data except the last 16 bytes; 3658c2ecf20Sopenharmony_ci * for disk encryption that usually means 4080 or 496 bytes. But ChaCha 3668c2ecf20Sopenharmony_ci * implementations tend to be most efficient when passed a whole number 3678c2ecf20Sopenharmony_ci * of 64-byte ChaCha blocks, or sometimes even a multiple of 256 bytes. 3688c2ecf20Sopenharmony_ci * And here it doesn't matter whether the last 16 bytes are written to, 3698c2ecf20Sopenharmony_ci * as the second hash step will overwrite them. Thus, round the XChaCha 3708c2ecf20Sopenharmony_ci * length up to the next 64-byte boundary if possible. 3718c2ecf20Sopenharmony_ci */ 3728c2ecf20Sopenharmony_ci stream_len = bulk_len; 3738c2ecf20Sopenharmony_ci if (round_up(stream_len, CHACHA_BLOCK_SIZE) <= req->cryptlen) 3748c2ecf20Sopenharmony_ci stream_len = round_up(stream_len, CHACHA_BLOCK_SIZE); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci skcipher_request_set_tfm(&rctx->u.streamcipher_req, tctx->streamcipher); 3778c2ecf20Sopenharmony_ci skcipher_request_set_crypt(&rctx->u.streamcipher_req, req->src, 3788c2ecf20Sopenharmony_ci req->dst, stream_len, &rctx->rbuf); 3798c2ecf20Sopenharmony_ci skcipher_request_set_callback(&rctx->u.streamcipher_req, 3808c2ecf20Sopenharmony_ci req->base.flags, 3818c2ecf20Sopenharmony_ci adiantum_streamcipher_done, req); 3828c2ecf20Sopenharmony_ci return crypto_skcipher_encrypt(&rctx->u.streamcipher_req) ?: 3838c2ecf20Sopenharmony_ci adiantum_finish(req); 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic int adiantum_encrypt(struct skcipher_request *req) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci return adiantum_crypt(req, true); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int adiantum_decrypt(struct skcipher_request *req) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci return adiantum_crypt(req, false); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic int adiantum_init_tfm(struct crypto_skcipher *tfm) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci struct skcipher_instance *inst = skcipher_alg_instance(tfm); 3998c2ecf20Sopenharmony_ci struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst); 4008c2ecf20Sopenharmony_ci struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 4018c2ecf20Sopenharmony_ci struct crypto_skcipher *streamcipher; 4028c2ecf20Sopenharmony_ci struct crypto_cipher *blockcipher; 4038c2ecf20Sopenharmony_ci struct crypto_shash *hash; 4048c2ecf20Sopenharmony_ci unsigned int subreq_size; 4058c2ecf20Sopenharmony_ci int err; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci streamcipher = crypto_spawn_skcipher(&ictx->streamcipher_spawn); 4088c2ecf20Sopenharmony_ci if (IS_ERR(streamcipher)) 4098c2ecf20Sopenharmony_ci return PTR_ERR(streamcipher); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci blockcipher = crypto_spawn_cipher(&ictx->blockcipher_spawn); 4128c2ecf20Sopenharmony_ci if (IS_ERR(blockcipher)) { 4138c2ecf20Sopenharmony_ci err = PTR_ERR(blockcipher); 4148c2ecf20Sopenharmony_ci goto err_free_streamcipher; 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci hash = crypto_spawn_shash(&ictx->hash_spawn); 4188c2ecf20Sopenharmony_ci if (IS_ERR(hash)) { 4198c2ecf20Sopenharmony_ci err = PTR_ERR(hash); 4208c2ecf20Sopenharmony_ci goto err_free_blockcipher; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci tctx->streamcipher = streamcipher; 4248c2ecf20Sopenharmony_ci tctx->blockcipher = blockcipher; 4258c2ecf20Sopenharmony_ci tctx->hash = hash; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci BUILD_BUG_ON(offsetofend(struct adiantum_request_ctx, u) != 4288c2ecf20Sopenharmony_ci sizeof(struct adiantum_request_ctx)); 4298c2ecf20Sopenharmony_ci subreq_size = max(sizeof_field(struct adiantum_request_ctx, 4308c2ecf20Sopenharmony_ci u.hash_desc) + 4318c2ecf20Sopenharmony_ci crypto_shash_descsize(hash), 4328c2ecf20Sopenharmony_ci sizeof_field(struct adiantum_request_ctx, 4338c2ecf20Sopenharmony_ci u.streamcipher_req) + 4348c2ecf20Sopenharmony_ci crypto_skcipher_reqsize(streamcipher)); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, 4378c2ecf20Sopenharmony_ci offsetof(struct adiantum_request_ctx, u) + 4388c2ecf20Sopenharmony_ci subreq_size); 4398c2ecf20Sopenharmony_ci return 0; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cierr_free_blockcipher: 4428c2ecf20Sopenharmony_ci crypto_free_cipher(blockcipher); 4438c2ecf20Sopenharmony_cierr_free_streamcipher: 4448c2ecf20Sopenharmony_ci crypto_free_skcipher(streamcipher); 4458c2ecf20Sopenharmony_ci return err; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic void adiantum_exit_tfm(struct crypto_skcipher *tfm) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci struct adiantum_tfm_ctx *tctx = crypto_skcipher_ctx(tfm); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci crypto_free_skcipher(tctx->streamcipher); 4538c2ecf20Sopenharmony_ci crypto_free_cipher(tctx->blockcipher); 4548c2ecf20Sopenharmony_ci crypto_free_shash(tctx->hash); 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic void adiantum_free_instance(struct skcipher_instance *inst) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci struct adiantum_instance_ctx *ictx = skcipher_instance_ctx(inst); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci crypto_drop_skcipher(&ictx->streamcipher_spawn); 4628c2ecf20Sopenharmony_ci crypto_drop_cipher(&ictx->blockcipher_spawn); 4638c2ecf20Sopenharmony_ci crypto_drop_shash(&ictx->hash_spawn); 4648c2ecf20Sopenharmony_ci kfree(inst); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci/* 4688c2ecf20Sopenharmony_ci * Check for a supported set of inner algorithms. 4698c2ecf20Sopenharmony_ci * See the comment at the beginning of this file. 4708c2ecf20Sopenharmony_ci */ 4718c2ecf20Sopenharmony_cistatic bool adiantum_supported_algorithms(struct skcipher_alg *streamcipher_alg, 4728c2ecf20Sopenharmony_ci struct crypto_alg *blockcipher_alg, 4738c2ecf20Sopenharmony_ci struct shash_alg *hash_alg) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci if (strcmp(streamcipher_alg->base.cra_name, "xchacha12") != 0 && 4768c2ecf20Sopenharmony_ci strcmp(streamcipher_alg->base.cra_name, "xchacha20") != 0) 4778c2ecf20Sopenharmony_ci return false; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (blockcipher_alg->cra_cipher.cia_min_keysize > BLOCKCIPHER_KEY_SIZE || 4808c2ecf20Sopenharmony_ci blockcipher_alg->cra_cipher.cia_max_keysize < BLOCKCIPHER_KEY_SIZE) 4818c2ecf20Sopenharmony_ci return false; 4828c2ecf20Sopenharmony_ci if (blockcipher_alg->cra_blocksize != BLOCKCIPHER_BLOCK_SIZE) 4838c2ecf20Sopenharmony_ci return false; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (strcmp(hash_alg->base.cra_name, "nhpoly1305") != 0) 4868c2ecf20Sopenharmony_ci return false; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci return true; 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_cistatic int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci u32 mask; 4948c2ecf20Sopenharmony_ci const char *nhpoly1305_name; 4958c2ecf20Sopenharmony_ci struct skcipher_instance *inst; 4968c2ecf20Sopenharmony_ci struct adiantum_instance_ctx *ictx; 4978c2ecf20Sopenharmony_ci struct skcipher_alg *streamcipher_alg; 4988c2ecf20Sopenharmony_ci struct crypto_alg *blockcipher_alg; 4998c2ecf20Sopenharmony_ci struct shash_alg *hash_alg; 5008c2ecf20Sopenharmony_ci int err; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask); 5038c2ecf20Sopenharmony_ci if (err) 5048c2ecf20Sopenharmony_ci return err; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); 5078c2ecf20Sopenharmony_ci if (!inst) 5088c2ecf20Sopenharmony_ci return -ENOMEM; 5098c2ecf20Sopenharmony_ci ictx = skcipher_instance_ctx(inst); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* Stream cipher, e.g. "xchacha12" */ 5128c2ecf20Sopenharmony_ci err = crypto_grab_skcipher(&ictx->streamcipher_spawn, 5138c2ecf20Sopenharmony_ci skcipher_crypto_instance(inst), 5148c2ecf20Sopenharmony_ci crypto_attr_alg_name(tb[1]), 0, mask); 5158c2ecf20Sopenharmony_ci if (err) 5168c2ecf20Sopenharmony_ci goto err_free_inst; 5178c2ecf20Sopenharmony_ci streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci /* Block cipher, e.g. "aes" */ 5208c2ecf20Sopenharmony_ci err = crypto_grab_cipher(&ictx->blockcipher_spawn, 5218c2ecf20Sopenharmony_ci skcipher_crypto_instance(inst), 5228c2ecf20Sopenharmony_ci crypto_attr_alg_name(tb[2]), 0, mask); 5238c2ecf20Sopenharmony_ci if (err) 5248c2ecf20Sopenharmony_ci goto err_free_inst; 5258c2ecf20Sopenharmony_ci blockcipher_alg = crypto_spawn_cipher_alg(&ictx->blockcipher_spawn); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* NHPoly1305 ε-∆U hash function */ 5288c2ecf20Sopenharmony_ci nhpoly1305_name = crypto_attr_alg_name(tb[3]); 5298c2ecf20Sopenharmony_ci if (nhpoly1305_name == ERR_PTR(-ENOENT)) 5308c2ecf20Sopenharmony_ci nhpoly1305_name = "nhpoly1305"; 5318c2ecf20Sopenharmony_ci err = crypto_grab_shash(&ictx->hash_spawn, 5328c2ecf20Sopenharmony_ci skcipher_crypto_instance(inst), 5338c2ecf20Sopenharmony_ci nhpoly1305_name, 0, mask); 5348c2ecf20Sopenharmony_ci if (err) 5358c2ecf20Sopenharmony_ci goto err_free_inst; 5368c2ecf20Sopenharmony_ci hash_alg = crypto_spawn_shash_alg(&ictx->hash_spawn); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* Check the set of algorithms */ 5398c2ecf20Sopenharmony_ci if (!adiantum_supported_algorithms(streamcipher_alg, blockcipher_alg, 5408c2ecf20Sopenharmony_ci hash_alg)) { 5418c2ecf20Sopenharmony_ci pr_warn("Unsupported Adiantum instantiation: (%s,%s,%s)\n", 5428c2ecf20Sopenharmony_ci streamcipher_alg->base.cra_name, 5438c2ecf20Sopenharmony_ci blockcipher_alg->cra_name, hash_alg->base.cra_name); 5448c2ecf20Sopenharmony_ci err = -EINVAL; 5458c2ecf20Sopenharmony_ci goto err_free_inst; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Instance fields */ 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci err = -ENAMETOOLONG; 5518c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, 5528c2ecf20Sopenharmony_ci "adiantum(%s,%s)", streamcipher_alg->base.cra_name, 5538c2ecf20Sopenharmony_ci blockcipher_alg->cra_name) >= CRYPTO_MAX_ALG_NAME) 5548c2ecf20Sopenharmony_ci goto err_free_inst; 5558c2ecf20Sopenharmony_ci if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, 5568c2ecf20Sopenharmony_ci "adiantum(%s,%s,%s)", 5578c2ecf20Sopenharmony_ci streamcipher_alg->base.cra_driver_name, 5588c2ecf20Sopenharmony_ci blockcipher_alg->cra_driver_name, 5598c2ecf20Sopenharmony_ci hash_alg->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) 5608c2ecf20Sopenharmony_ci goto err_free_inst; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci inst->alg.base.cra_blocksize = BLOCKCIPHER_BLOCK_SIZE; 5638c2ecf20Sopenharmony_ci inst->alg.base.cra_ctxsize = sizeof(struct adiantum_tfm_ctx); 5648c2ecf20Sopenharmony_ci inst->alg.base.cra_alignmask = streamcipher_alg->base.cra_alignmask | 5658c2ecf20Sopenharmony_ci hash_alg->base.cra_alignmask; 5668c2ecf20Sopenharmony_ci /* 5678c2ecf20Sopenharmony_ci * The block cipher is only invoked once per message, so for long 5688c2ecf20Sopenharmony_ci * messages (e.g. sectors for disk encryption) its performance doesn't 5698c2ecf20Sopenharmony_ci * matter as much as that of the stream cipher and hash function. Thus, 5708c2ecf20Sopenharmony_ci * weigh the block cipher's ->cra_priority less. 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_ci inst->alg.base.cra_priority = (4 * streamcipher_alg->base.cra_priority + 5738c2ecf20Sopenharmony_ci 2 * hash_alg->base.cra_priority + 5748c2ecf20Sopenharmony_ci blockcipher_alg->cra_priority) / 7; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci inst->alg.setkey = adiantum_setkey; 5778c2ecf20Sopenharmony_ci inst->alg.encrypt = adiantum_encrypt; 5788c2ecf20Sopenharmony_ci inst->alg.decrypt = adiantum_decrypt; 5798c2ecf20Sopenharmony_ci inst->alg.init = adiantum_init_tfm; 5808c2ecf20Sopenharmony_ci inst->alg.exit = adiantum_exit_tfm; 5818c2ecf20Sopenharmony_ci inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(streamcipher_alg); 5828c2ecf20Sopenharmony_ci inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(streamcipher_alg); 5838c2ecf20Sopenharmony_ci inst->alg.ivsize = TWEAK_SIZE; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci inst->free = adiantum_free_instance; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci err = skcipher_register_instance(tmpl, inst); 5888c2ecf20Sopenharmony_ci if (err) { 5898c2ecf20Sopenharmony_cierr_free_inst: 5908c2ecf20Sopenharmony_ci adiantum_free_instance(inst); 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci return err; 5938c2ecf20Sopenharmony_ci} 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci/* adiantum(streamcipher_name, blockcipher_name [, nhpoly1305_name]) */ 5968c2ecf20Sopenharmony_cistatic struct crypto_template adiantum_tmpl = { 5978c2ecf20Sopenharmony_ci .name = "adiantum", 5988c2ecf20Sopenharmony_ci .create = adiantum_create, 5998c2ecf20Sopenharmony_ci .module = THIS_MODULE, 6008c2ecf20Sopenharmony_ci}; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic int __init adiantum_module_init(void) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci return crypto_register_template(&adiantum_tmpl); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic void __exit adiantum_module_exit(void) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci crypto_unregister_template(&adiantum_tmpl); 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cisubsys_initcall(adiantum_module_init); 6138c2ecf20Sopenharmony_cimodule_exit(adiantum_module_exit); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Adiantum length-preserving encryption mode"); 6168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 6178c2ecf20Sopenharmony_ciMODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); 6188c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("adiantum"); 619