【发布时间】:2018-04-05 00:58:10
【问题描述】:
我目前正在开发一个内核模块,我正在执行 RSA 签名验证。我的模块是针对 4.4 内核的,所以我决定使用较低级别的akcipher API。我一直使用当前的implementation 或public_key_verify_signature 作为指导。我的做法是:
- 分配一个 crypto_akcipher 结构:
*tfm = crypto_alloc_akcipher("rsa", 0, 0); - 分配一个 akcipher_request 结构:
req = akcipher_request_alloc(*tfm, GFP_KERNEL); - 为请求设置公钥:
err = crypto_akcipher_set_pub_key(*tfm, data, len); - 将接收到的签名放入分散列表并将其设置为 akcipher_request 的参数:
akcipher_request_set_crypt(req, &src, &dst, sig->s_size, MAX_OUT); - 最后调用
crypto_akcipher_verify(req),它应该会计算出预期的摘要 - 将预期摘要与收到的摘要进行比较以验证签名
我目前处于我认为我正确使用 API 但crypto_akcipher_verify 的输出不符合它在较新的public_key_verify_signature 示例中使用的方式的地步。这让我很困惑,因为它似乎输出了正确摘要的一部分。
例如,当收到正确签名的请求时,我会得到以下结果:
Expected Digest:
e52bed356dcbf8e4b3c1458ac3e4cb49e77512e6
Computated outbuf:
01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003015300906052b0e03021a05000408e52bed356dcbf8e4
计算出的outbuf 的最后 8 个字节是预期的 20 字节摘要的前 8 个字节。但是outbuf 的其余部分似乎是垃圾。 (虽然每次都是一致的,但它总是0x01,后面跟着很多0xffs,最后是003015300906052b0e03021a05000408,最后8个字节)。这是负责调用crypto_akcipher_verify(req)的代码块:
// Init completion
init_completion(&(res.completion));
// Put the data into our request structure
memcpy(inbuf, sig->s, sig->s_size);
sg_init_one(&src, inbuf, sig->s_size);
sg_init_one(&dst, outbuf, MAX_OUT);
akcipher_request_set_crypt(req, &src, &dst, sig->s_size, MAX_OUT);
// Set the completion routine callback
// results from the verify routine will be stored in &res
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP, op_complete, &res);
// Compute the expected digest
err = wait_async_op(&res, crypto_akcipher_verify(req));
if(err) {
printk(KERN_INFO "[!] Digest computation failed %d\n", err);
kfree(inbuf);
kfree(outbuf);
return err;
}
printk(KERN_INFO "\nComputation:\n");
hexdump(outbuf, req->dst_len);
/* Do the actual verification step. */
if (req->dst_len != sig->digest_size ||
memcmp(sig->digest, outbuf, sig->digest_size) != 0) {
printk(KERN_INFO "[!] Signature verification failed - Key Rejected: %d\n", -EKEYREJECTED);
printk(KERN_INFO "[!] Sig len: %d Computed len: %d\n", sig->digest_size, req->dst_len);
kfree(inbuf);
kfree(outbuf);
return -EKEYREJECTED;
}
任何帮助或指出正确的方向将不胜感激。对不起,如果这篇文章不是非常简洁。
【问题讨论】:
标签: c linux-kernel cryptography rsa