Implement signatures with private keys bound to TPM 2.0
This commit is contained in:
parent
72fcce92d7
commit
e8736028e6
|
@ -119,6 +119,21 @@ struct tpm_tss_t {
|
||||||
tpm_quote_mode_t *quote_mode,
|
tpm_quote_mode_t *quote_mode,
|
||||||
tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig);
|
tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a signature over a data hash using a TPM key handle (TPM 2.0 only)
|
||||||
|
*
|
||||||
|
* @param handle object handle of TPM key to be used for signature
|
||||||
|
* @param hierarchy hierarchy the TPM key object is attached to
|
||||||
|
* @param scheme scheme to be used for signature
|
||||||
|
* @param data data to be hashed and signed
|
||||||
|
* @param pin PIN code or empty chunk
|
||||||
|
* @param signature returns signature
|
||||||
|
* @return TRUE if signature succeeded
|
||||||
|
*/
|
||||||
|
bool (*sign)(tpm_tss_t *this, uint32_t hierarchy, uint32_t handle,
|
||||||
|
signature_scheme_t scheme, chunk_t data, chunk_t pin,
|
||||||
|
chunk_t *signature);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a tpm_tss_t.
|
* Destroy a tpm_tss_t.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -582,6 +582,13 @@ err1:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(tpm_tss_t, sign, bool,
|
||||||
|
private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
|
||||||
|
signature_scheme_t scheme, chunk_t data, chunk_t pin, chunk_t *signature)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(tpm_tss_t, destroy, void,
|
METHOD(tpm_tss_t, destroy, void,
|
||||||
private_tpm_tss_trousers_t *this)
|
private_tpm_tss_trousers_t *this)
|
||||||
{
|
{
|
||||||
|
@ -622,8 +629,9 @@ tpm_tss_t *tpm_tss_trousers_create()
|
||||||
.generate_aik = _generate_aik,
|
.generate_aik = _generate_aik,
|
||||||
.get_public = _get_public,
|
.get_public = _get_public,
|
||||||
.read_pcr = _read_pcr,
|
.read_pcr = _read_pcr,
|
||||||
.quote = _quote,
|
|
||||||
.extend_pcr = _extend_pcr,
|
.extend_pcr = _extend_pcr,
|
||||||
|
.quote = _quote,
|
||||||
|
.sign = _sign,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.load_aik = _load_aik,
|
.load_aik = _load_aik,
|
||||||
|
|
|
@ -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.rspAuths = &session_data_array[0];
|
||||||
sessions_data.rspAuthsCount = 1;
|
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 */
|
/* read public key for a given object handle from TPM 2.0 NVRAM */
|
||||||
rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
|
rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
|
||||||
&qualified_name, &sessions_data);
|
&qualified_name, &sessions_data);
|
||||||
|
|
||||||
PlatformCommand(this->tcti_context, MS_SIM_POWER_OFF);
|
|
||||||
|
|
||||||
if (rval != TPM_RC_SUCCESS)
|
if (rval != TPM_RC_SUCCESS)
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
|
DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
|
||||||
|
@ -646,6 +639,196 @@ METHOD(tpm_tss_t, quote, bool,
|
||||||
return TRUE;
|
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, destroy, void,
|
METHOD(tpm_tss_t, destroy, void,
|
||||||
private_tpm_tss_tss2_t *this)
|
private_tpm_tss_tss2_t *this)
|
||||||
{
|
{
|
||||||
|
@ -670,6 +853,7 @@ tpm_tss_t *tpm_tss_tss2_create()
|
||||||
.read_pcr = _read_pcr,
|
.read_pcr = _read_pcr,
|
||||||
.extend_pcr = _extend_pcr,
|
.extend_pcr = _extend_pcr,
|
||||||
.quote = _quote,
|
.quote = _quote,
|
||||||
|
.sign = _sign,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue