From 976755ebcbd7258bf187548012c51089f6a37b99 Mon Sep 17 00:00:00 2001 From: "YiLin.Li" Date: Wed, 16 Aug 2023 10:53:34 +0800 Subject: [PATCH] src/anolisos-tss.md: add the anolisos-tss.md Signed-off-by: YiLin.Li --- src/anolisos-tss.md | 139 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/anolisos-tss.md diff --git a/src/anolisos-tss.md b/src/anolisos-tss.md new file mode 100644 index 0000000..29af3da --- /dev/null +++ b/src/anolisos-tss.md @@ -0,0 +1,139 @@ +# TSS概述 + +TPM 软件栈 (TSS) 是一种软件规范,提供用于访问 TPM 的标准 API。 应用程序开发人员可以使用此软件规范来更好地使用TPM和开发基于TPM的应用程序,以实现更防篡改的效果等。 + +TSS 工作组的目的是为希望使用 TPM 的应用程序供应商提供一组标准 API。 该小组致力于制定一个中立的规范,该规范将提供硬件差异的抽象,以便应用程序供应商可以编写无论使用什么硬件、操作系统或环境都可以工作的应用程序。 TSS 还旨在为应用程序提供与本地或远程 TPM 对话的方法。 + +# 各个语言的TPM TSS软件栈现状 + +TPM的软件栈非常繁荣,涉及到多个语言以及多个开源项目。以下表格仅列出部分主流开发语言(C/Go/Java/Python/Rust)的主流TPM TSS软件栈现状。 + +TSS项目 | 开发语言 | 对TPM1.2/TPM2.0的支持情况 | 简介与现状 + :-------: | :-------: | :-------: | :-------: + [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) | C | 支持TPM 2.0 | 基于TCG标准实现的TPM2软件栈;包括FAPI、ESAPI、SAPI、MU、TCTI多层APIs, 在多个主流OS发行版本中被集成,用户量多,基于该开源项目开发的TPM知名项目有tpm2-tools和tpm2-abrmd等 +[IBM's TPM 2.0 TSS](https://sourceforge.net/projects/ibmtpm20tss/) | C | 支持TPM 1.2和TPM 2.0 | 在功能上等于但在API上不兼容TCG标准的ESAPI、SAPI、TCTI等API,用户相比于tpm2-tss少很多。 +[go-tpm](https://github.com/google/go-tpm) | Go | 支持TPM 1.2和TPM 2.0 | Google开源的Go语言的TSS软件栈项目,提供[legacy APIs](https://pkg.go.dev/github.com/google/go-tpm@v0.9.0/legacy/tpm2#section-sourcefiles)和与TPM2.0 APIs 1:1映射的[Direct APIs](https://pkg.go.dev/github.com/google/go-tpm@v0.9.0/tpm2#pkg-overview), 这些APIs没有完整实现TPM 1.2/2.0的整个规范。 +[go-tpm2](https://github.com/canonical/go-tpm2) | Go | 支持TPM 2.0 | canonical实现的用于与TPM 2.0交互的Go库,没有google/go-tpm活跃,且采用更加严格的LGPL3.0 license +[JSR 321](https://jcp.org/en/jsr/detail?id=321) | Java | 支持TPM 1.2 | JSR 321是基于Java的可信计算API标准规范,由[TPM/J](https://sourceforge.net/projects/tpmj/)和[IAIK/OpenTC](https://trustedjava.sourceforge.net/index.php?item=jtss/about)两个Java TPM软件栈开源项目共同发起并在2011年被JCP接受,但因为10年来没有更新后又被撤销。且该标准不支持TPM 2.0 +[tpm2-pytss](https://github.com/tpm2-software/tpm2-pytss) | Python | 支持TPM 2.0 | pytss在tpm2-tss上实现的wrapper,便于python用户较好地使用tpm2-tss软件栈开发基于TPM 2.0的Python应用程序 +[rust-tss-esapi](https://github.com/parallaxsecond/rust-tss-esapi) | Rust | 支持TPM 2.0 | rust-tss-esapi是基于tpm2-tss的ESAPI开发的wrapper,便于RUST用户较好地使用tpm2-tss软件栈开发基于TPM 2.0的RUST应用程序。包括Keylime在内的一些TPM知名开源项目都是该项目的使用者。 + +# 龙蜥社区在TPM TSS软件栈的贡献 + +龙蜥社区一直坚持upstream first原则,在多个TSS上游社区积极贡献代码,一共在tpm2-tss等四个仓库贡献并合入30来个patch, 包括多个feature和bugfix等, 其中 +- feature:在tpm2-tools贡献用来处理TPM errata tpm2_errata库和用来删除指定句柄的tpm2_flushcontext工具等。 + +| 开源软件名称 | 总计commit数量 | 总计修改行数 | +| :- | --: | --: | +| [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) | 1 | -0/+1 | +| [tpm2-abrmd](https://github.com/tpm2-software/tpm2-abrmd) | 7 | -14/+499 | +| [tpm2-tools](https://github.com/tpm2-software/tpm2-tools) | 21 | -52/+982 | +| [go-tpm-tools](https://github.com/google/go-tpm-tools/)| 1 | -9/+8 | + +# 龙蜥Anolis OS引入的TPM2 TSS软件栈及使用指南 + +通过上文对各个语言的TPM TSS软件栈现状的分析,可以看到TPM软件栈分为两类: +- 一种是各个语言原生实现的:其中tpm2-tss是基于TCG标准实现的被广泛使用。 +- 一种是基于其它语言实现的wrapper(tpm2-pytss和rust-tss-esapi均基于C语言的tpm2-tss封装的wrapper)。 + +结合调研结果,龙蜥社区引入 +- [tpm2-tss](https://gitee.com/src-anolis-os/tpm2-tss)及配套的[tpm2-abrmd](https://gitee.com/src-anolis-os/tpm2-abrmd)和[tpm2-tools](https://gitee.com/src-anolis-os/tpm2-tools)来满足大部分可信计算用户的需求。 +- [python-tpm2-pytss](https://gitee.com/src-anolis-os/python-tpm2-pytss)这个基于tpm2-tss的软件栈来满足可信计算Python用户的需求。 + +用户可以在对应的Anolis OS版本中yum安装即可使用。 + +此外,值得一提的是: +- 海光在龙蜥社区贡献了tpm2-tss和tpm2-tools的仓库部分组件/库的国密功能,详见[hygon-tpm2-tss](https://gitee.com/anolis/hygon-tpm2-tss)和[hygon-tpm2-tools](https://gitee.com/anolis/hygon-tpm2-tools),这些特性也都集成到Anolis OS对应版本的yum源中。 +- 龙蜥社区也在跟进和探索知名开源项目keylime,keylime部分组件依赖于rust的TSS软件栈rust-tss-esapi,未来也有计划将rust-tss-esapi引入来更好的服务可信计算Rust用户。 + +# tpm2-tss架构、开发接口和开发示例 +## tpm2-tss架构 + +TSS包含以下由高到低的几层软件:FAPI,ESAPI,SAPI,TCTI(TPM Command Transmission Interface, TPM命令传输接口),TAB(TPM Access Broker,TPM访问代理),RM(Resource Manager),和设备驱动。 +- 大多数的用户层引用程序基于FAPI开发就可以了,因为FAPI实现了TPM百分之八十的常用应用场景。使用这一层开发应用就像是使用JAVA,C#等高级语言开发应用一样方便。FAPI对应的库为`libtss2-fapi`,对应的标准为[TCG Feature API (FAPI) Specification,TCG TSS 2.0 JSON Data Types and Policy Language Specification](https://trustedcomputinggroup.org/wp-content/uploads/TSS_JSON_Policy_v0p7_r08_pub.pdf)。 +- 往下一层是ESAPI,它需要你对TPM了解很深,它实现了TPM2命令的1:1映射,但是同时提供了会话管理以及加解密的辅助功能。这有点像使用C++开发应用程序。ESAPI对应的库为libtss-esys +, 对应的标准为[TCG TSS 2.0 Enhanced System API (ESAPI) Specification](https://trustedcomputinggroup.org/wp-content/uploads/TSS_ESAPI_v1p0_r08_pub.pdf)。 +- 应用程序也可以直接基于SAPI这一层,它实现了TPM2命令的1:1映射,但这需要你对TPM了如指掌。这就像是使用C语言编写应用程序,而不是用高级语言。它提供了TPM的所有功能,但是要想用好它你必须对TPM有很深的理解。SAPI对应的库为`libtss2‑sys`,对应的标准为[TCG TSS 2.0 System Level API (SAPI) Specification](https://trustedcomputinggroup.org/wp-content/uploads/TSS_SAPI_v1p1_r29_pub_20190806.pdf)。 +- TCTI层用于向TPM发送命令并接收TPM对命令的响应。应用可以直接通过TCTI发送命令的数据流并解析接收到的响应数据流。这就像是使用汇编语言来编写应用程序。它对应的库为`libtss2‑tcti‑device`、`libtss2‑tcti‑tbs`等,对应的标准为[TCG TSS 2.0 TPM Command Transmission Interface (TCTI) API Specification](https://trustedcomputinggroup.org/wp-content/uploads/TCG_TSS_TCTI_v1p0_r18_pub.pdf)。 +- TAB这一层主要负责多线程环境下TPM资源的同步。也就是说它允许多个线程同时访问TPM而不发生冲突。 +- 因为TPM内部的存储资源非常有限,所以需要一个资源管理器RM,它的原理于虚拟内存管理类似,它可以将TPM对象和会话换进换出TPM。 +- 最后一层就是设备驱动,它主要是控制通信外设与TPM互相传输数据。如果你愿意的话,直接调用设备驱动接口来编写应用程序也是可以的,当然这就像是你用二进制数据编写程序一样。 + +![undefined](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/136439/1692165449775-5f211546-3054-40ec-923d-929fac7bcd15.png) + +## tpm2-tss开发接口 + +对于开发者和用户而言,tpm2-tss中使用最多的是FAPI和ESAPI,他们均提供了非常多的APIs供开发者使用。tpm2-tss提供一个文档详细的介绍了[FAPI](https://tpm2-tss.readthedocs.io/en/latest/group__fapi.html)和[ESAPI](https://tpm2-tss.readthedocs.io/en/latest/group__esys.html)中各个APIs的用法以及参数的含义,对用户快速理解和使用这些APIs非常有帮助。 + +tpm2-tools这个开源项目就是使用ESAPI进行开发并提供给用户对应的TPM 2.0工具。以ESAPI为例,ESAPI的接口分为四类: +- [Esys Context ESYS_CONTEXT相关APIs](https://tpm2-tss.readthedocs.io/en/latest/group___e_s_y_s___c_o_n_t_e_x_t.html):提供一些上下文相关的接口函数,用来初始化和释放上下文、获取底层的SAPI和TCTI上下文等。 +- [Esys Tpm Resource ESYS_TR](https://tpm2-tss.readthedocs.io/en/latest/group___e_s_y_s___t_r.html): 负责管理该层TPM软件资源相关的ESAPI。 +- [Esys TPM Commands](https://tpm2-tss.readthedocs.io/en/latest/group__esys__tpm.html): 与TPM 2.0命令1:1映射的ESAPI,调用对应的ESAPI命令最终会转换为对应的TPM 2.0命令。 +- [Internals of Enhanced System API](https://tpm2-tss.readthedocs.io/en/latest/group__iesys.html): 该层内部使用的一些ESAPI,包轮一些内部类型以及加密相关的APIs等。 + +## tpm2-tss开发示例 + +tpm2-tools这个开源项目就是使用ESAPI进行开发并提供给用户对应的TPM 2.0工具,也是tpm2-tss一个好的开发示例。以tpm2-tools为例,如果想调用ESAPI进行开发,首先参考`tools/tpm2_tool.h`去include对应的库,例如 + +```C +#include +``` + +然后参考`tools/tpm2_tool.c`的[ctx_init函数](https://github.com/tpm2-software/tpm2-tools/blob/master/tools/tpm2_tool.c#L46)去调用`Esys_Initialize`这个ESAPI来初始化ESAPI的上下文,例如 + +```C +static ESYS_CONTEXT *ctx_init(TSS2_TCTI_CONTEXT *tcti_ctx) { + + ESYS_CONTEXT *esys_ctx; + + TSS2_RC rval = Esys_Initialize(&esys_ctx, tcti_ctx, NULL); + if (rval != TPM2_RC_SUCCESS) { + LOG_PERR(Esys_Initialize, rval); + return NULL; + } + + return esys_ctx; +} +``` + +接下来调用ESAPI的TPM命令相关的API来与TPM进行通信完成对应的操作,比如读取PCR值可以参考`lib/tpm2.c`的[tpm2_pcr_read函数](https://github.com/tpm2-software/tpm2-tools/blob/master/lib/tpm2.c#L613)来调用`Esys_PCR_Read`这个ESAPI进行读取, + +```C +tool_rc tpm2_pcr_read(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, + ESYS_TR shandle2, ESYS_TR shandle3, + const TPML_PCR_SELECTION *pcr_selection_in, UINT32 *pcr_update_counter, + TPML_PCR_SELECTION **pcr_selection_out, TPML_DIGEST **pcr_values, + TPM2B_DIGEST *cp_hash, TPMI_ALG_HASH parameter_hash_algorithm) { + + TSS2_RC rval = TSS2_RC_SUCCESS; + tool_rc rc = tool_rc_success; + …… + + rval = Esys_PCR_Read(esys_context, shandle1, shandle2, shandle3, + pcr_selection_in, pcr_update_counter, pcr_selection_out, pcr_values); + if (rval != TSS2_RC_SUCCESS) { + LOG_PERR(Esys_PCR_Read, rval); + return tool_rc_from_tpm(rval); + } +} +``` + +最后当我们的所有操作完成后,需要参考`tools/tpm2_tool.c`的[esys_teardown函数](https://github.com/tpm2-software/tpm2-tools/blob/master/tools/tpm2_tool.c#L46)去调用`Esys_Finalize`这个ESAPI来销毁ESAPI的上下文,比如 + +```C +static void esys_teardown(ESYS_CONTEXT **esys_context) { + + if (esys_context == NULL) + return; + if (*esys_context == NULL) + return; + Esys_Finalize(esys_context); +``` + +# 龙蜥社区TSS软件栈规划 + +未来龙蜥社区将 +- 持续跟进上游社区各个语言TSS软件栈的动态并积极参与贡献,同时也会把这些成果引入到Anolis OS中。 +- 接受社区各个参与方在TSS软件栈上的贡献,并以实践文档等方式输出到可信计算SIG中。 +- 提供更多的实践指南,使用文档等,便于用户更好地使用。 +- …… -- Gitee