mbedTLS 2.16.2验证DER证书链报-0x2700错误咨询
问题描述
- 开发环境:基于mbedTLS 2.16.2版本开发DER格式证书链验证功能
- 证书结构:三级PKI体系,证书均为独立DER文件存储,分别为根CA证书(Root_CA)、中间CA证书(Intermediate_CA)、设备证书(Device_CERT)
- 异常现象:使用
openssl verify命令可成功验证证书链有效性,但自研验证程序运行失败,返回错误:Error: -0x2700; flag: 8 - 核心疑问:当前实现的DER格式证书链验证流程是否正确
问题代码
void verify_cert_chain_driver( void ) { int32_t r = -1; uint32_t flags = 0; mbedtls_x509_crt ca, chain; do{ r = parse_from_file( &ca, "x509-root-ca.der" ); if( EXIT_SUCCESS != r ) break; r = parse_from_file( &chain, "x509-intermediate-ca.der" ); if( EXIT_SUCCESS != r ) break; r = parse_from_file( &chain, "x509-dev-cert.der" ); if( EXIT_SUCCESS != r ) break; r = mbedtls_x509_crt_verify( &chain, &ca, NULL, NULL, &flags, NULL, NULL ); if( EXIT_SUCCESS != r ) break; printf( "Verify OK\r\n" ); }while(0); if( 0 != r ) printf( "Error: 0x%04x; flag: %u\r\n", r, flags ); }
错误原因
你的验证流程存在3个核心问题,直接导致验证失败:
- 证书被覆盖:常规
parse_from_file封装都会在解析前调用mbedtls_x509_crt_init重置传入的证书结构体,你第二次调用该函数加载设备证书时,会清空第一次加载的中间CA证书,最终chain链表中仅存在设备证书,缺少中间CA构建验证路径,无法追溯到根信任锚。 - 链表顺序错误:
mbedtls_x509_crt_verify接口要求第一个参数传入的待验证证书链表,首节点必须是叶子设备证书,后续节点按签发顺序依次追加中间CA证书。你当前先加载中间CA、后追加设备证书的逻辑,会导致中间CA成为链表首节点,不符合接口的证书顺序要求。 - 缺少显式初始化:如果你的
parse_from_file没有内置结构体初始化逻辑,栈上定义的ca和chain结构体内存为随机值,内部指针是野指针,直接解析会触发内存异常。
错误码可以直接定位问题:
-0x2700对应mbedTLS标准错误MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,即证书验证通用失败flag=8对应验证标志MBEDTLS_X509_BADCERT_NOT_TRUSTED,即待验证证书无法追溯到受信任的根CA,和缺少中间CA的现象完全匹配。
修正方案
按照mbedTLS接口要求调整加载逻辑,修正后参考代码如下:
void verify_cert_chain_driver( void ) { int32_t r = -1; uint32_t flags = 0; mbedtls_x509_crt ca, chain; // 显式初始化证书结构体 mbedtls_x509_crt_init( &ca ); mbedtls_x509_crt_init( &chain ); do{ // 加载根CA到信任锚链表 r = mbedtls_x509_crt_parse_file( &ca, "x509-root-ca.der" ); if( EXIT_SUCCESS != r ) break; // 先加载叶子设备证书作为chain链表首节点 r = mbedtls_x509_crt_parse_file( &chain, "x509-dev-cert.der" ); if( EXIT_SUCCESS != r ) break; // 再追加中间CA证书到chain链表,构建设备->中间CA的验证路径 r = mbedtls_x509_crt_parse_file( &chain, "x509-intermediate-ca.der" ); if( EXIT_SUCCESS != r ) break; r = mbedtls_x509_crt_verify( &chain, &ca, NULL, NULL, &flags, NULL, NULL ); if( EXIT_SUCCESS != r ) break; printf( "Verify OK\r\n" ); }while(0); if( 0 != r ) printf( "Error: 0x%04x; flag: %u\r\n", r, flags ); // 释放证书结构体内存 mbedtls_x509_crt_free( &ca ); mbedtls_x509_crt_free( &chain ); }
注意:如果要保留自定义的
parse_from_file封装,需要保证该函数仅在第一次解析前调用初始化,后续追加证书时直接调用mbedtls_x509_crt_parse_file即可,避免重置链表清空已加载的证书。
内容的提问来源于stack exchange,提问作者Gopi
相关产品推荐
相关产品推荐

