最近更新时间:2012/6/14 10:24
参考书籍《可信计算》(A Practical Guide of Trusted Computing, 机械工业出版社)。
详细讲解书中 第八章--使用TPM密钥 的示例,因为openssl的开发库变动,所以使用不同的openssl API不保证成功,书中代码有一些不能直接调试通过,我对无法通过的部分做了改动,下面部分经测试无误,但仍然不完整,仅进行到创建AIK这一步,创建AIK的过程可能会另开一篇博文。
另需要注意的是,由于我的openssl-tpm-engine无法安装成功,所以关于openssl我使用了一些内嵌的函数实现,而非直接使用openssl-tpm-engine的API,下面是代码部分:
MyFunc_KeyHierarchy.c:
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <tss/platform.h>
- #include <tss/tss_typedef.h>
- #include <tss/tss_structs.h>
- #include <tss/tss_defines.h>
- #include <tss/tspi.h>
- #include <openssl/rsa.h>
- #include <openssl/err.h>
- #include <openssl/ssl.h>
- //下面三个参数在书中都没有定义,此处为我本人主动定义
- #define ENTROPY_SIZE 10
- #define MAX_PASS_LEN 4097
- #define RANDOM_DEVICE "/dev/random"
- #define SOFTWARE_KEY_FILE_PATH "/home/darcy/exercise/TPM/test.key"
- #define CA_KEY_FILE_PATH "/home/darcy/exercise/TPM/test1.key"
- TSS_HCONTEXT hContext;
- TSS_HKEY hSRK;
- TSS_HTPM hTPM;
- //获取错误信息,工具函数
- const char *get_error(TSS_RESULT res)
- {
- switch(ERROR_CODE(res))
- {
- case 0x0001L:
- return "Authentication failed";
- case TSS_SUCCESS:
- return "success";
- case TSS_E_INVALID_HANDLE:
- return "hContext or phObject is an invalid handle";
- case TSS_E_BAD_PARAMETER:
- return "persistent storage type is not valid/One or more parameters is incorrect";
- case TSS_E_INTERNAL_ERROR:
- return "an error occurred internal to the TSS";
- case TSS_E_PS_KEY_NOTFOUND:
- return "NOT FOUND SRK";
- case TSS_E_INVALID_ATTRIB_FLAG:
- return "attrib flag is incorrect";
- case TSS_E_INVALID_ATTRIB_SUBFLAG:
- return "subflag is incorrect";
- case TSS_E_INVALID_ATTRIB_DATA:
- return "ulAttrib is incorrect";
- case TSS_E_KEY_ALREADY_REGISTERED:
- return "UUID used";
- case TSS_E_KEY_NOT_LOADED:
- return "the addressed key is currently not loaded";
- default:
- return "unknown error";
- }
- }
- //判断操作是否成功
- void
- Assert(TSS_RESULT result, char *functionName)
- {
- if(result != TSS_SUCCESS)
- {
- printf("%s Error: %s\n", functionName, get_error(result));
- exit(1);
- }
- }
- //计算size,返回密钥大小
- TSS_FLAG
- get_tss_key_size(UINT32 size)
- {
- if(size <= 512){
- return TSS_KEY_SIZE_512;
- }else if(size <= 1024){
- return TSS_KEY_SIZE_1024;
- }else if(size <= 2048){
- return TSS_KEY_SIZE_2048;
- }else if(size <= 4096){
- return TSS_KEY_SIZE_4096;
- }else if(size <= 8192){
- return TSS_KEY_SIZE_8192;
- }else if(size <= 16384){
- return TSS_KEY_SIZE_16384;
- }
- return TSS_KEY_SIZE_2048;
- }
- void
- openssl_print_errors()
- {
- ERR_load_ERR_strings();
- ERR_load_crypto_strings();
- ERR_print_errors_fp(stderr);
- }
- RSA *
- openssl_read_key(char *filename)
- {
- BIO *b = NULL;
- RSA *rsa = NULL;
- b = BIO_new_file(filename, "r");
- if (b == NULL) {
- fprintf(stderr, "Error opening file for read: %s\n", filename);
- return NULL;
- }
- if ((rsa = PEM_read_bio_RSAPrivateKey(b, NULL, 0, NULL)) == NULL) {
- fprintf(stderr, "Reading key %s from disk failed.\n", filename);
- openssl_print_errors();
- }
- BIO_free(b);
- return rsa;
- }
- int
- openssl_get_modulus_and_prime(RSA *rsa, unsigned int *size_n, unsigned char *n,
- unsigned int *size_p, unsigned char *p)
- {
- /* get the modulus from the RSA object */
- if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) {
- openssl_print_errors();
- return -1;
- }
- /* get one of the primes from the RSA object */
- if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) {
- openssl_print_errors();
- return -1;
- }
- return 0;
- }
- //获取系统随机数函数
- TSS_RESULT
- MyFunc_GetRandom(UINT32 size, BYTE *data)
- {
- FILE *f = NULL;
- f = fopen(RANDOM_DEVICE, "r");
- if (f == NULL) {
- //书中采用了LogError函数,此处我直接使用printf
- printf("open of %s failed: %s", RANDOM_DEVICE,
- strerror(errno));
- return TSS_E_INTERNAL_ERROR;
- }
- if (fread(data, size, 1, f) == 0) {
- printf("fread of %s failed: %s", RANDOM_DEVICE,
- strerror(errno));
- fclose(f);
- return TSS_E_INTERNAL_ERROR;
- }
- fclose(f);
- return TSS_SUCCESS;
- }
- TSS_RESULT
- MyFunc_CreateTPMKey(TSS_HKEY hParentKey,
- TSS_FLAG initFlags,
- TSS_HPCRS hPcrs,
- TSS_HKEY *hKey)
- {
- TSS_RESULT result;
- TSS_HPOLICY hPolicy;
- char *secret = "test";
- /* create the key object */
- result = Tspi_Context_CreateObject(hContext,TSS_OBJECT_TYPE_RSAKEY,
- initFlags, hKey);
- if (result) {
- printf("Tspi_Context_CreateObject failed: %s\n",
- get_error(result));
- return result;
- }
- /* Get the policy object, implicitly created when we created the
- * key object */
- result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY,TSS_POLICY_USAGE, &hPolicy);
- if (result) {
- printf("Tspi_GetPolicyObject failed: %s\n", get_error(result));
- Tspi_Context_CloseObject(hContext, *hKey);
- return result;
- }
- /* If we’re creating this key with no password, set the secret
- * mode so that the popup will be supressed */
- if (!(initFlags & TSS_KEY_AUTHORIZATION)) {
- result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE,
- 0, NULL);
- if(result)
- {
- printf("Tspi_Policy_SetSecret error: %s\n", get_error(result));
- }
- }
- /* Make the call to the TPM to create the key */
- result = Tspi_Key_CreateKey(*hKey, hParentKey, hPcrs);
- if (result) {
- printf("Tspi_Key_CreateKey failed: %s\n", get_error(result));
- Tspi_Context_CloseObject(hContext, *hKey);
- return result;
- }
-
- if(result == TSS_SUCCESS)
- {
- printf("Create TPM key succeed!\n");
- }
- return TSS_SUCCESS;
- }
- TSS_RESULT
- MyFunc_WrapKey(char *path,
- TSS_HKEY hParentKey,
- TSS_FLAG initFlags,
- TSS_HPCRS hPcrs,
- TSS_HKEY *hKey)
- {
- RSA *rsa;
- UINT32 pubKeyLen;
- BYTE *pubKey;
- TSS_RESULT result;
- unsigned char n[2048], p[2048];
- int sizeN, sizeP;
- UINT32 keySize;
- TSS_HPOLICY keyMigPolicy;
- /* Read in the plaintext key from disk. */
- if ((rsa = openssl_read_key(path)) == NULL) {
- printf("Failed opening OpenSSL key file!\n");
- return TSS_E_FAIL;
- }
- /* Pull the SRK’s pub key into the hSRK object. Note that this is
- * not necessary for any key but the SRK. The SRK’s pub key is not
- * stored in system persistent storage as other keys are. This
- * protects it from being loaded by unauthorized users who could
- * then use it to identify the machine from across the Internet. */
- //result = Tspi_Key_GetPubKey(hSRK, &pubKeyLen, &pubKey);
- result = Tspi_TPM_OwnerGetSRKPubKey(hTPM, &pubKeyLen, &pubKey);
- if (result != TSS_SUCCESS) {
- printf("Tspi_Key_GetPubKey failed: %s\n", get_error(result));
- RSA_free(rsa);
- printf("Error code:%d!\n", result);
- return result;
- }
- /* Free here since the pubKey data is stored internally to the
- * hSRK object in addition to being returned above */
- //Tspi_Context_FreeMemory(hContext, pubKey);
- /* convert the OpenSSL key’s size in bits to a TSS key size flag
- * suitable for including in initFlags. */
- if ((keySize = get_tss_key_size(RSA_size(rsa) * 8)) == 0){
- return TSS_E_BAD_PARAMETER;
- }
- /* create the TSS key object */
- /*TSS_FLAG tempFlag = TSS_KEY_SIZE_2048|
- TSS_KEY_TYPE_STORAGE|
- TSS_KEY_AUTHORIZATION;*/
- result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
- keySize|initFlags, hKey);
- if (result != TSS_SUCCESS) {
- printf("Tspi_Context_CreateObject failed: %s\n",
- get_error(result));
- return result;
- }
- /*if This function handles the OpenSSL calls to extract the public N
- * and private P, parts of the software RSA key. Both of these
- * components will be put into the wrapped TSS key object. */
- if(openssl_get_modulus_and_prime(rsa, &sizeN, n, &sizeP, p) != 0) {
- Tspi_Context_CloseObject(hContext, *hKey);
- *hKey = 0;
- return result;
- }
- /* set the public key data in the TSS object */
- result = Tspi_SetAttribData(*hKey, TSS_TSPATTRIB_RSAKEY_INFO,
- TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
- sizeN, n);
- if (result != TSS_SUCCESS) {
- printf("Tspi_SetAttribData failed: %s; Error number:%.2x\n", get_error(result),result);
- Tspi_Context_CloseObject(hContext, *hKey);
- *hKey = 0;
- return result;
- }
- /* set the private key data in the TSS object */
- result = Tspi_SetAttribData(*hKey, TSS_TSPATTRIB_KEY_BLOB,
- TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY,
- sizeP, p);
- if (result != TSS_SUCCESS) {
- printf("Tspi_SetAttribData failed: %s\n", get_error(result));
- Tspi_Context_CloseObject(hContext, *hKey);
- *hKey = 0;
- return result;
- }
-
- result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, &keyMigPolicy);
- Assert(result, "Tspi_GetPolicyObject");
- BYTE wellKnownSecret[] = TSS_WELL_KNOWN_SECRET;
- result = Tspi_Policy_SetSecret(keyMigPolicy,TSS_SECRET_MODE_SHA1,
- 20, wellKnownSecret);
- Assert(result, "Tspi_Policy_SetSecret");
- result = Tspi_Policy_AssignToObject(keyMigPolicy, *hKey);
- Assert(result, "Tspi_Policy_AssignToObject");
- /* Call the TSS to do the key wrapping */
- result = Tspi_Key_WrapKey(*hKey, hParentKey, hPcrs);
- //result = Tspi_Key_CreateKey(*hKey, hParentKey, 0);
- if (result != TSS_SUCCESS) {
- printf("Tspi_Key_WrapKey failed: %s; Error number:%.2x\n", get_error(result), result);
- Tspi_Context_CloseObject(hContext, *hKey);
- *hKey = 0;
- }
- RSA_free(rsa);
- if(result ==TSS_SUCCESS)
- {
- printf("Wrap key succeed!\n");
- }
- return result;
- }
- /*create the key hierarchy*/
- int MyFunc_CreateKeyHierarchy()
- {
- //TSS_HCONTEXT hContext;
- //TSS_HTPM hTPM;
- TSS_HPOLICY hSRKPolicy, hTpmPolicy;
- BYTE entropyData[ENTROPY_SIZE];
- BYTE secretData[] = TSS_WELL_KNOWN_SECRET;
- int secretDataLen = TCPA_SHA1_160_HASH_LEN;
- BYTE tpmPasswd[] = "helloworld";
- int tpmPasswdLen = strlen(tpmPasswd);
- BYTE srkPasswd[] = "helloworld";
- //char *secretData = "helloworld";
- TSS_FLAG initFlags;
- TSS_UUID swMigKeyUuid, systemMigKeyUuid;
- TSS_HKEY hUserSWMigKey, hSystemMigKey, hKeyPcrs;
- TSS_HKEY hMigKeyBind, hSealingKey, hMAKey;
- TSS_HKEY hAIKey, hMtncKey;
- TSS_HPOLICY hUserSWMigKeyPolicy;
- TSS_HPCRS hPcrs;
- UINT32 pcrLen;
- BYTE *pcrValue;
- TSS_RESULT result;
- TSS_BOOL tpmState;
- BYTE userPass[MAX_PASS_LEN];
- BYTE *random;
- UINT32 aik_label_len, credSize;
- BYTE *aik_label, *cred;
- TSS_UUID AIKUuid;
- TSS_VALIDATION validationData;
- BYTE *ticket;
- UINT32 ticketLen;
- BYTE *mtncBlob, *migBlob;
- UINT32 mtncBlobLen, migBlobLen;
- int i; //loop index
- TSS_UUID SRK_UUID = TSS_UUID_SRK;
- /* OpenSSL objects */
- RSA *ca_rsa, *migration_pub_rsa, *maintenance_pub_rsa;
- /* Make any necessary setup calls to OpenSSL */
- //init_external_libraries();
- /* SSL init*/
- //书中使用的init_external_libraries找不到函数,用别的方式代替
- SSL_library_init();
- /* load all SSL */
- OpenSSL_add_all_algorithms();
- /* load all SSL error message */
- SSL_load_error_strings();
- Tspi_Context_Create(&hContext);
- Tspi_Context_Connect(hContext, NULL);
- result = Tspi_Context_GetTpmObject(hContext, &hTPM);
- if(result != TSS_SUCCESS)
- {
- printf("Tspi_Context_GetTpmObject Error: %s\n", get_error(result));
- exit(1);
- }
- /* Add entropy to the TPM’s random number generator from the
- * system’s random device */
- MyFunc_GetRandom(ENTROPY_SIZE, entropyData);
- Tspi_TPM_StirRandom(hTPM, ENTROPY_SIZE, entropyData);
- printf("Random number:");
- for(i=0; i<ENTROPY_SIZE; i++)
- {
- printf("%.2x ", entropyData[i]);
- }
- printf("\n");
- /* Load the SRK from storage in the System Persistent Store */
- result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID,
- &hSRK);
- Assert(result, "Tspi_Context_LoadKeyByUUID");
- /*get the tpm policy to take the tpm ownership*/
- result = Tspi_GetPolicyObject(hTPM, TSS_POLICY_USAGE, &hTpmPolicy);
- Assert(result, "Tspi_GetPolicyObject for TPM");
- result = Tspi_Policy_SetSecret(hTpmPolicy, TSS_SECRET_MODE_PLAIN,
- tpmPasswdLen, tpmPasswd);
- Assert(result, "Tspi_Policy_SetSecret");
- /* Set the SRK’s password since it will be referenced below */
- //changed by zw
- //hContext做第一个参数的时候,始终报错TSS_E_BAD_PARAMETER,所以替换成hSRK
- result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSRKPolicy);
- Assert(result, "Tspi_GetPolicyObject");
- result = Tspi_Policy_SetSecret(hSRKPolicy, TSS_SECRET_MODE_PLAIN,
- strlen(srkPasswd), srkPasswd);
- //同样,因为我的机器上SRK没有设置密码认证,所有密钥模式为TSS_SECRET_MODE_NONE
- //result = Tspi_Policy_SetSecret(hSRKPolicy, TSS_SECRET_MODE_NONE,
- // 0, NULL);
- Assert(result, "Tspi_Policy_SetSecret");
- /*take ownership*/
- //result = Tspi_TPM_TakeOwnership(hTPM, hSRK, 0);
- //Assert(result, "Tspi_TPM_TakeOwnership");
- /* Wrap the software generated key with the SRK’s public key.
- * initFlags is set to make this key a migratable storage key
- * that requires a password. */
- initFlags = TSS_KEY_TYPE_STORAGE | TSS_KEY_MIGRATABLE |
- TSS_KEY_AUTHORIZATION;
-
- MyFunc_WrapKey(SOFTWARE_KEY_FILE_PATH, hSRK, initFlags, 0,
- &hUserSWMigKey);
-
- /* Register the wrapped key in user persistent storage */
- result = Tspi_Context_RegisterKey(hContext, hUserSWMigKey,
- TSS_PS_TYPE_USER, swMigKeyUuid,
- TSS_PS_TYPE_SYSTEM, SRK_UUID);
- Assert(result, "Tspi_Context_RegisterKey");
-
- result = Tspi_GetPolicyObject(hUserSWMigKey, TSS_POLICY_USAGE,
- &hUserSWMigKeyPolicy);
- Assert(result, "Tspi_GetPolicyObject");
- sprintf(userPass, "helloworld");
- Tspi_Policy_SetSecret(hUserSWMigKeyPolicy, TSS_SECRET_MODE_PLAIN,
- strlen(userPass), userPass);
- /* Zero-out the password entered, keeping it in memory for the
- * smallest amount of time possible */
- memset(userPass, 0, MAX_PASS_LEN);
- /* create a non-migratable signing key not bound to any PCRs */
- initFlags = TSS_KEY_TYPE_SIGNING | TSS_KEY_SIZE_2048 |
- TSS_KEY_NOT_MIGRATABLE;
- /* Pass ‘0’ as the handle to the PCRs object, to keep the TSS from
- * binding this key to any PCRs */
- MyFunc_CreateTPMKey(hSRK, initFlags, 0, &hSystemMigKey);
- /* Register the key in system persistent storage */
- Tspi_Context_RegisterKey(hContext, hSystemMigKey, TSS_PS_TYPE_SYSTEM,
- systemMigKeyUuid, TSS_PS_TYPE_SYSTEM,
- SRK_UUID);
- /* Create a PCR composite object with the current values of PCRs
- * 4 and 5 */
- Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_PCRS, 0, &hPcrs);
- Tspi_TPM_PcrRead(hTPM, 4, &pcrLen, &pcrValue);
- Tspi_PcrComposite_SetPcrValue(hPcrs, 4, pcrLen, pcrValue);
- /* Free the pcrValue data returned from the Tspi_TPM_PcrRead()
- * function. At this point, the value of the PCR register has been
- * copied into the PCR object hPcrs by the TSS. */
- Tspi_Context_FreeMemory(hContext, pcrValue);
- Tspi_TPM_PcrRead(hTPM, 5, &pcrLen, &pcrValue);
- Tspi_PcrComposite_SetPcrValue(hPcrs, 5, pcrLen, pcrValue);
- Tspi_Context_FreeMemory(hContext, pcrValue);
- /* Create a non-migratable signing key bound to PCRs 4 and 5 */
- initFlags = TSS_KEY_TYPE_SIGNING | TSS_KEY_SIZE_2048 |
- TSS_KEY_NOT_MIGRATABLE;
- /*
- *Passing the hPcrs handle here ensures the new key is bound to
- *PCRs 4 and 5. If the value of those PCRs changes, the key will
- *become unusable until a platform reset can return them to their
- *present state */
- MyFunc_CreateTPMKey(hSRK, initFlags, hPcrs, &hKeyPcrs);
- /* Read in the Privacy CA’s key from disk */
- ca_rsa = openssl_read_key(CA_KEY_FILE_PATH);
- aik_label = "My Identity Label";
- aik_label_len = strlen(aik_label) + 1;
- /*Create AIK*/
- /*MyFunc_CreateAIK(ca_rsa, aik_label, aik_label_len, &hAIKey,
- &credSize, cred);
- */
- return 0;
- }
- int main(void)
- {
- MyFunc_CreateKeyHierarchy();
- return 0;
- }
编译方法:
gcc -g -o MyFunc_KeyHierarchy MyFunc_KeyHierarchy.c -ltspi -lcrypto -lssl
(未完待续...)
阅读(8287) | 评论(1) | 转发(0) |