tpm2-software/tpm2-tss

SM2密钥对生成

Closed this issue · 15 comments

怎么使用TPM2-TSS的ESYS API生成SM2密钥对?使用Esys_CreatePrimary或者Esys_Create具体怎么生成SM2密钥对?

對於 ECC 金鑰,您可以使用 .curveID =TPM2_ECC_SM2_P256 作為 inPublic 參數。

感谢您百忙之中的指导;但是我这边是这样实现,还是报错:
dad9f13730605c8f0ac0817c68e97cd
234f8810d28d23a85e5a6e2f0b18804
运行后就报如下图错误:
905f78951d90ed2a9188525065b3af8

看起來擁有者層次結構 (ESYS_TR_RH_OWNER) 的授權不起作用。

大佬,您给看下,这个如何做才能生成SM2密钥对呢

TPM2中是否支持SM2算法跟TPM2芯片本身有关系吗

以下示例基于在 libtpms 上运行的 TSS 集成测试。

    TSS2_RC r;
    ESYS_TR objectHandle = ESYS_TR_NONE;

    TPM2B_PUBLIC *outPublic = NULL;
    TPM2B_CREATION_DATA *creationData = NULL;
    TPM2B_DIGEST *creationHash = NULL;
    TPMT_TK_CREATION *creationTicket = NULL;

    TPM2B_SENSITIVE_CREATE inSensitive = {
        .size = 0,
        .sensitive = {
            .userAuth = {
                 .size = 0,
                 .buffer = {0}
                 ,
             },
            .data = {
                 .size = 0,
                 .buffer = {0}
             }
        }
    };

    TPM2B_PUBLIC inPublicECC = {
        .size = 0,
        .publicArea = {
            .type = TPM2_ALG_ECC,
            .nameAlg = TPM2_ALG_SHA256,
            .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
                                 TPMA_OBJECT_RESTRICTED |
                                 TPMA_OBJECT_SIGN_ENCRYPT |
                                 TPMA_OBJECT_FIXEDTPM |
                                 TPMA_OBJECT_FIXEDPARENT |
                                 TPMA_OBJECT_SENSITIVEDATAORIGIN),
            .authPolicy = {
                 .size = 0,
             },
            .parameters.eccDetail = {
                 .symmetric = {
                     .algorithm = TPM2_ALG_NULL,
                     .keyBits.aes = 128,
                     .mode.aes = TPM2_ALG_CFB,
                 },
                 .scheme = {
                      .scheme = TPM2_ALG_ECDSA,
                      .details = {.ecdsa =
                                  {.hashAlg = TPM2_ALG_SHA256}
                      }
                  },
                 .curveID = TPM2_ECC_SM2_P256,
                 .kdf = {.scheme =
                         TPM2_ALG_NULL,
                         .details = {}
                  }
             },
            .unique.ecc = {
                 .x = {.size = 0,.buffer = {}},
                 .y = {.size = 0,.buffer = {}}
             }
            ,
        }
    };


    TPM2B_DATA outsideInfo = {
        .size = 0,
        .buffer = {}
        ,
    };

    TPML_PCR_SELECTION creationPCR = {
        .count = 0,
    };

    r = Esys_CreatePrimary(esys_context, ESYS_TR_RH_OWNER, ESYS_TR_PASSWORD,
                           ESYS_TR_NONE, ESYS_TR_NONE, &inSensitive, &inPublicECC,
                           &outsideInfo, &creationPCR, &objectHandle,
                           &outPublic, &creationData, &creationHash,
                           &creationTicket);

按照您这种方式,还是报错,我是用c++开发在ubuntu24.04系统上安装配置了最新的tpm2-tss,然后如下实现方式:

#include <iostream>
#include <string>
#include <iomanip>
#include <tss2/tss2_esys.h>
#include <tss2/tss2_common.h>
#include <tss2/tss2_tpm2_types.h>
#include <tss2/tss2_fapi.h>

