当前位置: 首页 > news >正文

Linux pkcs7_parse_message DER解码与signer_info

Linux pkcs7_parse_message DER解码与signer_info

PKCS#7解析器位于crypto/asymmetric_keys/pkcs7_parser.c,负责将DER编码的PKCS#7签名消息解码为struct pkcs7_message。该结构体包含签名者信息、证书链和被签名内容。

入口函数pkcs7_parse_message接收原始DER数据:

struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
{
struct pkcs7_parse_ctx *ctx;
struct pkcs7_message *msg;
int ret;

msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return ERR_PTR(-ENOMEM);

ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) {
pkcs7_free_message(msg);
return ERR_PTR(-ENOMEM);
}

ctx->msg = msg;
ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
if (ret < 0) {
pkcs7_free_message(msg);
msg = ERR_PTR(ret);
}

kfree(ctx);
return msg;
}

asn1_ber_decoder是内核的ASN.1 BER/DER解码器,通过预编译的pkcs7_decoder动作表驱动解析。该动作表由crypto/asymmetric_keys/pkcs7.asn1使用asn1_compiler生成。

解析过程中关键的数据结构struct pkcs7_signed_info存储签名者信息:

struct pkcs7_signed_info {
struct pkcs7_signed_info *next;
struct x509_certificate *signer;
struct asymmetric_key_id *sig_issuer;
struct asymmetric_key_id *sig_key;
unsigned int index;
bool unsupported_crypto;
bool blacklisted;
bool verified;
time64_t signing_time;
enum hash_algo hash_algo;
enum pkey_algo pkey_algo;
enum rsa_padding_type padding_algo;
const void *authattrs;
size_t authattrs_len;
struct public_key_signature *sig;
struct pkcs7_message *msg;
};

PKCS#7的SignedData结构包含多个SignerInfo。解析器处理每个SignerInfo时调用pkcs7_extract_signatory:

static int pkcs7_extract_signatory(struct pkcs7_parse_ctx *ctx, const u8 *data, size_t datalen)
{
struct pkcs7_signed_info *si;
int ret;

si = kzalloc(sizeof(*si), GFP_KERNEL);
if (!si)
return -ENOMEM;

si->msg = ctx->msg;
si->index = ctx->msg->num_signed_info++;

ret = asn1_ber_decoder(&pkcs7_signed_info_decoder, si, data, datalen);
if (ret < 0) {
kfree(si);
return ret;
}

si->next = ctx->msg->signed_infos;
ctx->msg->signed_infos = si;
return 0;
}

签名信息解析的详细动作在pkcs7_signed_info_decoder中处理,包含IssuerAndSerialNumber或SubjectKeyIdentifier的提取:

static int pkcs7_parse_issuer_and_sn(struct pkcs7_parse_ctx *ctx, const u8 *data, size_t datalen)
{
struct asn1_hdr hdr;
const u8 *end;
int ret;

ret = asn1_find_indefinite_length(data, datalen, &hdr);
if (ret < 0)
return ret;

end = hdr.data + hdr.len;
ctx->sinfo->sig_issuer = kzalloc(sizeof(struct asymmetric_key_id), GFP_KERNEL);
if (!ctx->sinfo->sig_issuer)
return -ENOMEM;

ctx->sinfo->sig_issuer->data = kmemdup(hdr.data, hdr.len, GFP_KERNEL);
ctx->sinfo->sig_issuer->datalen = hdr.len;
return 0;
}

digest算法和digest值通过pkcs7_parse_digest提取:

static int pkcs7_parse_digest(struct pkcs7_parse_ctx *ctx, const u8 *data, size_t datalen)
{
struct asn1_hdr hdr;
int ret;

ret = asn1_find_indefinite_length(data, datalen, &hdr);
if (ret < 0)
return ret;

ctx->sinfo->sig->digest = kmemdup(hdr.data, hdr.len, GFP_KERNEL);
ctx->sinfo->sig->digest_size = hdr.len;

switch (hdr.len) {
case 32:
ctx->sinfo->hash_algo = HASH_ALGO_SHA256;
break;
case 48:
ctx->sinfo->hash_algo = HASH_ALGO_SHA384;
break;
case 64:
ctx->sinfo->hash_algo = HASH_ALGO_SHA512;
break;
default:
return -ENOPKG;
}
return 0;
}

签名算法OID到pkey_algo的映射在pkcs7_parse_signing_algo中完成:

