使用Linux Kernel Crypto API的HMAC与OpenSSL命令的HMAC不同

时间:2014-10-02 19:14:52

标签: c linux linux-kernel openssl hmac

我尝试使用代码(使用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;
}

如果遗漏了某些内容,请告诉我。

1 个答案:

答案 0 :(得分:0)

在hash.h中定义的

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);
}