void test() {
    TSS2_RC rc;

    // 1.初始化TPM2
    ESYS_CONTEXT *esys_context = nullptr;
    TSS2_TCTI_CONTEXT *tcti = nullptr;
    TSS2_ABI_VERSION *abiVersion = nullptr;

    rc = Esys_Initialize(&esys_context, tcti, abiVersion);
    if (rc != TSS2_RC_SUCCESS) {
        // 错误处理
        std::cout << "Esys_Initialize---》初始化失败,错误码: " << rc << std::endl;
    } else {
        std::cout << "Esys_Initialize---》初始化成功!" << std::endl;
    }

    // 2.创建密钥对
    TPM2B_SENSITIVE_CREATE inSensitive;
    inSensitive.size = 0;
    inSensitive.sensitive.userAuth.size = 0;
    inSensitive.sensitive.userAuth.buffer[0] = {};
    inSensitive.sensitive.data.size = 0;
    inSensitive.sensitive.data.buffer[0] = {};

    TPM2B_PUBLIC inPublic;
    inPublic.size = 0;
    inPublic.publicArea.type = TPM2_ALG_ECC;
    inPublic.publicArea.nameAlg = TPM2_ALG_SHA256;
    inPublic.publicArea.objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
                                            TPMA_OBJECT_RESTRICTED |
                                            TPMA_OBJECT_SIGN_ENCRYPT |
                                            TPMA_OBJECT_FIXEDTPM |
                                            TPMA_OBJECT_FIXEDPARENT |
                                            TPMA_OBJECT_SENSITIVEDATAORIGIN);
    inPublic.publicArea.authPolicy.size = 0;
    inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_NULL;
    inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
    inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM2_ALG_CFB;

    inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_ECDSA;
    inPublic.publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = TPM2_ALG_SHA256;

    inPublic.publicArea.parameters.eccDetail.curveID = TPM2_ECC_SM2_P256;

    inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL;
    inPublic.publicArea.parameters.eccDetail.kdf.details = {};

    inPublic.publicArea.unique.ecc.x.size = 0;
    inPublic.publicArea.unique.ecc.x.buffer[0] = {};
    inPublic.publicArea.unique.ecc.y.size = 0;
    inPublic.publicArea.unique.ecc.y.buffer[0] = {};

    TPM2B_DATA outsideInfo = {0, {}};
    TPML_PCR_SELECTION creationPCR;
    creationPCR.count = 0;
    ESYS_TR objectHandle = ESYS_TR_NONE;
    TPM2B_PUBLIC *outPublic = nullptr;
    TPM2B_CREATION_DATA *creationData = nullptr;
    TPM2B_DIGEST *creationHash = nullptr;
    TPMT_TK_CREATION *creationTicket = nullptr;

    rc = Esys_CreatePrimary(esys_context,
                ESYS_TR_RH_OWNER,
                    ESYS_TR_PASSWORD,
                    ESYS_TR_NONE,
                    ESYS_TR_NONE,
                           &inSensitive,
                           &inPublic,
                           &outsideInfo,
                           &creationPCR,
                           &objectHandle,
                           &outPublic,
                           &creationData,
                           &creationHash,
                           &creationTicket);
    if (rc != TSS2_RC_SUCCESS) {
        std::cout << "Esys_CreatePrimary---》创建密钥对失败,错误码: " << rc << std::endl;
    } else {
        std::cout << "Esys_CreatePrimary---》创建密钥对成功!" << std::endl;
    }

    // 释放分配的内存
    rc = Esys_FlushContext(esys_context, objectHandle);
    if (esys_context) Esys_Finalize(&esys_context);
    Esys_Free(esys_context);
    Esys_Free(outPublic);
    Esys_Free(creationData);
    Esys_Free(creationHash);
    Esys_Free(creationTicket);

}

int main()
{
    test();
    return 0;
}

报错信息:
43d8291efa4c3d6a946d1f7e55fd0b8

我电脑是戴尔台式机,安装的是ubuntu24.04,按照您上面说的示例基于在 libtpms 上运行的 TSS 集成测试

因此您的筆記型電腦的 TPM 不支援 TPM2_ECC_SM2_P256。要對此進行測試,您可以使用 libtpms 作為 TPM 模擬器。

大佬,使用最新的libtpms作为TPM模拟器还是报错:
image
目前支持国密的算法吗?或者说是有什么条件限制吗?

我使用上面的 esys 示例和 tpm 工具创建了一个主数据库。 tpm 工具的示例 从 github 安装 litpms:

tpm2_startup -c  -Tlibtpms:tpm_state
tpm2_createprimary -G ecc_sm2_p256 -Tlibtpms:tpm_state
name-alg:
  value: sha256
  raw: 0xb
attributes:
  value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|restricted|decrypt
  raw: 0x30072
type:
  value: ecc
  raw: 0x23
curve-id:
  value: SM2 p256
  raw: 0x20
kdfa-alg:
  value: null
  raw: 0x10
kdfa-halg:
  value: (null)
  raw: 0x0
scheme:
  value: null
  raw: 0x10
scheme-halg:
  value: (null)
  raw: 0x0
sym-alg:
  value: aes
  raw: 0x6
sym-mode:
  value: cfb
  raw: 0x43
sym-keybits: 128
x: e71805c1fdbd36b2f0493b6b6c1eb56493e7237273bbdfa9d15993a16a04b644
y: 5a4f2dc1b2916bbc6938b22008839b280cbe8a1de8e9a5ea3ac0264c6157ee29

我是按照官网的这个安装教程:
https://tpm2-tools.readthedocs.io/en/stable/INSTALL/
如下:
image
不知道跟您说的安装方式一样吗?

我指的是 TPM 模拟器 libtms:
https://github.com/stefanberger/libtpms

我安装了这个libtms,需要怎么启动这个模拟器呢,然后怎么通过tpm2-tss、tpm2-tools、tpm2-abrmd连接这个模拟器呢

您可以在以下位置了解如何将 libtpms 与 swtpm 结合使用:
https://github.com/stefenberger/swtpm/wiki
TCTI 接口记录在:
https://github.com/tpm2-software/tpm2-tss/blob/master/doc/tcti.md
TCTI 也可以直接与“conf=libtpms:tpm_state”一起使用。
但是,此处必须执行 tpm 启动来初始化 tpm_state 文件。

非常感谢,我按您说的研究下