xref: /linux/arch/powerpc/crypto/md5-glue.c (revision 2aaba014)
1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
23265c4baSKim Phillips /*
33265c4baSKim Phillips  * Glue code for MD5 implementation for PPC assembler
43265c4baSKim Phillips  *
53265c4baSKim Phillips  * Based on generic implementation.
63265c4baSKim Phillips  *
73265c4baSKim Phillips  * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
83265c4baSKim Phillips  */
93265c4baSKim Phillips 
103265c4baSKim Phillips #include <crypto/internal/hash.h>
113265c4baSKim Phillips #include <linux/init.h>
123265c4baSKim Phillips #include <linux/module.h>
133265c4baSKim Phillips #include <linux/mm.h>
143265c4baSKim Phillips #include <linux/types.h>
153265c4baSKim Phillips #include <crypto/md5.h>
163265c4baSKim Phillips #include <asm/byteorder.h>
173265c4baSKim Phillips 
183265c4baSKim Phillips extern void ppc_md5_transform(u32 *state, const u8 *src, u32 blocks);
193265c4baSKim Phillips 
ppc_md5_clear_context(struct md5_state * sctx)203265c4baSKim Phillips static inline void ppc_md5_clear_context(struct md5_state *sctx)
213265c4baSKim Phillips {
223265c4baSKim Phillips 	int count = sizeof(struct md5_state) >> 2;
233265c4baSKim Phillips 	u32 *ptr = (u32 *)sctx;
243265c4baSKim Phillips 
253265c4baSKim Phillips 	/* make sure we can clear the fast way */
263265c4baSKim Phillips 	BUILD_BUG_ON(sizeof(struct md5_state) % 4);
273265c4baSKim Phillips 	do { *ptr++ = 0; } while (--count);
283265c4baSKim Phillips }
293265c4baSKim Phillips 
ppc_md5_init(struct shash_desc * desc)303265c4baSKim Phillips static int ppc_md5_init(struct shash_desc *desc)
313265c4baSKim Phillips {
323265c4baSKim Phillips 	struct md5_state *sctx = shash_desc_ctx(desc);
333265c4baSKim Phillips 
34a4015213SLABBE Corentin 	sctx->hash[0] = MD5_H0;
35a4015213SLABBE Corentin 	sctx->hash[1] = MD5_H1;
36a4015213SLABBE Corentin 	sctx->hash[2] = MD5_H2;
37a4015213SLABBE Corentin 	sctx->hash[3] =	MD5_H3;
383265c4baSKim Phillips 	sctx->byte_count = 0;
393265c4baSKim Phillips 
403265c4baSKim Phillips 	return 0;
413265c4baSKim Phillips }
423265c4baSKim Phillips 
ppc_md5_update(struct shash_desc * desc,const u8 * data,unsigned int len)433265c4baSKim Phillips static int ppc_md5_update(struct shash_desc *desc, const u8 *data,
443265c4baSKim Phillips 			unsigned int len)
453265c4baSKim Phillips {
463265c4baSKim Phillips 	struct md5_state *sctx = shash_desc_ctx(desc);
473265c4baSKim Phillips 	const unsigned int offset = sctx->byte_count & 0x3f;
483265c4baSKim Phillips 	unsigned int avail = 64 - offset;
493265c4baSKim Phillips 	const u8 *src = data;
503265c4baSKim Phillips 
513265c4baSKim Phillips 	sctx->byte_count += len;
523265c4baSKim Phillips 
533265c4baSKim Phillips 	if (avail > len) {
543265c4baSKim Phillips 		memcpy((char *)sctx->block + offset, src, len);
553265c4baSKim Phillips 		return 0;
563265c4baSKim Phillips 	}
573265c4baSKim Phillips 
583265c4baSKim Phillips 	if (offset) {
593265c4baSKim Phillips 		memcpy((char *)sctx->block + offset, src, avail);
603265c4baSKim Phillips 		ppc_md5_transform(sctx->hash, (const u8 *)sctx->block, 1);
613265c4baSKim Phillips 		len -= avail;
623265c4baSKim Phillips 		src += avail;
633265c4baSKim Phillips 	}
643265c4baSKim Phillips 
653265c4baSKim Phillips 	if (len > 63) {
663265c4baSKim Phillips 		ppc_md5_transform(sctx->hash, src, len >> 6);
673265c4baSKim Phillips 		src += len & ~0x3f;
683265c4baSKim Phillips 		len &= 0x3f;
693265c4baSKim Phillips 	}
703265c4baSKim Phillips 
713265c4baSKim Phillips 	memcpy((char *)sctx->block, src, len);
723265c4baSKim Phillips 	return 0;
733265c4baSKim Phillips }
743265c4baSKim Phillips 
ppc_md5_final(struct shash_desc * desc,u8 * out)753265c4baSKim Phillips static int ppc_md5_final(struct shash_desc *desc, u8 *out)
763265c4baSKim Phillips {
773265c4baSKim Phillips 	struct md5_state *sctx = shash_desc_ctx(desc);
783265c4baSKim Phillips 	const unsigned int offset = sctx->byte_count & 0x3f;
793265c4baSKim Phillips 	const u8 *src = (const u8 *)sctx->block;
803265c4baSKim Phillips 	u8 *p = (u8 *)src + offset;
813265c4baSKim Phillips 	int padlen = 55 - offset;
823265c4baSKim Phillips 	__le64 *pbits = (__le64 *)((char *)sctx->block + 56);
833265c4baSKim Phillips 	__le32 *dst = (__le32 *)out;
843265c4baSKim Phillips 
853265c4baSKim Phillips 	*p++ = 0x80;
863265c4baSKim Phillips 
873265c4baSKim Phillips 	if (padlen < 0) {
883265c4baSKim Phillips 		memset(p, 0x00, padlen + sizeof (u64));
893265c4baSKim Phillips 		ppc_md5_transform(sctx->hash, src, 1);
903265c4baSKim Phillips 		p = (char *)sctx->block;
913265c4baSKim Phillips 		padlen = 56;
923265c4baSKim Phillips 	}
933265c4baSKim Phillips 
943265c4baSKim Phillips 	memset(p, 0, padlen);
953265c4baSKim Phillips 	*pbits = cpu_to_le64(sctx->byte_count << 3);
963265c4baSKim Phillips 	ppc_md5_transform(sctx->hash, src, 1);
973265c4baSKim Phillips 
983265c4baSKim Phillips 	dst[0] = cpu_to_le32(sctx->hash[0]);
993265c4baSKim Phillips 	dst[1] = cpu_to_le32(sctx->hash[1]);
1003265c4baSKim Phillips 	dst[2] = cpu_to_le32(sctx->hash[2]);
1013265c4baSKim Phillips 	dst[3] = cpu_to_le32(sctx->hash[3]);
1023265c4baSKim Phillips 
1033265c4baSKim Phillips 	ppc_md5_clear_context(sctx);
1043265c4baSKim Phillips 	return 0;
1053265c4baSKim Phillips }
1063265c4baSKim Phillips 
ppc_md5_export(struct shash_desc * desc,void * out)1073265c4baSKim Phillips static int ppc_md5_export(struct shash_desc *desc, void *out)
1083265c4baSKim Phillips {
1093265c4baSKim Phillips 	struct md5_state *sctx = shash_desc_ctx(desc);
1103265c4baSKim Phillips 
1113265c4baSKim Phillips 	memcpy(out, sctx, sizeof(*sctx));
1123265c4baSKim Phillips 	return 0;
1133265c4baSKim Phillips }
1143265c4baSKim Phillips 
ppc_md5_import(struct shash_desc * desc,const void * in)1153265c4baSKim Phillips static int ppc_md5_import(struct shash_desc *desc, const void *in)
1163265c4baSKim Phillips {
1173265c4baSKim Phillips 	struct md5_state *sctx = shash_desc_ctx(desc);
1183265c4baSKim Phillips 
1193265c4baSKim Phillips 	memcpy(sctx, in, sizeof(*sctx));
1203265c4baSKim Phillips 	return 0;
1213265c4baSKim Phillips }
1223265c4baSKim Phillips 
1233265c4baSKim Phillips static struct shash_alg alg = {
1243265c4baSKim Phillips 	.digestsize	=	MD5_DIGEST_SIZE,
1253265c4baSKim Phillips 	.init		=	ppc_md5_init,
1263265c4baSKim Phillips 	.update		=	ppc_md5_update,
1273265c4baSKim Phillips 	.final		=	ppc_md5_final,
1283265c4baSKim Phillips 	.export		=	ppc_md5_export,
1293265c4baSKim Phillips 	.import		=	ppc_md5_import,
1303265c4baSKim Phillips 	.descsize	=	sizeof(struct md5_state),
1313265c4baSKim Phillips 	.statesize	=	sizeof(struct md5_state),
1323265c4baSKim Phillips 	.base		=	{
1333265c4baSKim Phillips 		.cra_name	=	"md5",
1343265c4baSKim Phillips 		.cra_driver_name=	"md5-ppc",
1353265c4baSKim Phillips 		.cra_priority	=	200,
1363265c4baSKim Phillips 		.cra_blocksize	=	MD5_HMAC_BLOCK_SIZE,
1373265c4baSKim Phillips 		.cra_module	=	THIS_MODULE,
1383265c4baSKim Phillips 	}
1393265c4baSKim Phillips };
1403265c4baSKim Phillips 
ppc_md5_mod_init(void)1413265c4baSKim Phillips static int __init ppc_md5_mod_init(void)
1423265c4baSKim Phillips {
1433265c4baSKim Phillips 	return crypto_register_shash(&alg);
1443265c4baSKim Phillips }
1453265c4baSKim Phillips 
ppc_md5_mod_fini(void)1463265c4baSKim Phillips static void __exit ppc_md5_mod_fini(void)
1473265c4baSKim Phillips {
1483265c4baSKim Phillips 	crypto_unregister_shash(&alg);
1493265c4baSKim Phillips }
1503265c4baSKim Phillips 
1513265c4baSKim Phillips module_init(ppc_md5_mod_init);
1523265c4baSKim Phillips module_exit(ppc_md5_mod_fini);
1533265c4baSKim Phillips 
1543265c4baSKim Phillips MODULE_LICENSE("GPL");
1553265c4baSKim Phillips MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, PPC assembler");
1563265c4baSKim Phillips 
1573265c4baSKim Phillips MODULE_ALIAS_CRYPTO("md5");
1583265c4baSKim Phillips MODULE_ALIAS_CRYPTO("md5-ppc");
159