162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Cryptographic API. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * ARIA Cipher Algorithm. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Documentation of ARIA can be found in RFC 5794. 862306a36Sopenharmony_ci * Copyright (c) 2022 Taehee Yoo <ap420073@gmail.com> 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Information for ARIA 1162306a36Sopenharmony_ci * http://210.104.33.10/ARIA/index-e.html (English) 1262306a36Sopenharmony_ci * http://seed.kisa.or.kr/ (Korean) 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Public domain version is distributed above. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <crypto/aria.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const u32 key_rc[20] = { 2062306a36Sopenharmony_ci 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0, 2162306a36Sopenharmony_ci 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0, 2262306a36Sopenharmony_ci 0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e, 2362306a36Sopenharmony_ci 0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0, 2462306a36Sopenharmony_ci 0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void aria_set_encrypt_key(struct aria_ctx *ctx, const u8 *in_key, 2862306a36Sopenharmony_ci unsigned int key_len) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci const __be32 *key = (const __be32 *)in_key; 3162306a36Sopenharmony_ci u32 w0[4], w1[4], w2[4], w3[4]; 3262306a36Sopenharmony_ci u32 reg0, reg1, reg2, reg3; 3362306a36Sopenharmony_ci const u32 *ck; 3462306a36Sopenharmony_ci int rkidx = 0; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci ck = &key_rc[(key_len - 16) / 2]; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci w0[0] = be32_to_cpu(key[0]); 3962306a36Sopenharmony_ci w0[1] = be32_to_cpu(key[1]); 4062306a36Sopenharmony_ci w0[2] = be32_to_cpu(key[2]); 4162306a36Sopenharmony_ci w0[3] = be32_to_cpu(key[3]); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci reg0 = w0[0] ^ ck[0]; 4462306a36Sopenharmony_ci reg1 = w0[1] ^ ck[1]; 4562306a36Sopenharmony_ci reg2 = w0[2] ^ ck[2]; 4662306a36Sopenharmony_ci reg3 = w0[3] ^ ck[3]; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci aria_subst_diff_odd(®0, ®1, ®2, ®3); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (key_len > 16) { 5162306a36Sopenharmony_ci w1[0] = be32_to_cpu(key[4]); 5262306a36Sopenharmony_ci w1[1] = be32_to_cpu(key[5]); 5362306a36Sopenharmony_ci if (key_len > 24) { 5462306a36Sopenharmony_ci w1[2] = be32_to_cpu(key[6]); 5562306a36Sopenharmony_ci w1[3] = be32_to_cpu(key[7]); 5662306a36Sopenharmony_ci } else { 5762306a36Sopenharmony_ci w1[2] = 0; 5862306a36Sopenharmony_ci w1[3] = 0; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci } else { 6162306a36Sopenharmony_ci w1[0] = 0; 6262306a36Sopenharmony_ci w1[1] = 0; 6362306a36Sopenharmony_ci w1[2] = 0; 6462306a36Sopenharmony_ci w1[3] = 0; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci w1[0] ^= reg0; 6862306a36Sopenharmony_ci w1[1] ^= reg1; 6962306a36Sopenharmony_ci w1[2] ^= reg2; 7062306a36Sopenharmony_ci w1[3] ^= reg3; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci reg0 = w1[0]; 7362306a36Sopenharmony_ci reg1 = w1[1]; 7462306a36Sopenharmony_ci reg2 = w1[2]; 7562306a36Sopenharmony_ci reg3 = w1[3]; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci reg0 ^= ck[4]; 7862306a36Sopenharmony_ci reg1 ^= ck[5]; 7962306a36Sopenharmony_ci reg2 ^= ck[6]; 8062306a36Sopenharmony_ci reg3 ^= ck[7]; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci aria_subst_diff_even(®0, ®1, ®2, ®3); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci reg0 ^= w0[0]; 8562306a36Sopenharmony_ci reg1 ^= w0[1]; 8662306a36Sopenharmony_ci reg2 ^= w0[2]; 8762306a36Sopenharmony_ci reg3 ^= w0[3]; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci w2[0] = reg0; 9062306a36Sopenharmony_ci w2[1] = reg1; 9162306a36Sopenharmony_ci w2[2] = reg2; 9262306a36Sopenharmony_ci w2[3] = reg3; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci reg0 ^= ck[8]; 9562306a36Sopenharmony_ci reg1 ^= ck[9]; 9662306a36Sopenharmony_ci reg2 ^= ck[10]; 9762306a36Sopenharmony_ci reg3 ^= ck[11]; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci aria_subst_diff_odd(®0, ®1, ®2, ®3); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci w3[0] = reg0 ^ w1[0]; 10262306a36Sopenharmony_ci w3[1] = reg1 ^ w1[1]; 10362306a36Sopenharmony_ci w3[2] = reg2 ^ w1[2]; 10462306a36Sopenharmony_ci w3[3] = reg3 ^ w1[3]; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w0, w1, 19); 10762306a36Sopenharmony_ci rkidx++; 10862306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w1, w2, 19); 10962306a36Sopenharmony_ci rkidx++; 11062306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w2, w3, 19); 11162306a36Sopenharmony_ci rkidx++; 11262306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w3, w0, 19); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci rkidx++; 11562306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w0, w1, 31); 11662306a36Sopenharmony_ci rkidx++; 11762306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w1, w2, 31); 11862306a36Sopenharmony_ci rkidx++; 11962306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w2, w3, 31); 12062306a36Sopenharmony_ci rkidx++; 12162306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w3, w0, 31); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci rkidx++; 12462306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w0, w1, 67); 12562306a36Sopenharmony_ci rkidx++; 12662306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w1, w2, 67); 12762306a36Sopenharmony_ci rkidx++; 12862306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w2, w3, 67); 12962306a36Sopenharmony_ci rkidx++; 13062306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w3, w0, 67); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci rkidx++; 13362306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w0, w1, 97); 13462306a36Sopenharmony_ci if (key_len > 16) { 13562306a36Sopenharmony_ci rkidx++; 13662306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w1, w2, 97); 13762306a36Sopenharmony_ci rkidx++; 13862306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w2, w3, 97); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (key_len > 24) { 14162306a36Sopenharmony_ci rkidx++; 14262306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w3, w0, 97); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci rkidx++; 14562306a36Sopenharmony_ci aria_gsrk(ctx->enc_key[rkidx], w0, w1, 109); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic void aria_set_decrypt_key(struct aria_ctx *ctx) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci int i; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 15562306a36Sopenharmony_ci ctx->dec_key[0][i] = ctx->enc_key[ctx->rounds][i]; 15662306a36Sopenharmony_ci ctx->dec_key[ctx->rounds][i] = ctx->enc_key[0][i]; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (i = 1; i < ctx->rounds; i++) { 16062306a36Sopenharmony_ci ctx->dec_key[i][0] = aria_m(ctx->enc_key[ctx->rounds - i][0]); 16162306a36Sopenharmony_ci ctx->dec_key[i][1] = aria_m(ctx->enc_key[ctx->rounds - i][1]); 16262306a36Sopenharmony_ci ctx->dec_key[i][2] = aria_m(ctx->enc_key[ctx->rounds - i][2]); 16362306a36Sopenharmony_ci ctx->dec_key[i][3] = aria_m(ctx->enc_key[ctx->rounds - i][3]); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci aria_diff_word(&ctx->dec_key[i][0], &ctx->dec_key[i][1], 16662306a36Sopenharmony_ci &ctx->dec_key[i][2], &ctx->dec_key[i][3]); 16762306a36Sopenharmony_ci aria_diff_byte(&ctx->dec_key[i][1], 16862306a36Sopenharmony_ci &ctx->dec_key[i][2], &ctx->dec_key[i][3]); 16962306a36Sopenharmony_ci aria_diff_word(&ctx->dec_key[i][0], &ctx->dec_key[i][1], 17062306a36Sopenharmony_ci &ctx->dec_key[i][2], &ctx->dec_key[i][3]); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciint aria_set_key(struct crypto_tfm *tfm, const u8 *in_key, unsigned int key_len) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci struct aria_ctx *ctx = crypto_tfm_ctx(tfm); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (key_len != 16 && key_len != 24 && key_len != 32) 17962306a36Sopenharmony_ci return -EINVAL; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(ctx->enc_key) != 272); 18262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(ctx->dec_key) != 272); 18362306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(int) != sizeof(ctx->rounds)); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci ctx->key_length = key_len; 18662306a36Sopenharmony_ci ctx->rounds = (key_len + 32) / 4; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci aria_set_encrypt_key(ctx, in_key, key_len); 18962306a36Sopenharmony_ci aria_set_decrypt_key(ctx); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aria_set_key); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic void __aria_crypt(struct aria_ctx *ctx, u8 *out, const u8 *in, 19662306a36Sopenharmony_ci u32 key[][ARIA_RD_KEY_WORDS]) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci const __be32 *src = (const __be32 *)in; 19962306a36Sopenharmony_ci __be32 *dst = (__be32 *)out; 20062306a36Sopenharmony_ci u32 reg0, reg1, reg2, reg3; 20162306a36Sopenharmony_ci int rounds, rkidx = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci rounds = ctx->rounds; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci reg0 = be32_to_cpu(src[0]); 20662306a36Sopenharmony_ci reg1 = be32_to_cpu(src[1]); 20762306a36Sopenharmony_ci reg2 = be32_to_cpu(src[2]); 20862306a36Sopenharmony_ci reg3 = be32_to_cpu(src[3]); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci aria_add_round_key(key[rkidx], ®0, ®1, ®2, ®3); 21162306a36Sopenharmony_ci rkidx++; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci aria_subst_diff_odd(®0, ®1, ®2, ®3); 21462306a36Sopenharmony_ci aria_add_round_key(key[rkidx], ®0, ®1, ®2, ®3); 21562306a36Sopenharmony_ci rkidx++; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci while ((rounds -= 2) > 0) { 21862306a36Sopenharmony_ci aria_subst_diff_even(®0, ®1, ®2, ®3); 21962306a36Sopenharmony_ci aria_add_round_key(key[rkidx], ®0, ®1, ®2, ®3); 22062306a36Sopenharmony_ci rkidx++; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci aria_subst_diff_odd(®0, ®1, ®2, ®3); 22362306a36Sopenharmony_ci aria_add_round_key(key[rkidx], ®0, ®1, ®2, ®3); 22462306a36Sopenharmony_ci rkidx++; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci reg0 = key[rkidx][0] ^ make_u32((u8)(x1[get_u8(reg0, 0)]), 22862306a36Sopenharmony_ci (u8)(x2[get_u8(reg0, 1)] >> 8), 22962306a36Sopenharmony_ci (u8)(s1[get_u8(reg0, 2)]), 23062306a36Sopenharmony_ci (u8)(s2[get_u8(reg0, 3)])); 23162306a36Sopenharmony_ci reg1 = key[rkidx][1] ^ make_u32((u8)(x1[get_u8(reg1, 0)]), 23262306a36Sopenharmony_ci (u8)(x2[get_u8(reg1, 1)] >> 8), 23362306a36Sopenharmony_ci (u8)(s1[get_u8(reg1, 2)]), 23462306a36Sopenharmony_ci (u8)(s2[get_u8(reg1, 3)])); 23562306a36Sopenharmony_ci reg2 = key[rkidx][2] ^ make_u32((u8)(x1[get_u8(reg2, 0)]), 23662306a36Sopenharmony_ci (u8)(x2[get_u8(reg2, 1)] >> 8), 23762306a36Sopenharmony_ci (u8)(s1[get_u8(reg2, 2)]), 23862306a36Sopenharmony_ci (u8)(s2[get_u8(reg2, 3)])); 23962306a36Sopenharmony_ci reg3 = key[rkidx][3] ^ make_u32((u8)(x1[get_u8(reg3, 0)]), 24062306a36Sopenharmony_ci (u8)(x2[get_u8(reg3, 1)] >> 8), 24162306a36Sopenharmony_ci (u8)(s1[get_u8(reg3, 2)]), 24262306a36Sopenharmony_ci (u8)(s2[get_u8(reg3, 3)])); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci dst[0] = cpu_to_be32(reg0); 24562306a36Sopenharmony_ci dst[1] = cpu_to_be32(reg1); 24662306a36Sopenharmony_ci dst[2] = cpu_to_be32(reg2); 24762306a36Sopenharmony_ci dst[3] = cpu_to_be32(reg3); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_civoid aria_encrypt(void *_ctx, u8 *out, const u8 *in) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct aria_ctx *ctx = (struct aria_ctx *)_ctx; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci __aria_crypt(ctx, out, in, ctx->enc_key); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aria_encrypt); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_civoid aria_decrypt(void *_ctx, u8 *out, const u8 *in) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct aria_ctx *ctx = (struct aria_ctx *)_ctx; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci __aria_crypt(ctx, out, in, ctx->dec_key); 26362306a36Sopenharmony_ci} 26462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(aria_decrypt); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic void __aria_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci struct aria_ctx *ctx = crypto_tfm_ctx(tfm); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci __aria_crypt(ctx, out, in, ctx->enc_key); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic void __aria_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct aria_ctx *ctx = crypto_tfm_ctx(tfm); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci __aria_crypt(ctx, out, in, ctx->dec_key); 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic struct crypto_alg aria_alg = { 28162306a36Sopenharmony_ci .cra_name = "aria", 28262306a36Sopenharmony_ci .cra_driver_name = "aria-generic", 28362306a36Sopenharmony_ci .cra_priority = 100, 28462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 28562306a36Sopenharmony_ci .cra_blocksize = ARIA_BLOCK_SIZE, 28662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct aria_ctx), 28762306a36Sopenharmony_ci .cra_alignmask = 3, 28862306a36Sopenharmony_ci .cra_module = THIS_MODULE, 28962306a36Sopenharmony_ci .cra_u = { 29062306a36Sopenharmony_ci .cipher = { 29162306a36Sopenharmony_ci .cia_min_keysize = ARIA_MIN_KEY_SIZE, 29262306a36Sopenharmony_ci .cia_max_keysize = ARIA_MAX_KEY_SIZE, 29362306a36Sopenharmony_ci .cia_setkey = aria_set_key, 29462306a36Sopenharmony_ci .cia_encrypt = __aria_encrypt, 29562306a36Sopenharmony_ci .cia_decrypt = __aria_decrypt 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci}; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic int __init aria_init(void) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci return crypto_register_alg(&aria_alg); 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic void __exit aria_fini(void) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci crypto_unregister_alg(&aria_alg); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cisubsys_initcall(aria_init); 31162306a36Sopenharmony_cimodule_exit(aria_fini); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciMODULE_DESCRIPTION("ARIA Cipher Algorithm"); 31462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 31562306a36Sopenharmony_ciMODULE_AUTHOR("Taehee Yoo <ap420073@gmail.com>"); 31662306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("aria"); 31762306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("aria-generic"); 318