Read AIK certificate/ AIK public key from file

This commit is contained in:
Sansar Choinyambuu
2011-09-08 12:08:16 +02:00
committed by Andreas Steffen
parent 05a1b347b2
commit 9816a29822
4 changed files with 101 additions and 376 deletions
@@ -288,17 +288,30 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
case TCG_PTS_GET_AIK:
{
chunk_t aik;
certificate_t *aik_cert;
public_key_t *aik_key;
bool is_naked_key;
if (!pts->get_aik(pts, &aik, &is_naked_key))
if (!pts->get_aik(pts, &aik_cert, &aik_key, &is_naked_key))
{
DBG1(DBG_IMC, "Obtaining AIK Certificate failed");
break;
}
/* Send AIK attribute */
attr = tcg_pts_attr_aik_create(is_naked_key, aik);
if(!is_naked_key && aik_cert)
{
attr = tcg_pts_attr_aik_create(is_naked_key, chunk_from_thing(aik_cert));
}
else if(is_naked_key && aik_key)
{
attr = tcg_pts_attr_aik_create(is_naked_key, chunk_from_thing(aik_key));
}
else
{
DBG1(DBG_IMC, "Neither AIK Certificate nor AIK public was provided");
break;
}
attr_list->insert_last(attr_list, attr);
break;
}
@@ -421,8 +421,26 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
attr_cast = (tcg_pts_attr_aik_t*)attr;
aik = attr_cast->get_aik(attr_cast);
is_naked_key = attr_cast->get_naked_flag(attr_cast);
pts->set_aik(pts, aik, is_naked_key);
if(!is_naked_key)
{
certificate_t *aik_cert;
aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_PEM, aik,
BUILD_END);
pts->set_aik_cert(pts, aik_cert);
}
else
{
public_key_t *aik_key;
aik_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
BUILD_BLOB_PEM, aik,
BUILD_END);
pts->set_aik_key(pts, aik_key);
}
attestation_state->set_handshake_state(attestation_state,
IMV_ATTESTATION_STATE_END);
break;
+51 -366
View File
@@ -80,9 +80,14 @@ struct private_pts_t {
chunk_t tpm_version_info;
/**
* Contains a Attestation Identity Key
* Contains a Attestation Identity Certificate
*/
chunk_t aik;
certificate_t *aik_cert;
/**
* Contains a Attestation Identity Public Key
*/
public_key_t *aik_key;
/**
* True if AIK is naked public key, not a certificate
@@ -101,7 +106,7 @@ METHOD(pts_t, set_proto_caps, void,
private_pts_t *this, pts_proto_caps_flag_t flags)
{
this->proto_caps = flags;
DBG2(DBG_TNC, "supported PTS protocol capabilities: %s%s%s%s%s",
DBG2(DBG_IMC, "supported PTS protocol capabilities: %s%s%s%s%s",
flags & PTS_PROTO_CAPS_C ? "C" : ".",
flags & PTS_PROTO_CAPS_V ? "V" : ".",
flags & PTS_PROTO_CAPS_D ? "D" : ".",
@@ -121,7 +126,7 @@ METHOD(pts_t, set_meas_algorithm, void,
hash_algorithm_t hash_alg;
hash_alg = pts_meas_to_hash_algorithm(algorithm);
DBG2(DBG_TNC, "selected PTS measurement algorithm is %N",
DBG2(DBG_IMC, "selected PTS measurement algorithm is %N",
hash_algorithm_names, hash_alg);
if (hash_alg != HASH_UNKNOWN)
{
@@ -142,12 +147,12 @@ static void print_tpm_version_info(private_pts_t *this)
this->tpm_version_info.ptr, &versionInfo);
if (result != TSS_SUCCESS)
{
DBG1(DBG_TNC, "could not parse tpm version info: tss error 0x%x",
DBG1(DBG_IMC, "could not parse tpm version info: tss error 0x%x",
result);
}
else
{
DBG2(DBG_TNC, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu,"
DBG2(DBG_IMC, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu,"
" Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s",
versionInfo.version.major, versionInfo.version.minor,
versionInfo.version.revMajor, versionInfo.version.revMinor,
@@ -188,396 +193,75 @@ METHOD(pts_t, set_tpm_version_info, void,
print_tpm_version_info(this);
}
/**
* Create a fake endorsement key cert using system's actual EK
*/
static TSS_RESULT 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)
{
DBG1(DBG_IMC, "Error in: Tspi_TPM_GetPubEndorsementKey");
return result;
}
result = Tspi_GetAttribData (hPubek, TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modulusLen, &modulus);
Tspi_Context_CloseObject (hContext, hPubek);
if (result != TSS_SUCCESS)
{
DBG1(DBG_IMC, "Error in: Tspi_Context_CloseObject");
return result;
}
if (modulusLen != 256)
{
DBG1(DBG_IMC, "Tspi_GetAttribData modulusLen != 256");
Tspi_Context_FreeMemory (hContext, modulus);
return result;
}
/* TODO define fakeEKCert
* pCertLen = sizeof(fakeEKCert);
*pCert = malloc (*pCertLen);
memcpy (*pCert, fakeEKCert, *pCertLen);
memcpy (*pCert + 0xc6, modulus, modulusLen);
*/
Tspi_Context_FreeMemory (hContext, modulus);
return TSS_SUCCESS;
}
/**
* 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 ();
sprintf (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", 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
* Obtain an AIK Certificate or public key
* If the certificate is available in give path, ignore whether key is there
* If certificate is not available take the public key at given path
*/
static bool obtain_aik(private_pts_t *this)
{
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;
static int level = 0;
BYTE *ekCert = NULL;
UINT32 ekCertLen = 0;
char url[128];
int result;
char *certificate_path;
char *key_path;
this->aik = chunk_empty;
this->is_naked_key = false;
certificate_path = lib->settings->get_str(lib->settings,
"libimcv.plugins.imc-attestation.aik_cert", NULL);
key_path = lib->settings->get_str(lib->settings,
"libimcv.plugins.imc-attestation.aik_key", NULL);
curl_global_init (CURL_GLOBAL_ALL);
DBG2(DBG_IMC,"AIK Certificate path %s",certificate_path);
DBG2(DBG_IMC,"AIK Public Key path %s", key_path);
DBG3(DBG_IMC, "Retrieving PCA certificate...");
/* TPM has EK Certificate */
if (REALEK)
if(certificate_path && (this->aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_FROM_FILE, certificate_path,
BUILD_END)))
{
level = 1;
this->is_naked_key = FALSE;
}
x509 = readPCAcert (level);
if (x509 == NULL)
else if(key_path && (this->aik_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
BUILD_FROM_FILE, key_path,
BUILD_END)))
{
DBG1(DBG_IMC, "Error reading PCA key");
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");
goto err;
}
X509_free (x509);
result = Tspi_Context_Create(&hContext);
if (result != TSS_SUCCESS)
{
DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Create", result);
goto err;
}
result = Tspi_Context_Connect(hContext, NULL);
if (result != TSS_SUCCESS)
{
DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_Connect", result);
goto err;
}
result = Tspi_Context_GetTpmObject (hContext, &hTPM);
if (result != TSS_SUCCESS)
{
DBG1(DBG_IMC, "Error 0x%x on Tspi_Context_GetTpmObject", 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", 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", 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", 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", 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", 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", 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", result);
goto err;
}
if ((size_n = BN_bn2bin(rsa->n, n)) <= 0)
{
DBG1(DBG_IMC, "BN_bn2bin failed");
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", 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", result);
goto err;
}
if (!REALEK)
{
result = makeEKCert(hContext, hTPM, &ekCertLen, &ekCert);
if (result != TSS_SUCCESS)
{
DBG1(DBG_IMC, "Error 0x%x on makeEKCert", 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", result);
goto err;
}
}
DBG3(DBG_IMC, "Generating attestation identity key...");
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", result);
goto err;
}
DBG3(DBG_IMC, "Sending request to PrivacyCA.com...");
/* Send to server */
f_tmp = tmpfile();
hCurl = curl_easy_init ();
sprintf (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", result);
exit (result);
}
curl_slist_free_all(slist);
DBG3(DBG_IMC, "Processing response from PrivacyCA...");
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");
goto err;
}
fclose (f_tmp);
asymBufSize = sizeof(asymBuf);
if (symBufSize <= asymBufSize)
{
DBG1(DBG_IMC, "Bad response from PrivacyCA.com: %s", 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", 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", result);
goto err;
}
/* 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");
goto err;
}
if (tbuf-credBuf != credBufSize)
{
DBG1(DBG_IMC, "Note, not all data from privacy ca was parsed correctly");
}
if (x509)
{
BUF_MEM *mem_buf;
BIO* bp;
u_int32_t len;
bp = BIO_new(BIO_s_mem());
PEM_write_bio_X509(bp, x509);
len = BIO_get_mem_data(bp, &mem_buf);
char tmp[len+1];
memcpy(tmp, mem_buf, len);
tmp[len] = '\0';
DBG3(DBG_IMC,"X509 Certificate (PEM format):");
DBG3(DBG_IMC,"%s", tmp);
this->aik = chunk_create(tmp, len + 1);
this->aik = chunk_clone(this->aik);
X509_free (x509);
this->is_naked_key = TRUE;
}
else
{
DBG1(DBG_IMC, "Neither AIK Key blob, nor AIK Certificate is available");
goto err;
DBG1(DBG_IMC, "Neither AIK Public Key nor AIK Certificate is available");
return FALSE;
}
DBG3(DBG_IMC, "Succeeded at obtaining AIK Certificate from Privacy CA!");
return TRUE;
err:
return FALSE;
}
METHOD(pts_t, get_aik, bool,
private_pts_t *this, chunk_t *aik, bool *is_naked_key)
private_pts_t *this, certificate_t **aik_cert, public_key_t **aik_key, bool *is_naked_key)
{
if (obtain_aik(this) != TRUE )
{
return FALSE;
}
*aik = this->aik;
*aik_cert = this->aik_cert;
*aik_key = this->aik_key;
*is_naked_key = this->is_naked_key;
return TRUE;
}
METHOD(pts_t, set_aik, void,
private_pts_t *this, chunk_t aik, bool is_naked_key)
METHOD(pts_t, set_aik_cert, void,
private_pts_t *this, certificate_t *aik_cert)
{
this->aik = chunk_clone(aik);
this->is_naked_key = is_naked_key;
this->aik_cert = aik_cert;
this->is_naked_key = FALSE;
}
METHOD(pts_t, set_aik_key, void,
private_pts_t *this, public_key_t *aik_key)
{
this->aik_key = aik_key;
this->is_naked_key = TRUE;
}
/**
@@ -749,7 +433,7 @@ static bool has_tpm(private_pts_t *this)
return TRUE;
err:
DBG1(DBG_TNC, "TPM not available: tss error 0x%x", result);
DBG1(DBG_IMC, "TPM not available: tss error 0x%x", result);
return FALSE;
}
@@ -771,7 +455,8 @@ pts_t *pts_create(bool is_imc)
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
.get_aik = _get_aik,
.set_aik = _set_aik,
.set_aik_cert = _set_aik_cert,
.set_aik_key = _set_aik_key,
.do_measurements = _do_measurements,
.destroy = _destroy,
},
+14 -5
View File
@@ -95,19 +95,28 @@ struct pts_t {
/**
* Get Attestation Identity Key
*
* @param aik chunk containing a AIK naked public key or certificate
* @param aik_cert structure containing a AIK naked public certificate
* @param aik_key structure containing a AIK naked public key
* @param is_naked_key TRUE if AIK is naked public key, without certificate
* @return TRUE if AIK available
*/
bool (*get_aik)(pts_t *this, chunk_t *aik, bool *is_naked_key);
bool (*get_aik)(pts_t *this, certificate_t **aik_cert, public_key_t **aik_key, bool *is_naked_key);
/**
* Set Attestation Identity Certificate
*
* @param aik_cert structure containing a AIK naked public certificate
* @param is_naked_key TRUE if AIK is naked public key, without certificate
*/
void (*set_aik_cert)(pts_t *this, certificate_t *aik_cert);
/**
* Set Attestation Identity Key
*
* @param aik chunk containing a AIK naked public key or certificate
* @param is_naked_key TRUE if AIK is naked public key, without certificate
* @param aik_key structure containing a AIK naked public key
* @param is_naked_key TRUE if AIK is naked public key, without certificate
*/
void (*set_aik)(pts_t *this, chunk_t aik, bool is_naked_key);
void (*set_aik_key)(pts_t *this, public_key_t *aik_key);
/**
* Do PTS File Measurements