SHA-1 hash calculate in Kernel.
hi all: I built a module for calculate the SHA-1. The code is: ################## #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/crypto.h> #include <linux/err.h> #include <linux/scatterlist.h> MODULE_LICENSE("Dual BSD/GPL"); #define SHA1_LENGTH 20 static int hello_init(void) { /* * http://lxr.oss.org.cn/source/fs/ecryptfs/crypto.c?v=2.6.30 */ struct scatterlist sg; struct hash_desc desc; //way 1 /* char *plaintext = "c"; size_t len = strlen(plaintext); */ //way 2 /* char *plaintext = kmalloc(sizeof(char), GFP_KERNEL); plaintext = "c"; size_t len = 1; */ // way 3. /* char plaintext[1] = {'c'}; size_t len = 1; */ // way 4. /* char *plaintext = (char *)__get_free_page(GFP_KERNEL); memcpy(plaintext, "c", 1); size_t len = 1; */ int rc = 0; int i; char hashtext[SHA1_LENGTH]; memset(hashtext, 0x00, SHA1_LENGTH); printk(KERN_INFO "sha1: %s\n", __FUNCTION__); sg_init_one(&sg, plaintext, len); desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); desc.flags = 0; rc = crypto_hash_init(&desc); if (rc) { printk(KERN_ERR "%s: Error initializing crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_update(&desc, &sg, len); if (rc) { printk(KERN_ERR "%s: Error updating crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_final(&desc, hashtext); if (rc) { printk(KERN_ERR "%s: Error finalizing crypto hash; rc = [%d]\n", __func__, rc); goto out; } crypto_free_hash(desc.tfm); for (i = 0; i < 20; i++) { printk(KERN_INFO "%02x-%d\n", hashtext[i]&0xff, i); } out: printk(KERN_INFO "end\n"); return rc; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); ################## I can just get the right result by way 3 and 4, In way 1 and 2 , I get the wrong result, I check the result by link: http://www.xorbin.com/tools/sha1-hash-calculator . Please tell me why? Thank you.
lx <lxlenovostar@gmail.com> writes:
hi all: I built a module for calculate the SHA-1. The code is: ################## #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/crypto.h> #include <linux/err.h> #include <linux/scatterlist.h> MODULE_LICENSE("Dual BSD/GPL");
#define SHA1_LENGTH 20
static int hello_init(void) { /* * http://lxr.oss.org.cn/source/fs/ecryptfs/crypto.c?v=2.6.30 */ struct scatterlist sg; struct hash_desc desc;
//way 1 /* char *plaintext = "c"; size_t len = strlen(plaintext); */
//way 2 /* char *plaintext = kmalloc(sizeof(char), GFP_KERNEL); plaintext = "c"; size_t len = 1; */
// way 3. /* char plaintext[1] = {'c'}; size_t len = 1; */
// way 4. /* char *plaintext = (char *)__get_free_page(GFP_KERNEL); memcpy(plaintext, "c", 1); size_t len = 1; */
int rc = 0; int i; char hashtext[SHA1_LENGTH];
memset(hashtext, 0x00, SHA1_LENGTH); printk(KERN_INFO "sha1: %s\n", __FUNCTION__);
sg_init_one(&sg, plaintext, len); desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); desc.flags = 0;
rc = crypto_hash_init(&desc); if (rc) { printk(KERN_ERR "%s: Error initializing crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_update(&desc, &sg, len); if (rc) { printk(KERN_ERR "%s: Error updating crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_final(&desc, hashtext); if (rc) { printk(KERN_ERR "%s: Error finalizing crypto hash; rc = [%d]\n", __func__, rc); goto out; } crypto_free_hash(desc.tfm);
for (i = 0; i < 20; i++) { printk(KERN_INFO "%02x-%d\n", hashtext[i]&0xff, i); }
out: printk(KERN_INFO "end\n"); return rc; }
static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); }
module_init(hello_init); module_exit(hello_exit); ################## I can just get the right result by way 3 and 4, In way 1 and 2 , I get the wrong result,
I suggest you add something like this: printk(KERN_INFO "plaintext='%c', len=%zu, valid=%s\n", *plaintext, len, virt_addr_valid(plaintext) ? "true" : "false"); and then go figure out the relationship between that and the correct result :) Bjørn
From: kernelnewbies-bounces@kernelnewbies.org [mailto:kernelnewbies-bounces@kernelnewbies.org] On Behalf Of lx Sent: Friday, August 28, 2015 12:36 AM To: kernelnewbies Subject: SHA-1 hash calculate in Kernel. hi all: I built a module for calculate the SHA-1. The code is: ################## #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/crypto.h> #include <linux/err.h> #include <linux/scatterlist.h> MODULE_LICENSE("Dual BSD/GPL"); #define SHA1_LENGTH 20 static int hello_init(void) { /* * http://lxr.oss.org.cn/source/fs/ecryptfs/crypto.c?v=2.6.30 */ struct scatterlist sg; struct hash_desc desc; //way 1 /* char *plaintext = "c"; size_t len = strlen(plaintext); */ //way 2 /* char *plaintext = kmalloc(sizeof(char), GFP_KERNEL); plaintext = "c"; size_t len = 1; */ // way 3. /* char plaintext[1] = {'c'}; size_t len = 1; */ // way 4. /* char *plaintext = (char *)__get_free_page(GFP_KERNEL); memcpy(plaintext, "c", 1); size_t len = 1; */ int rc = 0; int i; char hashtext[SHA1_LENGTH]; memset(hashtext, 0x00, SHA1_LENGTH); printk(KERN_INFO "sha1: %s\n", __FUNCTION__); sg_init_one(&sg, plaintext, len); desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); desc.flags = 0; rc = crypto_hash_init(&desc); if (rc) { printk(KERN_ERR "%s: Error initializing crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_update(&desc, &sg, len); if (rc) { printk(KERN_ERR "%s: Error updating crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_final(&desc, hashtext); if (rc) { printk(KERN_ERR "%s: Error finalizing crypto hash; rc = [%d]\n", __func__, rc); goto out; } crypto_free_hash(desc.tfm); for (i = 0; i < 20; i++) { printk(KERN_INFO "%02x-%d\n", hashtext[i]&0xff, i); } out: printk(KERN_INFO "end\n"); return rc; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); ################## I can just get the right result by way 3 and 4, In way 1 and 2 , I get the wrong result, I check the result by link: http://www.xorbin.com/tools/sha1-hash-calculator . Please tell me why? Thank you. I don’t know why the crypto function isn’t generating the right result in the first two cases. Just pointing out that way 1 and way 2 are identical except that way 2 leaks the memory that was kmalloc()’ed. This in way 2 is a pointer assignment, not a buffer copy: plaintext = "c"; The big difference it seems between ways 1 and 2 and ways 3 and 4 is in the former, plaintext points to a string constant that I believe is going to be read only whereas in the latter, plaintext points to r/w memory. Maybe the crypto functions need r/w access? Jeff Haran
On Fre, 2015-08-28 at 15:36 +0800, lx wrote: [...]
//way 2 /* char *plaintext = kmalloc(sizeof(char), GFP_KERNEL); plaintext = "c";
I don't think that this line doesn't give any warning ... Kind regards, Bernd -- "I dislike type abstraction if it has no real reason. And saving on typing is not a good reason - if your typing speed is the main issue when you're coding, you're doing something seriously wrong." - Linus Torvalds
hi all: I finally implement it by learning form the function of tcp md5 checksum. This is the relative kernel source <http://lxr.oss.org.cn/source/net/ipv4/tcp.c?v=2.6.30#L2667>. The SHA-1 implement is here <https://github.com/lxlenovostar/kernel_test/blob/master/model/kernel_hash/sha.c>.But I still have a question about __virt_addr_valid. ############################## #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/crypto.h> #include <linux/err.h> #include <linux/scatterlist.h> #include <linux/mm.h> #define SHA1_LENGTH 20 static inline int phys_addr_valid(resource_size_t addr) { #ifdef CONFIG_PHYS_ADDR_T_64BIT return !(addr >> boot_cpu_data.x86_phys_bits); #else return 1; #endif } bool __virt_addr_valid(unsigned long x) { unsigned long old_x; old_x = x; //The kernel text is mapped into the region starting from__START_KERNEL_MAP if (x >= __START_KERNEL_map) { if (x >= MODULES_VADDR && x <= MODULES_END) { printk(KERN_INFO "right here"); } x -= __START_KERNEL_map; if (x >= KERNEL_IMAGE_SIZE) { printk(KERN_INFO "error1"); return false; } x += phys_base; } else { if (x < PAGE_OFFSET) { printk(KERN_INFO "error2"); return false; } x -= PAGE_OFFSET; if (!phys_addr_valid(x)) { printk(KERN_INFO "error3"); return false; } } return pfn_valid(x >> PAGE_SHIFT); } static int minit(void) { /* * http://lxr.oss.org.cn/source/fs/ecryptfs/crypto.c?v=2.6.30 */ struct scatterlist sg; struct hash_desc desc; int rc = 0; int i; char hashtext[SHA1_LENGTH]; char *plaintext = NULL; printk(KERN_INFO "valid=%s\n", virt_addr_valid(plaintext) ? "true" : "false"); plaintext = "c"; printk(KERN_INFO "valid=%s\n", virt_addr_valid(plaintext) ? "true" : "false"); size_t len = strlen(plaintext); sg_init_one(&sg, (u8 *)plaintext, len); desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); desc.flags = 0; rc = crypto_hash_init(&desc); if (rc) { printk(KERN_ERR "%s: Error initializing crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_update(&desc, &sg, len); if (rc) { printk(KERN_ERR "%s: Error updating crypto hash; rc = [%d]\n", __func__, rc); goto out; } rc = crypto_hash_final(&desc, hashtext); if (rc) { printk(KERN_ERR "%s: Error finalizing crypto hash; rc = [%d]\n", __func__, rc); goto out; } crypto_free_hash(desc.tfm); for (i = 0; i < 20; i++) { //printk(KERN_INFO "%02x-%d\n", hashtext[i]&0xff, i); } out: return rc; } static void mexit(void) { printk("Exit %s.\n", THIS_MODULE->name); } ############################## I make and insmod it. the log is: ############################## [root@localhost sha]# dmesg -c error2 valid=false right here error1 valid=false ############################## I think plaintext is between MODULES_VADDR and MODULES_END, So why the address in MODULES not a valid virtual address? Thank you. 2015-08-29 19:49 GMT+08:00 Bernd Petrovitsch <bernd@petrovitsch.priv.at>:
On Fre, 2015-08-28 at 15:36 +0800, lx wrote: [...]
//way 2 /* char *plaintext = kmalloc(sizeof(char), GFP_KERNEL); plaintext = "c";
I don't think that this line doesn't give any warning ...
Kind regards, Bernd -- "I dislike type abstraction if it has no real reason. And saving on typing is not a good reason - if your typing speed is the main issue when you're coding, you're doing something seriously wrong." - Linus Torvalds
participants (4)
-
Bernd Petrovitsch -
Bjørn Mork -
Jeff Haran -
lx