接前一篇文章:tpm2-tools源码分析之tpm2_getrandom.c(2)
本文对tpm2_getrandom.c中的tpm2_tool_onrun函数进行i详细解析。
先再次贴出该函数源码:
static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {UNUSED(flags);/** 1. Process options*//** 2. Process inputs*/tool_rc rc = process_inputs(ectx);if (rc != tool_rc_success) {return rc;}/** 3. TPM2_CC_ call*/rc = get_random(ectx);if (rc != tool_rc_success) {return rc;}/** 4. Process outputs*/return process_outputs();
}
根据tpm2_tool_onrun函数中的注释,此函数分为4个步骤。不过第1个步骤没有任何函数和动作,因此实际上调用了3个函数:process_inputs、ger_random、process_outputs。实际上这个流程也是一个通用流程。
(1)process_inputs函数
process_inputs函数的作用是输入的处理。它在同文件(tpm2_getrrandom.c)中,代码如下:
process_inputs
这个函数又分为以下几个步骤:
1)对象和授权的初始化
由于tpm2_getrandom不需要授权,因此这一步骤实际上不需要。
2)恢复辅助会话
调用tpm2_util_aux_sessions_setup函数恢复辅助会话。对应代码片段如下:
tool_rc rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt,ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session);
if (rc != tool_rc_success) {return rc;
}
tpm2_util_aux_sessions_setup函数在lib/tpm2_util.c中,代码如下:
#define MAX_SESSION_CNT 3
tool_rc tpm2_util_aux_sessions_setup(ESYS_CONTEXT *ectx, uint8_t session_cnt,const char **session_path, ESYS_TR *session_handle,tpm2_session **session) {/** If no aux sessions were specified, simply return.*/if (!session_cnt) {return tool_rc_success;}if (session_cnt > MAX_SESSION_CNT) {LOG_ERR("A max of 3 sessions allowed");return tool_rc_general_error;}uint8_t session_idx = 0;for (session_idx = 0; session_idx < (session_cnt); session_idx++) {if (session_path[session_idx]) {tool_rc rc = tpm2_session_restore(ectx,session_path[session_idx], false, &session[session_idx]);if (rc != tool_rc_success) {LOG_ERR("Could not restore aux-session #%s",session_path[session_idx]);return rc;}session_handle[session_idx] =tpm2_session_get_handle(session[session_idx]);}}return tool_rc_success;
}
对于lib库中的代码,后续会有专门的文章进行分析,在此不作重点分析。
再来重点说一下ctx。ctx是同文件(tools/tpm2_getrandom.c)中定义并初始化,代码如下:
static tpm_random_ctx ctx = {.aux_session_handle[0] = ESYS_TR_NONE,.aux_session_handle[1] = ESYS_TR_NONE,.aux_session_handle[2] = ESYS_TR_NONE,.parameter_hash_algorithm = TPM2_ALG_ERROR,
};
ctx是tpm_random_ctx结构的成员,该结构也在同文件中定义,代码如下:
typedef struct tpm_random_ctx tpm_random_ctx;
#define MAX_AUX_SESSIONS 3
#define MAX_SESSIONS 3
struct tpm_random_ctx {/** Input options*/UINT16 num_of_bytes;bool force;bool hex;/** Outputs*/char *output_file;TPM2B_DIGEST *random_bytes;/** Parameter hashes*/const char *cp_hash_path;TPM2B_DIGEST cp_hash;const char *rp_hash_path;TPM2B_DIGEST rp_hash;TPMI_ALG_HASH parameter_hash_algorithm;bool is_command_dispatch;/** Aux Sessions*/uint8_t aux_session_cnt;tpm2_session *aux_session[MAX_AUX_SESSIONS];const char *aux_session_path[MAX_AUX_SESSIONS];ESYS_TR aux_session_handle[MAX_AUX_SESSIONS];
};
3)特定于命令的初始化
对应代码片段如下:
/** Error if bytes requested is bigger than max hash size, which is what TPMs* should bound their requests by and always have available per the spec.** Per 16.1 of:* - https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf** Allow the force flag to override this behavior.*/if (!ctx.force) {UINT32 max = 0;rc = get_max_random(ectx, &max);if (rc != tool_rc_success) {return rc;}if (ctx.num_of_bytes > max) {LOG_ERR("TPM getrandom is bounded by max hash size, which is: ""%"PRIu32"\n""Please lower your request (preferred) and try again or"" use --force (advanced)", max);return tool_rc_general_error;}}
这段代码的意思是:如果命令参数选项中并未指定-f即强制选项,则需要检查并确保请求的大小在TPM的哈希大小限制内。最大字节数通过get_max_random函数获得,该函数在同文件(tools/tpm2_getrandom.c)中,代码如下:
static tool_rc get_max_random(ESYS_CONTEXT *ectx, UINT32 *value) {TPMS_CAPABILITY_DATA *cap_data = NULL;tool_rc rc = tpm2_capability_get(ectx, TPM2_CAP_TPM_PROPERTIES,TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES, &cap_data);if (rc != tool_rc_success) {return rc;}UINT32 i;for (i = 0; i < cap_data->data.tpmProperties.count; i++) {TPMS_TAGGED_PROPERTY *p = &cap_data->data.tpmProperties.tpmProperty[i];if (p->property == TPM2_PT_MAX_DIGEST) {*value = p->value;free(cap_data);return tool_rc_success;}}LOG_ERR("TPM does not have property TPM2_PT_MAX_DIGEST");free(cap_data);return tool_rc_general_error;
}
可见,get_max_random函数的核心是调用了tpm2_capability_get函数。tpm2_capability_get函数在lib/tpm2_capability.c中,代码如下:
tool_rc tpm2_capability_get(ESYS_CONTEXT *ectx, TPM2_CAP capability,UINT32 property, UINT32 count,TPMS_CAPABILITY_DATA **capability_data) {return tpm2_capability_get_ex(ectx, capability,property, count, false, capability_data);
}
4)用于计算pHash的配置
此步骤又分为2个子步骤:
4.a)确定哈希和算法
对应代码片断如下:
/** 4.a Determine pHash length and alg*/
tpm2_session *all_sessions[MAX_SESSIONS] = {ctx.aux_session[0],ctx.aux_session[1],ctx.aux_session[2]
};const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0;
const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0;ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx,cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions);
4.b)确定哈希和算法
对应代码片断如下:
/** 4.b Determine if TPM2_CC_ is to be dispatched* !rphash && !cphash [Y]* !rphash && cphash [N]* rphash && !cphash [Y]* rphash && cphash [Y]*/ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ?false : true;
这一段代码就对应上一篇文章中提到的“当cphash被选择,而rphash选项没有被选择,则该工具不会实际执行命令,它只是返回一个cpHash。
至此,tpm2_tool_onrun函数的第1个函数process_inputs函数就分析完了。下一篇文章起分析余下的函数。
上一篇:Linux就该这么学(五)