aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2017-02-13 19:06:18 +0100
committerAndreas Steffen <andreas.steffen@strongswan.org>2017-02-21 20:37:32 +0100
commite8736028e6a228adc0072f112543cb8b64879397 (patch)
treedfa9ea67ebb72883d27aed1901594d4e0e7b89aa /src
parent72fcce92d75c4db9179b7b4b62e25902103234de (diff)
downloadstrongswan-e8736028e6a228adc0072f112543cb8b64879397.tar.bz2
strongswan-e8736028e6a228adc0072f112543cb8b64879397.tar.xz
Implement signatures with private keys bound to TPM 2.0
Diffstat (limited to 'src')
-rw-r--r--src/libtpmtss/tpm_tss.h15
-rw-r--r--src/libtpmtss/tpm_tss_trousers.c10
-rw-r--r--src/libtpmtss/tpm_tss_tss2.c198
3 files changed, 215 insertions, 8 deletions
diff --git a/src/libtpmtss/tpm_tss.h b/src/libtpmtss/tpm_tss.h
index 4f4b9e2cf..270e7dfcf 100644
--- a/src/libtpmtss/tpm_tss.h
+++ b/src/libtpmtss/tpm_tss.h
@@ -120,6 +120,21 @@ struct tpm_tss_t {
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.
*/
void (*destroy)(tpm_tss_t *this);
diff --git a/src/libtpmtss/tpm_tss_trousers.c b/src/libtpmtss/tpm_tss_trousers.c
index 8be3ad877..550e6218a 100644
--- a/src/libtpmtss/tpm_tss_trousers.c
+++ b/src/libtpmtss/tpm_tss_trousers.c
@@ -582,6 +582,13 @@ err1:
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,
private_tpm_tss_trousers_t *this)
{
@@ -622,8 +629,9 @@ tpm_tss_t *tpm_tss_trousers_create()
.generate_aik = _generate_aik,
.get_public = _get_public,
.read_pcr = _read_pcr,
- .quote = _quote,
.extend_pcr = _extend_pcr,
+ .quote = _quote,
+ .sign = _sign,
.destroy = _destroy,
},
.load_aik = _load_aik,
diff --git a/src/libtpmtss/tpm_tss_tss2.c b/src/libtpmtss/tpm_tss_tss2.c
index d0f76ac45..358961745 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,196 @@ 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, destroy, void,
private_tpm_tss_tss2_t *this)
{
@@ -670,6 +853,7 @@ tpm_tss_t *tpm_tss_tss2_create()
.read_pcr = _read_pcr,
.extend_pcr = _extend_pcr,
.quote = _quote,
+ .sign = _sign,
.destroy = _destroy,
},
);