File: magma_generic.c

package info (click to toggle)
gost-crypto 0.3-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 1,664 kB
  • sloc: ansic: 21,052; makefile: 31
file content (101 lines) | stat: -rw-r--r-- 2,629 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * GOST R 34.12-2015 (Magma) cipher.
 *
 * Copyright (c) 2018 Dmitry Eremin-Solenikov <dbaryshkov@gmail.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/crypto.h>
#include <linux/module.h>
#include <asm/unaligned.h>
#include <crypto/magma.h>
#include <crypto/gost28147.h>

struct crypto_magma_ctx {
	u32 key[MAGMA_KEY_SIZE/4];
};

static int magma_set_key(struct crypto_tfm *tfm, const u8 *in_key,
		unsigned int key_len)
{
	struct crypto_magma_ctx *ctx = crypto_tfm_ctx(tfm);
	u32 *flags = &tfm->crt_flags;
	int i;

	if (key_len != MAGMA_KEY_SIZE) {
		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
		return -EINVAL;
	};

	for (i = 0; i < MAGMA_KEY_SIZE / 4; i++, in_key += 4)
		ctx->key[i] = get_unaligned_be32(in_key);

	return 0;
}

static void magma_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
	const struct crypto_magma_ctx *ctx = crypto_tfm_ctx(tfm);
	const u32 *kp = ctx->key;
	u32 block[2];

	block[0] = get_unaligned_be32(in + 4);
	block[1] = get_unaligned_be32(in);
	crypto_gost28147_encrypt(kp, gost28147_param_TC26_Z.sbox, block, block);
	put_unaligned_be32(block[0], out + 4);
	put_unaligned_be32(block[1], out);
}

static void magma_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
	const struct crypto_magma_ctx *ctx = crypto_tfm_ctx(tfm);
	const u32 *kp = ctx->key;
	u32 block[2];

	block[0] = get_unaligned_be32(in + 4);
	block[1] = get_unaligned_be32(in);
	crypto_gost28147_decrypt(kp, gost28147_param_TC26_Z.sbox, block, block);
	put_unaligned_be32(block[0], out + 4);
	put_unaligned_be32(block[1], out);
}

static struct crypto_alg magma_alg = {
	.cra_name		=	"magma",
	.cra_driver_name	=	"magma-generic",
	.cra_priority		=	100,
	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
	.cra_blocksize		=	MAGMA_BLOCK_SIZE,
	.cra_ctxsize		=	sizeof(struct crypto_magma_ctx),
	.cra_module		=	THIS_MODULE,
	.cra_u			=	{
		.cipher = {
			.cia_min_keysize	= MAGMA_KEY_SIZE,
			.cia_max_keysize	= MAGMA_KEY_SIZE,
			.cia_setkey		= magma_set_key,
			.cia_encrypt		= magma_encrypt,
			.cia_decrypt		= magma_decrypt
		}
	}
};

static int __init magma_init(void)
{
	return crypto_register_alg(&magma_alg);
}

static void __exit magma_fini(void)
{
	crypto_unregister_alg(&magma_alg);
}

module_init(magma_init);
module_exit(magma_fini);

MODULE_DESCRIPTION("GOST R 34.12-2015 (Magma) algorithm");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("magma");
MODULE_ALIAS_CRYPTO("magma-generic");