3.1.5.实验代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static char *str;
static char *out;
module_param(str,charp,0644);
module_param(out,charp,0644);
int md5_hash(const char *str, u32 len,u8 *out)
{
u32 digestsize = 0;
u32 size = 0;
struct shash_desc *smd5;
int err = 0;
struct crypto_shash *md5 = crypto_alloc_shash("md5",0,0);
if(IS_ERR(md5)) {
printk("md5 transform alloc failed!\n");
return -1;
}
size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
smd5 = kmalloc(size,GFP_KERNEL);
if(!smd5) {
err = -1;
goto Kmalloc_err;
}
smd5->tfm = md5;
smd5->flags = 0x0;
err = crypto_shash_init(smd5);
if(err){
err = -1;
goto init_err;
}
len = strlen(str);
printk("plain length is %d\n",len);
crypto_shash_update(smd5,str,len);
err = crypto_shash_final(smd5,out);
printk("md5 result is %d\n",err);
digestsize = crypto_shash_digestsize(md5);
printk("digest size is %d\n",digestsize);
init_err:
kfree(smd5);
Kmalloc_err:
crypto_free_shash(md5);
return err;
}
static int __init md5_init(void)
{
u32 len = strlen(str);
printk("This module just test how to use alg API\n");
if(md5_hash(str,len,out) == -1){
printk("hash alg failed\n");
return -1;
}
printk("md5 alg succeeded\n");
return 0;
}
static void __exit md5_exit(void)
{
printk("Test is over!!!\n");
return ;
}
module_init(md5_init);
module_exit(md5_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alan");
MODULE_DESCRIPTION("Test md5 API");
模块对应的Makefile文件
obj-m +=md51.o
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=源码路径/linux-3.5.4
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
3.2.演示验证结果1
模块的编译操作,见图3-3。
图3-3模块编译
如果编译模块时出现错误提示或警告信息,就要根据提示修改代码。
模块加载操作,见图3-4。
图3-4模块的加载操作
在模块加载时会出现以下几种问题。
1. 插入的模块已经存在,说明之前已经加载过此模块,要卸载之后才能重新加载。
2. 出现参数输入错误。查找模块是否为带参模块,如果是带参模块则加载时传入参数。
3. 没有操作权限。首先操作是否使用了root权限,模块操作要求以root来执行;然后实在找不出来可以查看dmesg信息,里面对错误提示进行了说明。
实验结果见下图3-5。
图3-5实验结果
从结果可以看出第一句属于提示消息,告知用户这个模块实现的功能。plain length is 21为消息序列的大小,单位是字节。实验结果主要从md5 result is 0和digest size is 16得出。现在对结果进行如下解释说明。
要使用一个算法,首先要为这个算法分配算法对象,算法对象里面包含了为算法分配的内核空间等信息。主要通过crypto_alloc_xxx实现,其中xxx为算法或算法所属的类型。md5算法为其分配空间通过crypto_alloc_shash(“md5”,0,0)实现,函数的原型为:struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,u32 mask)。其中参数alg_name表明了算法的名称,type表明了算法的类型,而mask表明了算法的掩码。分配成功算法对象之后,可以陆续调用对应的算法操作的钩子函数实现算法。MD5的算法操作集shash_alg里面就包含了算法实现的钩子函数。MD5的主要操作有初始化操作函数crypto_shash_init,更新函数crypto_shash_update,以及后续处理函数crypto_shash_final。最后返回函数的处理结果0,返回0表示算法调用成功,返回-1表示算法调用失败。digest size is 16说明md5的消息摘要大小为16字节,128位。表明算法调用成功。
通过以MD5为例说明使用算法API的通用方法。要使用一个算法,首先看API是否导出?如果API没有导出说明内核不希望使用该API。反之,则按以下步骤处理:
1. 正确使用头文件,如果头文件都使用错了,模块就没法运行。
2. 为算法分配算法对象。
3. 分配对象成功之后调用算法操作集里面定义好的钩子函数进行算法实现。
4. 进行模块的初始化和卸载函数的处理操作。