我一直在寻找一段时间,但没有找到足够的文档/示例来说明如何使用 linux 附带的 CryptoAPI 创建系统调用/在内核领域。
如果有人知道好的来源,请告诉我,我想知道如何仅在内核空间内执行 SHA1 / MD5 和 Blowfish / AES。
我一直在寻找一段时间,但没有找到足够的文档/示例来说明如何使用 linux 附带的 CryptoAPI 创建系统调用/在内核领域。
如果有人知道好的来源,请告诉我,我想知道如何仅在内核空间内执行 SHA1 / MD5 和 Blowfish / AES。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/scatterlist.h>
#define SHA1_LENGTH 20
static int __init sha1_init(void)
{
struct scatterlist sg;
struct crypto_hash *tfm;
struct hash_desc desc;
unsigned char output[SHA1_LENGTH];
unsigned char buf[10];
int i;
printk(KERN_INFO "sha1: %s\n", __FUNCTION__);
memset(buf, 'A', 10);
memset(output, 0x00, SHA1_LENGTH);
tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
desc.tfm = tfm;
desc.flags = 0;
sg_init_one(&sg, buf, 10);
crypto_hash_init(&desc);
crypto_hash_update(&desc, &sg, 10);
crypto_hash_final(&desc, output);
for (i = 0; i < 20; i++) {
printk(KERN_ERR "%d-%d\n", output[i], i);
}
crypto_free_hash(tfm);
return 0;
}
static void __exit sha1_exit(void)
{
printk(KERN_INFO "sha1: %s\n", __FUNCTION__);
}
module_init(sha1_init);
module_exit(sha1_exit);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Me");
内核中有几个地方使用了加密模块:eCryptfs 文件系统 (linux/fs/ecryptfs/) 和 802.11 无线堆栈 (linux/drivers/staging/rtl8187se/ieee80211/)。这两个都使用 AES,但您可以将在那里找到的内容推断为 MD5。
另一个很好的例子来自 security/seclvl.c 中的 2.6.18 内核源代码
注意:如果需要,您可以更改 CRYPTO_TFM_REQ_MAY_SLEEP
static int
plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len)
{
struct crypto_tfm *tfm;
struct scatterlist sg;
if (len > PAGE_SIZE) {
seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
"characters). Largest possible is %lu "
"bytes.\n", len, PAGE_SIZE);
return -EINVAL;
}
tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP);
if (tfm == NULL) {
seclvl_printk(0, KERN_ERR,
"Failed to load transform for SHA1\n");
return -EINVAL;
}
sg_init_one(&sg, (u8 *)plaintext, len);
crypto_digest_init(tfm);
crypto_digest_update(tfm, &sg, 1);
crypto_digest_final(tfm, hash);
crypto_free_tfm(tfm);
return 0;
}
Cryptodev-linux
https://github.com/cryptodev-linux/cryptodev-linux
它是一个内核模块,通过/dev/crypto
.
正如其他人所提到的,内核似乎没有将加密 API 暴露给用户空间本身,这是一种耻辱,因为内核已经可以在内部使用本机硬件加速加密功能。
加密操作 cryptodev 支持:https ://github.com/nmav/cryptodev-linux/blob/383922cabeea7dca354415e8c590f8e932f4d7a8/crypto/cryptodev.h
加密操作 Linux x86 支持:https ://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/x86/crypto?id=refs/tags/v4.0
One critical note:
Never compare the return value of crypto_alloc_hash
function to NULL for detecting the failure.
Steps:
Always use IS_ERR
function for this purpose. Comparing to NULL
does not capture the error, hence you get segmentation faults later on.
If IS_ERR returns fail, you possibly have a missing crypto algorithm compiled into your kernel image (or as a module). Make sure you have selected the appropriate crypto algo. form make menuconfig
.
如何仅在内核空间内执行 SHA1 / MD5 和 Blowfish / AES。
使用二元素散点列表散列数据的示例:
结构crypto_hash *tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); 如果(tfm == NULL) 失败; char *output_buf = kmalloc(crypto_hash_digestsize(tfm), GFP_KERNEL); if (output_buf == NULL) 失败; 结构 scatterlist sg[2]; 结构 hash_desc desc = {.tfm = tfm}; ret = crypto_hash_init(&desc); 如果 (ret != 0) 失败; sg_init_table(sg, ARRAY_SIZE(sg)); sg_set_buf(&sg[0], "你好", 5); sg_set_buf(&sg[1], "世界", 6); ret = crypto_hash_digest(&desc, sg, 11, output_buf); 如果 (ret != 0) 失败;
最好的起点是内核源代码中的 Documentation/crytpo。dm-crypt 是可能使用内核加密 API 的众多组件之一,您可以参考它来了解使用情况。