diff options
Diffstat (limited to 'src/libtpmtss/tpm_tss_tss2.c')
-rw-r--r-- | src/libtpmtss/tpm_tss_tss2.c | 225 |
1 files changed, 218 insertions, 7 deletions
diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c index d0f76ac45..9a4b9a40c 100644 --- a/src/libtpmtss/tpm_tss_tss2.c +++ b/src/libtpmtss/tpm_tss_tss2.c @@ -317,16 +317,9 @@ bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle, sessions_data.rspAuths = &session_data_array[0]; sessions_data.rspAuthsCount = 1; - /* always send simulator platform command, ignored by true RM */ - PlatformCommand(this->tcti_context ,MS_SIM_POWER_ON ); - PlatformCommand(this->tcti_context, MS_SIM_NV_ON ); - /* 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); - - PlatformCommand(this->tcti_context, MS_SIM_POWER_OFF); - if (rval != TPM_RC_SUCCESS) { DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x", @@ -646,6 +639,222 @@ METHOD(tpm_tss_t, quote, bool, 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); + + /* 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, destroy, void, private_tpm_tss_tss2_t *this) { @@ -670,6 +879,8 @@ tpm_tss_t *tpm_tss_tss2_create() .read_pcr = _read_pcr, .extend_pcr = _extend_pcr, .quote = _quote, + .sign = _sign, + .get_random = _get_random, .destroy = _destroy, }, ); |