diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2018-09-24 15:11:14 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2018-09-24 15:11:14 +0200 |
commit | e0e280b7669435b991b7e457abd8aa450930b3e8 (patch) | |
tree | 3e6084f13b14ad2df104e2ce6e589eb96c5f7ac9 /src/libtpmtss/tpm_tss_tss2.c | |
parent | 51a71ee15c1bcf0e82f363a16898f571e211f9c3 (diff) | |
download | vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.tar.gz vyos-strongswan-e0e280b7669435b991b7e457abd8aa450930b3e8.zip |
New upstream version 5.7.0
Diffstat (limited to 'src/libtpmtss/tpm_tss_tss2.c')
-rw-r--r-- | src/libtpmtss/tpm_tss_tss2.c | 1176 |
1 files changed, 0 insertions, 1176 deletions
diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c deleted file mode 100644 index 90a16c103..000000000 --- a/src/libtpmtss/tpm_tss_tss2.c +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * Copyright (C) 2016 Andreas Steffen - * HSR Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "tpm_tss_tss2.h" -#include "tpm_tss_tss2_names.h" - -#ifdef TSS_TSS2 - -#include <asn1/asn1.h> -#include <asn1/oid.h> -#include <bio/bio_reader.h> - -#include <tpm20.h> - -#ifdef TSS2_TCTI_TABRMD -#include <tcti/tcti-tabrmd.h> -#endif /* TSS2_TCTI_TABRMD */ - -#ifdef TSS2_TCTI_SOCKET -#include <tcti_socket.h> - -#define TCTI_SOCKET_DEFAULT_ADDRESS "127.0.0.1" -#define TCTI_SOCKET_DEFAULT_PORT 2323 -#endif /* TSS2_TCTI_SOCKET */ - -#define LABEL "TPM 2.0 -" - -typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t; - -/** - * Private data of an tpm_tss_tss2_t object. - */ -struct private_tpm_tss_tss2_t { - - /** - * Public tpm_tss_tss2_t interface. - */ - tpm_tss_t public; - - /** - * TCTI context - */ - TSS2_TCTI_CONTEXT *tcti_context; - - /** - * SYS context - */ - TSS2_SYS_CONTEXT *sys_context; - - /** - * Number of supported algorithms - */ - size_t supported_algs_count; - - /** - * List of supported algorithms - */ - TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET]; -}; - -/** - * Some symbols required by libtctisocket - */ -FILE *outFp; -uint8_t simulator = 1; - -int TpmClientPrintf (uint8_t type, const char *format, ...) -{ - return 0; -} - -/** - * Convert hash algorithm to TPM_ALG_ID - */ -static TPM_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg) -{ - switch (alg) - { - case HASH_SHA1: - return TPM_ALG_SHA1; - case HASH_SHA256: - return TPM_ALG_SHA256; - case HASH_SHA384: - return TPM_ALG_SHA384; - case HASH_SHA512: - return TPM_ALG_SHA512; - default: - return TPM_ALG_ERROR; - } -} - -/** - * Convert TPM_ALG_ID to hash algorithm - */ -static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM_ALG_ID alg) -{ - switch (alg) - { - case TPM_ALG_SHA1: - return HASH_SHA1; - case TPM_ALG_SHA256: - return HASH_SHA256; - case TPM_ALG_SHA384: - return HASH_SHA384; - case TPM_ALG_SHA512: - return HASH_SHA512; - default: - return HASH_UNKNOWN; - } -} - -/** - * Check if an algorithm given by its TPM_ALG_ID is supported by the TPM - */ -static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id) -{ - int i; - - if (alg_id == TPM_ALG_ERROR) - { - return FALSE; - } - - for (i = 0; i < this->supported_algs_count; i++) - { - if (this->supported_algs[i] == alg_id) - { - return TRUE; - } - } - - return FALSE; -} - -/** - * Get a list of supported algorithms - */ -static bool get_algs_capability(private_tpm_tss_tss2_t *this) -{ - TPMS_CAPABILITY_DATA cap_data; - TPMS_TAGGED_PROPERTY tp; - TPMI_YES_NO more_data; - TPM_ALG_ID alg; - uint32_t rval, i, offset, revision = 0, year = 0; - size_t len = BUF_LEN; - char buf[BUF_LEN], manufacturer[5], vendor_string[17]; - char *pos = buf; - int written; - - /* get fixed properties */ - rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES, - PT_FIXED, MAX_TPM_PROPERTIES, &more_data, &cap_data, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_TPM_PROPERTIES: 0x%06x", - LABEL, rval); - return FALSE; - } - memset(manufacturer, '\0', sizeof(manufacturer)); - memset(vendor_string, '\0', sizeof(vendor_string)); - - /* print fixed properties */ - for (i = 0; i < cap_data.data.tpmProperties.count; i++) - { - tp = cap_data.data.tpmProperties.tpmProperty[i]; - switch (tp.property) - { - case TPM_PT_REVISION: - revision = tp.value; - break; - case TPM_PT_YEAR: - year = tp.value; - break; - case TPM_PT_MANUFACTURER: - htoun32(manufacturer, tp.value); - break; - case TPM_PT_VENDOR_STRING_1: - case TPM_PT_VENDOR_STRING_2: - case TPM_PT_VENDOR_STRING_3: - case TPM_PT_VENDOR_STRING_4: - offset = 4 * (tp.property - TPM_PT_VENDOR_STRING_1); - htoun32(vendor_string + offset, tp.value); - break; - default: - break; - } - } - DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u", LABEL, manufacturer, - vendor_string, (float)revision/100, year); - - /* get supported algorithms */ - rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS, - 0, TPM_PT_ALGORITHM_SET, &more_data, &cap_data, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x", - LABEL, rval); - return FALSE; - } - - /* Number of supported algorithms */ - this->supported_algs_count = cap_data.data.algorithms.count; - - /* store and print supported algorithms */ - for (i = 0; i < this->supported_algs_count; i++) - { - alg = cap_data.data.algorithms.algProperties[i].alg; - this->supported_algs[i] = alg; - - written = snprintf(pos, len, " %N", tpm_alg_id_names, alg); - if (written < 0 || written >= len) - { - break; - } - pos += written; - len -= written; - } - DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf); - - /* get supported ECC curves */ - rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ECC_CURVES, - 0, TPM_PT_LOADED_CURVES, &more_data, &cap_data, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x", - LABEL, rval); - return FALSE; - } - - /* reset print buffer */ - pos = buf; - len = BUF_LEN; - - /* print supported ECC curves */ - for (i = 0; i < cap_data.data.eccCurves.count; i++) - { - written = snprintf(pos, len, " %N", tpm_ecc_curve_names, - cap_data.data.eccCurves.eccCurves[i]); - if (written < 0 || written >= len) - { - break; - } - pos += written; - len -= written; - } - DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf); - - return TRUE; -} - -/** - * Initialize TSS2 TCTI TABRMD context - */ -static bool initialize_tcti_tabrmd_context(private_tpm_tss_tss2_t *this) -{ -#ifdef TSS2_TCTI_TABRMD - size_t tcti_context_size; - uint32_t rval; - - /* determine size of tcti context */ - rval = tss2_tcti_tabrmd_init(NULL, &tcti_context_size); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x", - LABEL, rval); - return FALSE; - } - - /* allocate and initialize memory for tcti context */ - this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size); - memset(this->tcti_context, 0x00, tcti_context_size); - - /* initialize tcti context */ - rval = tss2_tcti_tabrmd_init(this->tcti_context, &tcti_context_size); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x " - "via tabrmd interface", LABEL, rval); - return FALSE; - } - return TRUE; -#else /* TSS2_TCTI_TABRMD */ - return FALSE; -#endif /* TSS2_TCTI_TABRMD */ -} - -/** - * Initialize TSS2 TCTI Socket context - */ -static bool initialize_tcti_socket_context(private_tpm_tss_tss2_t *this) -{ -#ifdef TSS2_TCTI_SOCKET - size_t tcti_context_size; - uint32_t rval; - - TCTI_SOCKET_CONF rm_if_config = { TCTI_SOCKET_DEFAULT_ADDRESS, - TCTI_SOCKET_DEFAULT_PORT - }; - - /* determine size of tcti context */ - rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x", - LABEL, rval); - return FALSE; - } - - /* allocate memory for tcti context */ - this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size); - - /* initialize tcti context */ - rval = InitSocketTcti(this->tcti_context, &tcti_context_size, - &rm_if_config, 0); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x " - "via socket interface", LABEL, rval); - return FALSE; - } - return TRUE; -#else /* TSS2_TCTI_SOCKET */ - return FALSE; -#endif /* TSS2_TCTI_SOCKET */ -} - -/** - * Initialize TSS2 Sys context - */ -static bool initialize_sys_context(private_tpm_tss_tss2_t *this) -{ - uint32_t sys_context_size; - uint32_t rval; - - TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP, - TSS_SAPI_FIRST_FAMILY, - TSS_SAPI_FIRST_LEVEL, - TSS_SAPI_FIRST_VERSION - }; - - /* determine size of sys context */ - sys_context_size = Tss2_Sys_GetContextSize(0); - - /* allocate memory for sys context */ - this->sys_context = malloc(sys_context_size); - - /* initialize sys context */ - rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size, - this->tcti_context, &abi_version); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x", - LABEL, rval); - return FALSE; - } - - /* get a list of supported algorithms and ECC curves */ - return get_algs_capability(this); -} - -/** - * Finalize TSS context - */ -static void finalize_context(private_tpm_tss_tss2_t *this) -{ - if (this->tcti_context) - { - tss2_tcti_finalize(this->tcti_context); - free(this->tcti_context); - } - if (this->sys_context) - { - Tss2_Sys_Finalize(this->sys_context); - free(this->sys_context); - } -} - -METHOD(tpm_tss_t, get_version, tpm_version_t, - private_tpm_tss_tss2_t *this) -{ - return TPM_VERSION_2_0; -} - -METHOD(tpm_tss_t, get_version_info, chunk_t, - private_tpm_tss_tss2_t *this) -{ - return chunk_empty; -} - -/** - * read the public key portion of a TSS 2.0 AIK key from NVRAM - */ -bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle, - TPM2B_PUBLIC *public) -{ - uint32_t rval; - - TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } }; - TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } }; - - TPMS_AUTH_RESPONSE session_data; - TSS2_SYS_RSP_AUTHS sessions_data; - TPMS_AUTH_RESPONSE *session_data_array[1]; - - session_data_array[0] = &session_data; - sessions_data.rspAuths = &session_data_array[0]; - sessions_data.rspAuthsCount = 1; - - /* read public key for a given object handle from TPM 2.0 NVRAM */ - rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name, - &qualified_name, &sessions_data); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x", - LABEL, handle, rval); - return FALSE; - } - return TRUE; -} - -METHOD(tpm_tss_t, generate_aik, bool, - private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob, - chunk_t *aik_pubkey, chunk_t *identity_req) -{ - return FALSE; -} - -METHOD(tpm_tss_t, get_public, chunk_t, - private_tpm_tss_tss2_t *this, uint32_t handle) -{ - TPM2B_PUBLIC public = { { 0, } }; - TPM_ALG_ID sig_alg, digest_alg; - chunk_t aik_blob, aik_pubkey = chunk_empty; - - if (!read_public(this, handle, &public)) - { - return chunk_empty; - } - - aik_blob = chunk_create((u_char*)&public, sizeof(public)); - DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob); - - /* convert TSS 2.0 AIK public key blot into PKCS#1 format */ - switch (public.t.publicArea.type) - { - case TPM_ALG_RSA: - { - TPM2B_PUBLIC_KEY_RSA *rsa; - TPMT_RSA_SCHEME *scheme; - chunk_t aik_exponent, aik_modulus; - - scheme = &public.t.publicArea.parameters.rsaDetail.scheme; - sig_alg = scheme->scheme; - digest_alg = scheme->details.anySig.hashAlg; - - rsa = &public.t.publicArea.unique.rsa; - aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size); - aik_exponent = chunk_from_chars(0x01, 0x00, 0x01); - - /* subjectPublicKeyInfo encoding of AIK RSA key */ - if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, - NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus, - CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END)) - { - DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key " - "failed", LABEL); - return chunk_empty; - } - break; - } - case TPM_ALG_ECC: - { - TPMS_ECC_POINT *ecc; - TPMT_ECC_SCHEME *scheme; - chunk_t ecc_point; - uint8_t *pos; - - scheme = &public.t.publicArea.parameters.eccDetail.scheme; - sig_alg = scheme->scheme; - digest_alg = scheme->details.anySig.hashAlg; - - ecc = &public.t.publicArea.unique.ecc; - - /* allocate space for bit string */ - pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING, - 2 + ecc->x.t.size + ecc->y.t.size); - /* bit string length is a multiple of octets */ - *pos++ = 0x00; - /* uncompressed ECC point format */ - *pos++ = 0x04; - /* copy x coordinate of ECC point */ - memcpy(pos, ecc->x.t.buffer, ecc->x.t.size); - pos += ecc->x.t.size; - /* copy y coordinate of ECC point */ - memcpy(pos, ecc->y.t.buffer, ecc->y.t.size); - /* subjectPublicKeyInfo encoding of AIK ECC key */ - aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_build_known_oid(OID_EC_PUBLICKEY), - asn1_build_known_oid(ecc->x.t.size == 32 ? - OID_PRIME256V1 : OID_SECT384R1)), - ecc_point); - break; - } - default: - DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL); - return chunk_empty; - } - DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash", - tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg); - return aik_pubkey; -} - -/** - * Configure a PCR Selection assuming a maximum of 24 registers - */ -static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs, - hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel) -{ - TPM_ALG_ID alg_id; - uint32_t pcr; - - /* check if hash algorithm is supported by TPM */ - alg_id = hash_alg_to_tpm_alg_id(alg); - if (!is_supported_alg(this, alg_id)) - { - DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", - LABEL, hash_algorithm_short_names, alg); - return FALSE; - } - - /* initialize the PCR Selection structure,*/ - pcr_sel->count = 1; - pcr_sel->pcrSelections[0].hash = alg_id; - pcr_sel->pcrSelections[0].sizeofSelect = 3; - pcr_sel->pcrSelections[0].pcrSelect[0] = 0; - pcr_sel->pcrSelections[0].pcrSelect[1] = 0; - pcr_sel->pcrSelections[0].pcrSelect[2] = 0; - - /* set the selected PCRs */ - for (pcr = 0; pcr < PLATFORM_PCR; pcr++) - { - if (pcrs & (1 << pcr)) - { - pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) ); - } - } - return TRUE; -} - -METHOD(tpm_tss_t, read_pcr, bool, - private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value, - hash_algorithm_t alg) -{ - TPML_PCR_SELECTION pcr_selection; - TPML_DIGEST pcr_values; - - uint32_t pcr_update_counter, rval; - uint8_t *pcr_value_ptr; - size_t pcr_value_len; - - if (pcr_num >= PLATFORM_PCR) - { - DBG1(DBG_PTS, "%s maximum number of supported PCR is %d", - LABEL, PLATFORM_PCR); - return FALSE; - } - - if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection)) - { - return FALSE; - } - - /* initialize the PCR Digest structure */ - memset(&pcr_values, 0, sizeof(TPML_DIGEST)); - - /* read the PCR value */ - rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection, - &pcr_update_counter, &pcr_selection, &pcr_values, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x", - LABEL, rval); - return FALSE; - } - pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer; - pcr_value_len = (size_t) pcr_values.digests[0].t.size; - - *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len)); - - return TRUE; -} - -METHOD(tpm_tss_t, extend_pcr, bool, - private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value, - chunk_t data, hash_algorithm_t alg) -{ - uint32_t rval; - TPM_ALG_ID alg_id; - TPML_DIGEST_VALUES digest_values; - TPMS_AUTH_COMMAND session_data_cmd; - TPMS_AUTH_RESPONSE session_data_rsp; - TSS2_SYS_CMD_AUTHS sessions_data_cmd; - TSS2_SYS_RSP_AUTHS sessions_data_rsp; - TPMS_AUTH_COMMAND *session_data_cmd_array[1]; - TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; - - session_data_cmd_array[0] = &session_data_cmd; - session_data_rsp_array[0] = &session_data_rsp; - - sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; - sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; - - sessions_data_cmd.cmdAuthsCount = 1; - sessions_data_rsp.rspAuthsCount = 1; - - session_data_cmd.sessionHandle = TPM_RS_PW; - session_data_cmd.hmac.t.size = 0; - session_data_cmd.nonce.t.size = 0; - - *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; - - /* check if hash algorithm is supported by TPM */ - alg_id = hash_alg_to_tpm_alg_id(alg); - if (!is_supported_alg(this, alg_id)) - { - DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", - LABEL, hash_algorithm_short_names, alg); - return FALSE; - } - - digest_values.count = 1; - digest_values.digests[0].hashAlg = alg_id; - - switch (alg) - { - case HASH_SHA1: - if (data.len != HASH_SIZE_SHA1) - { - return FALSE; - } - memcpy(digest_values.digests[0].digest.sha1, data.ptr, - HASH_SIZE_SHA1); - break; - case HASH_SHA256: - if (data.len != HASH_SIZE_SHA256) - { - return FALSE; - } - memcpy(digest_values.digests[0].digest.sha256, data.ptr, - HASH_SIZE_SHA256); - break; - case HASH_SHA384: - if (data.len != HASH_SIZE_SHA384) - { - return FALSE; - } - memcpy(digest_values.digests[0].digest.sha384, data.ptr, - HASH_SIZE_SHA384); - break; - case HASH_SHA512: - if (data.len != HASH_SIZE_SHA512) - { - return FALSE; - } - memcpy(digest_values.digests[0].digest.sha512, data.ptr, - HASH_SIZE_SHA512); - break; - default: - return FALSE; - } - - /* extend PCR */ - rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &sessions_data_cmd, - &digest_values, &sessions_data_rsp); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x", - LABEL, pcr_num, rval); - return FALSE; - } - - /* get updated PCR value */ - return read_pcr(this, pcr_num, pcr_value, alg); -} - -METHOD(tpm_tss_t, quote, bool, - private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel, - hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode, - tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig) -{ - chunk_t quoted_chunk, qualified_signer, extra_data, clock_info, - firmware_version, pcr_select, pcr_digest; - hash_algorithm_t pcr_digest_alg; - bio_reader_t *reader; - uint32_t rval; - - TPM2B_DATA qualifying_data; - TPML_PCR_SELECTION pcr_selection; - TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } }; - TPMT_SIG_SCHEME scheme; - TPMT_SIGNATURE sig; - TPMI_ALG_HASH hash_alg; - TPMS_AUTH_COMMAND session_data_cmd; - TPMS_AUTH_RESPONSE session_data_rsp; - TSS2_SYS_CMD_AUTHS sessions_data_cmd; - TSS2_SYS_RSP_AUTHS sessions_data_rsp; - TPMS_AUTH_COMMAND *session_data_cmd_array[1]; - TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; - - session_data_cmd_array[0] = &session_data_cmd; - session_data_rsp_array[0] = &session_data_rsp; - - sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; - sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; - - sessions_data_cmd.cmdAuthsCount = 1; - sessions_data_rsp.rspAuthsCount = 1; - - session_data_cmd.sessionHandle = TPM_RS_PW; - session_data_cmd.hmac.t.size = 0; - session_data_cmd.nonce.t.size = 0; - - *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; - - qualifying_data.t.size = data.len; - memcpy(qualifying_data.t.buffer, data.ptr, data.len); - - scheme.scheme = TPM_ALG_NULL; - memset(&sig, 0x00, sizeof(sig)); - - /* set Quote mode */ - *quote_mode = TPM_QUOTE_TPM2; - - if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection)) - { - return FALSE; - } - - rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd, - &qualifying_data, &scheme, &pcr_selection, "ed, - &sig, &sessions_data_rsp); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval); - return FALSE; - } - quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size); - - reader = bio_reader_create(chunk_skip(quoted_chunk, 6)); - if (!reader->read_data16(reader, &qualified_signer) || - !reader->read_data16(reader, &extra_data) || - !reader->read_data (reader, 17, &clock_info) || - !reader->read_data (reader, 8, &firmware_version) || - !reader->read_data (reader, 10, &pcr_select) || - !reader->read_data16(reader, &pcr_digest)) - { - DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL); - reader->destroy(reader); - return FALSE; - } - reader->destroy(reader); - - DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest); - DBG2(DBG_PTS, "TPM Quote Info: %B", "ed_chunk); - DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer); - DBG2(DBG_PTS, "extraData: %B", &extra_data); - DBG2(DBG_PTS, "clockInfo: %B", &clock_info); - DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version); - DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select); - - /* extract signature */ - switch (sig.sigAlg) - { - case TPM_ALG_RSASSA: - case TPM_ALG_RSAPSS: - *quote_sig = chunk_clone( - chunk_create( - sig.signature.rsassa.sig.t.buffer, - sig.signature.rsassa.sig.t.size)); - hash_alg = sig.signature.rsassa.hash; - break; - case TPM_ALG_ECDSA: - case TPM_ALG_ECDAA: - case TPM_ALG_SM2: - case TPM_ALG_ECSCHNORR: - *quote_sig = chunk_cat("cc", - chunk_create( - sig.signature.ecdsa.signatureR.t.buffer, - sig.signature.ecdsa.signatureR.t.size), - chunk_create( - sig.signature.ecdsa.signatureS.t.buffer, - sig.signature.ecdsa.signatureS.t.size)); - hash_alg = sig.signature.ecdsa.hash; - break; - default: - DBG1(DBG_PTS, "%s unsupported %N signature algorithm", - LABEL, tpm_alg_id_names, sig.sigAlg); - return FALSE; - }; - - DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg); - pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg); - - DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig); - - /* Create and initialize Quote Info object */ - *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg, - pcr_digest); - (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info, - pcr_select); - (*quote_info)->set_version_info(*quote_info, firmware_version); - - return TRUE; -} - -METHOD(tpm_tss_t, sign, bool, - private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle, - signature_scheme_t scheme, chunk_t data, chunk_t pin, chunk_t *signature) -{ - key_type_t key_type; - hash_algorithm_t hash_alg; - uint32_t rval; - - TPM_ALG_ID alg_id; - TPM2B_MAX_BUFFER buffer; - TPM2B_DIGEST hash = { { sizeof(TPM2B_DIGEST)-2, } }; - TPMT_TK_HASHCHECK validation; - TPM2B_PUBLIC public = { { 0, } }; - TPMT_SIG_SCHEME sig_scheme; - TPMT_SIGNATURE sig; - TPMS_AUTH_COMMAND session_data_cmd; - TPMS_AUTH_RESPONSE session_data_rsp; - TSS2_SYS_CMD_AUTHS sessions_data_cmd; - TSS2_SYS_RSP_AUTHS sessions_data_rsp; - TPMS_AUTH_COMMAND *session_data_cmd_array[1]; - TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; - - session_data_cmd_array[0] = &session_data_cmd; - session_data_rsp_array[0] = &session_data_rsp; - - sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; - sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; - - sessions_data_cmd.cmdAuthsCount = 1; - sessions_data_rsp.rspAuthsCount = 1; - - session_data_cmd.sessionHandle = TPM_RS_PW; - session_data_cmd.nonce.t.size = 0; - session_data_cmd.hmac.t.size = 0; - - if (pin.len > 0) - { - session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2, - pin.len); - memcpy(session_data_cmd.hmac.t.buffer, pin.ptr, - session_data_cmd.hmac.t.size); - } - *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; - - key_type = key_type_from_signature_scheme(scheme); - hash_alg = hasher_from_signature_scheme(scheme, NULL); - - /* Check if hash algorithm is supported by TPM */ - alg_id = hash_alg_to_tpm_alg_id(hash_alg); - if (!is_supported_alg(this, alg_id)) - { - DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM", - LABEL, hash_algorithm_short_names, hash_alg); - return FALSE; - } - - /* Get public key */ - if (!read_public(this, handle, &public)) - { - return FALSE; - } - - if (key_type == KEY_RSA && public.t.publicArea.type == TPM_ALG_RSA) - { - sig_scheme.scheme = TPM_ALG_RSASSA; - sig_scheme.details.rsassa.hashAlg = alg_id; - } - else if (key_type == KEY_ECDSA && public.t.publicArea.type == TPM_ALG_ECC) - { - sig_scheme.scheme = TPM_ALG_ECDSA; - sig_scheme.details.ecdsa.hashAlg = alg_id; - - } - else - { - DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key", - LABEL, signature_scheme_names, scheme); - return FALSE; - } - - if (data.len <= MAX_DIGEST_BUFFER) - { - memcpy(buffer.t.buffer, data.ptr, data.len); - buffer.t.size = data.len; - - rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy, - &hash, &validation, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval); - return FALSE; - } - } - else - { - TPMI_DH_OBJECT sequence_handle; - TPM2B_AUTH null_auth; - - null_auth.t.size = 0; - rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth, - alg_id, &sequence_handle, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x", - LABEL, rval); - return FALSE; - } - - while (data.len > 0) - { - buffer.t.size = min(data.len, MAX_DIGEST_BUFFER); - memcpy(buffer.t.buffer, data.ptr, buffer.t.size); - data.ptr += buffer.t.size; - data.len -= buffer.t.size; - - rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle, - &sessions_data_cmd, &buffer, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x", - LABEL, rval); - return FALSE; - } - } - buffer.t.size = 0; - - rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle, - &sessions_data_cmd, &buffer, hierarchy, - &hash, &validation, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x", - LABEL, rval); - return FALSE; - } - } - - rval = Tss2_Sys_Sign(this->sys_context, handle, &sessions_data_cmd, &hash, - &sig_scheme, &validation, &sig, &sessions_data_rsp); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval); - return FALSE; - } - - /* extract signature */ - switch (scheme) - { - case SIGN_RSA_EMSA_PKCS1_SHA1: - case SIGN_RSA_EMSA_PKCS1_SHA2_256: - case SIGN_RSA_EMSA_PKCS1_SHA2_384: - case SIGN_RSA_EMSA_PKCS1_SHA2_512: - *signature = chunk_clone( - chunk_create( - sig.signature.rsassa.sig.t.buffer, - sig.signature.rsassa.sig.t.size)); - break; - case SIGN_ECDSA_256: - case SIGN_ECDSA_384: - case SIGN_ECDSA_521: - *signature = chunk_cat("cc", - chunk_create( - sig.signature.ecdsa.signatureR.t.buffer, - sig.signature.ecdsa.signatureR.t.size), - chunk_create( - sig.signature.ecdsa.signatureS.t.buffer, - sig.signature.ecdsa.signatureS.t.size)); - break; - case SIGN_ECDSA_WITH_SHA256_DER: - case SIGN_ECDSA_WITH_SHA384_DER: - case SIGN_ECDSA_WITH_SHA512_DER: - *signature = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_integer("c", - chunk_create( - sig.signature.ecdsa.signatureR.t.buffer, - sig.signature.ecdsa.signatureR.t.size)), - asn1_integer("c", - chunk_create( - sig.signature.ecdsa.signatureS.t.buffer, - sig.signature.ecdsa.signatureS.t.size))); - break; - default: - DBG1(DBG_PTS, "%s unsupported %N signature scheme", - LABEL, signature_scheme_names, scheme); - return FALSE; - }; - - return TRUE; -} - -METHOD(tpm_tss_t, get_random, bool, - private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer) -{ - size_t len, random_len= sizeof(TPM2B_DIGEST)-2; - TPM2B_DIGEST random = { { random_len, } }; - uint8_t *pos = buffer; - uint32_t rval; - - while (bytes > 0) - { - len = min(bytes, random_len); - - rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL); - if (rval != TSS2_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval); - return FALSE; - } - memcpy(pos, random.t.buffer, random.t.size); - pos += random.t.size; - bytes -= random.t.size; - } - - return TRUE; -} - -METHOD(tpm_tss_t, get_data, bool, - private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle, - chunk_t pin, chunk_t *data) -{ - uint16_t nv_size, nv_offset = 0; - uint32_t rval; - - TPM2B_NAME nv_name = { { sizeof(TPM2B_NAME)-2, } }; - TPM2B_NV_PUBLIC nv_public = { { 0, } }; - TPM2B_MAX_NV_BUFFER nv_data = { { sizeof(TPM2B_MAX_NV_BUFFER)-2, } }; - TPMS_AUTH_COMMAND session_data_cmd; - TPMS_AUTH_RESPONSE session_data_rsp; - TSS2_SYS_CMD_AUTHS sessions_data_cmd; - TSS2_SYS_RSP_AUTHS sessions_data_rsp; - TPMS_AUTH_COMMAND *session_data_cmd_array[1]; - TPMS_AUTH_RESPONSE *session_data_rsp_array[1]; - - /* get size of NV object */ - rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public, - &nv_name, 0); - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval); - return FALSE; - } - nv_size = nv_public.t.nvPublic.dataSize; - *data = chunk_alloc(nv_size); - - /*prepare NV read session */ - session_data_cmd_array[0] = &session_data_cmd; - session_data_rsp_array[0] = &session_data_rsp; - - sessions_data_cmd.cmdAuths = &session_data_cmd_array[0]; - sessions_data_rsp.rspAuths = &session_data_rsp_array[0]; - - sessions_data_cmd.cmdAuthsCount = 1; - sessions_data_rsp.rspAuthsCount = 1; - - session_data_cmd.sessionHandle = TPM_RS_PW; - session_data_cmd.nonce.t.size = 0; - session_data_cmd.hmac.t.size = 0; - - if (pin.len > 0) - { - session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2, - pin.len); - memcpy(session_data_cmd.hmac.t.buffer, pin.ptr, - session_data_cmd.hmac.t.size); - } - *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0; - - /* read NV data an NV buffer block at a time */ - while (nv_size > 0) - { - rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, - &sessions_data_cmd, min(nv_size, MAX_NV_BUFFER_SIZE), - nv_offset, &nv_data, &sessions_data_rsp); - - if (rval != TPM_RC_SUCCESS) - { - DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval); - chunk_free(data); - return FALSE; - } - memcpy(data->ptr + nv_offset, nv_data.t.buffer, nv_data.t.size); - nv_offset += nv_data.t.size; - nv_size -= nv_data.t.size; - } - - return TRUE; -} - -METHOD(tpm_tss_t, destroy, void, - private_tpm_tss_tss2_t *this) -{ - finalize_context(this); - free(this); -} - -/** - * See header - */ -tpm_tss_t *tpm_tss_tss2_create() -{ - private_tpm_tss_tss2_t *this; - bool available; - - INIT(this, - .public = { - .get_version = _get_version, - .get_version_info = _get_version_info, - .generate_aik = _generate_aik, - .get_public = _get_public, - .read_pcr = _read_pcr, - .extend_pcr = _extend_pcr, - .quote = _quote, - .sign = _sign, - .get_random = _get_random, - .get_data = _get_data, - .destroy = _destroy, - }, - ); - - available = initialize_tcti_tabrmd_context(this); - if (!available) - { - available = initialize_tcti_socket_context(this); - } - if (available) - { - available = initialize_sys_context(this); - } - DBG1(DBG_PTS, "TPM 2.0 via TSS2 %savailable", available ? "" : "not "); - - if (!available) - { - destroy(this); - return NULL; - } - return &this->public; -} - -#else /* TSS_TSS2 */ - -tpm_tss_t *tpm_tss_tss2_create() -{ - return NULL; -} - -#endif /* TSS_TSS2 */ - - |