linux/crypto/algboss.c
<<
>>
Prefs
   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_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_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");
 274
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.