| /* Software-based Trusted Platform Module (TPM) Emulator |
| * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net> |
| * |
| * This module is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published |
| * by the Free Software Foundation; either version 2 of the License, |
| * or (at your option) any later version. |
| * |
| * This module is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * $Id: tpm_ticks.c 364 2010-02-11 10:24:45Z mast $ |
| */ |
| |
| #include "tpm_emulator.h" |
| #include "tpm_commands.h" |
| #include "tpm_data.h" |
| #include "tpm_handles.h" |
| #include "tpm_marshalling.h" |
| |
| /* |
| * Timing Ticks ([TPM_Part3], Section 23) |
| * The TPM timing ticks are always available for use. The association of |
| * timing ticks to actual time is a protocol that occurs outside of the TPM. |
| * See the design document for details. |
| */ |
| |
| TPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime) |
| { |
| info("TPM_GetTicks()"); |
| memcpy(currentTime, &tpmData.stany.data.currentTicks, |
| sizeof(TPM_CURRENT_TICKS)); |
| return TPM_SUCCESS; |
| } |
| |
| TPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay, |
| TPM_DIGEST *digestToStamp, TPM_AUTH *auth1, |
| TPM_CURRENT_TICKS *currentTicks, |
| UINT32 *sigSize, BYTE **sig) |
| { |
| TPM_RESULT res; |
| TPM_KEY_DATA *key; |
| BYTE *info, *ptr; |
| UINT32 info_length, len; |
| info("TPM_TickStampBlob()"); |
| /* get key */ |
| key = tpm_get_key(keyHandle); |
| if (key == NULL) return TPM_INVALID_KEYHANDLE; |
| /* verify authorization */ |
| if (auth1->authHandle != TPM_INVALID_HANDLE |
| || key->authDataUsage != TPM_AUTH_NEVER) { |
| res = tpm_verify_auth(auth1, key->usageAuth, keyHandle); |
| if (res != TPM_SUCCESS) return res; |
| } |
| if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY |
| && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE; |
| if (key->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) |
| return TPM_INAPPROPRIATE_SIG; |
| /* get current ticks */ |
| TPM_GetTicks(currentTicks); |
| /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */ |
| *sigSize = key->key.size >> 3; |
| *sig = tpm_malloc(*sigSize); |
| if (*sig == NULL) return TPM_FAIL; |
| /* setup TPM_SIGN_INFO structure */ |
| info_length = 30 + sizeof(TPM_DIGEST) + sizeof_TPM_CURRENT_TICKS(currentTicks); |
| info = tpm_malloc(info_length); |
| if (info == NULL) { |
| tpm_free(*sig); |
| return TPM_FAIL; |
| } |
| memcpy(&info[0], "\x00\x05TSTP", 6); |
| memcpy(&info[6], antiReplay->nonce, 20); |
| ptr = &info[26]; len = info_length - 26; |
| tpm_marshal_UINT32(&ptr, &len, info_length - 30); |
| memcpy(ptr, digestToStamp->digest, sizeof(TPM_DIGEST)); |
| ptr += sizeof(TPM_DIGEST); len -= sizeof(TPM_DIGEST); |
| if (tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks) |
| || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, info, info_length, *sig)) { |
| tpm_free(*sig); |
| tpm_free(info); |
| return TPM_FAIL; |
| } |
| return TPM_SUCCESS; |
| } |
| |
| void tpm_update_ticks(void) |
| { |
| if (tpmData.stany.data.currentTicks.tag == 0) { |
| tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS; |
| tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks(); |
| tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce, |
| sizeof(TPM_NONCE)); |
| tpmData.stany.data.currentTicks.tickRate = 1; |
| } else { |
| tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks(); |
| } |
| } |
| |