This reverts commit 1b5dd7104e
.
Bug: 116008047
Change-Id: If9192b30cdb4212fb6c8111d70c532a109695fbd
Signed-off-by: Alistair Strachan <astrachan@google.com>
tirimbino
parent
fef6a1c04a
commit
a3ac63b188
@ -1,299 +0,0 @@ |
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Speck: a lightweight block cipher |
||||
* |
||||
* Copyright (c) 2018 Google, Inc |
||||
* |
||||
* Speck has 10 variants, including 5 block sizes. For now we only implement |
||||
* the variants Speck128/128, Speck128/192, Speck128/256, Speck64/96, and |
||||
* Speck64/128. Speck${B}/${K} denotes the variant with a block size of B bits |
||||
* and a key size of K bits. The Speck128 variants are believed to be the most |
||||
* secure variants, and they use the same block size and key sizes as AES. The |
||||
* Speck64 variants are less secure, but on 32-bit processors are usually |
||||
* faster. The remaining variants (Speck32, Speck48, and Speck96) are even less |
||||
* secure and/or not as well suited for implementation on either 32-bit or |
||||
* 64-bit processors, so are omitted. |
||||
* |
||||
* Reference: "The Simon and Speck Families of Lightweight Block Ciphers" |
||||
* https://eprint.iacr.org/2013/404.pdf
|
||||
* |
||||
* In a correspondence, the Speck designers have also clarified that the words |
||||
* should be interpreted in little-endian format, and the words should be |
||||
* ordered such that the first word of each block is 'y' rather than 'x', and |
||||
* the first key word (rather than the last) becomes the first round key. |
||||
*/ |
||||
|
||||
#include <asm/unaligned.h> |
||||
#include <linux/bitops.h> |
||||
#include <linux/crypto.h> |
||||
#include <linux/init.h> |
||||
#include <linux/module.h> |
||||
|
||||
/* Speck128 */ |
||||
|
||||
#define SPECK128_BLOCK_SIZE 16 |
||||
|
||||
#define SPECK128_128_KEY_SIZE 16 |
||||
#define SPECK128_128_NROUNDS 32 |
||||
|
||||
#define SPECK128_192_KEY_SIZE 24 |
||||
#define SPECK128_192_NROUNDS 33 |
||||
|
||||
#define SPECK128_256_KEY_SIZE 32 |
||||
#define SPECK128_256_NROUNDS 34 |
||||
|
||||
struct speck128_tfm_ctx { |
||||
u64 round_keys[SPECK128_256_NROUNDS]; |
||||
int nrounds; |
||||
}; |
||||
|
||||
static __always_inline void speck128_round(u64 *x, u64 *y, u64 k) |
||||
{ |
||||
*x = ror64(*x, 8); |
||||
*x += *y; |
||||
*x ^= k; |
||||
*y = rol64(*y, 3); |
||||
*y ^= *x; |
||||
} |
||||
|
||||
static __always_inline void speck128_unround(u64 *x, u64 *y, u64 k) |
||||
{ |
||||
*y ^= *x; |
||||
*y = ror64(*y, 3); |
||||
*x ^= k; |
||||
*x -= *y; |
||||
*x = rol64(*x, 8); |
||||
} |
||||
|
||||
static void speck128_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
||||
{ |
||||
const struct speck128_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u64 y = get_unaligned_le64(in); |
||||
u64 x = get_unaligned_le64(in + 8); |
||||
int i; |
||||
|
||||
for (i = 0; i < ctx->nrounds; i++) |
||||
speck128_round(&x, &y, ctx->round_keys[i]); |
||||
|
||||
put_unaligned_le64(y, out); |
||||
put_unaligned_le64(x, out + 8); |
||||
} |
||||
|
||||
static void speck128_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
||||
{ |
||||
const struct speck128_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u64 y = get_unaligned_le64(in); |
||||
u64 x = get_unaligned_le64(in + 8); |
||||
int i; |
||||
|
||||
for (i = ctx->nrounds - 1; i >= 0; i--) |
||||
speck128_unround(&x, &y, ctx->round_keys[i]); |
||||
|
||||
put_unaligned_le64(y, out); |
||||
put_unaligned_le64(x, out + 8); |
||||
} |
||||
|
||||
static int speck128_setkey(struct crypto_tfm *tfm, const u8 *key, |
||||
unsigned int keylen) |
||||
{ |
||||
struct speck128_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u64 l[3]; |
||||
u64 k; |
||||
int i; |
||||
|
||||
switch (keylen) { |
||||
case SPECK128_128_KEY_SIZE: |
||||
k = get_unaligned_le64(key); |
||||
l[0] = get_unaligned_le64(key + 8); |
||||
ctx->nrounds = SPECK128_128_NROUNDS; |
||||
for (i = 0; i < ctx->nrounds; i++) { |
||||
ctx->round_keys[i] = k; |
||||
speck128_round(&l[0], &k, i); |
||||
} |
||||
break; |
||||
case SPECK128_192_KEY_SIZE: |
||||
k = get_unaligned_le64(key); |
||||
l[0] = get_unaligned_le64(key + 8); |
||||
l[1] = get_unaligned_le64(key + 16); |
||||
ctx->nrounds = SPECK128_192_NROUNDS; |
||||
for (i = 0; i < ctx->nrounds; i++) { |
||||
ctx->round_keys[i] = k; |
||||
speck128_round(&l[i % 2], &k, i); |
||||
} |
||||
break; |
||||
case SPECK128_256_KEY_SIZE: |
||||
k = get_unaligned_le64(key); |
||||
l[0] = get_unaligned_le64(key + 8); |
||||
l[1] = get_unaligned_le64(key + 16); |
||||
l[2] = get_unaligned_le64(key + 24); |
||||
ctx->nrounds = SPECK128_256_NROUNDS; |
||||
for (i = 0; i < ctx->nrounds; i++) { |
||||
ctx->round_keys[i] = k; |
||||
speck128_round(&l[i % 3], &k, i); |
||||
} |
||||
break; |
||||
default: |
||||
return -EINVAL; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* Speck64 */ |
||||
|
||||
#define SPECK64_BLOCK_SIZE 8 |
||||
|
||||
#define SPECK64_96_KEY_SIZE 12 |
||||
#define SPECK64_96_NROUNDS 26 |
||||
|
||||
#define SPECK64_128_KEY_SIZE 16 |
||||
#define SPECK64_128_NROUNDS 27 |
||||
|
||||
struct speck64_tfm_ctx { |
||||
u32 round_keys[SPECK64_128_NROUNDS]; |
||||
int nrounds; |
||||
}; |
||||
|
||||
static __always_inline void speck64_round(u32 *x, u32 *y, u32 k) |
||||
{ |
||||
*x = ror32(*x, 8); |
||||
*x += *y; |
||||
*x ^= k; |
||||
*y = rol32(*y, 3); |
||||
*y ^= *x; |
||||
} |
||||
|
||||
static __always_inline void speck64_unround(u32 *x, u32 *y, u32 k) |
||||
{ |
||||
*y ^= *x; |
||||
*y = ror32(*y, 3); |
||||
*x ^= k; |
||||
*x -= *y; |
||||
*x = rol32(*x, 8); |
||||
} |
||||
|
||||
static void speck64_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
||||
{ |
||||
const struct speck64_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u32 y = get_unaligned_le32(in); |
||||
u32 x = get_unaligned_le32(in + 4); |
||||
int i; |
||||
|
||||
for (i = 0; i < ctx->nrounds; i++) |
||||
speck64_round(&x, &y, ctx->round_keys[i]); |
||||
|
||||
put_unaligned_le32(y, out); |
||||
put_unaligned_le32(x, out + 4); |
||||
} |
||||
|
||||
static void speck64_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) |
||||
{ |
||||
const struct speck64_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u32 y = get_unaligned_le32(in); |
||||
u32 x = get_unaligned_le32(in + 4); |
||||
int i; |
||||
|
||||
for (i = ctx->nrounds - 1; i >= 0; i--) |
||||
speck64_unround(&x, &y, ctx->round_keys[i]); |
||||
|
||||
put_unaligned_le32(y, out); |
||||
put_unaligned_le32(x, out + 4); |
||||
} |
||||
|
||||
static int speck64_setkey(struct crypto_tfm *tfm, const u8 *key, |
||||
unsigned int keylen) |
||||
{ |
||||
struct speck64_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
||||
u32 l[3]; |
||||
u32 k; |
||||
int i; |
||||
|
||||
switch (keylen) { |
||||
case SPECK64_96_KEY_SIZE: |
||||
k = get_unaligned_le32(key); |
||||
l[0] = get_unaligned_le32(key + 4); |
||||
l[1] = get_unaligned_le32(key + 8); |
||||
ctx->nrounds = SPECK64_96_NROUNDS; |
||||
for (i = 0; i < ctx->nrounds; i++) { |
||||
ctx->round_keys[i] = k; |
||||
speck64_round(&l[i % 2], &k, i); |
||||
} |
||||
break; |
||||
case SPECK64_128_KEY_SIZE: |
||||
k = get_unaligned_le32(key); |
||||
l[0] = get_unaligned_le32(key + 4); |
||||
l[1] = get_unaligned_le32(key + 8); |
||||
l[2] = get_unaligned_le32(key + 12); |
||||
ctx->nrounds = SPECK64_128_NROUNDS; |
||||
for (i = 0; i < ctx->nrounds; i++) { |
||||
ctx->round_keys[i] = k; |
||||
speck64_round(&l[i % 3], &k, i); |
||||
} |
||||
break; |
||||
default: |
||||
return -EINVAL; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* Algorithm definitions */ |
||||
|
||||
static struct crypto_alg speck_algs[] = { |
||||
{ |
||||
.cra_name = "speck128", |
||||
.cra_driver_name = "speck128-generic", |
||||
.cra_priority = 100, |
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
||||
.cra_blocksize = SPECK128_BLOCK_SIZE, |
||||
.cra_ctxsize = sizeof(struct speck128_tfm_ctx), |
||||
.cra_module = THIS_MODULE, |
||||
.cra_u = { |
||||
.cipher = { |
||||
.cia_min_keysize = SPECK128_128_KEY_SIZE, |
||||
.cia_max_keysize = SPECK128_256_KEY_SIZE, |
||||
.cia_setkey = speck128_setkey, |
||||
.cia_encrypt = speck128_encrypt, |
||||
.cia_decrypt = speck128_decrypt |
||||
} |
||||
} |
||||
}, { |
||||
.cra_name = "speck64", |
||||
.cra_driver_name = "speck64-generic", |
||||
.cra_priority = 100, |
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
||||
.cra_blocksize = SPECK64_BLOCK_SIZE, |
||||
.cra_ctxsize = sizeof(struct speck64_tfm_ctx), |
||||
.cra_module = THIS_MODULE, |
||||
.cra_u = { |
||||
.cipher = { |
||||
.cia_min_keysize = SPECK64_96_KEY_SIZE, |
||||
.cia_max_keysize = SPECK64_128_KEY_SIZE, |
||||
.cia_setkey = speck64_setkey, |
||||
.cia_encrypt = speck64_encrypt, |
||||
.cia_decrypt = speck64_decrypt |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
static int __init speck_module_init(void) |
||||
{ |
||||
return crypto_register_algs(speck_algs, ARRAY_SIZE(speck_algs)); |
||||
} |
||||
|
||||
static void __exit speck_module_exit(void) |
||||
{ |
||||
crypto_unregister_algs(speck_algs, ARRAY_SIZE(speck_algs)); |
||||
} |
||||
|
||||
module_init(speck_module_init); |
||||
module_exit(speck_module_exit); |
||||
|
||||
MODULE_DESCRIPTION("Speck block cipher (generic)"); |
||||
MODULE_LICENSE("GPL"); |
||||
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>"); |
||||
MODULE_ALIAS_CRYPTO("speck128"); |
||||
MODULE_ALIAS_CRYPTO("speck128-generic"); |
||||
MODULE_ALIAS_CRYPTO("speck64"); |
||||
MODULE_ALIAS_CRYPTO("speck64-generic"); |
Loading…
Reference in new issue