18275d1aaSTim Chen /* 28275d1aaSTim Chen * Cryptographic API. 38275d1aaSTim Chen * 48275d1aaSTim Chen * Glue code for the SHA256 Secure Hash Algorithm assembler 58275d1aaSTim Chen * implementation using supplemental SSE3 / AVX / AVX2 instructions. 68275d1aaSTim Chen * 78275d1aaSTim Chen * This file is based on sha256_generic.c 88275d1aaSTim Chen * 98275d1aaSTim Chen * Copyright (C) 2013 Intel Corporation. 108275d1aaSTim Chen * 118275d1aaSTim Chen * Author: 128275d1aaSTim Chen * Tim Chen <tim.c.chen@linux.intel.com> 138275d1aaSTim Chen * 148275d1aaSTim Chen * This program is free software; you can redistribute it and/or modify it 158275d1aaSTim Chen * under the terms of the GNU General Public License as published by the Free 168275d1aaSTim Chen * Software Foundation; either version 2 of the License, or (at your option) 178275d1aaSTim Chen * any later version. 188275d1aaSTim Chen * 198275d1aaSTim Chen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 208275d1aaSTim Chen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 218275d1aaSTim Chen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 228275d1aaSTim Chen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 238275d1aaSTim Chen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 248275d1aaSTim Chen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 258275d1aaSTim Chen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 268275d1aaSTim Chen * SOFTWARE. 278275d1aaSTim Chen */ 288275d1aaSTim Chen 298275d1aaSTim Chen 308275d1aaSTim Chen #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 318275d1aaSTim Chen 328275d1aaSTim Chen #include <crypto/internal/hash.h> 33f2abe0d7SEric Biggers #include <crypto/internal/simd.h> 348275d1aaSTim Chen #include <linux/init.h> 358275d1aaSTim Chen #include <linux/module.h> 368275d1aaSTim Chen #include <linux/mm.h> 378275d1aaSTim Chen #include <linux/types.h> 38*a24d22b2SEric Biggers #include <crypto/sha2.h> 391631030aSArd Biesheuvel #include <crypto/sha256_base.h> 408275d1aaSTim Chen #include <linux/string.h> 41f2abe0d7SEric Biggers #include <asm/simd.h> 428275d1aaSTim Chen 4341419a28SKees Cook asmlinkage void sha256_transform_ssse3(struct sha256_state *state, 4441419a28SKees Cook const u8 *data, int blocks); 458275d1aaSTim Chen 46eb7d6ba8SHans de Goede static int _sha256_update(struct shash_desc *desc, const u8 *data, 4741419a28SKees Cook unsigned int len, sha256_block_fn *sha256_xform) 488275d1aaSTim Chen { 498275d1aaSTim Chen struct sha256_state *sctx = shash_desc_ctx(desc); 508275d1aaSTim Chen 51f2abe0d7SEric Biggers if (!crypto_simd_usable() || 521631030aSArd Biesheuvel (sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE) 531631030aSArd Biesheuvel return crypto_sha256_update(desc, data, len); 541631030aSArd Biesheuvel 5541419a28SKees Cook /* 5641419a28SKees Cook * Make sure struct sha256_state begins directly with the SHA256 5741419a28SKees Cook * 256-bit internal state, as this is what the asm functions expect. 5841419a28SKees Cook */ 591631030aSArd Biesheuvel BUILD_BUG_ON(offsetof(struct sha256_state, state) != 0); 601631030aSArd Biesheuvel 611631030aSArd Biesheuvel kernel_fpu_begin(); 6241419a28SKees Cook sha256_base_do_update(desc, data, len, sha256_xform); 631631030aSArd Biesheuvel kernel_fpu_end(); 648275d1aaSTim Chen 658275d1aaSTim Chen return 0; 668275d1aaSTim Chen } 678275d1aaSTim Chen 685dda42fcStim static int sha256_finup(struct shash_desc *desc, const u8 *data, 6941419a28SKees Cook unsigned int len, u8 *out, sha256_block_fn *sha256_xform) 701631030aSArd Biesheuvel { 71f2abe0d7SEric Biggers if (!crypto_simd_usable()) 721631030aSArd Biesheuvel return crypto_sha256_finup(desc, data, len, out); 731631030aSArd Biesheuvel 748275d1aaSTim Chen kernel_fpu_begin(); 751631030aSArd Biesheuvel if (len) 7641419a28SKees Cook sha256_base_do_update(desc, data, len, sha256_xform); 7741419a28SKees Cook sha256_base_do_finalize(desc, sha256_xform); 788275d1aaSTim Chen kernel_fpu_end(); 798275d1aaSTim Chen 801631030aSArd Biesheuvel return sha256_base_finish(desc, out); 818275d1aaSTim Chen } 828275d1aaSTim Chen 835dda42fcStim static int sha256_ssse3_update(struct shash_desc *desc, const u8 *data, 845dda42fcStim unsigned int len) 855dda42fcStim { 86eb7d6ba8SHans de Goede return _sha256_update(desc, data, len, sha256_transform_ssse3); 875dda42fcStim } 885dda42fcStim 895dda42fcStim static int sha256_ssse3_finup(struct shash_desc *desc, const u8 *data, 905dda42fcStim unsigned int len, u8 *out) 915dda42fcStim { 925dda42fcStim return sha256_finup(desc, data, len, out, sha256_transform_ssse3); 935dda42fcStim } 945dda42fcStim 958275d1aaSTim Chen /* Add padding and return the message digest. */ 968275d1aaSTim Chen static int sha256_ssse3_final(struct shash_desc *desc, u8 *out) 978275d1aaSTim Chen { 981631030aSArd Biesheuvel return sha256_ssse3_finup(desc, NULL, 0, out); 99a710f761SJussi Kivilinna } 100a710f761SJussi Kivilinna 1015dda42fcStim static struct shash_alg sha256_ssse3_algs[] = { { 1028275d1aaSTim Chen .digestsize = SHA256_DIGEST_SIZE, 1031631030aSArd Biesheuvel .init = sha256_base_init, 1048275d1aaSTim Chen .update = sha256_ssse3_update, 1058275d1aaSTim Chen .final = sha256_ssse3_final, 1061631030aSArd Biesheuvel .finup = sha256_ssse3_finup, 1078275d1aaSTim Chen .descsize = sizeof(struct sha256_state), 1088275d1aaSTim Chen .base = { 1098275d1aaSTim Chen .cra_name = "sha256", 1108275d1aaSTim Chen .cra_driver_name = "sha256-ssse3", 1118275d1aaSTim Chen .cra_priority = 150, 1128275d1aaSTim Chen .cra_blocksize = SHA256_BLOCK_SIZE, 1138275d1aaSTim Chen .cra_module = THIS_MODULE, 1148275d1aaSTim Chen } 115a710f761SJussi Kivilinna }, { 116a710f761SJussi Kivilinna .digestsize = SHA224_DIGEST_SIZE, 1171631030aSArd Biesheuvel .init = sha224_base_init, 118a710f761SJussi Kivilinna .update = sha256_ssse3_update, 1191631030aSArd Biesheuvel .final = sha256_ssse3_final, 1201631030aSArd Biesheuvel .finup = sha256_ssse3_finup, 121a710f761SJussi Kivilinna .descsize = sizeof(struct sha256_state), 122a710f761SJussi Kivilinna .base = { 123a710f761SJussi Kivilinna .cra_name = "sha224", 124a710f761SJussi Kivilinna .cra_driver_name = "sha224-ssse3", 125a710f761SJussi Kivilinna .cra_priority = 150, 126a710f761SJussi Kivilinna .cra_blocksize = SHA224_BLOCK_SIZE, 127a710f761SJussi Kivilinna .cra_module = THIS_MODULE, 128a710f761SJussi Kivilinna } 129a710f761SJussi Kivilinna } }; 1308275d1aaSTim Chen 1315dda42fcStim static int register_sha256_ssse3(void) 1325dda42fcStim { 1335dda42fcStim if (boot_cpu_has(X86_FEATURE_SSSE3)) 1345dda42fcStim return crypto_register_shashes(sha256_ssse3_algs, 1355dda42fcStim ARRAY_SIZE(sha256_ssse3_algs)); 1365dda42fcStim return 0; 1375dda42fcStim } 1385dda42fcStim 1395dda42fcStim static void unregister_sha256_ssse3(void) 1405dda42fcStim { 1415dda42fcStim if (boot_cpu_has(X86_FEATURE_SSSE3)) 1425dda42fcStim crypto_unregister_shashes(sha256_ssse3_algs, 1435dda42fcStim ARRAY_SIZE(sha256_ssse3_algs)); 1445dda42fcStim } 1455dda42fcStim 14641419a28SKees Cook asmlinkage void sha256_transform_avx(struct sha256_state *state, 14741419a28SKees Cook const u8 *data, int blocks); 1485dda42fcStim 1495dda42fcStim static int sha256_avx_update(struct shash_desc *desc, const u8 *data, 1505dda42fcStim unsigned int len) 1515dda42fcStim { 152eb7d6ba8SHans de Goede return _sha256_update(desc, data, len, sha256_transform_avx); 1535dda42fcStim } 1545dda42fcStim 1555dda42fcStim static int sha256_avx_finup(struct shash_desc *desc, const u8 *data, 1565dda42fcStim unsigned int len, u8 *out) 1575dda42fcStim { 1585dda42fcStim return sha256_finup(desc, data, len, out, sha256_transform_avx); 1595dda42fcStim } 1605dda42fcStim 1615dda42fcStim static int sha256_avx_final(struct shash_desc *desc, u8 *out) 1625dda42fcStim { 1635dda42fcStim return sha256_avx_finup(desc, NULL, 0, out); 1645dda42fcStim } 1655dda42fcStim 1665dda42fcStim static struct shash_alg sha256_avx_algs[] = { { 1675dda42fcStim .digestsize = SHA256_DIGEST_SIZE, 1685dda42fcStim .init = sha256_base_init, 1695dda42fcStim .update = sha256_avx_update, 1705dda42fcStim .final = sha256_avx_final, 1715dda42fcStim .finup = sha256_avx_finup, 1725dda42fcStim .descsize = sizeof(struct sha256_state), 1735dda42fcStim .base = { 1745dda42fcStim .cra_name = "sha256", 1755dda42fcStim .cra_driver_name = "sha256-avx", 1765dda42fcStim .cra_priority = 160, 1775dda42fcStim .cra_blocksize = SHA256_BLOCK_SIZE, 1785dda42fcStim .cra_module = THIS_MODULE, 1795dda42fcStim } 1805dda42fcStim }, { 1815dda42fcStim .digestsize = SHA224_DIGEST_SIZE, 1825dda42fcStim .init = sha224_base_init, 1835dda42fcStim .update = sha256_avx_update, 1845dda42fcStim .final = sha256_avx_final, 1855dda42fcStim .finup = sha256_avx_finup, 1865dda42fcStim .descsize = sizeof(struct sha256_state), 1875dda42fcStim .base = { 1885dda42fcStim .cra_name = "sha224", 1895dda42fcStim .cra_driver_name = "sha224-avx", 1905dda42fcStim .cra_priority = 160, 1915dda42fcStim .cra_blocksize = SHA224_BLOCK_SIZE, 1925dda42fcStim .cra_module = THIS_MODULE, 1935dda42fcStim } 1945dda42fcStim } }; 1955dda42fcStim 1965dda42fcStim static bool avx_usable(void) 1978275d1aaSTim Chen { 198d91cab78SDave Hansen if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) { 199da154e82SBorislav Petkov if (boot_cpu_has(X86_FEATURE_AVX)) 2008275d1aaSTim Chen pr_info("AVX detected but unusable.\n"); 2018275d1aaSTim Chen return false; 2028275d1aaSTim Chen } 2038275d1aaSTim Chen 2048275d1aaSTim Chen return true; 2058275d1aaSTim Chen } 2065dda42fcStim 2075dda42fcStim static int register_sha256_avx(void) 2085dda42fcStim { 2095dda42fcStim if (avx_usable()) 2105dda42fcStim return crypto_register_shashes(sha256_avx_algs, 2115dda42fcStim ARRAY_SIZE(sha256_avx_algs)); 2125dda42fcStim return 0; 2135dda42fcStim } 2145dda42fcStim 2155dda42fcStim static void unregister_sha256_avx(void) 2165dda42fcStim { 2175dda42fcStim if (avx_usable()) 2185dda42fcStim crypto_unregister_shashes(sha256_avx_algs, 2195dda42fcStim ARRAY_SIZE(sha256_avx_algs)); 2205dda42fcStim } 2215dda42fcStim 22241419a28SKees Cook asmlinkage void sha256_transform_rorx(struct sha256_state *state, 22341419a28SKees Cook const u8 *data, int blocks); 2245dda42fcStim 2255dda42fcStim static int sha256_avx2_update(struct shash_desc *desc, const u8 *data, 2265dda42fcStim unsigned int len) 2275dda42fcStim { 228eb7d6ba8SHans de Goede return _sha256_update(desc, data, len, sha256_transform_rorx); 2295dda42fcStim } 2305dda42fcStim 2315dda42fcStim static int sha256_avx2_finup(struct shash_desc *desc, const u8 *data, 2325dda42fcStim unsigned int len, u8 *out) 2335dda42fcStim { 2345dda42fcStim return sha256_finup(desc, data, len, out, sha256_transform_rorx); 2355dda42fcStim } 2365dda42fcStim 2375dda42fcStim static int sha256_avx2_final(struct shash_desc *desc, u8 *out) 2385dda42fcStim { 2395dda42fcStim return sha256_avx2_finup(desc, NULL, 0, out); 2405dda42fcStim } 2415dda42fcStim 2425dda42fcStim static struct shash_alg sha256_avx2_algs[] = { { 2435dda42fcStim .digestsize = SHA256_DIGEST_SIZE, 2445dda42fcStim .init = sha256_base_init, 2455dda42fcStim .update = sha256_avx2_update, 2465dda42fcStim .final = sha256_avx2_final, 2475dda42fcStim .finup = sha256_avx2_finup, 2485dda42fcStim .descsize = sizeof(struct sha256_state), 2495dda42fcStim .base = { 2505dda42fcStim .cra_name = "sha256", 2515dda42fcStim .cra_driver_name = "sha256-avx2", 2525dda42fcStim .cra_priority = 170, 2535dda42fcStim .cra_blocksize = SHA256_BLOCK_SIZE, 2545dda42fcStim .cra_module = THIS_MODULE, 2555dda42fcStim } 2565dda42fcStim }, { 2575dda42fcStim .digestsize = SHA224_DIGEST_SIZE, 2585dda42fcStim .init = sha224_base_init, 2595dda42fcStim .update = sha256_avx2_update, 2605dda42fcStim .final = sha256_avx2_final, 2615dda42fcStim .finup = sha256_avx2_finup, 2625dda42fcStim .descsize = sizeof(struct sha256_state), 2635dda42fcStim .base = { 2645dda42fcStim .cra_name = "sha224", 2655dda42fcStim .cra_driver_name = "sha224-avx2", 2665dda42fcStim .cra_priority = 170, 2675dda42fcStim .cra_blocksize = SHA224_BLOCK_SIZE, 2685dda42fcStim .cra_module = THIS_MODULE, 2695dda42fcStim } 2705dda42fcStim } }; 2715dda42fcStim 2725dda42fcStim static bool avx2_usable(void) 2735dda42fcStim { 2745dda42fcStim if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) && 2755dda42fcStim boot_cpu_has(X86_FEATURE_BMI2)) 2765dda42fcStim return true; 2775dda42fcStim 2785dda42fcStim return false; 2795dda42fcStim } 2805dda42fcStim 2815dda42fcStim static int register_sha256_avx2(void) 2825dda42fcStim { 2835dda42fcStim if (avx2_usable()) 2845dda42fcStim return crypto_register_shashes(sha256_avx2_algs, 2855dda42fcStim ARRAY_SIZE(sha256_avx2_algs)); 2865dda42fcStim return 0; 2875dda42fcStim } 2885dda42fcStim 2895dda42fcStim static void unregister_sha256_avx2(void) 2905dda42fcStim { 2915dda42fcStim if (avx2_usable()) 2925dda42fcStim crypto_unregister_shashes(sha256_avx2_algs, 2935dda42fcStim ARRAY_SIZE(sha256_avx2_algs)); 2945dda42fcStim } 2955dda42fcStim 2965dda42fcStim #ifdef CONFIG_AS_SHA256_NI 29741419a28SKees Cook asmlinkage void sha256_ni_transform(struct sha256_state *digest, 29841419a28SKees Cook const u8 *data, int rounds); 2995dda42fcStim 3005dda42fcStim static int sha256_ni_update(struct shash_desc *desc, const u8 *data, 3015dda42fcStim unsigned int len) 3025dda42fcStim { 303eb7d6ba8SHans de Goede return _sha256_update(desc, data, len, sha256_ni_transform); 3045dda42fcStim } 3055dda42fcStim 3065dda42fcStim static int sha256_ni_finup(struct shash_desc *desc, const u8 *data, 3075dda42fcStim unsigned int len, u8 *out) 3085dda42fcStim { 3095dda42fcStim return sha256_finup(desc, data, len, out, sha256_ni_transform); 3105dda42fcStim } 3115dda42fcStim 3125dda42fcStim static int sha256_ni_final(struct shash_desc *desc, u8 *out) 3135dda42fcStim { 3145dda42fcStim return sha256_ni_finup(desc, NULL, 0, out); 3155dda42fcStim } 3165dda42fcStim 3175dda42fcStim static struct shash_alg sha256_ni_algs[] = { { 3185dda42fcStim .digestsize = SHA256_DIGEST_SIZE, 3195dda42fcStim .init = sha256_base_init, 3205dda42fcStim .update = sha256_ni_update, 3215dda42fcStim .final = sha256_ni_final, 3225dda42fcStim .finup = sha256_ni_finup, 3235dda42fcStim .descsize = sizeof(struct sha256_state), 3245dda42fcStim .base = { 3255dda42fcStim .cra_name = "sha256", 3265dda42fcStim .cra_driver_name = "sha256-ni", 3275dda42fcStim .cra_priority = 250, 3285dda42fcStim .cra_blocksize = SHA256_BLOCK_SIZE, 3295dda42fcStim .cra_module = THIS_MODULE, 3305dda42fcStim } 3315dda42fcStim }, { 3325dda42fcStim .digestsize = SHA224_DIGEST_SIZE, 3335dda42fcStim .init = sha224_base_init, 3345dda42fcStim .update = sha256_ni_update, 3355dda42fcStim .final = sha256_ni_final, 3365dda42fcStim .finup = sha256_ni_finup, 3375dda42fcStim .descsize = sizeof(struct sha256_state), 3385dda42fcStim .base = { 3395dda42fcStim .cra_name = "sha224", 3405dda42fcStim .cra_driver_name = "sha224-ni", 3415dda42fcStim .cra_priority = 250, 3425dda42fcStim .cra_blocksize = SHA224_BLOCK_SIZE, 3435dda42fcStim .cra_module = THIS_MODULE, 3445dda42fcStim } 3455dda42fcStim } }; 3465dda42fcStim 3475dda42fcStim static int register_sha256_ni(void) 3485dda42fcStim { 3495dda42fcStim if (boot_cpu_has(X86_FEATURE_SHA_NI)) 3505dda42fcStim return crypto_register_shashes(sha256_ni_algs, 3515dda42fcStim ARRAY_SIZE(sha256_ni_algs)); 3525dda42fcStim return 0; 3535dda42fcStim } 3545dda42fcStim 3555dda42fcStim static void unregister_sha256_ni(void) 3565dda42fcStim { 3575dda42fcStim if (boot_cpu_has(X86_FEATURE_SHA_NI)) 3585dda42fcStim crypto_unregister_shashes(sha256_ni_algs, 3595dda42fcStim ARRAY_SIZE(sha256_ni_algs)); 3605dda42fcStim } 3615dda42fcStim 3625dda42fcStim #else 3635dda42fcStim static inline int register_sha256_ni(void) { return 0; } 3645dda42fcStim static inline void unregister_sha256_ni(void) { } 3658275d1aaSTim Chen #endif 3668275d1aaSTim Chen 3678275d1aaSTim Chen static int __init sha256_ssse3_mod_init(void) 3688275d1aaSTim Chen { 3695dda42fcStim if (register_sha256_ssse3()) 3705dda42fcStim goto fail; 3718275d1aaSTim Chen 3725dda42fcStim if (register_sha256_avx()) { 3735dda42fcStim unregister_sha256_ssse3(); 3745dda42fcStim goto fail; 3758275d1aaSTim Chen } 3768275d1aaSTim Chen 3775dda42fcStim if (register_sha256_avx2()) { 3785dda42fcStim unregister_sha256_avx(); 3795dda42fcStim unregister_sha256_ssse3(); 3805dda42fcStim goto fail; 3818275d1aaSTim Chen } 3828275d1aaSTim Chen 3835dda42fcStim if (register_sha256_ni()) { 3845dda42fcStim unregister_sha256_avx2(); 3855dda42fcStim unregister_sha256_avx(); 3865dda42fcStim unregister_sha256_ssse3(); 3875dda42fcStim goto fail; 3888275d1aaSTim Chen } 3898275d1aaSTim Chen 3905dda42fcStim return 0; 3915dda42fcStim fail: 3928275d1aaSTim Chen return -ENODEV; 3938275d1aaSTim Chen } 3948275d1aaSTim Chen 3958275d1aaSTim Chen static void __exit sha256_ssse3_mod_fini(void) 3968275d1aaSTim Chen { 3975dda42fcStim unregister_sha256_ni(); 3985dda42fcStim unregister_sha256_avx2(); 3995dda42fcStim unregister_sha256_avx(); 4005dda42fcStim unregister_sha256_ssse3(); 4018275d1aaSTim Chen } 4028275d1aaSTim Chen 4038275d1aaSTim Chen module_init(sha256_ssse3_mod_init); 4048275d1aaSTim Chen module_exit(sha256_ssse3_mod_fini); 4058275d1aaSTim Chen 4068275d1aaSTim Chen MODULE_LICENSE("GPL"); 4078275d1aaSTim Chen MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated"); 4088275d1aaSTim Chen 4095d26a105SKees Cook MODULE_ALIAS_CRYPTO("sha256"); 4101a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha256-ssse3"); 4111a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha256-avx"); 4121a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha256-avx2"); 4135d26a105SKees Cook MODULE_ALIAS_CRYPTO("sha224"); 4141a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha224-ssse3"); 4151a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha224-avx"); 4161a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha224-avx2"); 4171a445e8eSStephan Mueller #ifdef CONFIG_AS_SHA256_NI 4181a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha256-ni"); 4191a445e8eSStephan Mueller MODULE_ALIAS_CRYPTO("sha224-ni"); 4201a445e8eSStephan Mueller #endif 421