linux/arch/x86/crypto/fpu.c
<<
>>
Prefs
   1/*
   2 * FPU: Wrapper for blkcipher touching fpu
   3 *
   4 * Copyright (c) Intel Corp.
   5 *   Author: Huang Ying <ying.huang@intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the Free
   9 * Software Foundation; either version 2 of the License, or (at your option)
  10 * any later version.
  11 *
  12 */
  13
  14#include <crypto/algapi.h>
  15#include <linux/err.h>
  16#include <linux/init.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/slab.h>
  20#include <linux/crypto.h>
  21#include <asm/i387.h>
  22
  23struct crypto_fpu_ctx {
  24        struct crypto_blkcipher *child;
  25};
  26
  27static int crypto_fpu_setkey(struct crypto_tfm *parent, const u8 *key,
  28                             unsigned int keylen)
  29{
  30        struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(parent);
  31        struct crypto_blkcipher *child = ctx->child;
  32        int err;
  33
  34        crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  35        crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
  36                                   CRYPTO_TFM_REQ_MASK);
  37        err = crypto_blkcipher_setkey(child, key, keylen);
  38        crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
  39                                     CRYPTO_TFM_RES_MASK);
  40        return err;
  41}
  42
  43static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in,
  44                              struct scatterlist *dst, struct scatterlist *src,
  45                              unsigned int nbytes)
  46{
  47        int err;
  48        struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
  49        struct crypto_blkcipher *child = ctx->child;
  50        struct blkcipher_desc desc = {
  51                .tfm = child,
  52                .info = desc_in->info,
  53                .flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
  54        };
  55
  56        kernel_fpu_begin();
  57        err = crypto_blkcipher_crt(desc.tfm)->encrypt(&desc, dst, src, nbytes);
  58        kernel_fpu_end();
  59        return err;
  60}
  61
  62static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in,
  63                              struct scatterlist *dst, struct scatterlist *src,
  64                              unsigned int nbytes)
  65{
  66        int err;
  67        struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
  68        struct crypto_blkcipher *child = ctx->child;
  69        struct blkcipher_desc desc = {
  70                .tfm = child,
  71                .info = desc_in->info,
  72                .flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
  73        };
  74
  75        kernel_fpu_begin();
  76        err = crypto_blkcipher_crt(desc.tfm)->decrypt(&desc, dst, src, nbytes);
  77        kernel_fpu_end();
  78        return err;
  79}
  80
  81static int crypto_fpu_init_tfm(struct crypto_tfm *tfm)
  82{
  83        struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
  84        struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  85        struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
  86        struct crypto_blkcipher *cipher;
  87
  88        cipher = crypto_spawn_blkcipher(spawn);
  89        if (IS_ERR(cipher))
  90                return PTR_ERR(cipher);
  91
  92        ctx->child = cipher;
  93        return 0;
  94}
  95
  96static void crypto_fpu_exit_tfm(struct crypto_tfm *tfm)
  97{
  98        struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
  99        crypto_free_blkcipher(ctx->child);
 100}
 101
 102static struct crypto_instance *crypto_fpu_alloc(struct rtattr **tb)
 103{
 104        struct crypto_instance *inst;
 105        struct crypto_alg *alg;
 106        int err;
 107
 108        err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
 109        if (err)
 110                return ERR_PTR(err);
 111
 112        alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
 113                                  CRYPTO_ALG_TYPE_MASK);
 114        if (IS_ERR(alg))
 115                return ERR_CAST(alg);
 116
 117        inst = crypto_alloc_instance("fpu", alg);
 118        if (IS_ERR(inst))
 119                goto out_put_alg;
 120
 121        inst->alg.cra_flags = alg->cra_flags;
 122        inst->alg.cra_priority = alg->cra_priority;
 123        inst->alg.cra_blocksize = alg->cra_blocksize;
 124        inst->alg.cra_alignmask = alg->cra_alignmask;
 125        inst->alg.cra_type = alg->cra_type;
 126        inst->alg.cra_blkcipher.ivsize = alg->cra_blkcipher.ivsize;
 127        inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
 128        inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
 129        inst->alg.cra_ctxsize = sizeof(struct crypto_fpu_ctx);
 130        inst->alg.cra_init = crypto_fpu_init_tfm;
 131        inst->alg.cra_exit = crypto_fpu_exit_tfm;
 132        inst->alg.cra_blkcipher.setkey = crypto_fpu_setkey;
 133        inst->alg.cra_blkcipher.encrypt = crypto_fpu_encrypt;
 134        inst->alg.cra_blkcipher.decrypt = crypto_fpu_decrypt;
 135
 136out_put_alg:
 137        crypto_mod_put(alg);
 138        return inst;
 139}
 140
 141static void crypto_fpu_free(struct crypto_instance *inst)
 142{
 143        crypto_drop_spawn(crypto_instance_ctx(inst));
 144        kfree(inst);
 145}
 146
 147static struct crypto_template crypto_fpu_tmpl = {
 148        .name = "fpu",
 149        .alloc = crypto_fpu_alloc,
 150        .free = crypto_fpu_free,
 151        .module = THIS_MODULE,
 152};
 153
 154int __init crypto_fpu_init(void)
 155{
 156        return crypto_register_template(&crypto_fpu_tmpl);
 157}
 158
 159void __exit crypto_fpu_exit(void)
 160{
 161        crypto_unregister_template(&crypto_fpu_tmpl);
 162}
 163
 164MODULE_ALIAS_CRYPTO("fpu");
 165