当前位置: 首页 > 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.cnnetsun.cn/news/2915700.html

相关文章:

  • 深入浅出:在高通8255的QNX/Android双系统下,Virtual Device与Pass-Through到底怎么选?
  • 【2027最新】基于SpringBoot+Vue的HTML问卷调查系统管理系统源码+MyBatis+MySQL
  • 如何用开源工具彻底掌控你的拯救者笔记本性能
  • 动态李代数在量子计算中的核心作用与应用解析
  • BLDC方波驱动 vs PMSM正弦波驱动:你的项目到底该选哪个?(从原理到选型指南)
  • 从GLUT到freeglut:一个开源替代库如何简化你的跨平台OpenGL ES项目
  • Spring Boot 2.7.5 项目里,把数据源从Druid换成HikariCP要几步?
  • 华硕笔记本性能控制难题?GHelper解锁轻量级硬件管理新方案
  • 时序数据库底层实战:手写极简TSDB,时间分区压缩、降采样查询,适配监控指标_IoT海量打点
  • 投稿Elsevier前必看:关于作者简介(Biography)的3个真相与1个偷懒技巧
  • Meta-Embeddings:让NLP模型自主选择最优架构的元认知机制
  • SillyTavern 5大高效优化技巧:让AI聊天响应速度提升200%
  • AI CEO架构:2027企业智能决策临界点实战指南
  • Python排序算法动画可视化教学工具
  • 别再乱装CUDA了!手把手教你根据ONNX Runtime版本选对CUDA和cuDNN(附避坑清单)
  • 从‘Hello World’到项目上线:一个机器视觉新手的Halcon与VisionMaster学习路径全记录
  • 别再纠结了!嵌入式项目选eMMC、SPI NOR还是SPI NAND?一张图帮你搞定选型
  • MLflow生产级落地:三平面架构与Git/Docker自动追溯实战
  • Windows音频路由终极指南:3步搞定多设备音频管理难题
  • 为你的汽车ECU选型:什么时候该用带SHE的芯片?成本与安全性的平衡术
  • 使用ChartJS实现堆叠柱状图
  • CrewAI实战案例分析:三个成功落地的Multi-Agent应用拆解
  • 除了USGS网页版,还有这3种方法批量获取Landsat数据:GEE脚本、API与下载管理器对比
  • 5分钟完全掌握:Windows USB设备安全弹出终极解决方案
  • webrtc源码解析概要介绍
  • Oracle EBS 两大系统中,长期股权投资(长投)的核算逻辑 + 标准会计分录(成本法、权益法全覆盖),并顺带讲清系统差异,方便你直接落地配置
  • 别再纠结选哪种了!手把手教你根据项目需求(机器人/AR/质检)挑选深度相机(TOF、双目、结构光)
  • 你的显卡能跑Speos吗?保姆级评测:从游戏卡到专业卡,GPU加速性能与性价比全解析
  • VEML7700光照传感器选型与配置避坑指南:如何根据应用场景设置增益和积分时间?
  • 告别配置烦恼:为什么我在RuoYi-Vue-Plus项目中选择了HikariCP作为默认数据源?