libtpmtss: Implemented TSS2 quote() method
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 16 Jun 2016 15:40:10 +0000 (17:40 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 26 Jun 2016 16:19:05 +0000 (18:19 +0200)
conf/plugins/imc-attestation.opt
src/libtpmtss/tpm_tss_tss2.c

index c2dbe42..925ac4e 100644 (file)
@@ -7,6 +7,9 @@ libimcv.plugins.imc-attestation.aik_cert =
 libimcv.plugins.imc-attestation.aik_pubkey =
        AIK public key file.
 
+libimcv.plugins.imc-attestation.aik_handle =
+       AIK object handle.
+
 libimcv.plugins.imc-attestation.mandatory_dh_groups = yes
        Enforce mandatory Diffie-Hellman groups.
 
index 5d8658b..81d659c 100644 (file)
@@ -393,18 +393,16 @@ METHOD(tpm_tss_t, get_public, chunk_t,
        return aik_pubkey;
 }
 
-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)
+/**
+ * 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)
 {
-    TPML_PCR_SELECTION  pcr_sel_in, pcr_sel_out;
-       TPML_DIGEST pcr_values;
        TPM_ALG_ID alg_id;
+       uint32_t pcr;
 
-       uint32_t pcr_update_counter, rval;
-       uint8_t *pcr_value_ptr;
-       size_t   pcr_value_len;
-
+       /* check if hash algorithm is supported by TPM */
        alg_id = hash_alg_to_tpm_alg_id(alg);
        if (!is_supported_alg(this, alg_id))
        {
@@ -413,6 +411,36 @@ METHOD(tpm_tss_t, read_pcr, bool,
                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",
@@ -420,23 +448,17 @@ METHOD(tpm_tss_t, read_pcr, bool,
                return FALSE;
        }
 
-       /* initialize the PCR Selection structure */
-       pcr_sel_in.count = 1;
-       pcr_sel_in.pcrSelections[0].hash = alg_id;
-       pcr_sel_in.pcrSelections[0].sizeofSelect = 3;
-       pcr_sel_in.pcrSelections[0].pcrSelect[0] = 0;
-       pcr_sel_in.pcrSelections[0].pcrSelect[1] = 0;
-       pcr_sel_in.pcrSelections[0].pcrSelect[2] = 0;
-
-       /* set the desired PCR */
-       pcr_sel_in.pcrSelections[0].pcrSelect[pcr_num / 8] = 1 << (pcr_num % 8);
+       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_sel_in,
-                               &pcr_update_counter, &pcr_sel_out, &pcr_values, 0);
+       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",
@@ -464,8 +486,102 @@ METHOD(tpm_tss_t, quote, bool,
        hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t mode, chunk_t *pcr_comp,
        chunk_t *quote_sig)
 {
-       /* TODO */
-       return FALSE;
+       chunk_t quote_info;
+       uint32_t rval;
+
+       TPM2B_DATA qualifying_data;
+       TPML_PCR_SELECTION  pcr_selection;
+       TPMS_ATTEST *attest;
+       TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } };
+       TPM2B_DIGEST digest;
+       TPMT_SIGNATURE sig;
+       TPMT_SIG_SCHEME scheme;
+       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));
+
+       if (mode == TPM_QUOTE || mode == TPM_QUOTE2_VERSION_INFO)
+       {
+               DBG1(DBG_PTS, "%s TPM Quote mode not supported", LABEL);
+               return FALSE;
+       }
+
+       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,  &quoted,
+                                                 &sig, &sessions_data_rsp);
+       if (rval != TPM_RC_SUCCESS)
+       {
+               DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
+               return FALSE;
+       }
+
+       attest = (TPMS_ATTEST *)quoted.t.attestationData;
+       digest = attest->attested.quote.pcrDigest;
+       *pcr_comp = chunk_clone(chunk_create(digest.t.buffer, digest.t.size));
+       DBG2(DBG_PTS, "Hash of PCR Composite: %#B", pcr_comp);
+
+       quote_info = chunk_create(quoted.t.attestationData, quoted.t.size);
+       DBG2(DBG_PTS, "TPM Quote Info: %B",&quote_info);
+
+       /* 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));
+                       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));
+                       break;
+               default:
+                       DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
+                                                  LABEL, tpm_alg_id_names, sig.sigAlg);
+                       return FALSE;
+       };
+       DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
+
+       return TRUE;
 }
 
 METHOD(tpm_tss_t, destroy, void,