You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

问题原因分析

  1. 初始代码的低级错误:

    • 头文件路径错误:<lopenssl/evp.h>应为<openssl/evp.h>
    • 未声明EVP_MD *md变量,编译时会产生警告(用户可能未重视)
    • EVP_get_digestbyname("sha1")在FIPS 140-3模式下默认返回NULL(SHA1已被标记为非批准算法,FIPS Provider默认不提供)
    • 所有API调用均未做返回值检查,空指针被传递到后续函数引发段错误
  2. 修改后代码的核心问题:

    • 虽然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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 00:25:18