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

能否通过tpm2-openssl provider用OSSL_STORE_open_ex加载带密码的TPM2密钥?

使用tpm2-openssl通过OSSL_STORE_open_ex加载带密码的TPM2密钥

可以实现,但需要注意TPM2密钥的授权机制在tpm2-openssl中的特殊处理——持久化TPM2密钥的用户授权(user auth)需要在**操作阶段(如签名、解密)**传递,而非仅在加载阶段。你遇到的错误码0x0000098e(授权HMAC校验失败),核心原因就是操作时未正确传递密钥密码。

解决方案

1. 确认密钥创建的正确性

你现有的密钥创建命令是合规的,确保持久化步骤完成后,TPM中已存储带密码的目标密钥:

# 创建主密钥并持久化
tpm2_createprimary -g sha256 -G ecc256 -f pem -o storagekey_PK.pem -c storagekey.ctx
tpm2_evictcontrol -c storagekey.ctx 0x81000001

# 创建带密码的密钥并持久化
tpm2_create -C 0x81000001 -g sha256 -G ecc256 -u client_PK.obj -r client_SK.obj -p "1234" -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign|decrypt"
tpm2_load -C 0x81000001 -u client_PK.obj -r client_SK.obj -c client_key.ctx
tpm2_evictcontrol -C o -c client_key.ctx 0x81000002

2. 正确的代码实现

以下是可直接使用的示例代码,核心是在签名上下文初始化后,通过OSSL_PARAM将密码传递到操作阶段:

#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/store.h>

int sign_with_tpm_key(const char *key_uri, const char *password, const unsigned char *msg, size_t msg_len, unsigned char **sig, size_t *sig_len) {
    OSSL_STORE_CTX *store_ctx = NULL;
    EVP_PKEY *pkey = NULL;
    EVP_MD_CTX *md_ctx = NULL;
    OSSL_PARAM params[3] = {0};
    int ret = 0;

    // 加载TPM2持久化密钥(加载阶段无需密码)
    store_ctx = OSSL_STORE_open_ex(key_uri, NULL, NULL, NULL, NULL, NULL);
    if (!store_ctx) goto cleanup;
    if (!OSSL_STORE_load(store_ctx, (void**)&pkey) || !pkey) goto cleanup;

    // 初始化签名上下文
    md_ctx = EVP_MD_CTX_new();
    if (!md_ctx) goto cleanup;
    if (EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1) goto cleanup;

    // 向操作上下文传递TPM2密钥授权密码
    params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_PASSWORD, (char*)password, 0);
    params[1] = OSSL_PARAM_construct_end();
    if (EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(md_ctx), params) != 1) goto cleanup;

    // 执行签名
    if (EVP_DigestSign(md_ctx, NULL, sig_len, msg, msg_len) != 1) goto cleanup;
    *sig = OPENSSL_malloc(*sig_len);
    if (!*sig) goto cleanup;
    if (EVP_DigestSign(md_ctx, *sig, sig_len, msg, msg_len) != 1) goto cleanup;

    ret = 1;

cleanup:
    OSSL_STORE_close(store_ctx);
    EVP_PKEY_free(pkey);
    EVP_MD_CTX_free(md_ctx);
    return ret;
}

3. 关键注意事项

  • URI格式:使用tpm2:handle=0x81000002作为密钥URI,无需添加?pass或?password参数。
  • 密码传递时机:加载阶段(OSSL_STORE_open_ex)不需要密码,因为持久化密钥已在TPM中;操作阶段(签名/解密)必须传递密码完成TPM授权。
  • ui_method替代方案:tpm2-openssl 1.3.0中自定义ui_method对操作阶段的授权支持不完善,优先使用OSSL_PARAM传递密码。

你的4种尝试的问题分析

  1. VERSION 1:未在操作阶段传递密码,TPM执行签名时要求授权但未收到,导致失败。
  2. VERSION 2:URI添加?pass不符合tpm2-openssl的规范,密钥加载流程无法识别该参数,导致加载失败。
  3. VERSION 3:自定义ui_method未被tpm2-openssl在操作阶段调用,无法传递授权密码,仍触发授权失败。
  4. VERSION 4:仅在加载阶段传递密码,操作阶段未传递,TPM仍要求授权,导致失败。

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:25:55