如何从 TPM 特定的“TPMT_PUBLIC”数据结构创建 OpenSSL 的“EVP_PKEY”格式的 ECC 公钥?

问题描述 投票:0回答:1

我正在开发一个需要使用 TPM(可信平台模块)的项目,并且需要验证 TPM 生成的 ECC 签名。验证需要在软件中完成,即在 TPM 之外,我们希望使用 OpenSSL (libcrypto) 来实现此目的。因此,TPM 的 ECC 公钥必须从 TPM 特定的

TPMT_PUBLIC
数据结构(其中由 TPM 提供)转换为
EVP_PKEY
格式可以与 OpenSSL (libcrypto) API 一起使用进行签名验证。


TPM 以以下结构提供 ECC 公钥,该结构不是由我定义,而是由 TPM 软件堆栈 (TSS) 定义,我必须使用它:

我从 TPM 获得的通用公钥结构(仅显示相关字段):

/* Definition of TPMT_PUBLIC Structure */
typedef struct TPMT_PUBLIC TPMT_PUBLIC;
struct TPMT_PUBLIC {
    /* ... */
    TPMU_PUBLIC_ID unique; /* For an asymmetric key this would be the public key. */
};

上面“唯一”字段中的键类型具体结构:

/* Definition of TPMU_PUBLIC_ID Union <INOUT S> */
typedef union TPMU_PUBLIC_ID TPMU_PUBLIC_ID;
union TPMU_PUBLIC_ID {
    TPM2B_DIGEST keyedHash;
    TPM2B_DIGEST sym;
    TPM2B_PUBLIC_KEY_RSA rsa;
    TPMS_ECC_POINT ecc; /* <-- This is what is used for ECC key !!! */
    TPMS_DERIVE derive;
};

TPM 提供的实际 ECC 公钥,如上面的“ecc”字段中所示:

/* Definition of ECC TPMS_ECC_POINT Structure */
typedef struct TPMS_ECC_POINT TPMS_ECC_POINT;
struct TPMS_ECC_POINT {
    TPM2B_ECC_PARAMETER x; /* X coordinate */
    TPM2B_ECC_PARAMETER y; /* Y coordinate */
};

x 和 y 坐标存储为:

/* Definition of ECC TPM2B_ECC_PARAMETER Structure */
typedef struct TPM2B_ECC_PARAMETER TPM2B_ECC_PARAMETER;
struct TPM2B_ECC_PARAMETER {
    UINT16 size;
    BYTE buffer[128];
};

更多详细信息(不是我的代码)可以在这里找到:
https://github.com/tpm2-software/tpm2-tss/blob/master/include/tss2/tss2_tpm2_types.h


因此,我们实际上从 TPM 中获取了 ECC 公钥的“x”和“y”坐标,每个坐标都以“原始”字节数组的形式提供。这不是 OpenSSL 可以直接使用的某种格式,例如 PEM 编码的公钥!那么我如何将其转换为 OpenSSL 能够处理的 EVP_PKEY

 实例,例如通过 
EVP_PKEY_verify() 功能?不幸的是,我
没有
能够找到如何从“原始”值(x和y坐标)构造EVP_PKEY
格式的ECC密钥的示例。无论是在 OpenSSL 文档中还是其他地方......
(我已经根据“原始”RSA 模数和指数值构造了一个 RSA 密钥作为

EVP_PKEY

,所以我认为应该可以对 ECC 密钥做类似的事情)

谢谢您的建议!

c openssl public-key elliptic-curve tpm
1个回答
0
投票
o2i_ECPublicKey

可用于将八位字节流(即字节序列)转换为

EC_KEY
类型的 EC 公钥。
ec.h头文件包含以下内容:

/** Decodes a ec public key from a octet string. * \param key a pointer to a EC_KEY object which should be used * \param in memory buffer with the encoded public key * \param len length of the encoded public key * \return EC_KEY object with decoded public key or NULL if an error * occurred. */ EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);

第一个参数需要初始化,例如使用
EC_KEY_new_by_curve_name

。输入缓冲区预计是一个值为 4 的单字节,后跟该点的 X 坐标,然后是该点的 Y 坐标。

加载 

EC_KEY

后,您可以使用

EVP_PKEY_new
创建新的
EVP_PKEY
,然后使用
EVP_PKEY_set1_EC_KEY
EC_KEY
加载到
EC_KEY
中。
    

© www.soinside.com 2019 - 2024. All rights reserved.