static int pkcs7_parse_signing_algo(struct pkcs7_parse_ctx *ctx, const u8 *data, size_t datalen)
{
struct asn1_hdr hdr;
const u8 *end;
const struct oid_lookup *lookup;
int ret;

ret = asn1_find_indefinite_length(data, datalen, &hdr);
if (ret < 0)
return ret;

lookup = oid_lookup(hdr.data, hdr.len);
if (!lookup)
return -ENOPKG;

switch (lookup->oid) {
case OID_rsaEncryption:
case OID_sha1WithRSAEncryption:
case OID_sha256WithRSAEncryption:
case OID_sha384WithRSAEncryption:
case OID_sha512WithRSAEncryption:
ctx->sinfo->pkey_algo = PKEY_ALGO_RSA;
break;
case OID_id_ecdsa_with_sha256:
ctx->sinfo->pkey_algo = PKEY_ALGO_ECDSA;
break;
default:
return -ENOPKG;
}
return 0;
}

解析完成后,pkcs7_verify函数遍历signed_infos链表,对每个签名者执行验证:

int pkcs7_verify(struct pkcs7_message *pkcs7, enum key_being_used_for usage)
{
struct pkcs7_signed_info *sinfo;
int ret;

for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
ret = pkcs7_verify_one(pkcs7, sinfo);
if (ret < 0)
return ret;
sinfo->verified = true;
}
return 0;
}

pkcs7_validate_trust负责将每个签名者的证书链锚定到系统信任密钥环,通过keyring_search在".builtin_trusted_keys"中查找匹配的X.509证书。

http://www.gsyq.cn/news/1522373.html

相关文章:

  • 5步轻松配置XUnity.AutoTranslator:免费游戏翻译神器入门指南
  • Agent Runtime层的标准化时刻:Session+Harness+Sandbox架构解析
  • 乳腺癌生存预测的多模态机器学习框架解析与应用
  • Linux platform驱动匹配表与设备树解析流程
  • 2026年5月查重急救|论文AIGC率高别慌,学姐亲测6款降AI工具(附免费名单) - 降AI实验室
  • CefFlashBrowser:如何让Flash经典内容在现代系统中重获新生
  • 从命令行到桌面应用:SillyTavern AI聊天界面桌面化终极指南
  • 数据清洗不是预处理,而是决定模型成败的核心工程
  • Pandas合并三函数:merge、join、concat场景化选型指南
  • 时序数据库底层实战:手写极简TSDB,时间分区压缩、降采样查询,适配监控指标_IoT海量打点
  • 终极iOS激活锁绕过指南:applera1n工具完整使用教程
  • OpenCode:面向VS Code的本地化代码补全引擎
  • 手把手教你用U盘给创维E900V20C刷当贝桌面(Hi3798MV200芯片保姆级教程)
  • 如何快速上手SillyTavern:打造专属AI角色的终极完整指南
  • 梯度下降实战指南:从原理到调参排障的工程化落地
  • 地表温度数据怎么选?一篇讲清MODIS、GLASS、Landsat三大LST产品区别与实战场景
  • Python排序算法动态可视化:Matplotlib动画教学实践
  • ViT视觉可解释性三镜法:Token注意力、Rollout与特征消融
  • 终极Unity游戏翻译指南:如何用XUnity.AutoTranslator轻松玩转外文游戏
  • 不止于解锁和飞行:揭秘MAVROS中command_long的隐藏用法,比如一键提升IMU话题频率到200Hz
  • 别再傻傻分不清!.NET 4.8和.NET 8.0到底该选哪个?从项目实战角度帮你决策
  • 从node_modules的‘地狱’到‘天堂’:聊聊pnpm的硬链接和符号链接到底怎么省下你几十G硬盘空间
  • 如何通过CefFlashBrowser实现Flash数字资产的生态延续与现代化访问
  • 如何在5分钟内搭建个人游戏云主机:Sunshine游戏串流终极指南
  • LangChain 的整体架构:模型、工具、RAG、Agent、记忆、观测
  • 2026成都锦江区前台形象墙品牌评测:成都高新区logo形象墙/成都高新区广告招牌推荐/4家机构实测对比 - 优质品牌商家
  • 你的旧手机卡槽别浪费!华为NM卡 vs 传统MicroSD卡,扩容该怎么选?
  • 从MicroPython迁移到CircuitPython?先看看这8个坑我帮你踩过了
  • Embedding:文本怎么变成向量?语义检索为什么能工作?
  • WordPress评论AI自动回复插件开发实战