18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Cryptographic API.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * DES & Triple DES EDE Cipher Algorithms.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2005 Dag Arne Osvik <da@osvik.no>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
118c2ecf20Sopenharmony_ci#include <linux/bitops.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/errno.h>
158c2ecf20Sopenharmony_ci#include <linux/crypto.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <crypto/internal/des.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic int des_setkey(struct crypto_tfm *tfm, const u8 *key,
208c2ecf20Sopenharmony_ci		      unsigned int keylen)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	struct des_ctx *dctx = crypto_tfm_ctx(tfm);
238c2ecf20Sopenharmony_ci	int err;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	err = des_expand_key(dctx, key, keylen);
268c2ecf20Sopenharmony_ci	if (err == -ENOKEY) {
278c2ecf20Sopenharmony_ci		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
288c2ecf20Sopenharmony_ci			err = -EINVAL;
298c2ecf20Sopenharmony_ci		else
308c2ecf20Sopenharmony_ci			err = 0;
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci	if (err)
338c2ecf20Sopenharmony_ci		memset(dctx, 0, sizeof(*dctx));
348c2ecf20Sopenharmony_ci	return err;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic void crypto_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	const struct des_ctx *dctx = crypto_tfm_ctx(tfm);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	des_encrypt(dctx, dst, src);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic void crypto_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	const struct des_ctx *dctx = crypto_tfm_ctx(tfm);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	des_decrypt(dctx, dst, src);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
528c2ecf20Sopenharmony_ci			   unsigned int keylen)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
558c2ecf20Sopenharmony_ci	int err;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	err = des3_ede_expand_key(dctx, key, keylen);
588c2ecf20Sopenharmony_ci	if (err == -ENOKEY) {
598c2ecf20Sopenharmony_ci		if (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)
608c2ecf20Sopenharmony_ci			err = -EINVAL;
618c2ecf20Sopenharmony_ci		else
628c2ecf20Sopenharmony_ci			err = 0;
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci	if (err)
658c2ecf20Sopenharmony_ci		memset(dctx, 0, sizeof(*dctx));
668c2ecf20Sopenharmony_ci	return err;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic void crypto_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst,
708c2ecf20Sopenharmony_ci				    const u8 *src)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	des3_ede_encrypt(dctx, dst, src);
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic void crypto_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst,
788c2ecf20Sopenharmony_ci				    const u8 *src)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	const struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	des3_ede_decrypt(dctx, dst, src);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic struct crypto_alg des_algs[2] = { {
868c2ecf20Sopenharmony_ci	.cra_name		=	"des",
878c2ecf20Sopenharmony_ci	.cra_driver_name	=	"des-generic",
888c2ecf20Sopenharmony_ci	.cra_priority		=	100,
898c2ecf20Sopenharmony_ci	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
908c2ecf20Sopenharmony_ci	.cra_blocksize		=	DES_BLOCK_SIZE,
918c2ecf20Sopenharmony_ci	.cra_ctxsize		=	sizeof(struct des_ctx),
928c2ecf20Sopenharmony_ci	.cra_module		=	THIS_MODULE,
938c2ecf20Sopenharmony_ci	.cra_u			=	{ .cipher = {
948c2ecf20Sopenharmony_ci	.cia_min_keysize	=	DES_KEY_SIZE,
958c2ecf20Sopenharmony_ci	.cia_max_keysize	=	DES_KEY_SIZE,
968c2ecf20Sopenharmony_ci	.cia_setkey		=	des_setkey,
978c2ecf20Sopenharmony_ci	.cia_encrypt		=	crypto_des_encrypt,
988c2ecf20Sopenharmony_ci	.cia_decrypt		=	crypto_des_decrypt } }
998c2ecf20Sopenharmony_ci}, {
1008c2ecf20Sopenharmony_ci	.cra_name		=	"des3_ede",
1018c2ecf20Sopenharmony_ci	.cra_driver_name	=	"des3_ede-generic",
1028c2ecf20Sopenharmony_ci	.cra_priority		=	100,
1038c2ecf20Sopenharmony_ci	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
1048c2ecf20Sopenharmony_ci	.cra_blocksize		=	DES3_EDE_BLOCK_SIZE,
1058c2ecf20Sopenharmony_ci	.cra_ctxsize		=	sizeof(struct des3_ede_ctx),
1068c2ecf20Sopenharmony_ci	.cra_module		=	THIS_MODULE,
1078c2ecf20Sopenharmony_ci	.cra_u			=	{ .cipher = {
1088c2ecf20Sopenharmony_ci	.cia_min_keysize	=	DES3_EDE_KEY_SIZE,
1098c2ecf20Sopenharmony_ci	.cia_max_keysize	=	DES3_EDE_KEY_SIZE,
1108c2ecf20Sopenharmony_ci	.cia_setkey		=	des3_ede_setkey,
1118c2ecf20Sopenharmony_ci	.cia_encrypt		=	crypto_des3_ede_encrypt,
1128c2ecf20Sopenharmony_ci	.cia_decrypt		=	crypto_des3_ede_decrypt } }
1138c2ecf20Sopenharmony_ci} };
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic int __init des_generic_mod_init(void)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	return crypto_register_algs(des_algs, ARRAY_SIZE(des_algs));
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic void __exit des_generic_mod_fini(void)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	crypto_unregister_algs(des_algs, ARRAY_SIZE(des_algs));
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cisubsys_initcall(des_generic_mod_init);
1268c2ecf20Sopenharmony_cimodule_exit(des_generic_mod_fini);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1298c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
1308c2ecf20Sopenharmony_ciMODULE_AUTHOR("Dag Arne Osvik <da@osvik.no>");
1318c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des");
1328c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des-generic");
1338c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede");
1348c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede-generic");
135