Started implementing obtaining of AIK
authorSansar Choinyambuu <schoinya@hsr.ch>
Wed, 31 Aug 2011 13:04:05 +0000 (15:04 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Sep 2011 10:08:15 +0000 (12:08 +0200)
src/libimcv/Makefile.am
src/libimcv/tcg/pts/pts.c
src/libimcv/tcg/pts/pts.h

index 0791b54..133e824 100644 (file)
@@ -3,7 +3,7 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libtncif
 
 ipseclib_LTLIBRARIES = libimcv.la
 
-libimcv_la_LIBADD = $(top_builddir)/src/libtncif/libtncif.la -ltspi
+libimcv_la_LIBADD = $(top_builddir)/src/libtncif/libtncif.la -ltspi -lcurl
 
 libimcv_la_SOURCES = \
        imcv.h imcv.c \
index a19cb16..de33459 100644 (file)
 #include <debug.h>
 #include <crypto/hashers/hasher.h>
 
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+
+#include <curl/curl.h>
+
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
 
 #include <dirent.h>
 #include <errno.h>
 
+#include "fake_ek_cert.h"
+
 #define PTS_BUF_SIZE   32768
 
+/* Size of endorsement key in bytes */
+#define        EKSIZE          (2048/8)
+/* URL of Privacy CA */
+#define CAURL          "http://www.privacyca.com/"
+#define CERTURL                CAURL "api/pca/level%d?ResponseFormat=PEM"
+#define REQURL         CAURL "api/pca/level%d?ResponseFormat=Binary"
+
+/* TPM has EK Certificate */
+/* #define REALEK */
+
 typedef struct private_pts_t private_pts_t;
 
 /**
@@ -156,12 +173,333 @@ METHOD(pts_t, set_tpm_version_info, void,
 }
 
 /**
- * Obtain an AIK
+ * Create a fake endorsement key cert using system's actual EK 
+ */
+
+static bool makeEKCert(TSS_HCONTEXT hContext, TSS_HTPM hTPM, UINT32 *pCertLen, BYTE **pCert)
+{
+       TSS_RESULT      result;
+       TSS_HKEY        hPubek;
+       UINT32          modulusLen;
+       BYTE            *modulus;
+
+       result = Tspi_TPM_GetPubEndorsementKey (hTPM, TRUE, NULL, &hPubek);
+       if (result != TSS_SUCCESS)
+       {
+               goto err;
+       }
+       result = Tspi_GetAttribData (hPubek, TSS_TSPATTRIB_RSAKEY_INFO,
+               TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modulusLen, &modulus);
+       Tspi_Context_CloseObject (hContext, hPubek);
+       if (result != TSS_SUCCESS)
+       {
+               goto err;
+       }
+       if (modulusLen != 256) {
+               Tspi_Context_FreeMemory (hContext, modulus);
+               goto err;
+       }
+       *pCertLen = sizeof(fakeEKCert);
+       *pCert = malloc (*pCertLen);
+       memcpy (*pCert, fakeEKCert, *pCertLen);
+       memcpy (*pCert + 0xc6, modulus, modulusLen);
+       Tspi_Context_FreeMemory (hContext, modulus);
+
+       return TRUE;
+
+err:
+       DBG1(DBG_TNC, "TPM not available: tss error 0x%x", result);
+       return FALSE;
+}
+
+/** 
+ * Read the level N CA from privacyca.com 
+ * Assume Curl library has been initialized 
+ */
+
+static X509* readPCAcert (int level)
+{
+       CURL            *hCurl;
+       char            url[128];
+       FILE            *f_tmp = tmpfile();
+       X509            *x509;
+       int             result;
+
+       hCurl = curl_easy_init ();
+       DBG1(DBG_IMC, url, CERTURL, level);
+       curl_easy_setopt (hCurl, CURLOPT_URL, url);
+       curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (BYTE **)f_tmp);
+
+       if ((result = curl_easy_perform(hCurl))) {
+               DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d\n", result);
+               fclose(f_tmp);
+               return NULL;
+       }
+
+       rewind (f_tmp);
+       x509 = PEM_read_X509 (f_tmp, NULL, NULL, NULL);
+       fclose(f_tmp);
+
+       return x509;
+}
+
+
+/**
+ * Obtain an AIK, SRK and TPM Owner secret has to be both set to well known secret
+ * of 20 bytes of zero
  */
 static bool obtain_aik(chunk_t *aik, bool *is_naked_key)
 {
-       /* TODO: Start working here */
+       TSS_HCONTEXT    hContext;
+       TSS_HTPM        hTPM;
+       TSS_HKEY        hSRK;
+       TSS_HKEY        hPCAKey;
+       TSS_HKEY        hIdentKey;
+       TSS_HPOLICY     hSrkPolicy;
+       TSS_HPOLICY     hTPMPolicy;
+       TSS_UUID        SRK_UUID = TSS_UUID_SRK;
+       BYTE            secret[] = TSS_WELL_KNOWN_SECRET;
+       X509            *x509;
+       EVP_PKEY        *pcaKey;
+       RSA             *rsa = NULL;
+       CURL            *hCurl;
+       struct curl_slist *slist = NULL;
+       BYTE            n[16384/8];
+       int             size_n;
+       FILE            *f_tmp;
+       BYTE            *rgbTCPAIdentityReq;
+       UINT32          ulTCPAIdentityReqLength;
+       UINT32          initFlags = TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048  |
+                                       TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE;
+       BYTE            asymBuf[EKSIZE];
+       BYTE            *symBuf;
+       BYTE            *credBuf;
+       BYTE            *tbuf;
+       UINT32          asymBufSize;
+       UINT32          symBufSize;
+       UINT32          credBufSize;
+       BYTE            *blob;
+       UINT32          blobLen;
+#ifdef REALEK
+       const int       level = 1;
+#else
+       const int       level = 0;
+       BYTE            *ekCert = NULL;
+       UINT32          ekCertLen;
+#endif
+       char            url[128];
+       int             result;
+       
+       *aik = chunk_empty;
+       *is_naked_key = false;
+       
+       curl_global_init (CURL_GLOBAL_ALL);
+       DBG3(DBG_IMC, "Retrieving PCA certificate...\n");
+
+       x509 = readPCAcert (level);
+       if (x509 == NULL) {
+               DBG1(DBG_IMC, "Error reading PCA key\n");
+               goto err;
+       }
+       pcaKey = X509_get_pubkey(x509);
+       rsa = EVP_PKEY_get1_RSA(pcaKey);
+       if (rsa == NULL) {
+               DBG1(DBG_IMC, "Error reading RSA key from PCA\n");
+               goto err;
+       }
+       X509_free (x509);
+
+       result = Tspi_Context_Create(&hContext);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Create\n", result);
+               goto err;
+       }
+       result = Tspi_Context_Connect(hContext, NULL);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Connect\n", result);
+               goto err;
+       }
+       result = Tspi_Context_GetTpmObject (hContext, &hTPM);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_GetTpmObject\n", result);
+               goto err;
+       }
+       result = Tspi_Context_LoadKeyByUUID(hContext,
+                       TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK);
+        if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_LoadKeyByUUID for SRK\n", result);
+               goto err;
+       }
+       result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for SRK\n", result);
+               goto err;
+       }
+       result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for SRK\n", result);
+               goto err;
+       }
+       result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_GetPolicyObject for TPM\n", result);
+               goto err;
+       }
+       result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Policy_SetSecret for TPM\n", result);
+               goto err;
+       }
+
+       result = Tspi_Context_CreateObject(hContext,
+                                          TSS_OBJECT_TYPE_RSAKEY,
+                                          initFlags, &hIdentKey);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_CreateObject for key\n", result);
+               goto err;
+       }
+
+       result = Tspi_Context_CreateObject(hContext,
+                                          TSS_OBJECT_TYPE_RSAKEY,
+                                          TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048,
+                                          &hPCAKey);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_CreateObject for PCA\n", result);
+               goto err;
+       }
+       if ((size_n = BN_bn2bin(rsa->n, n)) <= 0) {
+               printf("BN_bn2bin failed\n");
+                goto err;;
+        }
+       result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
+               TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, size_n, n);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribData for PCA modulus\n", result);
+               goto err;
+       }
+       result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
+                                     TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
+                                     TSS_ES_RSAESPKCSV15);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_SetAttribUint32 for PCA encscheme\n", result);
+               goto err;
+       }
+
+#ifndef REALEK
+       result = makeEKCert(hContext, hTPM, &ekCertLen, &ekCert);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on makeEKCert\n", result);
+               goto err;
+       }
+
+       result = Tspi_SetAttribData(hTPM, TSS_TSPATTRIB_TPM_CREDENTIAL,
+                       TSS_TPMATTRIB_EKCERT, ekCertLen, ekCert);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on SetAttribData for EKCert\n", result);
+               goto err;
+       }
+#endif
+
+       DBG3(DBG_IMC, "Generating attestation identity key...\n");
+       result = Tspi_TPM_CollateIdentityRequest(hTPM, hSRK, hPCAKey, 0,
+                                                NULL, hIdentKey, TSS_ALG_AES,
+                                                &ulTCPAIdentityReqLength,
+                                                &rgbTCPAIdentityReq);
+       if (result != TSS_SUCCESS){
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_CollateIdentityRequest\n", result);
+               goto err;
+       }
+
+       DBG3(DBG_IMC, "Sending request to PrivacyCA.com...\n");
+
+       /* Send to server */
+       f_tmp = tmpfile();
+       hCurl = curl_easy_init ();
+       DBG3(DBG_IMC, "URL: %s\nRequest URL: %s\n Certificate Level: %d", url, REQURL, level);
+       curl_easy_setopt (hCurl, CURLOPT_URL, url);
+       curl_easy_setopt (hCurl, CURLOPT_POSTFIELDS, (void *)rgbTCPAIdentityReq);
+       curl_easy_setopt (hCurl, CURLOPT_POSTFIELDSIZE, ulTCPAIdentityReqLength);
+       curl_easy_setopt (hCurl, CURLOPT_WRITEDATA, (BYTE **)f_tmp);
+       slist = curl_slist_append (slist, "Pragma: no-cache");
+       slist = curl_slist_append (slist, "Content-Type: application/octet-stream");
+       slist = curl_slist_append (slist, "Content-Transfer-Encoding: binary");
+       curl_easy_setopt (hCurl, CURLOPT_HTTPHEADER, slist);
+       if ((result = curl_easy_perform(hCurl))) {
+               DBG1(DBG_IMC, "Unable to connect to Privacy CA, curl library result code %d\n", result);
+               exit (result);
+       }
+       curl_slist_free_all(slist);
+
+       DBG3(DBG_IMC, "Processing response from PrivacyCA...\n");
+
+       fflush (f_tmp);
+       symBufSize = ftell(f_tmp);
+       symBuf = malloc(symBufSize);
+       rewind(f_tmp);
+       if(!fread (symBuf, 1, symBufSize, f_tmp))
+       {
+               DBG1(DBG_IMC, "Failed to read buffer\n");
+               goto err;
+       }
+       
+       fclose (f_tmp);
+
+       asymBufSize = sizeof(asymBuf);
+       if (symBufSize <= asymBufSize)
+       {
+               DBG1(DBG_IMC, "Bad response from PrivacyCA.com: %s\n", symBuf);
+               goto err;
+       }
+
+       memcpy (asymBuf, symBuf, asymBufSize);
+       symBufSize -= asymBufSize;
+       symBuf += asymBufSize;
+
+       result = Tspi_Key_LoadKey (hIdentKey, hSRK);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_Key_LoadKey for AIK\n", result);
+               goto err;
+       }
+
+       result = Tspi_TPM_ActivateIdentity (hTPM, hIdentKey, asymBufSize, asymBuf,
+                                               symBufSize, symBuf,
+                                               &credBufSize, &credBuf);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_TPM_ActivateIdentity\n", result);
+               goto err;
+       }
+
+       /* Output key blob */
+       result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
+               TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
+       if (result != TSS_SUCCESS) {
+               DBG1(DBG_IMC, "Error 0x%x on Tspi_GetAttribData for key blob\n", result);
+               goto err;
+       }
+
+       /* TODO: Do something with blob variable */
+
+       Tspi_Context_FreeMemory (hContext, blob);
+
+       /* Output credential in PEM format */
+       tbuf = credBuf;
+       x509 = d2i_X509(NULL, (const BYTE **)&tbuf, credBufSize);
+       if (x509 == NULL) {
+               DBG1(DBG_IMC, "Unable to parse returned credential\n");
+               goto err;
+       }
+       if (tbuf-credBuf != credBufSize) {
+               DBG1(DBG_IMC, "Note, not all data from privacy ca was parsed correctly\n");
+       }
+       
+       /* TODO: Do something with X509 object */
+       X509_free (x509);
+
+       DBG3(DBG_IMC, "Succeeded at obtaining AIK Certificate from Privacy CA!\n");
        return TRUE;
+       
+err:
+       return FALSE;
 }
 
 METHOD(pts_t, get_aik, bool,
index 63e718c..f88effa 100644 (file)
@@ -27,6 +27,7 @@ typedef struct pts_t pts_t;
 #include "pts_meas_algo.h"
 #include <utils/linked_list.h>
 
+
 #include <library.h>
 
 typedef struct file_meas_entry_t file_meas_entry_t;