OpenSSL 3验证算法是否由FIPS模块提供时出现段错误求助
OpenSSL 3 FIPS Provider 算法归属测试段错误问题排查与修复
问题背景
用户使用OpenSSL 3搭配FIPS Provider,编写C代码测试算法是否由FIPS模块提供,参考官方方法后出现段错误。修改代码后,虽确认FIPS Provider已加载,但仍在EVP_MD_get0_provider调用处触发段错误。
初始测试代码(存在明显错误)
#include <stdio.h> #include <openssl/provider.h> #include <lopenssl/evp.h> // 头文件路径错误 int main(void) { EVP_MD_CTX * mdctx; md = EVP_get_digestbyname("sha1"); // 未声明变量md mdctx = EVP_MD_CTX_new(); EVP_DigestInit_ex2(mdctx,md,NULL); // 未检查md是否为NULL printf(OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(EVP_MD_CTX_get0_md(mdctx)))); // 无空指针检查 }
修改后的代码及环境信息
修改后的测试代码:
#include <stdio.h> #include <openssl/provider.h> #include <openssl/evp.h> int main(void) { EVP_MD_CTX * mdctx; mdctx = EVP_MD_CTX_new(); printf("EVP_DigestInit_ex(mdctx,EVP_sha256(),NULL): %d\n", EVP_DigestInit_ex(mdctx,EVP_sha256(),NULL)); printf("OSSL_PROVIDER_available: %d\n",OSSL_PROVIDER_available(NULL,"fips")); printf(OSSL_PROVIDER_get0_name(EVP_MD_get0_provider(EVP_MD_CTX_get0_md(mdctx)))); // 无空指针检查 }
OpenSSL配置文件:
config_diagnostics = 1 openssl_conf = openssl_init .include /Openssl/build/ssl/fipsmodule.cnf [openssl_init] providers = provider_sect [provider_sect] fips = fips_sect base = base_sect [base_sect] activate = 1
GDB调试输出:
EVP_DigestInit_ex(mdctx,EVP_sha256(),NULL): 1 OSSL_PROVIDER_available: 1 Program received signal SIGSEGV, Segmentation fault. ossl_provider_name (prov=0x0) at crypto/provider_core.c:1490 1490 return prov->name;
问题原因分析
初始代码的低级错误:
- 头文件路径错误:
<lopenssl/evp.h>应为<openssl/evp.h> - 未声明
EVP_MD *md变量,编译时会产生警告(用户可能未重视) EVP_get_digestbyname("sha1")在FIPS 140-3模式下默认返回NULL(SHA1已被标记为非批准算法,FIPS Provider默认不提供)- 所有API调用均未做返回值检查,空指针被传递到后续函数引发段错误
- 头文件路径错误:
修改后代码的核心问题:
- 虽然
EVP_DigestInit_ex返回成功,但EVP_MD_CTX_get0_md(mdctx)可能返回NULL(OpenSSL内部上下文状态未完全关联算法对象的provider信息) - 未对
EVP_MD_get0_provider的返回值做空指针检查,当provider为NULL时,调用OSSL_PROVIDER_get0_name直接访问空指针成员引发段错误
- 虽然
修复方案
1. 增加全面的错误检查
所有OpenSSL API调用的返回值都需要检查,避免空指针传递。
2. 直接从算法对象获取Provider信息
相较于从上下文间接获取,直接通过EVP_sha256()等算法函数返回的EVP_MD结构体获取Provider,结果更可靠,因为算法对象本身已明确关联到提供它的Provider。
3. 针对非批准算法的特殊处理(如SHA1)
若需测试SHA1,需在FIPS配置文件中显式启用非批准算法:
在fipsmodule.cnf的[fips_sect]中添加:
allow_non_fips_algorithms = 1
修复后的完整测试代码
#include <stdio.h> #include <openssl/provider.h> #include <openssl/evp.h> int main(void) { const EVP_MD *md = NULL; const OSSL_PROVIDER *prov = NULL; const char *prov_name = NULL; // 检查FIPS Provider是否可用 if (!OSSL_PROVIDER_available(NULL, "fips")) { fprintf(stderr, "FIPS Provider not available\n"); return 1; } // 获取SHA256算法对象(FIPS批准算法) md = EVP_sha256(); if (md == NULL) { fprintf(stderr, "Failed to get SHA256 digest\n"); return 1; } // 获取算法所属的Provider prov = EVP_MD_get0_provider(md); if (prov == NULL) { fprintf(stderr, "Failed to get provider for SHA256\n"); return 1; } // 获取Provider名称并输出 prov_name = OSSL_PROVIDER_get0_name(prov); printf("SHA256 is provided by: %s\n", prov_name); // 若需测试SHA1(需先在FIPS配置中启用非批准算法) md = EVP_sha1(); if (md != NULL) { prov = EVP_MD_get0_provider(md); if (prov != NULL) { prov_name = OSSL_PROVIDER_get0_name(prov); printf("SHA1 is provided by: %s\n", prov_name); } else { fprintf(stderr, "Failed to get provider for SHA1\n"); } } else { fprintf(stderr, "SHA1 not available (check FIPS config)\n"); } return 0; }
4. 编译与运行注意事项
编译时需链接OpenSSL库:
gcc -o fips_test fips_test.c -lcrypto
运行时需确保OpenSSL配置文件被正确加载,可通过环境变量指定:
OPENSSL_CONF=/path/to/your/openssl.cnf ./fips_test
验证结果
修复后的代码会输出类似如下内容:
SHA256 is provided by: fips SHA1 is provided by: base # 若启用非批准算法,SHA1可能由base Provider提供
内容的提问来源于stack exchange,提问作者pankul garg
相关产品推荐
相关产品推荐

