Esempio n. 1
0
static int encode_message(int type, uint8_t *data, size_t data_len, 
                          uint8_t *msg, size_t msg_len)
{
  size_t i;
  sha1_ctx_t ctx;

  /* encode message according to type */
  switch (type) {
    case RSA_SSA_PKCS1_SHA1:
      /* EM = 0x00||0x01||0xff-pad||0x00||SHA-1 DER header||SHA-1 digest */
      if (msg_len < 35 + 11) return -1;
      msg[0] = 0x00; msg[1] = 0x01;
      memset(&msg[2], 0xff, msg_len - 38); 
      msg[msg_len - 36] = 0x00;
      memcpy(&msg[msg_len - 35], "\x30\x21\x30\x09\x06\x05\x2b"
        "\x0e\x03\x02\x1a\x05\x00\x04\x14", 15);
      sha1_init(&ctx);
      sha1_update(&ctx, data, data_len);
      sha1_final(&ctx, &msg[msg_len - 20]);
      break;
    case RSA_SSA_PKCS1_SHA1_RAW:
      /* EM = 0x00||0x01||0xff-pad||0x00||SHA-1 DER header||SHA-1 digest */
      if (msg_len < 35 + 11 || data_len != 20) return -1;
      msg[0] = 0x00; msg[1] = 0x01;
      memset(&msg[2], 0xff, msg_len - 38);
      msg[msg_len - 36] = 0x00;
      memcpy(&msg[msg_len - 35], "\x30\x21\x30\x09\x06\x05\x2b"
        "\x0e\x03\x02\x1a\x05\x00\x04\x14", 15);
      memcpy(&msg[msg_len - 20], data, data_len);
      break;
    case RSA_SSA_PKCS1_DER:
      /* EM = 0x00||0x01||0xff-pad||0x00||DER encoded data */
      if (msg_len < data_len + 11) return -1;
      msg[0] = 0x00; msg[1] = 0x01;
      memset(&msg[2], 0xff, msg_len - data_len - 3);
      msg[msg_len - data_len - 1] = 0x00;
      memcpy(&msg[msg_len - data_len], data, data_len);
      break;
    case RSA_ES_PKCSV15:
      /* EM = 0x00||0x02||nonzero random-pad||0x00||data */
      if (msg_len < data_len + 11) return -1;
      msg[0] = 0x00; msg[1] = 0x02;
      tpm_get_random_bytes(&msg[2], msg_len - data_len - 3);
      for (i = 2; i < msg_len - data_len; i++)
        while (!msg[i]) get_random_bytes(&msg[i], 1);
      msg[msg_len - data_len - 1] = 0x00;
      memcpy(&msg[msg_len - data_len], data, data_len);
      break;
    case RSA_ES_OAEP_SHA1:
      /* DB = SHA-1("TCPA")||0x00-pad||0x01||data
         seed = random value of size SHA1_DIGEST_LENGTH
         masked-seed = seed xor MFG(seed, seed_len)
         masked-DB = DB xor MFG(seed, DB_len)
         EM = 0x00||masked-seed||masked-DB */
      if (msg_len < data_len + 2 * SHA1_DIGEST_LENGTH + 2) return -1;
      msg[0] = 0x00;
      get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH);
      sha1_init(&ctx);
      sha1_update(&ctx, (uint8_t *) "TCPA", 4);
      sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]);
      memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00, 
        msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2);
      msg[msg_len - data_len - 1] = 0x01;
      memcpy(&msg[msg_len - data_len], data, data_len);
      mask_generation(&msg[1], SHA1_DIGEST_LENGTH, 
        &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);
      mask_generation(&msg[1 + SHA1_DIGEST_LENGTH], 
        msg_len - SHA1_DIGEST_LENGTH - 1, &msg[1], SHA1_DIGEST_LENGTH);
      break; 
    default:
      /* unsupported encoding method */
      return -1;
  }
  return 0;
}
Esempio n. 2
0
TPM_RESULT TPM_EstablishTransport(TPM_KEY_HANDLE encHandle,
                                  TPM_TRANSPORT_PUBLIC *transPublic,
                                  UINT32 secretSize, BYTE *secret,
                                  TPM_AUTH *auth1,
                                  TPM_TRANSHANDLE *transHandle,
                                  TPM_MODIFIER_INDICATOR *locality,
                                  TPM_CURRENT_TICKS *currentTicks,
                                  TPM_NONCE *transNonceEven)
{
  TPM_RESULT res;
  TPM_KEY_DATA *key;
  TPM_TRANSPORT_AUTH trans_auth;
  TPM_SESSION_DATA *session;

  info("TPM_EstablishTransport()");
  /* setup authorization data */
  if (encHandle == TPM_KH_TRANSPORT) {
    if (auth1->authHandle != TPM_INVALID_HANDLE) return TPM_BADTAG;
    if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) return TPM_BAD_SCHEME;
    if (secretSize != 20) return TPM_BAD_PARAM_SIZE;
    memcpy(trans_auth.authData, secret, 20);
  } else {
    /* get key and verify its usage */
    key = tpm_get_key(encHandle);
    if (key == NULL) return TPM_INVALID_KEYHANDLE;
    if (key->keyUsage != TPM_KEY_STORAGE && key->keyUsage != TPM_KEY_LEGACY)
        return TPM_INVALID_KEYUSAGE;
    /* verify authorization */ 
    if (key->authDataUsage != TPM_AUTH_NEVER) {
      res = tpm_verify_auth(auth1, key->usageAuth, encHandle);
      if (res != TPM_SUCCESS) return res;
      if (decrypt_transport_auth(key, secret, secretSize, &trans_auth))
        return TPM_DECRYPT_ERROR;
    }
  }
  /* check whether the transport has to be encrypted */
  if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) {
    if (tpmData.permanent.flags.FIPS
        && transPublic->algID == TPM_ALG_MGF1) return TPM_INAPPROPRIATE_ENC;
    /* until now, only MGF1 is supported */
    if (transPublic->algID != TPM_ALG_MGF1) return TPM_BAD_KEY_PROPERTY;
  }
  /* initialize transport session */
  tpm_get_random_bytes(transNonceEven->nonce, sizeof(transNonceEven->nonce));
  *transHandle = tpm_get_free_session(TPM_ST_TRANSPORT);
  session = tpm_get_transport(*transHandle);
  if (session == NULL) return TPM_RESOURCES;
  session->transInternal.transHandle = *transHandle;
  memset(&session->transInternal.transDigest, 0, sizeof(TPM_DIGEST));
  memcpy(&session->transInternal.transPublic, transPublic,
    sizeof_TPM_TRANSPORT_PUBLIC((*transPublic)));
  memcpy(&session->transInternal.transNonceEven, transNonceEven, sizeof(TPM_NONCE));
  memcpy(&session->nonceEven, transNonceEven, sizeof(TPM_NONCE));
  memcpy(&session->transInternal.authData, trans_auth.authData, sizeof(TPM_AUTHDATA));
  *locality = tpmData.stany.flags.localityModifier;
  memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS));
  /* perform transport logging */
  if (transPublic->transAttributes & TPM_TRANSPORT_LOG) {
    tpm_sha1_ctx_t sha1;
    BYTE *ptr, buf[4 + 4 + 4 + sizeof_TPM_CURRENT_TICKS(x) + 20];
    UINT32 len;
    /* log input */
    memset(buf, 0, sizeof(buf));
    transport_log_in(auth1->digest, buf, &session->transInternal.transDigest);
    /* compute digest of output parameters and log output */
    ptr = buf; len = sizeof(buf);
    tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS);
    tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_EstablishTransport);
    tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality);
    tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks);
    tpm_marshal_TPM_NONCE(&ptr, &len, transNonceEven);
    tpm_sha1_init(&sha1);
    tpm_sha1_update(&sha1, buf, sizeof(buf));
    tpm_sha1_final(&sha1, buf);
    transport_log_out(buf, &session->transInternal.transDigest);
  }
  /* check whether this is a exclusive transport session */
  if (transPublic->transAttributes & TPM_TRANSPORT_EXCLUSIVE) {
    tpmData.stany.flags.transportExclusive = TRUE;
    tpmData.stany.data.transExclusive = *transHandle;
  }
  auth1->continueAuthSession = FALSE;
  return TPM_SUCCESS;
}
Esempio n. 3
0
TPM_RESULT TPM_SaveContext(TPM_HANDLE handle, TPM_RESOURCE_TYPE resourceType,
                           const BYTE label[16], UINT32 *contextSize,
                           TPM_CONTEXT_BLOB *contextBlob)
{
  TPM_CONTEXT_SENSITIVE context;
  TPM_SESSION_DATA *session = NULL;
  TPM_DAA_SESSION_DATA *sessionDAA = NULL;
  TPM_KEY_DATA *key = NULL;
  int i = 0;
  info("TPM_SaveContext() resourceType = %08x", resourceType);
  /* setup context data */
  context.tag = TPM_TAG_CONTEXT_SENSITIVE;
  context.resourceType = resourceType;
  if (resourceType == TPM_RT_AUTH || resourceType == TPM_RT_TRANS) {
    session = (resourceType == TPM_RT_AUTH) ? tpm_get_auth(handle) : 
               tpm_get_transport(handle);
    if (session == NULL) return TPM_INVALID_RESOURCE;
    /* store session data */
    memcpy(&context.internalData.session, session, sizeof(TPM_SESSION_DATA));
    context.internalSize = sizeof_TPM_SESSION_DATA((*session));
    /* set context nonce */
    memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, 
           sizeof(TPM_NONCE));
  } else if (resourceType == TPM_RT_KEY) {
    key = tpm_get_key(handle);
    debug("resourceType = TPM_RT_KEY, handle = %08x, key = %p", handle, key);
    if (key == NULL) return TPM_INVALID_RESOURCE;
    if (key->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) return TPM_OWNER_CONTROL;
    /* store key data (shallow copy is ok) */
    memcpy(&context.internalData.key, key, sizeof(TPM_KEY_DATA));
    context.internalSize = sizeof_TPM_KEY_DATA((*key));
    /* set context nonce */
    memcpy(&context.contextNonce, &tpmData.stclear.data.contextNonceKey, 
           sizeof(TPM_NONCE));
  } else if (resourceType == TPM_RT_DAA_TPM) {
    sessionDAA = tpm_get_daa(handle);
    if (sessionDAA == NULL) return TPM_INVALID_RESOURCE;
    /* store sessionDAA data */
    memcpy(&context.internalData.sessionDAA, sessionDAA,
           sizeof(TPM_DAA_SESSION_DATA));
    context.internalSize = sizeof(TPM_DAA_SESSION_DATA);
    /* set context nonce */
    memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, 
           sizeof(TPM_NONCE));
  } else {
    return TPM_INVALID_RESOURCE;
  }
  /* setup context blob */
  contextBlob->tag = TPM_TAG_CONTEXTBLOB;
  contextBlob->resourceType = resourceType;
  contextBlob->handle = handle;
  memset(&contextBlob->integrityDigest, 0, sizeof(TPM_DIGEST));
  memcpy(contextBlob->label, label, sizeof(contextBlob->label));
  contextBlob->additionalSize = TPM_SYM_KEY_SIZE;
  contextBlob->additionalData = tpm_malloc(contextBlob->additionalSize);
  if (contextBlob->additionalData == NULL) return TPM_FAIL;
  tpm_get_random_bytes(contextBlob->additionalData, 
                       contextBlob->additionalSize);
  /* increment context counter */
  if (resourceType == TPM_RT_KEY) {
    contextBlob->contextCount = 0;
  } else {
    if (tpmData.stany.data.contextCount >= 0xfffffffc) {
      tpm_free(contextBlob->additionalData);
      return TPM_TOOMANYCONTEXTS;
    }
    contextBlob->contextCount = ++tpmData.stany.data.contextCount;
    for (i = 0; i < TPM_MAX_SESSION_LIST; i++) {
      if (tpmData.stany.data.contextList[i] == 0) break;
    }
    if (i >= TPM_MAX_SESSION_LIST) {
      tpm_free(contextBlob->additionalData);
      return TPM_NOCONTEXTSPACE;
    }
    tpmData.stany.data.contextCount++;
    tpmData.stany.data.contextList[i] = tpmData.stany.data.contextCount;
    contextBlob->contextCount = tpmData.stany.data.contextCount;
  }
  debug("context counter = %d", tpmData.stany.data.contextCount);
  /* encrypt sensitive data */
  if (encrypt_context(contextBlob->additionalData, contextBlob->additionalSize,
      &context, &contextBlob->sensitiveData, &contextBlob->sensitiveSize)) {
        tpm_free(contextBlob->additionalData);
        return TPM_ENCRYPT_ERROR;
  }
  /* compute context digest */
  if (compute_context_digest(contextBlob, &contextBlob->integrityDigest)) {
    tpm_free(contextBlob->additionalData);
    return TPM_FAIL;
  }
  *contextSize = sizeof_TPM_CONTEXT_BLOB((*contextBlob));
  if (resourceType != TPM_RT_KEY) {
    /* The TPM MUST invalidate all information regarding the resource 
     * except for information needed for reloading. */
    if (resourceType != TPM_RT_DAA_TPM)
      session->type = TPM_ST_INVALID;
    else {
      memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA));
      sessionDAA->type = TPM_ST_INVALID;
      tpmData.stany.data.currentDAA = 0;
    }
  }
  return TPM_SUCCESS;
}
Esempio n. 4
0
void tpm_init_data(void)
{
  /* endorsement key */
  uint8_t ek_n[] =  "\xa8\xdb\xa9\x42\xa8\xf3\xb8\x06\x85\x90\x76\x93\xad\xf7"
    "\x74\xec\x3f\xd3\x3d\x9d\xe8\x2e\xff\x15\xed\x0e\xce\x5f\x93"
    "\x92\xeb\xd1\x96\x2b\x72\x18\x81\x79\x12\x9d\x9c\x40\xd7\x1a"
    "\x21\xda\x5f\x56\xe0\xc9\x48\x31\xdd\x96\xdc\xbb\x45\xc6\x8e"
    "\xad\x58\x23\xcb\xbe\xbb\x13\x2d\x6b\x86\xc5\x57\xf5\xdd\x48"
    "\xc1\x3d\xcd\x4d\xda\x81\xc4\x43\x17\xaa\x05\x40\x33\x62\x0a"
    "\x59\xdb\x28\xcd\xb5\x08\x31\xbb\x06\xf5\xf7\x71\xae\x21\xa8"
    "\xf2\x2f\x0e\x17\x80\x5d\x9c\xdf\xaa\xe9\x89\x09\x54\x65\x2b"
    "\x46\xfb\x9d\xb2\x00\x70\x63\x0d\x9a\x6d\x3d\x5e\x11\x78\x65"
    "\x90\xe6\x26\xee\x77\xbe\x08\xff\x07\x60\x5a\xcc\xf1\x0a\xbd"
    "\x44\x92\x6b\xca\xb6\xce\x66\xf9\x93\x40\xae\xf3\x3e\x53\x02"
    "\x3c\xa6\x81\xb3\xbe\xad\x6e\x6c\xa6\xf0\xeb\xdf\xe9\xa2\x83"
    "\x36\x0e\x52\x0d\x64\x17\xd9\xff\xa1\x74\x7c\x2b\xbc\x6a\xcc"
    "\xe5\x4e\xb4\x52\xd9\xec\x43\xbd\x26\x6a\x2b\x19\x19\x6e\x97"
    "\xb8\x1d\x9f\x7b\xe7\x32\x2d\xdd\x7c\x51\xc8\xe4\xf3\x02\xd4"
    "\x7c\x90\x44\xa0\x33\x72\x81\x75\xa9\x16\x27\x5c\x00\x1d\x07"
    "\x81\xd4\xf7\xac\xcb\xfe\xd6\x60\x03\x6f\x7a\xcc\x00\xd1\xc4"
    "\x85\x37";
  uint8_t ek_e[] = "\x01\x00\x01";
  uint8_t ek_p[] = "\xd7\xea\x61\x15\x8b\xa3\x71\xdf\xa8\x74\x77\xca\x88\x95"
    "\xd0\x76\x17\x43\x2c\xf6\x23\x27\x44\xb9\x0e\x18\x35\x7e\xe4"
    "\xc3\xcb\x13\x6e\xfc\x38\x02\x1e\x77\x26\x40\x9d\x17\xb2\x39"
    "\x9c\x7f\x5f\x98\xe6\xf2\x55\x0c\x12\x05\x4c\xb3\x51\xae\x29"
    "\xe7\xcd\xce\x41\x0b\x28\x4d\x97\x13\x4b\x60\xc8\xd8\x70\x81"
    "\xf9\x1c\x12\x44\xdf\x53\x0a\x87\x9d\x33\x92\x4a\x34\x69\xf0"
    "\x70\x5e\x1b\x5d\x65\xc7\x84\x90\xa2\x62\xdf\x83\x14\x10\x69"
    "\xe2\xa7\x18\x43\xd7\x1f\x60\xc9\x03\x8f\xd6\xa4\xce\xb2\x9d"
    "\x40\x37\x70\x17\x4c\xe3\x69\xd4\x59";
  uint8_t ek_q[] = "\xc8\x34\xd2\xd0\x7c\xfa\xdc\x68\xe2\x72\xd7\x92\xe2\x50"
    "\x93\xfc\xbb\x72\x55\x4d\x6b\x7a\x0c\x0b\xcf\x87\x66\x1f\x81"
    "\x71\xf3\x50\xcb\xaa\xe6\x43\x7e\xbe\x11\xc4\xec\x00\x53\xf4"
    "\x78\x13\x2b\x59\x26\x4a\x9f\x91\x61\x8f\xa7\x07\x64\x11\x5a"
    "\xf4\xaf\x9c\x9b\x5a\x5d\x69\x20\x17\x55\x74\xba\xd8\xe4\x59"
    "\x39\x1a\x0a\x7b\x4a\x30\xf0\xc8\x7f\xd9\xaf\x72\xc5\xb6\x71"
    "\xd1\xc0\x8b\x5b\xa2\x2e\xa7\x15\xca\x50\x75\x10\x48\x9c\x2b"
    "\x18\xb9\x67\x8f\x5d\x64\xc3\x28\x9f\x2f\x16\x2f\x08\xda\x47"
    "\xec\x86\x43\x0c\x80\x99\x07\x34\x0f";
  int i;
  info("initializing TPM data to default values");
  /* reset all data to NULL, FALSE or 0 */
  memset(&tpmData, 0, sizeof(tpmData));
  tpmData.permanent.data.tag = TPM_TAG_PERMANENT_DATA;
  /* set permanent flags */
  tpmData.permanent.flags.tag = TPM_TAG_PERMANENT_FLAGS;
  tpmData.permanent.flags.disable = FALSE;
  tpmData.permanent.flags.deactivated = FALSE;
  tpmData.permanent.flags.ownership = TRUE;
  tpmData.permanent.flags.readPubek = TRUE;
  tpmData.permanent.flags.allowMaintenance = TRUE;
  tpmData.permanent.flags.enableRevokeEK = TRUE;
  tpmData.permanent.flags.readSRKPub = TRUE;
  tpmData.permanent.flags.nvLocked = TRUE;
  /* set TPM vision */
  memcpy(&tpmData.permanent.data.version, 
         &tpm_version, sizeof(TPM_VERSION));
  /* seed PRNG */
  tpm_get_extern_random_bytes(&tpmData.permanent.data.rngState,
    sizeof(tpmData.permanent.data.rngState));
  /* setup PCR attributes */
  for (i = 0; i < TPM_NUM_PCR && i < 16; i++) {
    init_pcr_attr(i, FALSE, 0x00, 0x1f);
  }
  if (TPM_NUM_PCR >= 24) {
    init_pcr_attr(16, TRUE, 0x1f, 0x1f);
    init_pcr_attr(17, TRUE, 0x10, 0x1c);
    init_pcr_attr(18, TRUE, 0x10, 0x1c);
    init_pcr_attr(19, TRUE, 0x10, 0x0c);
    init_pcr_attr(20, TRUE, 0x14, 0x0e);
    init_pcr_attr(21, TRUE, 0x04, 0x04);
    init_pcr_attr(22, TRUE, 0x04, 0x04);
    init_pcr_attr(23, TRUE, 0x1f, 0x1f);
  }
  for (i = 24; i < TPM_NUM_PCR; i++) {
    init_pcr_attr(i, TRUE, 0x00, 0x00);
  }
  if (tpmConf & TPM_CONF_GENERATE_EK) {
    /* generate a new endorsement key */
    tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048);
  } else {
    /* setup endorsement key */
    tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey, 
      RSA_MSB_FIRST, ek_n, 256, ek_e, 3, ek_p, ek_q);
  }
  if (tpmConf & TPM_CONF_GENERATE_SEED_DAA) {
    /* generate the DAA seed */
    tpm_get_random_bytes(tpmData.permanent.data.tpmDAASeed.nonce, 
      sizeof(tpmData.permanent.data.tpmDAASeed.nonce));
  } else {
    /* setup DAA seed */
    memcpy(tpmData.permanent.data.tpmDAASeed.nonce, 
      "\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
      "\x00\x00\x00\x77", sizeof(TPM_NONCE));
  }
  memcpy(tpmData.permanent.data.ekReset.nonce, "\xde\xad\xbe\xef", 4);
  /* initialize predefined non-volatile storage */
  init_nv_storage();
  /* set the timeout and duration values */
  init_timeouts();
