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

algboss.c (5591B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Create default crypto algorithm instances.
      4 *
      5 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
      6 */
      7
      8#include <crypto/internal/aead.h>
      9#include <linux/completion.h>
     10#include <linux/ctype.h>
     11#include <linux/err.h>
     12#include <linux/init.h>
     13#include <linux/kthread.h>
     14#include <linux/module.h>
     15#include <linux/notifier.h>
     16#include <linux/rtnetlink.h>
     17#include <linux/sched/signal.h>
     18#include <linux/slab.h>
     19#include <linux/string.h>
     20
     21#include "internal.h"
     22
     23struct cryptomgr_param {
     24	struct rtattr *tb[CRYPTO_MAX_ATTRS + 2];
     25
     26	struct {
     27		struct rtattr attr;
     28		struct crypto_attr_type data;
     29	} type;
     30
     31	struct {
     32		struct rtattr attr;
     33		struct crypto_attr_alg data;
     34	} attrs[CRYPTO_MAX_ATTRS];
     35
     36	char template[CRYPTO_MAX_ALG_NAME];
     37
     38	struct crypto_larval *larval;
     39
     40	u32 otype;
     41	u32 omask;
     42};
     43
     44struct crypto_test_param {
     45	char driver[CRYPTO_MAX_ALG_NAME];
     46	char alg[CRYPTO_MAX_ALG_NAME];
     47	u32 type;
     48};
     49
     50static int cryptomgr_probe(void *data)
     51{
     52	struct cryptomgr_param *param = data;
     53	struct crypto_template *tmpl;
     54	int err;
     55
     56	tmpl = crypto_lookup_template(param->template);
     57	if (!tmpl)
     58		goto out;
     59
     60	do {
     61		err = tmpl->create(tmpl, param->tb);
     62	} while (err == -EAGAIN && !signal_pending(current));
     63
     64	crypto_tmpl_put(tmpl);
     65
     66out:
     67	complete_all(&param->larval->completion);
     68	crypto_alg_put(&param->larval->alg);
     69	kfree(param);
     70	module_put_and_kthread_exit(0);
     71}
     72
     73static int cryptomgr_schedule_probe(struct crypto_larval *larval)
     74{
     75	struct task_struct *thread;
     76	struct cryptomgr_param *param;
     77	const char *name = larval->alg.cra_name;
     78	const char *p;
     79	unsigned int len;
     80	int i;
     81
     82	if (!try_module_get(THIS_MODULE))
     83		goto err;
     84
     85	param = kzalloc(sizeof(*param), GFP_KERNEL);
     86	if (!param)
     87		goto err_put_module;
     88
     89	for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++)
     90		;
     91
     92	len = p - name;
     93	if (!len || *p != '(')
     94		goto err_free_param;
     95
     96	memcpy(param->template, name, len);
     97
     98	i = 0;
     99	for (;;) {
    100		name = ++p;
    101
    102		for (; isalnum(*p) || *p == '-' || *p == '_'; p++)
    103			;
    104
    105		if (*p == '(') {
    106			int recursion = 0;
    107
    108			for (;;) {
    109				if (!*++p)
    110					goto err_free_param;
    111				if (*p == '(')
    112					recursion++;
    113				else if (*p == ')' && !recursion--)
    114					break;
    115			}
    116
    117			p++;
    118		}
    119
    120		len = p - name;
    121		if (!len)
    122			goto err_free_param;
    123
    124		param->attrs[i].attr.rta_len = sizeof(param->attrs[i]);
    125		param->attrs[i].attr.rta_type = CRYPTOA_ALG;
    126		memcpy(param->attrs[i].data.name, name, len);
    127
    128		param->tb[i + 1] = &param->attrs[i].attr;
    129		i++;
    130
    131		if (i >= CRYPTO_MAX_ATTRS)
    132			goto err_free_param;
    133
    134		if (*p == ')')
    135			break;
    136
    137		if (*p != ',')
    138			goto err_free_param;
    139	}
    140
    141	if (!i)
    142		goto err_free_param;
    143
    144	param->tb[i + 1] = NULL;
    145
    146	param->type.attr.rta_len = sizeof(param->type);
    147	param->type.attr.rta_type = CRYPTOA_TYPE;
    148	param->type.data.type = larval->alg.cra_flags & ~CRYPTO_ALG_TESTED;
    149	param->type.data.mask = larval->mask & ~CRYPTO_ALG_TESTED;
    150	param->tb[0] = &param->type.attr;
    151
    152	param->otype = larval->alg.cra_flags;
    153	param->omask = larval->mask;
    154
    155	crypto_alg_get(&larval->alg);
    156	param->larval = larval;
    157
    158	thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe");
    159	if (IS_ERR(thread))
    160		goto err_put_larval;
    161
    162	return NOTIFY_STOP;
    163
    164err_put_larval:
    165	crypto_alg_put(&larval->alg);
    166err_free_param:
    167	kfree(param);
    168err_put_module:
    169	module_put(THIS_MODULE);
    170err:
    171	return NOTIFY_OK;
    172}
    173
    174static int cryptomgr_test(void *data)
    175{
    176	struct crypto_test_param *param = data;
    177	u32 type = param->type;
    178	int err = 0;
    179
    180#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
    181	goto skiptest;
    182#endif
    183
    184	if (type & CRYPTO_ALG_TESTED)
    185		goto skiptest;
    186
    187	err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);
    188
    189skiptest:
    190	crypto_alg_tested(param->driver, err);
    191
    192	kfree(param);
    193	module_put_and_kthread_exit(0);
    194}
    195
    196static int cryptomgr_schedule_test(struct crypto_alg *alg)
    197{
    198	struct task_struct *thread;
    199	struct crypto_test_param *param;
    200	u32 type;
    201
    202	if (!try_module_get(THIS_MODULE))
    203		goto err;
    204
    205	param = kzalloc(sizeof(*param), GFP_KERNEL);
    206	if (!param)
    207		goto err_put_module;
    208
    209	memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver));
    210	memcpy(param->alg, alg->cra_name, sizeof(param->alg));
    211	type = alg->cra_flags;
    212
    213	/* Do not test internal algorithms. */
    214	if (type & CRYPTO_ALG_INTERNAL)
    215		type |= CRYPTO_ALG_TESTED;
    216
    217	param->type = type;
    218
    219	thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");
    220	if (IS_ERR(thread))
    221		goto err_free_param;
    222
    223	return NOTIFY_STOP;
    224
    225err_free_param:
    226	kfree(param);
    227err_put_module:
    228	module_put(THIS_MODULE);
    229err:
    230	return NOTIFY_OK;
    231}
    232
    233static int cryptomgr_notify(struct notifier_block *this, unsigned long msg,
    234			    void *data)
    235{
    236	switch (msg) {
    237	case CRYPTO_MSG_ALG_REQUEST:
    238		return cryptomgr_schedule_probe(data);
    239	case CRYPTO_MSG_ALG_REGISTER:
    240		return cryptomgr_schedule_test(data);
    241	case CRYPTO_MSG_ALG_LOADED:
    242		break;
    243	}
    244
    245	return NOTIFY_DONE;
    246}
    247
    248static struct notifier_block cryptomgr_notifier = {
    249	.notifier_call = cryptomgr_notify,
    250};
    251
    252static int __init cryptomgr_init(void)
    253{
    254	return crypto_register_notifier(&cryptomgr_notifier);
    255}
    256
    257static void __exit cryptomgr_exit(void)
    258{
    259	int err = crypto_unregister_notifier(&cryptomgr_notifier);
    260	BUG_ON(err);
    261}
    262
    263/*
    264 * This is arch_initcall() so that the crypto self-tests are run on algorithms
    265 * registered early by subsys_initcall().  subsys_initcall() is needed for
    266 * generic implementations so that they're available for comparison tests when
    267 * other implementations are registered later by module_init().
    268 */
    269arch_initcall(cryptomgr_init);
    270module_exit(cryptomgr_exit);
    271
    272MODULE_LICENSE("GPL");
    273MODULE_DESCRIPTION("Crypto Algorithm Manager");