diff options
Diffstat (limited to 'src/libimcv/tcg')
-rw-r--r-- | src/libimcv/tcg/pts/pts.c | 342 | ||||
-rw-r--r-- | src/libimcv/tcg/pts/pts.h | 1 |
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; |