#ifdef MTM_EMULATOR
  mtm_init_data();
#endif
}
TPM_RESULT TPM_TakeOwnership(TPM_PROTOCOL_ID protocolID,
                             UINT32 encOwnerAuthSize, BYTE *encOwnerAuth,
                             UINT32 encSrkAuthSize, BYTE *encSrkAuth,
                             TPM_KEY *srkParams, TPM_AUTH *auth1,
                             TPM_KEY *srkPub)
{
  TPM_RESULT res;
  tpm_rsa_private_key_t *ek = &tpmData.permanent.data.endorsementKey;
  TPM_KEY_DATA *srk = &tpmData.permanent.data.srk;
  size_t buf_size = ek->size >> 3;
  BYTE buf[buf_size];

  info("TPM_TakeOwnership()");
  if (!ek->size) return TPM_NO_ENDORSEMENT;
  if (protocolID != TPM_PID_OWNER) return TPM_BAD_PARAMETER;
  if (tpmData.permanent.flags.owned) return TPM_OWNER_SET;
  if (!tpmData.permanent.flags.ownership) return TPM_INSTALL_DISABLED;
  /* decrypt ownerAuth */
  if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encOwnerAuth, encOwnerAuthSize,
      buf, &buf_size) != 0) return TPM_DECRYPT_ERROR;
  if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY;
  memcpy(tpmData.permanent.data.ownerAuth, buf, buf_size);
  /* verify authorization */
  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
  if (res != TPM_SUCCESS) return res;
  if (tpm_get_auth(auth1->authHandle)->type != TPM_ST_OIAP)
    return TPM_AUTHFAIL;
  /* reset srk and decrypt srkAuth */
  memset(srk, 0, sizeof(*srk));
  if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encSrkAuth, encSrkAuthSize,
      buf, &buf_size) != 0) return TPM_DECRYPT_ERROR;
  if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY;
  memcpy(srk->usageAuth, buf, buf_size);
  /* validate SRK parameters */
  if (srkParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE
      || srkParams->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;
  if (srkParams->algorithmParms.algorithmID != TPM_ALG_RSA
      || srkParams->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1
      || srkParams->algorithmParms.sigScheme != TPM_SS_NONE
      || srkParams->algorithmParms.parmSize == 0
      || srkParams->algorithmParms.parms.rsa.keyLength != 2048
      || srkParams->algorithmParms.parms.rsa.numPrimes != 2
      || srkParams->algorithmParms.parms.rsa.exponentSize != 0
      || srkParams->PCRInfoSize != 0) return TPM_BAD_KEY_PROPERTY;
  /* setup and generate SRK */
  srk->keyFlags = srkParams->keyFlags;
  srk->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE;
  srk->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR;
  srk->keyUsage = srkParams->keyUsage;
  srk->encScheme = srkParams->algorithmParms.encScheme;
  srk->sigScheme = srkParams->algorithmParms.sigScheme;
  srk->authDataUsage = srkParams->authDataUsage;
  debug("srk->authDataUsage = %02x", srk->authDataUsage);
  srk->parentPCRStatus = FALSE;
  srkParams->algorithmParms.parms.rsa.keyLength = 2048;
  if (tpm_rsa_generate_key(&srk->key,
      srkParams->algorithmParms.parms.rsa.keyLength)) return TPM_FAIL;
  srk->payload = TPM_PT_ASYM;
  /* generate context, delegate, and DAA key */
  tpm_get_random_bytes(tpmData.permanent.data.contextKey,
    sizeof(tpmData.permanent.data.contextKey));
  tpm_get_random_bytes(tpmData.permanent.data.delegateKey,
      sizeof(tpmData.permanent.data.delegateKey));
  tpm_get_random_bytes(tpmData.permanent.data.daaKey,
      sizeof(tpmData.permanent.data.daaKey));
  /* export SRK */
  memcpy(srkPub, srkParams, sizeof(TPM_KEY));
  srkPub->pubKey.keyLength = srk->key.size >> 3;
  srkPub->pubKey.key = tpm_malloc(srkPub->pubKey.keyLength);
  if (srkPub->pubKey.key == NULL) {
    tpm_rsa_release_private_key(&srk->key);
    srk->payload = TPM_PT_NONE;
    return TPM_FAIL;
  }
  tpm_rsa_export_modulus(&srk->key, srkPub->pubKey.key, NULL);
  /* setup tpmProof/daaProof and set state to owned */
  tpm_get_random_bytes(tpmData.permanent.data.tpmProof.nonce,
    sizeof(tpmData.permanent.data.tpmProof.nonce));
  tpm_get_random_bytes(tpmData.permanent.data.daaProof.nonce,
    sizeof(tpmData.permanent.data.daaProof.nonce));
  tpmData.permanent.flags.readPubek = FALSE;
  tpmData.permanent.flags.owned = TRUE;
  return TPM_SUCCESS;
}