aboutsummaryrefslogtreecommitdiffstats
path: root/src/libimcv/tcg
diff options
context:
space:
mode:
authorSansar Choinyambuu <schoinya@hsr.ch>2011-08-31 15:04:05 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2011-09-08 12:08:15 +0200
commit90c963439e1aa72b575dc05c6bd4d7d58a55fc30 (patch)
tree8d42263303e25f6cd80f43225aaab8496ff6f49a /src/libimcv/tcg
parent46fd48797df3c7067ddce20987b39b9bd63bc2cd (diff)
downloadstrongswan-90c963439e1aa72b575dc05c6bd4d7d58a55fc30.tar.bz2
strongswan-90c963439e1aa72b575dc05c6bd4d7d58a55fc30.tar.xz
Started implementing obtaining of AIK
Diffstat (limited to 'src/libimcv/tcg')
-rw-r--r--src/libimcv/tcg/pts/pts.c342
-rw-r--r--src/libimcv/tcg/pts/pts.h1
2 files changed, 341 insertions, 2 deletions
diff --git a/src/libimcv/tcg/pts/pts.c b/src/libimcv/tcg/pts/pts.c
index a19cb1624..de3345977 100644
--- a/src/libimcv/tcg/pts/pts.c
+++ b/src/libimcv/tcg/pts/pts.c
@@ -18,14 +18,31 @@
#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,
diff --git a/src/libimcv/tcg/pts/pts.h b/src/libimcv/tcg/pts/pts.h
index 63e718c42..f88effa8d 100644
--- a/src/libimcv/tcg/pts/pts.h
+++ b/src/libimcv/tcg/pts/pts.h
@@ -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;