cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

crc64-rocksoft.c (3283B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2
      3#include <linux/types.h>
      4#include <linux/module.h>
      5#include <linux/crc64.h>
      6#include <linux/err.h>
      7#include <linux/init.h>
      8#include <crypto/hash.h>
      9#include <crypto/algapi.h>
     10#include <linux/static_key.h>
     11#include <linux/notifier.h>
     12
     13static struct crypto_shash __rcu *crc64_rocksoft_tfm;
     14static DEFINE_STATIC_KEY_TRUE(crc64_rocksoft_fallback);
     15static DEFINE_MUTEX(crc64_rocksoft_mutex);
     16static struct work_struct crc64_rocksoft_rehash_work;
     17
     18static int crc64_rocksoft_notify(struct notifier_block *self, unsigned long val, void *data)
     19{
     20	struct crypto_alg *alg = data;
     21
     22	if (val != CRYPTO_MSG_ALG_LOADED ||
     23	    strcmp(alg->cra_name, CRC64_ROCKSOFT_STRING))
     24		return NOTIFY_DONE;
     25
     26	schedule_work(&crc64_rocksoft_rehash_work);
     27	return NOTIFY_OK;
     28}
     29
     30static void crc64_rocksoft_rehash(struct work_struct *work)
     31{
     32	struct crypto_shash *new, *old;
     33
     34	mutex_lock(&crc64_rocksoft_mutex);
     35	old = rcu_dereference_protected(crc64_rocksoft_tfm,
     36					lockdep_is_held(&crc64_rocksoft_mutex));
     37	new = crypto_alloc_shash(CRC64_ROCKSOFT_STRING, 0, 0);
     38	if (IS_ERR(new)) {
     39		mutex_unlock(&crc64_rocksoft_mutex);
     40		return;
     41	}
     42	rcu_assign_pointer(crc64_rocksoft_tfm, new);
     43	mutex_unlock(&crc64_rocksoft_mutex);
     44
     45	if (old) {
     46		synchronize_rcu();
     47		crypto_free_shash(old);
     48	} else {
     49		static_branch_disable(&crc64_rocksoft_fallback);
     50	}
     51}
     52
     53static struct notifier_block crc64_rocksoft_nb = {
     54	.notifier_call = crc64_rocksoft_notify,
     55};
     56
     57u64 crc64_rocksoft_update(u64 crc, const unsigned char *buffer, size_t len)
     58{
     59	struct {
     60		struct shash_desc shash;
     61		u64 crc;
     62	} desc;
     63	int err;
     64
     65	if (static_branch_unlikely(&crc64_rocksoft_fallback))
     66		return crc64_rocksoft_generic(crc, buffer, len);
     67
     68	rcu_read_lock();
     69	desc.shash.tfm = rcu_dereference(crc64_rocksoft_tfm);
     70	desc.crc = crc;
     71	err = crypto_shash_update(&desc.shash, buffer, len);
     72	rcu_read_unlock();
     73
     74	BUG_ON(err);
     75
     76	return desc.crc;
     77}
     78EXPORT_SYMBOL_GPL(crc64_rocksoft_update);
     79
     80u64 crc64_rocksoft(const unsigned char *buffer, size_t len)
     81{
     82	return crc64_rocksoft_update(0, buffer, len);
     83}
     84EXPORT_SYMBOL_GPL(crc64_rocksoft);
     85
     86static int __init crc64_rocksoft_mod_init(void)
     87{
     88	INIT_WORK(&crc64_rocksoft_rehash_work, crc64_rocksoft_rehash);
     89	crypto_register_notifier(&crc64_rocksoft_nb);
     90	crc64_rocksoft_rehash(&crc64_rocksoft_rehash_work);
     91	return 0;
     92}
     93
     94static void __exit crc64_rocksoft_mod_fini(void)
     95{
     96	crypto_unregister_notifier(&crc64_rocksoft_nb);
     97	cancel_work_sync(&crc64_rocksoft_rehash_work);
     98	crypto_free_shash(rcu_dereference_protected(crc64_rocksoft_tfm, 1));
     99}
    100
    101module_init(crc64_rocksoft_mod_init);
    102module_exit(crc64_rocksoft_mod_fini);
    103
    104static int crc64_rocksoft_transform_show(char *buffer, const struct kernel_param *kp)
    105{
    106	struct crypto_shash *tfm;
    107	int len;
    108
    109	if (static_branch_unlikely(&crc64_rocksoft_fallback))
    110		return sprintf(buffer, "fallback\n");
    111
    112	rcu_read_lock();
    113	tfm = rcu_dereference(crc64_rocksoft_tfm);
    114	len = snprintf(buffer, PAGE_SIZE, "%s\n",
    115		       crypto_shash_driver_name(tfm));
    116	rcu_read_unlock();
    117
    118	return len;
    119}
    120
    121module_param_call(transform, NULL, crc64_rocksoft_transform_show, NULL, 0444);
    122
    123MODULE_AUTHOR("Keith Busch <kbusch@kernel.org>");
    124MODULE_DESCRIPTION("Rocksoft model CRC64 calculation (library API)");
    125MODULE_LICENSE("GPL");
    126MODULE_SOFTDEP("pre: crc64");