18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Cryptographic API. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Blowfish Cipher Algorithm, by Bruce Schneier. 68c2ecf20Sopenharmony_ci * http://www.counterpane.com/blowfish.html 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Adapted from Kerneli implementation. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org> 118c2ecf20Sopenharmony_ci * Copyright (c) Kyle McMartin <kyle@debian.org> 128c2ecf20Sopenharmony_ci * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/mm.h> 178c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 188c2ecf20Sopenharmony_ci#include <linux/crypto.h> 198c2ecf20Sopenharmony_ci#include <linux/types.h> 208c2ecf20Sopenharmony_ci#include <crypto/blowfish.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * Round loop unrolling macros, S is a pointer to a S-Box array 248c2ecf20Sopenharmony_ci * organized in 4 unsigned longs at a row. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci#define GET32_3(x) (((x) & 0xff)) 278c2ecf20Sopenharmony_ci#define GET32_2(x) (((x) >> (8)) & (0xff)) 288c2ecf20Sopenharmony_ci#define GET32_1(x) (((x) >> (16)) & (0xff)) 298c2ecf20Sopenharmony_ci#define GET32_0(x) (((x) >> (24)) & (0xff)) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \ 328c2ecf20Sopenharmony_ci S[512 + GET32_2(x)]) + S[768 + GET32_3(x)]) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); }) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct bf_ctx *ctx = crypto_tfm_ctx(tfm); 398c2ecf20Sopenharmony_ci const __be32 *in_blk = (const __be32 *)src; 408c2ecf20Sopenharmony_ci __be32 *const out_blk = (__be32 *)dst; 418c2ecf20Sopenharmony_ci const u32 *P = ctx->p; 428c2ecf20Sopenharmony_ci const u32 *S = ctx->s; 438c2ecf20Sopenharmony_ci u32 yl = be32_to_cpu(in_blk[0]); 448c2ecf20Sopenharmony_ci u32 yr = be32_to_cpu(in_blk[1]); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci ROUND(yr, yl, 0); 478c2ecf20Sopenharmony_ci ROUND(yl, yr, 1); 488c2ecf20Sopenharmony_ci ROUND(yr, yl, 2); 498c2ecf20Sopenharmony_ci ROUND(yl, yr, 3); 508c2ecf20Sopenharmony_ci ROUND(yr, yl, 4); 518c2ecf20Sopenharmony_ci ROUND(yl, yr, 5); 528c2ecf20Sopenharmony_ci ROUND(yr, yl, 6); 538c2ecf20Sopenharmony_ci ROUND(yl, yr, 7); 548c2ecf20Sopenharmony_ci ROUND(yr, yl, 8); 558c2ecf20Sopenharmony_ci ROUND(yl, yr, 9); 568c2ecf20Sopenharmony_ci ROUND(yr, yl, 10); 578c2ecf20Sopenharmony_ci ROUND(yl, yr, 11); 588c2ecf20Sopenharmony_ci ROUND(yr, yl, 12); 598c2ecf20Sopenharmony_ci ROUND(yl, yr, 13); 608c2ecf20Sopenharmony_ci ROUND(yr, yl, 14); 618c2ecf20Sopenharmony_ci ROUND(yl, yr, 15); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci yl ^= P[16]; 648c2ecf20Sopenharmony_ci yr ^= P[17]; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci out_blk[0] = cpu_to_be32(yr); 678c2ecf20Sopenharmony_ci out_blk[1] = cpu_to_be32(yl); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct bf_ctx *ctx = crypto_tfm_ctx(tfm); 738c2ecf20Sopenharmony_ci const __be32 *in_blk = (const __be32 *)src; 748c2ecf20Sopenharmony_ci __be32 *const out_blk = (__be32 *)dst; 758c2ecf20Sopenharmony_ci const u32 *P = ctx->p; 768c2ecf20Sopenharmony_ci const u32 *S = ctx->s; 778c2ecf20Sopenharmony_ci u32 yl = be32_to_cpu(in_blk[0]); 788c2ecf20Sopenharmony_ci u32 yr = be32_to_cpu(in_blk[1]); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci ROUND(yr, yl, 17); 818c2ecf20Sopenharmony_ci ROUND(yl, yr, 16); 828c2ecf20Sopenharmony_ci ROUND(yr, yl, 15); 838c2ecf20Sopenharmony_ci ROUND(yl, yr, 14); 848c2ecf20Sopenharmony_ci ROUND(yr, yl, 13); 858c2ecf20Sopenharmony_ci ROUND(yl, yr, 12); 868c2ecf20Sopenharmony_ci ROUND(yr, yl, 11); 878c2ecf20Sopenharmony_ci ROUND(yl, yr, 10); 888c2ecf20Sopenharmony_ci ROUND(yr, yl, 9); 898c2ecf20Sopenharmony_ci ROUND(yl, yr, 8); 908c2ecf20Sopenharmony_ci ROUND(yr, yl, 7); 918c2ecf20Sopenharmony_ci ROUND(yl, yr, 6); 928c2ecf20Sopenharmony_ci ROUND(yr, yl, 5); 938c2ecf20Sopenharmony_ci ROUND(yl, yr, 4); 948c2ecf20Sopenharmony_ci ROUND(yr, yl, 3); 958c2ecf20Sopenharmony_ci ROUND(yl, yr, 2); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci yl ^= P[1]; 988c2ecf20Sopenharmony_ci yr ^= P[0]; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci out_blk[0] = cpu_to_be32(yr); 1018c2ecf20Sopenharmony_ci out_blk[1] = cpu_to_be32(yl); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic struct crypto_alg alg = { 1058c2ecf20Sopenharmony_ci .cra_name = "blowfish", 1068c2ecf20Sopenharmony_ci .cra_driver_name = "blowfish-generic", 1078c2ecf20Sopenharmony_ci .cra_priority = 100, 1088c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 1098c2ecf20Sopenharmony_ci .cra_blocksize = BF_BLOCK_SIZE, 1108c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct bf_ctx), 1118c2ecf20Sopenharmony_ci .cra_alignmask = 3, 1128c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 1138c2ecf20Sopenharmony_ci .cra_u = { .cipher = { 1148c2ecf20Sopenharmony_ci .cia_min_keysize = BF_MIN_KEY_SIZE, 1158c2ecf20Sopenharmony_ci .cia_max_keysize = BF_MAX_KEY_SIZE, 1168c2ecf20Sopenharmony_ci .cia_setkey = blowfish_setkey, 1178c2ecf20Sopenharmony_ci .cia_encrypt = bf_encrypt, 1188c2ecf20Sopenharmony_ci .cia_decrypt = bf_decrypt } } 1198c2ecf20Sopenharmony_ci}; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic int __init blowfish_mod_init(void) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci return crypto_register_alg(&alg); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic void __exit blowfish_mod_fini(void) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci crypto_unregister_alg(&alg); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cisubsys_initcall(blowfish_mod_init); 1328c2ecf20Sopenharmony_cimodule_exit(blowfish_mod_fini); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1358c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Blowfish Cipher Algorithm"); 1368c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("blowfish"); 1378c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("blowfish-generic"); 138