⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 padlock-sha.c

📁 linux 内核源代码
💻 C
字号:
/* * Cryptographic API. * * Support for VIA PadLock hardware crypto engine. * * Copyright (c) 2006  Michal Ludvig <michal@logix.cz> * * 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 <crypto/algapi.h>#include <crypto/sha.h>#include <linux/err.h>#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/cryptohash.h>#include <linux/interrupt.h>#include <linux/kernel.h>#include <linux/scatterlist.h>#include "padlock.h"#define SHA1_DEFAULT_FALLBACK	"sha1-generic"#define SHA256_DEFAULT_FALLBACK "sha256-generic"struct padlock_sha_ctx {	char		*data;	size_t		used;	int		bypass;	void (*f_sha_padlock)(const char *in, char *out, int count);	struct hash_desc fallback;};static inline struct padlock_sha_ctx *ctx(struct crypto_tfm *tfm){	return crypto_tfm_ctx(tfm);}/* We'll need aligned address on the stack */#define NEAREST_ALIGNED(ptr) \	((void *)ALIGN((size_t)(ptr), PADLOCK_ALIGNMENT))static struct crypto_alg sha1_alg, sha256_alg;static void padlock_sha_bypass(struct crypto_tfm *tfm){	if (ctx(tfm)->bypass)		return;	crypto_hash_init(&ctx(tfm)->fallback);	if (ctx(tfm)->data && ctx(tfm)->used) {		struct scatterlist sg;		sg_init_one(&sg, ctx(tfm)->data, ctx(tfm)->used);		crypto_hash_update(&ctx(tfm)->fallback, &sg, sg.length);	}	ctx(tfm)->used = 0;	ctx(tfm)->bypass = 1;}static void padlock_sha_init(struct crypto_tfm *tfm){	ctx(tfm)->used = 0;	ctx(tfm)->bypass = 0;}static void padlock_sha_update(struct crypto_tfm *tfm,			const uint8_t *data, unsigned int length){	/* Our buffer is always one page. */	if (unlikely(!ctx(tfm)->bypass &&		     (ctx(tfm)->used + length > PAGE_SIZE)))		padlock_sha_bypass(tfm);	if (unlikely(ctx(tfm)->bypass)) {		struct scatterlist sg;		sg_init_one(&sg, (uint8_t *)data, length);		crypto_hash_update(&ctx(tfm)->fallback, &sg, length);		return;	}	memcpy(ctx(tfm)->data + ctx(tfm)->used, data, length);	ctx(tfm)->used += length;}static inline void padlock_output_block(uint32_t *src,		 	uint32_t *dst, size_t count){	while (count--)		*dst++ = swab32(*src++);}static void padlock_do_sha1(const char *in, char *out, int count){	/* We can't store directly to *out as it may be unaligned. */	/* BTW Don't reduce the buffer size below 128 Bytes!	 *     PadLock microcode needs it that big. */	char buf[128+16];	char *result = NEAREST_ALIGNED(buf);	((uint32_t *)result)[0] = SHA1_H0;	((uint32_t *)result)[1] = SHA1_H1;	((uint32_t *)result)[2] = SHA1_H2;	((uint32_t *)result)[3] = SHA1_H3;	((uint32_t *)result)[4] = SHA1_H4; 	asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */		      : "+S"(in), "+D"(result)		      : "c"(count), "a"(0));	padlock_output_block((uint32_t *)result, (uint32_t *)out, 5);}static void padlock_do_sha256(const char *in, char *out, int count){	/* We can't store directly to *out as it may be unaligned. */	/* BTW Don't reduce the buffer size below 128 Bytes!	 *     PadLock microcode needs it that big. */	char buf[128+16];	char *result = NEAREST_ALIGNED(buf);	((uint32_t *)result)[0] = SHA256_H0;	((uint32_t *)result)[1] = SHA256_H1;	((uint32_t *)result)[2] = SHA256_H2;	((uint32_t *)result)[3] = SHA256_H3;	((uint32_t *)result)[4] = SHA256_H4;	((uint32_t *)result)[5] = SHA256_H5;	((uint32_t *)result)[6] = SHA256_H6;	((uint32_t *)result)[7] = SHA256_H7;	asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */		      : "+S"(in), "+D"(result)		      : "c"(count), "a"(0));	padlock_output_block((uint32_t *)result, (uint32_t *)out, 8);}static void padlock_sha_final(struct crypto_tfm *tfm, uint8_t *out){	if (unlikely(ctx(tfm)->bypass)) {		crypto_hash_final(&ctx(tfm)->fallback, out);		ctx(tfm)->bypass = 0;		return;	}	/* Pass the input buffer to PadLock microcode... */	ctx(tfm)->f_sha_padlock(ctx(tfm)->data, out, ctx(tfm)->used);	ctx(tfm)->used = 0;}static int padlock_cra_init(struct crypto_tfm *tfm){	const char *fallback_driver_name = tfm->__crt_alg->cra_name;	struct crypto_hash *fallback_tfm;	/* For now we'll allocate one page. This	 * could eventually be configurable one day. */	ctx(tfm)->data = (char *)__get_free_page(GFP_KERNEL);	if (!ctx(tfm)->data)		return -ENOMEM;	/* Allocate a fallback and abort if it failed. */	fallback_tfm = crypto_alloc_hash(fallback_driver_name, 0,					 CRYPTO_ALG_ASYNC |					 CRYPTO_ALG_NEED_FALLBACK);	if (IS_ERR(fallback_tfm)) {		printk(KERN_WARNING PFX "Fallback driver '%s' could not be loaded!\n",		       fallback_driver_name);		free_page((unsigned long)(ctx(tfm)->data));		return PTR_ERR(fallback_tfm);	}	ctx(tfm)->fallback.tfm = fallback_tfm;	return 0;}static int padlock_sha1_cra_init(struct crypto_tfm *tfm){	ctx(tfm)->f_sha_padlock = padlock_do_sha1;	return padlock_cra_init(tfm);}static int padlock_sha256_cra_init(struct crypto_tfm *tfm){	ctx(tfm)->f_sha_padlock = padlock_do_sha256;	return padlock_cra_init(tfm);}static void padlock_cra_exit(struct crypto_tfm *tfm){	if (ctx(tfm)->data) {		free_page((unsigned long)(ctx(tfm)->data));		ctx(tfm)->data = NULL;	}	crypto_free_hash(ctx(tfm)->fallback.tfm);	ctx(tfm)->fallback.tfm = NULL;}static struct crypto_alg sha1_alg = {	.cra_name		=	"sha1",	.cra_driver_name	=	"sha1-padlock",	.cra_priority		=	PADLOCK_CRA_PRIORITY,	.cra_flags		=	CRYPTO_ALG_TYPE_DIGEST |					CRYPTO_ALG_NEED_FALLBACK,	.cra_blocksize		=	SHA1_BLOCK_SIZE,	.cra_ctxsize		=	sizeof(struct padlock_sha_ctx),	.cra_module		=	THIS_MODULE,	.cra_list		=	LIST_HEAD_INIT(sha1_alg.cra_list),	.cra_init		=	padlock_sha1_cra_init,	.cra_exit		=	padlock_cra_exit,	.cra_u			=	{		.digest = {			.dia_digestsize	=	SHA1_DIGEST_SIZE,			.dia_init   	= 	padlock_sha_init,			.dia_update 	=	padlock_sha_update,			.dia_final  	=	padlock_sha_final,		}	}};static struct crypto_alg sha256_alg = {	.cra_name		=	"sha256",	.cra_driver_name	=	"sha256-padlock",	.cra_priority		=	PADLOCK_CRA_PRIORITY,	.cra_flags		=	CRYPTO_ALG_TYPE_DIGEST |					CRYPTO_ALG_NEED_FALLBACK,	.cra_blocksize		=	SHA256_BLOCK_SIZE,	.cra_ctxsize		=	sizeof(struct padlock_sha_ctx),	.cra_module		=	THIS_MODULE,	.cra_list		=	LIST_HEAD_INIT(sha256_alg.cra_list),	.cra_init		=	padlock_sha256_cra_init,	.cra_exit		=	padlock_cra_exit,	.cra_u			=	{		.digest = {			.dia_digestsize	=	SHA256_DIGEST_SIZE,			.dia_init   	= 	padlock_sha_init,			.dia_update 	=	padlock_sha_update,			.dia_final  	=	padlock_sha_final,		}	}};static int __init padlock_init(void){	int rc = -ENODEV;	if (!cpu_has_phe) {		printk(KERN_ERR PFX "VIA PadLock Hash Engine not detected.\n");		return -ENODEV;	}	if (!cpu_has_phe_enabled) {		printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");		return -ENODEV;	}	rc = crypto_register_alg(&sha1_alg);	if (rc)		goto out;	rc = crypto_register_alg(&sha256_alg);	if (rc)		goto out_unreg1;	printk(KERN_NOTICE PFX "Using VIA PadLock ACE for SHA1/SHA256 algorithms.\n");	return 0;out_unreg1:	crypto_unregister_alg(&sha1_alg);out:	printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n");	return rc;}static void __exit padlock_fini(void){	crypto_unregister_alg(&sha1_alg);	crypto_unregister_alg(&sha256_alg);}module_init(padlock_init);module_exit(padlock_fini);MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support.");MODULE_LICENSE("GPL");MODULE_AUTHOR("Michal Ludvig");MODULE_ALIAS("sha1");MODULE_ALIAS("sha256");MODULE_ALIAS("sha1-padlock");MODULE_ALIAS("sha256-padlock");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -