162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Cryptographic API.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * DES & Triple DES EDE Cipher Algorithms.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2005 Dag Arne Osvik <da@osvik.no>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <asm/byteorder.h>
1162306a36Sopenharmony_ci#include <crypto/algapi.h>
1262306a36Sopenharmony_ci#include <linux/bitops.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/errno.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <crypto/internal/des.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic int des_setkey(struct crypto_tfm *tfm, const u8 *key,
2062306a36Sopenharmony_ci		      unsigned int keylen)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	struct des_ctx *dctx = crypto_tfm_ctx(tfm);
2362306a36Sopenharmony_ci	int err;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	err = des_expand_key(dctx, key, keylen);
2662306a36Sopenharmony_ci	if (err == -ENOKEY) {
2762306a36Sopenharmony_ci		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
2862306a36Sopenharmony_ci			err = -EINVAL;
2962306a36Sopenharmony_ci		else
3062306a36Sopenharmony_ci			err = 0;
3162306a36Sopenharmony_ci	}
3262306a36Sopenharmony_ci	if (err)
3362306a36Sopenharmony_ci		memset(dctx, 0, sizeof(*dctx));
3462306a36Sopenharmony_ci	return err;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic void crypto_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	const struct des_ctx *dctx = crypto_tfm_ctx(tfm);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	des_encrypt(dctx, dst, src);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic void crypto_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	const struct des_ctx *dctx = crypto_tfm_ctx(tfm);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	des_decrypt(dctx, dst, src);
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
5262306a36Sopenharmony_ci			   unsigned int keylen)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
5562306a36Sopenharmony_ci	int err;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	err = des3_ede_expand_key(dctx, key, keylen);
5862306a36Sopenharmony_ci	if (err == -ENOKEY) {
5962306a36Sopenharmony_ci		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
6062306a36Sopenharmony_ci			err = -EINVAL;
6162306a36Sopenharmony_ci		else
6262306a36Sopenharmony_ci			err = 0;
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci	if (err)
6562306a36Sopenharmony_ci		memset(dctx, 0, sizeof(*dctx));
6662306a36Sopenharmony_ci	return err;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic void crypto_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst,
7062306a36Sopenharmony_ci				    const u8 *src)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	des3_ede_encrypt(dctx, dst, src);
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic void crypto_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst,
7862306a36Sopenharmony_ci				    const u8 *src)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	des3_ede_decrypt(dctx, dst, src);
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic struct crypto_alg des_algs[2] = { {
8662306a36Sopenharmony_ci	.cra_name		=	"des",
8762306a36Sopenharmony_ci	.cra_driver_name	=	"des-generic",
8862306a36Sopenharmony_ci	.cra_priority		=	100,
8962306a36Sopenharmony_ci	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
9062306a36Sopenharmony_ci	.cra_blocksize		=	DES_BLOCK_SIZE,
9162306a36Sopenharmony_ci	.cra_ctxsize		=	sizeof(struct des_ctx),
9262306a36Sopenharmony_ci	.cra_module		=	THIS_MODULE,
9362306a36Sopenharmony_ci	.cra_u			=	{ .cipher = {
9462306a36Sopenharmony_ci	.cia_min_keysize	=	DES_KEY_SIZE,
9562306a36Sopenharmony_ci	.cia_max_keysize	=	DES_KEY_SIZE,
9662306a36Sopenharmony_ci	.cia_setkey		=	des_setkey,
9762306a36Sopenharmony_ci	.cia_encrypt		=	crypto_des_encrypt,
9862306a36Sopenharmony_ci	.cia_decrypt		=	crypto_des_decrypt } }
9962306a36Sopenharmony_ci}, {
10062306a36Sopenharmony_ci	.cra_name		=	"des3_ede",
10162306a36Sopenharmony_ci	.cra_driver_name	=	"des3_ede-generic",
10262306a36Sopenharmony_ci	.cra_priority		=	100,
10362306a36Sopenharmony_ci	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
10462306a36Sopenharmony_ci	.cra_blocksize		=	DES3_EDE_BLOCK_SIZE,
10562306a36Sopenharmony_ci	.cra_ctxsize		=	sizeof(struct des3_ede_ctx),
10662306a36Sopenharmony_ci	.cra_module		=	THIS_MODULE,
10762306a36Sopenharmony_ci	.cra_u			=	{ .cipher = {
10862306a36Sopenharmony_ci	.cia_min_keysize	=	DES3_EDE_KEY_SIZE,
10962306a36Sopenharmony_ci	.cia_max_keysize	=	DES3_EDE_KEY_SIZE,
11062306a36Sopenharmony_ci	.cia_setkey		=	des3_ede_setkey,
11162306a36Sopenharmony_ci	.cia_encrypt		=	crypto_des3_ede_encrypt,
11262306a36Sopenharmony_ci	.cia_decrypt		=	crypto_des3_ede_decrypt } }
11362306a36Sopenharmony_ci} };
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int __init des_generic_mod_init(void)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	return crypto_register_algs(des_algs, ARRAY_SIZE(des_algs));
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic void __exit des_generic_mod_fini(void)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	crypto_unregister_algs(des_algs, ARRAY_SIZE(des_algs));
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cisubsys_initcall(des_generic_mod_init);
12662306a36Sopenharmony_cimodule_exit(des_generic_mod_fini);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
12962306a36Sopenharmony_ciMODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
13062306a36Sopenharmony_ciMODULE_AUTHOR("Dag Arne Osvik <da@osvik.no>");
13162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des");
13262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des-generic");
13362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede");
13462306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede-generic");
135