summaryrefslogtreecommitdiff
path: root/linux/crypto
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-10-03 19:22:17 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2017-02-28 03:05:38 -0900
commita5b5eba7f788bb77cf57f9c94f3474a2d439ab0b (patch)
tree278813d1b1a9024174531376d41a2ba04a3b27f6 /linux/crypto
parente4d1c93d85a5b86c04599bfc9f658308d741fd41 (diff)
New on disk format - encryption
Diffstat (limited to 'linux/crypto')
-rw-r--r--linux/crypto/algapi.c315
-rw-r--r--linux/crypto/api.c227
-rw-r--r--linux/crypto/blkcipher.c47
-rw-r--r--linux/crypto/chacha20_generic.c99
-rw-r--r--linux/crypto/cipher.c123
-rw-r--r--linux/crypto/internal.h63
-rw-r--r--linux/crypto/poly1305_generic.c76
-rw-r--r--linux/crypto/sha1_generic.c85
-rw-r--r--linux/crypto/sha256_generic.c69
-rw-r--r--linux/crypto/shash.c252
10 files changed, 362 insertions, 994 deletions
diff --git a/linux/crypto/algapi.c b/linux/crypto/algapi.c
deleted file mode 100644
index 5e8e97b9..00000000
--- a/linux/crypto/algapi.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Cryptographic API for algorithms (i.e., low-level API).
- *
- * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- */
-
-#include <linux/byteorder.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/printk.h>
-#include <linux/rtnetlink.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include "internal.h"
-
-static inline int crypto_set_driver_name(struct crypto_alg *alg)
-{
- static const char suffix[] = "-generic";
- char *driver_name = alg->cra_driver_name;
- int len;
-
- if (*driver_name)
- return 0;
-
- len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
- if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
- return -ENAMETOOLONG;
-
- memcpy(driver_name + len, suffix, sizeof(suffix));
- return 0;
-}
-
-static int crypto_check_alg(struct crypto_alg *alg)
-{
- if (alg->cra_alignmask & (alg->cra_alignmask + 1))
- return -EINVAL;
-
- if (alg->cra_blocksize > PAGE_SIZE / 8)
- return -EINVAL;
-
- if (alg->cra_priority < 0)
- return -EINVAL;
-
- atomic_set(&alg->cra_refcnt, 1);
-
- return crypto_set_driver_name(alg);
-}
-
-static int __crypto_register_alg(struct crypto_alg *alg)
-{
- struct crypto_alg *q;
- int ret = -EAGAIN;
-
- INIT_LIST_HEAD(&alg->cra_users);
-
- ret = -EEXIST;
-
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (q == alg)
- goto err;
-
- if (!strcmp(q->cra_driver_name, alg->cra_name) ||
- !strcmp(q->cra_name, alg->cra_driver_name))
- goto err;
- }
-
- list_add(&alg->cra_list, &crypto_alg_list);
- return 0;
-err:
- return ret;
-}
-
-void crypto_remove_final(struct list_head *list)
-{
- struct crypto_alg *alg;
- struct crypto_alg *n;
-
- list_for_each_entry_safe(alg, n, list, cra_list) {
- list_del_init(&alg->cra_list);
- crypto_alg_put(alg);
- }
-}
-
-int crypto_register_alg(struct crypto_alg *alg)
-{
- int err;
-
- err = crypto_check_alg(alg);
- if (err)
- return err;
-
- down_write(&crypto_alg_sem);
- err = __crypto_register_alg(alg);
- up_write(&crypto_alg_sem);
-
- return err;
-}
-
-static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
-{
- if (unlikely(list_empty(&alg->cra_list)))
- return -ENOENT;
-
- list_del_init(&alg->cra_list);
- return 0;
-}
-
-int crypto_unregister_alg(struct crypto_alg *alg)
-{
- int ret;
- LIST_HEAD(list);
-
- down_write(&crypto_alg_sem);
- ret = crypto_remove_alg(alg, &list);
- up_write(&crypto_alg_sem);
-
- if (ret)
- return ret;
-
- BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
- if (alg->cra_destroy)
- alg->cra_destroy(alg);
-
- crypto_remove_final(&list);
- return 0;
-}
-
-int crypto_register_algs(struct crypto_alg *algs, int count)
-{
- int i, ret;
-
- for (i = 0; i < count; i++) {
- ret = crypto_register_alg(&algs[i]);
- if (ret)
- goto err;
- }
-
- return 0;
-
-err:
- for (--i; i >= 0; --i)
- crypto_unregister_alg(&algs[i]);
-
- return ret;
-}
-
-int crypto_unregister_algs(struct crypto_alg *algs, int count)
-{
- int i, ret;
-
- for (i = 0; i < count; i++) {
- ret = crypto_unregister_alg(&algs[i]);
- if (ret)
- pr_err("Failed to unregister %s %s: %d\n",
- algs[i].cra_driver_name, algs[i].cra_name, ret);
- }
-
- return 0;
-}
-
-struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
-{
- struct rtattr *rta = tb[0];
- struct crypto_attr_type *algt;
-
- if (!rta)
- return ERR_PTR(-ENOENT);
- if (RTA_PAYLOAD(rta) < sizeof(*algt))
- return ERR_PTR(-EINVAL);
- if (rta->rta_type != CRYPTOA_TYPE)
- return ERR_PTR(-EINVAL);
-
- algt = RTA_DATA(rta);
-
- return algt;
-}
-
-int crypto_check_attr_type(struct rtattr **tb, u32 type)
-{
- struct crypto_attr_type *algt;
-
- algt = crypto_get_attr_type(tb);
- if (IS_ERR(algt))
- return PTR_ERR(algt);
-
- if ((algt->type ^ type) & algt->mask)
- return -EINVAL;
-
- return 0;
-}
-
-const char *crypto_attr_alg_name(struct rtattr *rta)
-{
- struct crypto_attr_alg *alga;
-
- if (!rta)
- return ERR_PTR(-ENOENT);
- if (RTA_PAYLOAD(rta) < sizeof(*alga))
- return ERR_PTR(-EINVAL);
- if (rta->rta_type != CRYPTOA_ALG)
- return ERR_PTR(-EINVAL);
-
- alga = RTA_DATA(rta);
- alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
-
- return alga->name;
-}
-
-struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
- const struct crypto_type *frontend,
- u32 type, u32 mask)
-{
- const char *name;
-
- name = crypto_attr_alg_name(rta);
- if (IS_ERR(name))
- return ERR_CAST(name);
-
- return crypto_find_alg(name, frontend, type, mask);
-}
-
-int crypto_attr_u32(struct rtattr *rta, u32 *num)
-{
- struct crypto_attr_u32 *nu32;
-
- if (!rta)
- return -ENOENT;
- if (RTA_PAYLOAD(rta) < sizeof(*nu32))
- return -EINVAL;
- if (rta->rta_type != CRYPTOA_U32)
- return -EINVAL;
-
- nu32 = RTA_DATA(rta);
- *num = nu32->num;
-
- return 0;
-}
-
-static inline void crypto_inc_byte(u8 *a, unsigned int size)
-{
- u8 *b = (a + size);
- u8 c;
-
- for (; size; size--) {
- c = *--b + 1;
- *b = c;
- if (c)
- break;
- }
-}
-
-void crypto_inc(u8 *a, unsigned int size)
-{
- __be32 *b = (__be32 *)(a + size);
- u32 c;
-
- for (; size >= 4; size -= 4) {
- c = be32_to_cpu(*--b) + 1;
- *b = cpu_to_be32(c);
- if (c)
- return;
- }
-
- crypto_inc_byte(a, size);
-}
-
-static inline void crypto_xor_byte(u8 *a, const u8 *b, unsigned int size)
-{
- for (; size; size--)
- *a++ ^= *b++;
-}
-
-void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
-{
- u32 *a = (u32 *)dst;
- u32 *b = (u32 *)src;
-
- for (; size >= 4; size -= 4)
- *a++ ^= *b++;
-
- crypto_xor_byte((u8 *)a, (u8 *)b, size);
-}
-
-unsigned int crypto_alg_extsize(struct crypto_alg *alg)
-{
- return alg->cra_ctxsize +
- (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
-}
-
-int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
- u32 type, u32 mask)
-{
- int ret = 0;
- struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);
-
- if (!IS_ERR(alg)) {
- crypto_alg_put(alg);
- ret = 1;
- }
-
- return ret;
-}
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Cryptographic algorithms API");
diff --git a/linux/crypto/api.c b/linux/crypto/api.c
index 513a48aa..2d24630e 100644
--- a/linux/crypto/api.c
+++ b/linux/crypto/api.c
@@ -1,12 +1,7 @@
/*
- * Scatterlist Cryptographic API.
+ * Cryptographic API for algorithms (i.e., low-level API).
*
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2002 David S. Miller (davem@redhat.com)
- * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
- * and Nettle, by Niels Möller.
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -19,183 +14,80 @@
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/param.h>
-#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/string.h>
+
+#include <crypto/algapi.h>
#include "internal.h"
-LIST_HEAD(crypto_alg_list);
-DECLARE_RWSEM(crypto_alg_sem);
+static LIST_HEAD(crypto_alg_list);
+static DECLARE_RWSEM(crypto_alg_sem);
-static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
- u32 mask)
+static unsigned crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
{
- struct crypto_alg *q, *alg = NULL;
- int best = -2;
-
- list_for_each_entry(q, &crypto_alg_list, cra_list) {
- int exact, fuzzy;
-
- if ((q->cra_flags ^ type) & mask)
- continue;
-
- exact = !strcmp(q->cra_driver_name, name);
- fuzzy = !strcmp(q->cra_name, name);
- if (!exact && !(fuzzy && q->cra_priority > best))
- continue;
-
- if (unlikely(!crypto_alg_get(q)))
- continue;
-
- best = q->cra_priority;
- if (alg)
- crypto_alg_put(alg);
- alg = q;
-
- if (exact)
- break;
- }
+ return alg->cra_type->ctxsize(alg, type, mask);
+}
- return alg;
+unsigned crypto_alg_extsize(struct crypto_alg *alg)
+{
+ return alg->cra_ctxsize;
}
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
- /*
- * If the internal flag is set for a cipher, require a caller to
- * to invoke the cipher with the internal flag to use that cipher.
- * Also, if a caller wants to allocate a cipher that may or may
- * not be an internal cipher, use type | CRYPTO_ALG_INTERNAL and
- * !(mask & CRYPTO_ALG_INTERNAL).
- */
- if (!((type | mask) & CRYPTO_ALG_INTERNAL))
- mask |= CRYPTO_ALG_INTERNAL;
-
down_read(&crypto_alg_sem);
- alg = __crypto_alg_lookup(name, type, mask);
- up_read(&crypto_alg_sem);
+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ if (!((alg->cra_flags ^ type) & mask) &&
+ !strcmp(alg->cra_name, name))
+ goto found;
- return alg ?: ERR_PTR(-ENOENT);
-}
-
-static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
-{
- const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
-
- if (type_obj)
- return type_obj->init(tfm, type, mask);
-
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- return crypto_init_cipher_ops(tfm);
- default:
- break;
- }
+ alg = ERR_PTR(-ENOENT);
+found:
+ up_read(&crypto_alg_sem);
- BUG();
- return -EINVAL;
+ return alg;
}
static void crypto_exit_ops(struct crypto_tfm *tfm)
{
- const struct crypto_type *type = tfm->__crt_alg->cra_type;
-
- if (type) {
- if (tfm->exit)
- tfm->exit(tfm);
- return;
- }
-
- switch (crypto_tfm_alg_type(tfm)) {
- case CRYPTO_ALG_TYPE_CIPHER:
- crypto_exit_cipher_ops(tfm);
- break;
-
- default:
- BUG();
- }
-}
-
-static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
-{
- const struct crypto_type *type_obj = alg->cra_type;
- unsigned int len;
-
- len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
- if (type_obj)
- return len + type_obj->ctxsize(alg, type, mask);
-
- switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
- default:
- BUG();
-
- case CRYPTO_ALG_TYPE_CIPHER:
- len += crypto_cipher_ctxsize(alg);
- break;
- }
-
- return len;
+ if (tfm->exit)
+ tfm->exit(tfm);
}
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
- u32 mask)
+static struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg,
+ u32 type, u32 mask)
{
struct crypto_tfm *tfm = NULL;
- unsigned int tfm_size;
+ unsigned tfm_size;
int err = -ENOMEM;
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
tfm = kzalloc(tfm_size, GFP_KERNEL);
if (tfm == NULL)
- goto out_err;
+ return ERR_PTR(-ENOMEM);
tfm->__crt_alg = alg;
- err = crypto_init_ops(tfm, type, mask);
+ err = alg->cra_type->init(tfm, type, mask);
if (err)
goto out_free_tfm;
if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
goto cra_init_failed;
- goto out;
+ return tfm;
cra_init_failed:
crypto_exit_ops(tfm);
out_free_tfm:
kfree(tfm);
-out_err:
- tfm = ERR_PTR(err);
-out:
- return tfm;
+ return ERR_PTR(err);
}
-/*
- * crypto_alloc_base - Locate algorithm and allocate transform
- * @alg_name: Name of algorithm
- * @type: Type of algorithm
- * @mask: Mask for type comparison
- *
- * This function should not be used by new algorithm types.
- * Please use crypto_alloc_tfm instead.
- *
- * crypto_alloc_base() will first attempt to locate an already loaded
- * algorithm. If that fails and the kernel supports dynamically loadable
- * modules, it will then attempt to load a module of the same name or
- * alias. If that fails it will send a query to any loaded crypto manager
- * to construct an algorithm on the fly. A refcount is grabbed on the
- * algorithm which is then associated with the new transform.
- *
- * The returned transform is of a non-determinate type. Most people
- * should use one of the more specific allocation functions such as
- * crypto_alloc_blkcipher.
- *
- * In case of error the return value is an error pointer.
- */
struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
{
struct crypto_alg *alg;
@@ -208,31 +100,29 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
}
tfm = __crypto_alloc_tfm(alg, type, mask);
- if (IS_ERR(tfm)) {
- crypto_alg_put(alg);
+ if (IS_ERR(tfm))
return tfm;
- }
return tfm;
}
-void *crypto_create_tfm(struct crypto_alg *alg,
- const struct crypto_type *frontend)
+static void *crypto_create_tfm(struct crypto_alg *alg,
+ const struct crypto_type *frontend)
{
- char *mem;
struct crypto_tfm *tfm = NULL;
- unsigned int tfmsize;
- unsigned int total;
+ unsigned tfmsize;
+ unsigned total;
+ void *mem;
int err = -ENOMEM;
tfmsize = frontend->tfmsize;
total = tfmsize + sizeof(*tfm) + frontend->extsize(alg);
mem = kzalloc(total, GFP_KERNEL);
- if (mem == NULL)
+ if (!mem)
goto out_err;
- tfm = (struct crypto_tfm *)(mem + tfmsize);
+ tfm = mem + tfmsize;
tfm->__crt_alg = alg;
err = frontend->init_tfm(tfm);
@@ -254,28 +144,23 @@ out:
return mem;
}
-struct crypto_alg *crypto_find_alg(const char *alg_name,
- const struct crypto_type *frontend,
- u32 type, u32 mask)
+static struct crypto_alg *crypto_find_alg(const char *alg_name,
+ const struct crypto_type *frontend,
+ u32 type, u32 mask)
{
- struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask) =
- crypto_alg_mod_lookup;
-
if (frontend) {
type &= frontend->maskclear;
mask &= frontend->maskclear;
type |= frontend->type;
mask |= frontend->maskset;
-
- if (frontend->lookup)
- lookup = frontend->lookup;
}
- return lookup(alg_name, type, mask);
+ return crypto_alg_mod_lookup(alg_name, type, mask);
}
void *crypto_alloc_tfm(const char *alg_name,
- const struct crypto_type *frontend, u32 type, u32 mask)
+ const struct crypto_type *frontend,
+ u32 type, u32 mask)
{
struct crypto_alg *alg;
void *tfm;
@@ -285,10 +170,8 @@ void *crypto_alloc_tfm(const char *alg_name,
return ERR_CAST(alg);
tfm = crypto_create_tfm(alg, frontend);
- if (IS_ERR(tfm)) {
- crypto_alg_put(alg);
+ if (IS_ERR(tfm))
return tfm;
- }
return tfm;
}
@@ -305,22 +188,16 @@ void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
if (!tfm->exit && alg->cra_exit)
alg->cra_exit(tfm);
crypto_exit_ops(tfm);
- crypto_alg_put(alg);
kzfree(mem);
}
-int crypto_has_alg(const char *name, u32 type, u32 mask)
+int crypto_register_alg(struct crypto_alg *alg)
{
- int ret = 0;
- struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask);
+ INIT_LIST_HEAD(&alg->cra_users);
- if (!IS_ERR(alg)) {
- crypto_alg_put(alg);
- ret = 1;
- }
+ down_write(&crypto_alg_sem);
+ list_add(&alg->cra_list, &crypto_alg_list);
+ up_write(&crypto_alg_sem);
- return ret;
+ return 0;
}
-
-MODULE_DESCRIPTION("Cryptographic core API");
-MODULE_LICENSE("GPL");
diff --git a/linux/crypto/blkcipher.c b/linux/crypto/blkcipher.c
new file mode 100644
index 00000000..31f91418
--- /dev/null
+++ b/linux/crypto/blkcipher.c
@@ -0,0 +1,47 @@
+/*
+ * Block chaining cipher operations.
+ *
+ * Generic encrypt/decrypt wrapper for ciphers, handles operations across
+ * multiple page boundaries by using temporary blocks. In user context,
+ * the kernel is given a chance to schedule us once per page.
+ *
+ * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <crypto/algapi.h>
+#include "internal.h"
+
+static unsigned crypto_blkcipher_ctxsize(struct crypto_alg *alg,
+ u32 type, u32 mask)
+{
+ return alg->cra_ctxsize;
+}
+
+static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+ struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
+ struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+
+ BUG_ON((mask & CRYPTO_ALG_TYPE_MASK) != CRYPTO_ALG_TYPE_MASK);
+
+ crt->setkey = alg->setkey;
+ crt->encrypt = alg->encrypt;
+ crt->decrypt = alg->decrypt;
+ return 0;
+}
+
+const struct crypto_type crypto_blkcipher_type = {
+ .ctxsize = crypto_blkcipher_ctxsize,
+ .init = crypto_init_blkcipher_ops,
+};
diff --git a/linux/crypto/chacha20_generic.c b/linux/crypto/chacha20_generic.c
new file mode 100644
index 00000000..7ac68321
--- /dev/null
+++ b/linux/crypto/chacha20_generic.c
@@ -0,0 +1,99 @@
+/*
+ * ChaCha20 256-bit cipher algorithm, RFC7539
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/byteorder.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/scatterlist.h>
+#include <asm/unaligned.h>
+
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/chacha20.h>
+
+#include <sodium/crypto_stream_chacha20.h>
+
+struct chacha20_ctx {
+ u32 key[8];
+};
+
+static int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int keysize)
+{
+ struct chacha20_ctx *ctx = crypto_tfm_ctx(tfm);
+ int i;
+
+ if (keysize != CHACHA20_KEY_SIZE)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(ctx->key); i++)
+ ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32));
+
+ return 0;
+}
+
+static int crypto_chacha20_crypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned nbytes)
+{
+ struct chacha20_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct scatterlist *sg = src;
+ u32 iv[4];
+ int ret;
+
+ BUG_ON(src != dst);
+
+ memcpy(iv, desc->info, sizeof(iv));
+
+ while (1) {
+ ret = crypto_stream_chacha20_xor_ic(sg_virt(sg),
+ sg_virt(sg),
+ sg->length,
+ (void *) &iv[2],
+ iv[0] | ((u64) iv[1] << 32),
+ (void *) ctx->key);
+ BUG_ON(ret);
+
+ nbytes -= sg->length;
+
+ if (sg_is_last(sg))
+ break;
+
+ BUG_ON(sg->length % CHACHA20_BLOCK_SIZE);
+ iv[0] += sg->length / CHACHA20_BLOCK_SIZE;
+ sg = sg_next(sg);
+ };
+
+ BUG_ON(nbytes);
+
+ return 0;
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "chacha20",
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_ctxsize = sizeof(struct chacha20_ctx),
+ .cra_u = {
+ .blkcipher = {
+ .setkey = crypto_chacha20_setkey,
+ .encrypt = crypto_chacha20_crypt,
+ .decrypt = crypto_chacha20_crypt,
+ },
+ },
+};
+
+__attribute__((constructor(110)))
+static int chacha20_generic_mod_init(void)
+{
+ return crypto_register_alg(&alg);
+}
diff --git a/linux/crypto/cipher.c b/linux/crypto/cipher.c
deleted file mode 100644
index 6f47ac6c..00000000
--- a/linux/crypto/cipher.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Cipher operations.
- *
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/crypto.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include "internal.h"
-
-static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
- unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
- int ret;
- u8 *buffer, *alignbuffer;
- unsigned long absize;
-
- absize = keylen + alignmask;
- buffer = kmalloc(absize, GFP_ATOMIC);
- if (!buffer)
- return -ENOMEM;
-
- alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
- memcpy(alignbuffer, key, keylen);
- ret = cia->cia_setkey(tfm, alignbuffer, keylen);
- memset(alignbuffer, 0, keylen);
- kfree(buffer);
- return ret;
-
-}
-
-static int setkey_default(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
- unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
-
- tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
- if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
- tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- return -EINVAL;
- }
-
- if ((unsigned long)key & alignmask)
- return setkey_unaligned(tfm, key, keylen);
-
- return cia->cia_setkey(tfm, key, keylen);
-}
-
-static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
- const u8 *),
- struct crypto_tfm *tfm,
- u8 *dst, const u8 *src)
-{
- unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
- unsigned int size = crypto_tfm_alg_blocksize(tfm);
- u8 buffer[size + alignmask];
- u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
-
- memcpy(tmp, src, size);
- fn(tfm, tmp, tmp);
- memcpy(dst, tmp, size);
-}
-
-static void cipher_encrypt_unaligned(struct crypto_tfm *tfm,
- u8 *dst, const u8 *src)
-{
- unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
- struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
-
- if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
- cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src);
- return;
- }
-
- cipher->cia_encrypt(tfm, dst, src);
-}
-
-static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,
- u8 *dst, const u8 *src)
-{
- unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
- struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
-
- if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
- cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src);
- return;
- }
-
- cipher->cia_decrypt(tfm, dst, src);
-}
-
-int crypto_init_cipher_ops(struct crypto_tfm *tfm)
-{
- struct cipher_tfm *ops = &tfm->crt_cipher;
- struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
-
- ops->cit_setkey = setkey_default;
- ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ?
- cipher_encrypt_unaligned : cipher->cia_encrypt;
- ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
- cipher_decrypt_unaligned : cipher->cia_decrypt;
-
- return 0;
-}
-
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
-{
-}
diff --git a/linux/crypto/internal.h b/linux/crypto/internal.h
index b00dcea2..5b21f836 100644
--- a/linux/crypto/internal.h
+++ b/linux/crypto/internal.h
@@ -13,66 +13,11 @@
#ifndef _CRYPTO_INTERNAL_H
#define _CRYPTO_INTERNAL_H
-#include <crypto/algapi.h>
-#include <linux/completion.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/rwsem.h>
-#include <linux/slab.h>
+struct crypto_type;
+struct crypto_alg;
-struct crypto_instance;
-struct crypto_template;
-
-struct crypto_larval {
- struct crypto_alg alg;
- struct crypto_alg *adult;
- struct completion completion;
- u32 mask;
-};
-
-extern struct list_head crypto_alg_list;
-extern struct rw_semaphore crypto_alg_sem;
-
-static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg)
-{
- return alg->cra_ctxsize;
-}
-
-int crypto_init_cipher_ops(struct crypto_tfm *tfm);
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
-
-void crypto_remove_final(struct list_head *list);
-struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
- u32 mask);
-void *crypto_create_tfm(struct crypto_alg *alg,
- const struct crypto_type *frontend);
-struct crypto_alg *crypto_find_alg(const char *alg_name,
- const struct crypto_type *frontend,
- u32 type, u32 mask);
-void *crypto_alloc_tfm(const char *alg_name,
- const struct crypto_type *frontend, u32 type, u32 mask);
-
-int crypto_register_notifier(struct notifier_block *nb);
-int crypto_unregister_notifier(struct notifier_block *nb);
-
-unsigned int crypto_alg_extsize(struct crypto_alg *alg);
-
-int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
- u32 type, u32 mask);
-
-static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
-{
- atomic_inc(&alg->cra_refcnt);
- return alg;
-}
-
-static inline void crypto_alg_put(struct crypto_alg *alg)
-{
- if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
- alg->cra_destroy(alg);
-}
+void *crypto_alloc_tfm(const char *, const struct crypto_type *, u32, u32);
+unsigned int crypto_alg_extsize(struct crypto_alg *);
#endif /* _CRYPTO_INTERNAL_H */
diff --git a/linux/crypto/poly1305_generic.c b/linux/crypto/poly1305_generic.c
new file mode 100644
index 00000000..5d385d54
--- /dev/null
+++ b/linux/crypto/poly1305_generic.c
@@ -0,0 +1,76 @@
+/*
+ * Poly1305 authenticator algorithm, RFC7539
+ *
+ * Copyright (C) 2015 Martin Willi
+ *
+ * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/byteorder.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <crypto/internal/hash.h>
+#include <crypto/poly1305.h>
+
+struct poly1305_desc_ctx {
+ bool key_done;
+ crypto_onetimeauth_poly1305_state s;
+};
+
+
+static int poly1305_init(struct shash_desc *desc)
+{
+ struct poly1305_desc_ctx *state = shash_desc_ctx(desc);
+
+ state->key_done = false;
+ return 0;
+}
+
+static int poly1305_update(struct shash_desc *desc,
+ const u8 *src, unsigned len)
+{
+ struct poly1305_desc_ctx *state = shash_desc_ctx(desc);
+
+ if (!state->key_done) {
+ BUG_ON(len != crypto_onetimeauth_poly1305_KEYBYTES);
+
+ state->key_done = true;
+ return crypto_onetimeauth_poly1305_init(&state->s, src);
+ }
+
+ return crypto_onetimeauth_poly1305_update(&state->s, src, len);
+}
+
+static int poly1305_final(struct shash_desc *desc, u8 *out)
+{
+ struct poly1305_desc_ctx *state = shash_desc_ctx(desc);
+
+ return crypto_onetimeauth_poly1305_final(&state->s, out);
+}
+
+static struct shash_alg poly1305_alg = {
+ .digestsize = crypto_onetimeauth_poly1305_BYTES,
+ .init = poly1305_init,
+ .update = poly1305_update,
+ .final = poly1305_final,
+ .descsize = sizeof(struct poly1305_desc_ctx),
+ .base = {
+ .cra_name = "poly1305",
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ },
+};
+
+__attribute__((constructor(110)))
+static int poly1305_mod_init(void)
+{
+ return crypto_register_shash(&poly1305_alg);
+}
diff --git a/linux/crypto/sha1_generic.c b/linux/crypto/sha1_generic.c
deleted file mode 100644
index 31b5d12e..00000000
--- a/linux/crypto/sha1_generic.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Cryptographic API.
- *
- * SHA1 Secure Hash Algorithm.
- *
- * Derived from cryptoapi implementation, adapted for in-place
- * scatterlist interface.
- *
- * Copyright (c) Alan Smithee.
- * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
- * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- */
-#include <crypto/internal/hash.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/cryptohash.h>
-#include <linux/types.h>
-#include <crypto/sha.h>
-#include <crypto/sha1_base.h>
-#include <asm/byteorder.h>
-
-const u8 sha1_zero_message_hash[SHA1_DIGEST_SIZE] = {
- 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
- 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
- 0xaf, 0xd8, 0x07, 0x09
-};
-
-static void sha1_generic_block_fn(struct sha1_state *sst, u8 const *src,
- int blocks)
-{
- u32 temp[SHA_WORKSPACE_WORDS];
-
- while (blocks--) {
- sha_transform(sst->state, src, temp);
- src += SHA1_BLOCK_SIZE;
- }
- memzero_explicit(temp, sizeof(temp));
-}
-
-int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- return sha1_base_do_update(desc, data, len, sha1_generic_block_fn);
-}
-
-static int sha1_final(struct shash_desc *desc, u8 *out)
-{
- sha1_base_do_finalize(desc, sha1_generic_block_fn);
- return sha1_base_finish(desc, out);
-}
-
-int crypto_sha1_finup(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
-{
- sha1_base_do_update(desc, data, len, sha1_generic_block_fn);
- return sha1_final(desc, out);
-}
-
-static struct shash_alg alg = {
- .digestsize = SHA1_DIGEST_SIZE,
- .init = sha1_base_init,
- .update = crypto_sha1_update,
- .final = sha1_final,
- .finup = crypto_sha1_finup,
- .descsize = sizeof(struct sha1_state),
- .base = {
- .cra_name = "sha1",
- .cra_driver_name= "sha1-generic",
- .cra_flags = CRYPTO_ALG_TYPE_SHASH,
- .cra_blocksize = SHA1_BLOCK_SIZE,
- .cra_module = THIS_MODULE,
- }
-};
-
-__attribute__((constructor(110)))
-static int __init sha1_generic_mod_init(void)
-{
- return crypto_register_shash(&alg);
-}
diff --git a/linux/crypto/sha256_generic.c b/linux/crypto/sha256_generic.c
new file mode 100644
index 00000000..0bd272f0
--- /dev/null
+++ b/linux/crypto/sha256_generic.c
@@ -0,0 +1,69 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/byteorder.h>
+#include <linux/types.h>
+#include <asm/unaligned.h>
+
+#include <linux/crypto.h>
+#include <crypto/internal/hash.h>
+
+#include <sodium/crypto_hash_sha256.h>
+
+static int sha256_init(struct shash_desc *desc)
+{
+ crypto_hash_sha256_state *state = shash_desc_ctx(desc);
+
+ return crypto_hash_sha256_init(state);
+}
+
+static int sha256_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+{
+ crypto_hash_sha256_state *state = shash_desc_ctx(desc);
+
+ return crypto_hash_sha256_update(state, data, len);
+}
+
+static int sha256_final(struct shash_desc *desc, u8 *out)
+{
+ crypto_hash_sha256_state *state = shash_desc_ctx(desc);
+
+ return crypto_hash_sha256_final(state, out);
+}
+
+static struct shash_alg sha256_alg = {
+ .digestsize = crypto_hash_sha256_BYTES,
+ .init = sha256_init,
+ .update = sha256_update,
+ .final = sha256_final,
+ .descsize = sizeof(crypto_hash_sha256_state),
+ .base = {
+ .cra_name = "sha256",
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ }
+};
+
+__attribute__((constructor(110)))
+static int __init sha256_generic_mod_init(void)
+{
+ return crypto_register_shash(&sha256_alg);
+}
diff --git a/linux/crypto/shash.c b/linux/crypto/shash.c
index 406ddfe8..4f07a8b8 100644
--- a/linux/crypto/shash.c
+++ b/linux/crypto/shash.c
@@ -13,181 +13,25 @@
#include <crypto/internal/hash.h>
#include <linux/err.h>
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include "internal.h"
-static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- return -ENOSYS;
-}
-
-static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- unsigned long absize;
- u8 *buffer, *alignbuffer;
- int err;
-
- absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
- buffer = kmalloc(absize, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
- memcpy(alignbuffer, key, keylen);
- err = shash->setkey(tfm, alignbuffer, keylen);
- kzfree(buffer);
- return err;
-}
-
-int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
-
- if ((unsigned long)key & alignmask)
- return shash_setkey_unaligned(tfm, key, keylen);
-
- return shash->setkey(tfm, key, keylen);
-}
-
-static inline unsigned int shash_align_buffer_size(unsigned len,
- unsigned long mask)
-{
- typedef u8 __attribute__ ((aligned)) u8_aligned;
- return len + (mask & ~(__alignof__(u8_aligned) - 1));
-}
-
-static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- unsigned int unaligned_len = alignmask + 1 -
- ((unsigned long)data & alignmask);
- u8 ubuf[shash_align_buffer_size(unaligned_len, alignmask)]
- __attribute__ ((aligned));
- u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
- int err;
-
- if (unaligned_len > len)
- unaligned_len = len;
-
- memcpy(buf, data, unaligned_len);
- err = shash->update(desc, buf, unaligned_len);
- memset(buf, 0, unaligned_len);
-
- return err ?:
- shash->update(desc, data + unaligned_len, len - unaligned_len);
-}
-
-int crypto_shash_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
-
- if ((unsigned long)data & alignmask)
- return shash_update_unaligned(desc, data, len);
-
- return shash->update(desc, data, len);
-}
-
-static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- unsigned long alignmask = crypto_shash_alignmask(tfm);
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned int ds = crypto_shash_digestsize(tfm);
- u8 ubuf[shash_align_buffer_size(ds, alignmask)]
- __attribute__ ((aligned));
- u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
- int err;
-
- err = shash->final(desc, buf);
- if (err)
- goto out;
-
- memcpy(out, buf, ds);
-
-out:
- memset(buf, 0, ds);
- return err;
-}
-
-int crypto_shash_final(struct shash_desc *desc, u8 *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
-
- if ((unsigned long)out & alignmask)
- return shash_final_unaligned(desc, out);
-
- return shash->final(desc, out);
-}
-
-static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int shash_finup(struct shash_desc *desc, const u8 *data,
+ unsigned len, u8 *out)
{
return crypto_shash_update(desc, data, len) ?:
crypto_shash_final(desc, out);
}
-int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
-
- if (((unsigned long)data | (unsigned long)out) & alignmask)
- return shash_finup_unaligned(desc, data, len, out);
-
- return shash->finup(desc, data, len, out);
-}
-
-static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int shash_digest(struct shash_desc *desc, const u8 *data,
+ unsigned len, u8 *out)
{
return crypto_shash_init(desc) ?:
crypto_shash_finup(desc, data, len, out);
}
-int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
-{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
- unsigned long alignmask = crypto_shash_alignmask(tfm);
-
- if (((unsigned long)data | (unsigned long)out) & alignmask)
- return shash_digest_unaligned(desc, data, len, out);
-
- return shash->digest(desc, data, len, out);
-}
-
-static int shash_default_export(struct shash_desc *desc, void *out)
-{
- memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
- return 0;
-}
-
-static int shash_default_import(struct shash_desc *desc, const void *in)
-{
- memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
- return 0;
-}
-
static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_shash *hash = __crypto_shash_cast(tfm);
@@ -197,98 +41,32 @@ static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
}
static const struct crypto_type crypto_shash_type = {
- .extsize = crypto_alg_extsize,
- .init_tfm = crypto_shash_init_tfm,
- .maskclear = ~CRYPTO_ALG_TYPE_MASK,
- .maskset = CRYPTO_ALG_TYPE_MASK,
- .type = CRYPTO_ALG_TYPE_SHASH,
- .tfmsize = offsetof(struct crypto_shash, base),
+ .extsize = crypto_alg_extsize,
+ .init_tfm = crypto_shash_init_tfm,
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_SHASH,
+ .tfmsize = offsetof(struct crypto_shash, base),
};
-struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
- u32 mask)
+struct crypto_shash *crypto_alloc_shash(const char *alg_name,
+ u32 type, u32 mask)
{
return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
}
-static int shash_prepare_alg(struct shash_alg *alg)
+int crypto_register_shash(struct shash_alg *alg)
{
struct crypto_alg *base = &alg->base;
- if (alg->digestsize > PAGE_SIZE / 8 ||
- alg->descsize > PAGE_SIZE / 8 ||
- alg->statesize > PAGE_SIZE / 8)
- return -EINVAL;
-
base->cra_type = &crypto_shash_type;
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
if (!alg->finup)
- alg->finup = shash_finup_unaligned;
+ alg->finup = shash_finup;
if (!alg->digest)
- alg->digest = shash_digest_unaligned;
- if (!alg->export) {
- alg->export = shash_default_export;
- alg->import = shash_default_import;
- alg->statesize = alg->descsize;
- }
- if (!alg->setkey)
- alg->setkey = shash_no_setkey;
-
- return 0;
-}
-
-int crypto_register_shash(struct shash_alg *alg)
-{
- struct crypto_alg *base = &alg->base;
- int err;
-
- err = shash_prepare_alg(alg);
- if (err)
- return err;
+ alg->digest = shash_digest;
return crypto_register_alg(base);
}
-
-int crypto_unregister_shash(struct shash_alg *alg)
-{
- return crypto_unregister_alg(&alg->base);
-}
-
-int crypto_register_shashes(struct shash_alg *algs, int count)
-{
- int i, ret;
-
- for (i = 0; i < count; i++) {
- ret = crypto_register_shash(&algs[i]);
- if (ret)
- goto err;
- }
-
- return 0;
-
-err:
- for (--i; i >= 0; --i)
- crypto_unregister_shash(&algs[i]);
-
- return ret;
-}
-
-int crypto_unregister_shashes(struct shash_alg *algs, int count)
-{
- int i, ret;
-
- for (i = count - 1; i >= 0; --i) {
- ret = crypto_unregister_shash(&algs[i]);
- if (ret)
- pr_err("Failed to unregister %s %s: %d\n",
- algs[i].base.cra_driver_name,
- algs[i].base.cra_name, ret);
- }
-
- return 0;
-}
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Synchronous cryptographic hash type");