我尝试使用代码(使用Linux Kernel Crypto API)来计算文件上的HMAC-SHA512。 令人惊讶的是,根据内核代码和OpenSSL命令计算的HMAC是不同的。
OpenSSL命令是:
openssl rand -base64 16
plakOhrXlfnBENPVBo91kg==
openssl dgst -sha512 -mac hmac -macopt key:plakOhrXlfnBENPVBo91kg== ../hello6.ko
HMAC-SHA512(../hello6.ko)= 9605f40851630f5b7a18fa30c7e5d6f1e77afb011d319efa515556d12ba6930f459825b3695a0d0d910a714724c0d99b36ccea5c878962b32a8de65dcbcc247d
内核代码中的HMAC-SHA512是:
84306723b713379aa666fe9aa75af3192a9707d19136c25dd2286c5f6d86dfd8f76ceaa0ce147b53c0e9f7bfab485f38f5139c687c34c840db7f7fa9438bf8b0d8df8e770088ffffc8de8e770088ffffc3f027a0ffffffff672c00000088fffff0de8e770088ffff1900000000000080672c000000000000e8de8e770088ffff
为什么这些HMAC对于相同的内容有所不同?任何摆脱这个问题的指针都非常有帮助。
Base64编码密钥由以下命令生成并存储在文件中:
openssl rand -base64 -out $Module_name.sha512key 16
HMAC在文件上生成并存储在文件中。 openssl dgst -sha512 -mac hmac -macopt key:$ HMAC_KEY $ HMAC_PATH / $ Module_name> TEMP.TXT
密钥和文件内容由以下代码阅读:
static char hmac[HMAC_SHA512_SIZE];
const char *kofilename = "/home/sri/Documents/Hello/hello6.ko";
const char *hmackey_file = "/home/sri/Documents/Hello/hello6.ko.sha512key";
const char *hmac_file = "/home/sri/Documents/Hello/hello6.ko.sha512";
unsigned char *data = NULL;
int readkostatus;
int readkeystatus;
int readhmacstatus;
unsigned char *hmackey = NULL;
unsigned char *stored_hmac = NULL;
readkeystatus = read_file(hmackey_file, &hmackey);
if(readkeystatus < 0)
goto readkeyerr;
printk(KERN_INFO "HMAC Key is :%s", hmackey);
readkostatus = read_kofile(kofilename, &data);
if(readkostatus < 0)
goto readkoerr;
printk(KERN_INFO "File data size is :%ld", strlen(data));
printk(KERN_INFO "File data is :%s", data);
hmac_sha512(hmackey, data, hmac, sizeof(hmac));
printk(KERN_INFO "FINAL HMAC:%s", hmac);
readhmacstatus = read_file(hmac_file, &stored_hmac);
if(readhmacstatus < 0)
goto readhmacerr;
printk(KERN_INFO "Stored HMAC:%s", stored_hmac);
if(!memcmp(stored_hmac, hmac, HMAC_SHA512_SIZE))
printk(KERN_INFO "HMACs match");
else
printk(KERN_INFO "HMACs do not match");
vfree(stored_hmac);
vfree(data);
vfree(hmackey);
return 0;
readkeyerr:
{
printk(KERN_INFO "hmac key read error:%d", readkeystatus);
return readkeystatus;
}
readkoerr:
{
printk(KERN_INFO "ko read error:%d", readkostatus);
return readkostatus;
}
readhmacerr:
{
printk(KERN_INFO "hmac read error:%d", readhmacstatus);
return readhmacstatus;
}
阅读文件的代码如下:
int read_file(const char *filename, unsigned char **data)
{
struct file* filp = NULL;
long filesize;
int ret = 0;
mm_segment_t old_fs = get_fs();
set_fs(get_ds());
filp = filp_open(filename, O_RDONLY, 0);
if(IS_ERR(filp)) {
ret = PTR_ERR(filp);
printk(KERN_INFO "kofile is not opened");
}
else
{
loff_t offset;
offset = 0;
filesize = filp->f_dentry->d_inode->i_size;
if (filesize <= 0 || filesize > 131072)
{
goto fileoperror;
}
*data = (unsigned char *)vmalloc(filesize);
if (*data == NULL)
goto datanull;
ret = vfs_read(filp, *data, filesize, &offset);
if(ret != filesize)
goto read_error;
filp_close(filp, NULL);
}
set_fs(old_fs);
return ret;
fileoperror:
{
filp_close(filp, NULL);
set_fs(old_fs);
printk(KERN_INFO "Invalid file operation '%s'\n", filename);
return (-EPERM);
}
datanull:
{
filp_close(filp, NULL);
set_fs(old_fs);
printk(KERN_INFO "Data Buffer is not allocated");
return (-EFAULT);
}
read_error:
{
filp_close(filp, NULL);
set_fs(old_fs);
printk(KERN_INFO "Failed to read '%s'.\n", filename);
return (-EFBIG);
}
}
int read_kofile(const char* filename, unsigned char **data)
{
return read_file(filename, data);
}
通过调用Crypto API在文件上计算HMAC-SHA-512:
#define HMAC_SHA512_SIZE 64
struct hmac_sha512_result {
struct completion completion;
int err;
};
static void hmac_sha512_complete(struct crypto_async_request *req, int err) {
struct hmac_sha512_result *r=req->data;
if(err==-EINPROGRESS)
return;
r->err=err;
complete(&r->completion);
}
int hmac_sha512(const unsigned char *key, // key
const unsigned char *data_in, // data in
unsigned char *hash_out, size_t outlen) { // hash buffer and length
int rc=0;
struct crypto_ahash *tfm;
struct scatterlist sg;
struct ahash_request *req;
struct hmac_sha512_result tresult;
void *hash_buf;
size_t klen = strlen(key);
size_t dlen = strlen(data_in);
int len = HMAC_SHA512_SIZE;
char hash_tmp[HMAC_SHA512_SIZE];
char *hash_res = hash_tmp;
printk(KERN_INFO "hmac_sha512: HMAC key is %s ", key);
/* Set hash output to 0 initially */
memset(hash_out, 0, outlen);
init_completion(&tresult.completion);
tfm=crypto_alloc_ahash("hmac(sha512)",0,0);
if(IS_ERR(tfm)) {
printk(KERN_ERR "hmac_sha512: crypto_alloc_ahash failed.\n");
rc=PTR_ERR(tfm);
goto err_tfm;
}
if(!(req=ahash_request_alloc(tfm,GFP_KERNEL))) {
printk(KERN_ERR "hmac_sha512: failed to allocate request for hmac(sha512)\n");
rc=-ENOMEM;
goto err_req;
}
if(crypto_ahash_digestsize(tfm)>len) {
printk(KERN_ERR "hmac_sha512: tfm size > result buffer.\n");
rc=-EINVAL;
goto err_req;
}
ahash_request_set_callback(req,CRYPTO_TFM_REQ_MAY_BACKLOG,
hmac_sha512_complete,&tresult);
if(!(hash_buf=kzalloc(dlen,GFP_KERNEL))) {
printk(KERN_ERR "hmac_sha512: failed to kzalloc hash_buf");
rc=-ENOMEM;
goto err_hash_buf;
}
memcpy(hash_buf,data_in,dlen);
sg_init_one(&sg,hash_buf,dlen);
crypto_ahash_clear_flags(tfm,-0);
if((rc=crypto_ahash_setkey(tfm,key,klen))){
printk(KERN_ERR "hmac_sha512: crypto_ahash_setkey failed\n");
goto err_setkey;
}
ahash_request_set_crypt(req,&sg,hash_res,dlen);
rc=crypto_ahash_digest(req);
switch(rc) {
case 0:
while (len--) {
snprintf(hash_out, outlen, "%02x", (*hash_res++ & 0x0FF));
hash_out += 2;
}
break;
case -EINPROGRESS:
case -EBUSY:
rc=wait_for_completion_interruptible(&tresult.completion);
if(!rc && !(rc=tresult.err)) {
INIT_COMPLETION(tresult.completion);
break;
} else {
printk(KERN_ERR "hmac_sha512: wait_for_completion_interruptible failed\n");
goto out;
}
default:
goto out;
}
out:
err_setkey:
kfree(hash_buf);
err_hash_buf:
ahash_request_free(req);
err_req:
crypto_free_ahash(tfm);
err_tfm:
return rc;
}
如果遗漏了某些内容,请告诉我。
答案 0 :(得分:0)
crypto_req_done
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/gfp.h>
#include <linux/msi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include <linux/ahci-remap.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <net/sock.h>
#include <linux/fs.h>
#include <asm/segment.h>
#include <linux/buffer_head.h>
#include <linux/libata.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
#include <linux/cdev.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/hashtable.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/signal_types.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/crypto.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define TESTMGR_POISON_BYTE 0xfe
static int do_ahash_op(int (*op)(struct ahash_request *req), struct ahash_request *req, struct crypto_wait *wait)
{
int err;
err = op(req);
return crypto_wait_req(err, wait);
}
static int check_nonfinal_ahash_op(const char *op, int err){
if(err < 0){
pr_err("alg: ahash: %s() failed with err %d on test vector %s\n", op, err, get_error(err));
return 1;
}
return 0;
}
现在是hmac_sha256:
int hmac_sha256(unsigned char *key, size_t key_size, unsigned char *ikm, size_t ikm_len, unsigned char *okm, size_t okm_len){
int rc, key_is_null;
struct crypto_ahash *tfm;
struct ahash_request *req;
struct scatterlist pending_sgl;
DECLARE_CRYPTO_WAIT(wait);
if(key == NULL){
key = kzalloc(32, GFP_KERNEL);
key_size = 32;
key_is_null = 1;
}else{key_is_null = 0;}
tfm = crypto_alloc_ahash("hmac(sha256)", 0, 0);
if(IS_ERR(tfm)) {
rc=PTR_ERR(tfm);
printk(KERN_ERR "hmac_sha256: crypto_alloc_ahash failed(%s).\n", get_error(rc));
goto err_tfm;
}
if(!(req = ahash_request_alloc(tfm, GFP_KERNEL))) {
rc =- ENOMEM;
printk(KERN_ERR "hmac_sha256: failed to allocate request for hmac(sha512)(%s).\n", get_error(rc));
}
if(key_size){
if((rc = crypto_ahash_setkey(tfm, key, key_size))){
printk(KERN_ERR "hmac_sha256: crypto_ahash_setkey failed.(%s)\n", get_error(rc));
goto out;
}
}
sg_init_table(&pending_sgl, 1);
memset(req->__ctx, TESTMGR_POISON_BYTE, crypto_ahash_reqsize(tfm));
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_req_done, &wait);
ahash_request_set_crypt(req, NULL, okm, 0);
rc = do_ahash_op(crypto_ahash_init, req, &wait);
rc = check_nonfinal_ahash_op("crypto_ahash_init", rc);
if (rc)
goto out;
sg_set_buf(&pending_sgl, ikm, ikm_len);
ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_req_done, &wait);
ahash_request_set_crypt(req, &pending_sgl, okm, okm_len);
rc = do_ahash_op(crypto_ahash_update, req, &wait);
rc = check_nonfinal_ahash_op("crypto_ahash_update", rc);
if(rc)
goto out;
rc = do_ahash_op(crypto_ahash_final, req, &wait);
rc = check_nonfinal_ahash_op("crypto_ahash_final", rc);
if (rc)
goto out;
dump_memory(okm, "hmac_sha256", okm_len);
out:
ahash_request_free(req);
crypto_free_ahash(tfm);
err_tfm:
if(key_is_null)
kfree(key);
return rc;
}
断腿!
int hkdf_extract(unsigned char *salt, size_t salt_len, unsigned char *ikm, size_t ikm_len, unsigned char *okm, size_t okm_len){
return hmac_sha256(salt, salt_len, ikm, ikm_len, okm, okm_len);
}