static TPM_RESULT execute_MTM_InstallRIM(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
  BYTE *ptr;
  UINT32 len;
  UINT32 rimCertSize;
  TPM_RIM_CERTIFICATE rimCertIn;
  TPM_RIM_CERTIFICATE rimCertOut;
  TPM_RESULT res;
  /* compute parameter digest */
  tpm_compute_in_param_digest(req);
  /* unmarshal input */
  ptr = req->param;
  len = req->paramSize;
  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)
      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCertIn)
      || len != 0) return TPM_BAD_PARAMETER;
  /* execute command */
  res = MTM_InstallRIM(&rimCertIn, &req->auth1, &rimCertOut);
  if (res != TPM_SUCCESS) return res;
  /* marshal output */
  rsp->paramSize = len = 4 + sizeof_TPM_RIM_CERTIFICATE(rimCertOut);
  rsp->param = ptr = tpm_malloc(len);
  if (ptr == NULL
      || tpm_marshal_UINT32(&ptr, &len, sizeof_TPM_RIM_CERTIFICATE(rimCertOut))
      || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCertOut)) {
    tpm_free(rsp->param);
    res = TPM_FAIL;
  }
  free_TPM_RIM_CERTIFICATE(rimCertOut);
  return res;
}
Exemple #2
0
static TPM_RESULT execute_TPM_UnBind(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
  BYTE *ptr;
  UINT32 len;
  TPM_KEY_HANDLE keyHandle;
  UINT32 inDataSize;
  BYTE *inData;
  UINT32 outDataSize;
  BYTE *outData = NULL;
  TPM_RESULT res;
  /* compute parameter digest */
  tpm_compute_in_param_digest(req);
  /* unmarshal input */
  ptr = req->param;
  len = req->paramSize;
  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)
      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)
      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)
      || len != 0) return TPM_BAD_PARAMETER;
  /* execute command */
  res = TPM_UnBind(keyHandle, inDataSize, inData, &req->auth1, &outDataSize, &outData);
  if (res != TPM_SUCCESS) return res;
  /* marshal output */
  rsp->paramSize = len = 4 + outDataSize;
  rsp->param = ptr = ExtendBuf;
  if (ptr == NULL
      || tpm_marshal_UINT32(&ptr, &len, outDataSize)
      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {
    free(rsp->param);
    res = TPM_FAIL;
  }
  free(outData);
  return res;
}
Exemple #3
0
static TPM_RESULT execute_TPM_OSAP(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
    BYTE *ptr;
    UINT32 len;
    TPM_ENTITY_TYPE entityType;
    UINT32 entityValue;
    TPM_NONCE nonceOddOSAP;
    TPM_AUTHHANDLE authHandle;
    TPM_NONCE nonceEven;
    TPM_NONCE nonceEvenOSAP;
    TPM_RESULT res;
    /* unmarshal input */
    ptr = req->param;
    len = req->paramSize;
    if (tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)
            || tpm_unmarshal_UINT32(&ptr, &len, &entityValue)
            || tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonceOddOSAP)
            || len != 0) return TPM_BAD_PARAMETER;
    /* execute command */
    res = TPM_OSAP(entityType, entityValue, &nonceOddOSAP, &authHandle, 
            &nonceEven, &nonceEvenOSAP);
    if (res != TPM_SUCCESS) return res;
    /* marshal output */
    rsp->paramSize = len = 4 + 20 + 20;
    rsp->param = ptr = malloc(len);
    if (ptr == NULL
            || tpm_marshal_TPM_AUTHHANDLE(&ptr, &len, authHandle)
            || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEven)
            || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEvenOSAP)) {
        free(rsp->param);
        res = TPM_FAIL;
    }
    return res;
}
static TPM_RESULT execute_MTM_LoadVerificationKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
  BYTE *ptr;
  UINT32 len;
  TPM_VERIFICATION_KEY_HANDLE parentKey;
  UINT32 verificationKeySize;
  TPM_VERIFICATION_KEY verificationKey;
  TPM_VERIFICATION_KEY_HANDLE verificationKeyHandle;
  BYTE loadMethod;
  TPM_RESULT res;
  /* compute parameter digest */
  tpm_compute_in_param_digest(req);
  /* unmarshal input */
  ptr = req->param;
  len = req->paramSize;
  if (tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &parentKey)
      || tpm_unmarshal_UINT32(&ptr, &len, &verificationKeySize)
      || tpm_unmarshal_TPM_VERIFICATION_KEY(&ptr, &len, &verificationKey)
      || len != 0) return TPM_BAD_PARAMETER;
  /* execute command  */
  res = MTM_LoadVerificationKey(parentKey, &verificationKey, &req->auth1,
    &verificationKeyHandle, &loadMethod);
  if (res != TPM_SUCCESS) return res;
  /* marshal output */
  rsp->paramSize = len = 4 + 1;
  rsp->param = ptr = tpm_malloc(len);
  if (ptr == NULL
      || tpm_marshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, verificationKeyHandle)
      || tpm_marshal_BYTE(&ptr, &len, loadMethod)) {
    tpm_free(rsp->param);
    res = TPM_FAIL;
  }
  return res;
}
static TPM_RESULT execute_MTM_VerifyRIMCertAndExtend(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
  BYTE *ptr;
  UINT32 len;
  UINT32 rimCertSize;
  TPM_RIM_CERTIFICATE rimCert;
  TPM_VERIFICATION_KEY_HANDLE rimKey;
  TPM_PCRVALUE outDigest;
  TPM_RESULT res;
  /* compute parameter digest */
  tpm_compute_in_param_digest(req);
  /* unmarshal input */
  ptr = req->param;
  len = req->paramSize;
  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)
      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCert)
      || tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &rimKey)
      || len != 0) return TPM_BAD_PARAMETER;
  /* execute command */
  res = MTM_VerifyRIMCertAndExtend(&rimCert, rimKey, &outDigest);
  /* marshal output */
  rsp->paramSize = len = 20;
  rsp->param = ptr = tpm_malloc(len);
  if (ptr == NULL
      || tpm_marshal_TPM_PCRVALUE(&ptr, &len, &outDigest)) {
    tpm_free(rsp->param);
    res = TPM_FAIL;
  }
  return res;
}
Exemple #6
0
static TPM_RESULT execute_TPM_TakeOwnership(TPM_REQUEST *req, TPM_RESPONSE *rsp) {
   BYTE *ptr;
   UINT32 len;
   TPM_PROTOCOL_ID protocolID;
   UINT32 encOwnerAuthSize;
   BYTE *encOwnerAuth;
   UINT32 encSrkAuthSize;
   BYTE *encSrkAuth;
   TPM_KEY srkParams;
   TPM_KEY srkPub;
   TPM_RESULT res;
   /* compute parameter digest */
   tpm_compute_in_param_digest(req);
   /* unmarshal input */
   ptr = req->param;
   len = req->paramSize;
   if (tpm_unmarshal_TPM_PROTOCOL_ID(&ptr, &len, &protocolID)
       || tpm_unmarshal_UINT32(&ptr, &len, &encOwnerAuthSize)
       || tpm_unmarshal_BLOB(&ptr, &len, &encOwnerAuth, encOwnerAuthSize)
       || tpm_unmarshal_UINT32(&ptr, &len, &encSrkAuthSize)
       || tpm_unmarshal_BLOB(&ptr, &len, &encSrkAuth, encSrkAuthSize)
       || tpm_unmarshal_TPM_KEY(&ptr, &len, &srkParams)
       || len != 0) return TPM_BAD_PARAMETER;
   /* execute command */
   res = TPM_TakeOwnership(protocolID, encOwnerAuthSize, encOwnerAuth, 
     encSrkAuthSize, encSrkAuth, &srkParams, &req->auth1, &srkPub);
   if (res != TPM_SUCCESS) return res;
   /* marshal output */
   rsp->paramSize = len = sizeof_TPM_KEY(srkPub);
   rsp->param = ptr = malloc(len);
   if (ptr == NULL
       || tpm_marshal_TPM_KEY(&ptr, &len, &srkPub)) {
     free(rsp->param);
     res = TPM_FAIL;
   }
   free_TPM_KEY(srkPub);
   return res;
 }
Exemple #7
0
int check_ordinal(tpmcmd_t* tpmcmd) {
   TPM_COMMAND_CODE ord;
   UINT32 len = 4;
   BYTE* ptr;
   unsigned int i;

   if(tpmcmd->req_len < 10) {
      return true;
   }

   ptr = tpmcmd->req + 6;
   tpm_unmarshal_UINT32(&ptr, &len, &ord);

   for(i = 0; i < n_badords; ++i) {
      if(ord == badords[i]) {
         error("Disabled command ordinal (%" PRIu32") requested!\n");
         return false;
      }
   }
   return true;
}
Exemple #8
0
TPM_RESULT cap_flag(UINT32 subCapSize, BYTE *subCap,
                    UINT32 *respSize, BYTE **resp)
{
  UINT32 type, len;
  BYTE *ptr;
  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &type)) return TPM_BAD_MODE;
  switch (type) {
    case TPM_CAP_FLAG_PERMANENT:
      debug("[TPM_CAP_FLAG_PERMANENT");
      *respSize = len = sizeof_TPM_PERMANENT_FLAGS(tpmData.permanent.flags);
      *resp = ptr = tpm_malloc(len);
      if (tpm_marshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags)) {
        tpm_free(*resp);
        return TPM_FAIL;
      }
      return TPM_SUCCESS;
    case TPM_CAP_FLAG_VOLATILE:
      debug("[TPM_CAP_FLAG_VOLATILE]");
      *respSize = len = sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags);
      *resp = ptr = tpm_malloc(len);
      if (tpm_marshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags)) {
        tpm_free(*resp);
        return TPM_FAIL;
      }
      return TPM_SUCCESS;
/* removed since v1.2 rev 94
    case TPM_CAP_FLAG_STANY:
      debug("[TPM_CAP_FLAG_STANY]");
      *respSize = len = sizeof_TPM_STANY_FLAGS(tpmData.stany.flags);
      *resp = ptr = tpm_malloc(len);
      if (tpm_marshal_TPM_STANY_FLAGS(&ptr, &len, &tpmData.stany.flags)) {
        tpm_free(*resp);
        return TPM_FAIL;
      }
*/
      return TPM_SUCCESS;
    default:
      return TPM_BAD_MODE;
  }
}
static TPM_RESULT execute_MTM_IncrementBootstrapCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)
{
  BYTE *ptr;
  UINT32 len;
  UINT32 rimCertSize;
  TPM_RIM_CERTIFICATE rimCert;
  TPM_VERIFICATION_KEY_HANDLE rimKey;
  TPM_RESULT res;
  /* compute parameter digest */
  tpm_compute_in_param_digest(req);
  /* unmarshal input */
  ptr = req->param;
  len = req->paramSize;
  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)
      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCert)
      || tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &rimKey)
      || len != 0) return TPM_BAD_PARAMETER;
  /* execute command */
  res = MTM_IncrementBootstrapCounter(&rimCert, rimKey);
  /* marshal output */
  rsp->paramSize = len = 0;
  rsp->param = ptr = NULL;
  return res;
}
Exemple #10
0
static TPM_RESULT cap_property(UINT32 subCapSize, BYTE *subCap, 
                               UINT32 *respSize, BYTE **resp)
{
  UINT32 i, j, property;

  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &property))
    return TPM_BAD_MODE;
  switch (property) {
    case TPM_CAP_PROP_PCR:
      debug("[TPM_CAP_PROP_PCR]");
      return return_UINT32(respSize, resp, TPM_NUM_PCR);

    case TPM_CAP_PROP_DIR:
      debug("[TPM_CAP_PROP_DIR]");
      return return_UINT32(respSize, resp, 1);

    case TPM_CAP_PROP_MANUFACTURER:
      debug("[TPM_CAP_PROP_MANUFACTURER]");
      return return_UINT32(respSize, resp, TPM_MANUFACTURER);

    case TPM_CAP_PROP_KEYS:
      debug("[TPM_CAP_PROP_KEYS]");
      for (i = 0, j = TPM_MAX_KEYS; i < TPM_MAX_KEYS; i++)
        if (tpmData.permanent.data.keys[i].valid) j--;
      return return_UINT32(respSize, resp, j); 

    case TPM_CAP_PROP_MIN_COUNTER:
      debug("[TPM_CAP_PROP_MIN_COUNTER]");
      return return_UINT32(respSize, resp, 1);

    case TPM_CAP_PROP_AUTHSESS:
      debug("[TPM_CAP_PROP_AUTHSESS]");
      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)
        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_TRANSESS:
      debug("[TPM_CAP_PROP_TRANSESS]");
      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)
        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_COUNTERS:
      debug("[TPM_CAP_PROP_COUNTERS]");
      for (i = 0, j = TPM_MAX_COUNTERS; i < TPM_MAX_COUNTERS; i++)
        if (tpmData.permanent.data.counters[i].valid) j--;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_MAX_AUTHSESS:
      debug("[TPM_CAP_PROP_MAX_AUTHSESS]");
      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);

    case TPM_CAP_PROP_MAX_TRANSESS:
      debug("[TPM_CAP_PROP_MAX_TRANSESS]");
      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);

    case TPM_CAP_PROP_MAX_COUNTERS:
      debug("[TPM_CAP_PROP_MAX_COUNTERS]");
      return return_UINT32(respSize, resp, TPM_MAX_COUNTERS);

    case TPM_CAP_PROP_MAX_KEYS:
      debug("[TPM_CAP_PROP_MAX_KEYS]");
      return return_UINT32(respSize, resp, TPM_MAX_KEYS);

    case TPM_CAP_PROP_OWNER:
      debug("[TPM_CAP_PROP_OWNER]");
      return return_BOOL(respSize, resp, tpmData.permanent.flags.owned);

    case TPM_CAP_PROP_CONTEXT:
      debug("[TPM_CAP_PROP_CONTEXT]");
      for (i = 0, j = 0; i < TPM_MAX_SESSION_LIST; i++)
        if (tpmData.stany.data.contextList[i] == 0) j++;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_MAX_CONTEXT:
      debug("[TPM_CAP_PROP_MAX_CONTEXT]");
      return return_UINT32(respSize, resp, TPM_MAX_SESSION_LIST);

    case TPM_CAP_PROP_FAMILYROWS:
      debug("[TPM_CAP_PROP_FAMILYROWS]");
      /* TODO: TPM_CAP_PROP_FAMILYROWS */
      return TPM_FAIL;

    case TPM_CAP_PROP_TIS_TIMEOUT:
      debug("[TPM_CAP_PROP_TIS_TIMEOUT]");
      /* TODO: TPM_CAP_PROP_TIS_TIMEOUT: Measure these values and determine correct ones */
      UINT32 len = *respSize = 16;
      BYTE *ptr = *resp = tpm_malloc(*respSize);
      if (ptr == NULL || 
          tpm_marshal_UINT32(&ptr, &len, 200000) ||
          tpm_marshal_UINT32(&ptr, &len, 200000) ||
          tpm_marshal_UINT32(&ptr, &len, 200000) ||
          tpm_marshal_UINT32(&ptr, &len, 200000)) {
        tpm_free(*resp);
        return TPM_FAIL;
      }
      return TPM_SUCCESS;

    case TPM_CAP_PROP_STARTUP_EFFECT:
      debug("[TPM_CAP_PROP_STARTUP_EFFECT]");
      /* TODO: TPM_CAP_PROP_STARTUP_EFFECT */
      return TPM_FAIL;

    case TPM_CAP_PROP_DELEGATE_ROW:
      debug("[TPM_CAP_PROP_DELEGATE_ROW]");
      /* TODO: TPM_CAP_PROP_DELEGATE_ROW */
      return TPM_FAIL;

    case TPM_CAP_PROP_DAA_MAX:
      debug("[TPM_CAP_PROP_DAA_MAX]");
      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS_DAA);

    case TPM_CAP_PROP_SESSION_DAA:
      debug("[TPM_CAP_PROP_SESSION_DAA]");
      for (i = 0, j = TPM_MAX_SESSIONS_DAA; i < TPM_MAX_SESSIONS_DAA; i++)
        if (tpmData.stany.data.sessionsDAA[i].type != TPM_ST_INVALID) j--;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_CONTEXT_DIST:
      debug("[TPM_CAP_PROP_CONTEXT_DIST]");
      /* TODO: TPM_CAP_PROP_CONTEXT_DIST */
      return TPM_FAIL;

    case TPM_CAP_PROP_DAA_INTERRUPT:
      debug("[TPM_CAP_PROP_DAA_INTERRUPT]");
      /* A value of TRUE indicates that the TPM will accept ANY command 
       * while executing a DAA Join or Sign. A value of FALSE indicates 
       * that the TPM will invalidate the DAA Join or Sign upon the 
       * receipt of any command other than the next join/sign in the 
       * session or a TPM_SaveContext. */
      return return_BOOL(respSize, resp, TRUE);

    case TPM_CAP_PROP_SESSIONS:
      debug("[TPM_CAP_PROP_SESSIONS]");
      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)
        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;
      return return_UINT32(respSize, resp, j);

    case TPM_CAP_PROP_MAX_SESSIONS:
      debug("[TPM_CAP_PROP_MAX_SESSIONS]");
      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);

    case TPM_CAP_PROP_CMK_RESTRICTION:
      debug("[TPM_CAP_PROP_CMK_RESTRICTION]");
      /* TODO: TPM_CAP_PROP_CMK_RESTRICTION */
      return TPM_FAIL;

    case TPM_CAP_PROP_DURATION:
      debug("[TPM_CAP_PROP_DURATION]");
      /* TODO: TPM_CAP_PROP_DURATION: Measure these values and return accurate ones */
      BYTE dur[]= {0x0,0x0,0x0,0xc,0x0,0x7,0xa1,0x20,0x0,0x1e,0x84,0x80,0x11,0xe1,0xa3,0x0}; 
      *respSize = 16;
      *resp = tpm_malloc(*respSize);
      memcpy(*resp,dur,16); 
      return TPM_FAIL;

    case TPM_CAP_PROP_ACTIVE_COUNTER:
      debug("[TPM_CAP_PROP_ACTIVE_COUNTER]");
      /* TODO: TPM_CAP_PROP_ACTIVE_COUNTER */
      return TPM_FAIL;

    case TPM_CAP_PROP_MAX_NV_AVAILABLE:
      debug("[TPM_CAP_PROP_MAX_NV_AVAILABLE]");
      /* TODO: TPM_CAP_PROP_MAX_NV_AVAILABLE */
      return TPM_FAIL;

    case TPM_CAP_PROP_INPUT_BUFFER:
      debug("[TPM_CAP_PROP_INPUT_BUFFER]");
      /* TODO: TPM_CAP_PROP_INPUT_BUFFER */
      return TPM_FAIL;

    default:
      return TPM_BAD_MODE;
  }
}
Exemple #11
0
static TPM_RESULT cap_handle(UINT32 subCapSize, BYTE *subCap,
                               UINT32 *respSize, BYTE **resp)
{
  UINT32 i, len, type;
  BYTE *ptr; 
  /* maximum of { TPM_MAX_KEYS, TPM_MAX_SESSIONS } */
  UINT32 list_size =
    (TPM_MAX_KEYS > TPM_MAX_SESSIONS) ? TPM_MAX_KEYS : TPM_MAX_SESSIONS;
  UINT32 handles[list_size];
  TPM_KEY_HANDLE_LIST list = { 0, handles };

  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &type))
    return TPM_BAD_MODE;
  switch (type) {
    case TPM_RT_KEY:
      debug("[TPM_RT_KEY]");
      for (i = 0; i < TPM_MAX_KEYS; i++)
        if (tpmData.permanent.data.keys[i].valid) {
          list.loaded++;
          list.handle[i] = INDEX_TO_KEY_HANDLE(i);
        }
      break;
    case TPM_RT_AUTH:
      debug("[TPM_RT_AUTH]");
      for (i = 0; i < TPM_MAX_SESSIONS; i++)
        if (tpmData.stany.data.sessions[i].type == TPM_ST_OIAP
            || tpmData.stany.data.sessions[i].type == TPM_ST_OSAP) {
          list.loaded++;
          list.handle[i] = INDEX_TO_AUTH_HANDLE(i);
        }
      break;
    case TPM_RT_TRANS:
      debug("[TPM_RT_TRANS]");
      for (i = 0; i < TPM_MAX_SESSIONS; i++)
        if (tpmData.stany.data.sessions[i].type == TPM_ST_TRANSPORT) {
          list.loaded++;
          list.handle[i] = INDEX_TO_TRANS_HANDLE(i);
        }
      break;
/* removed since v1.2 rev 94
    case TPM_RT_DELEGATE:
      debug("[TPM_RT_DELEGATE]");
      break;
*/
    case TPM_RT_COUNTER:
      debug("[TPM_RT_COUNTER]");
      for (i = 0; i < TPM_MAX_COUNTERS; i++)
        if (tpmData.permanent.data.counters[i].valid) {
          list.loaded++;
          list.handle[i] = INDEX_TO_COUNTER_HANDLE(i);
        }
      break;
    case TPM_RT_CONTEXT:
      /* TODO: implement TPM_CAP_HANDLE for TPM_RT_CONTEXT */
    default:
      return TPM_BAD_MODE;
  }
  /* marshal handle list */
  len = *respSize = 2 + list.loaded * 4;
  ptr = *resp = tpm_malloc(len);
  if (ptr == NULL || tpm_marshal_TPM_KEY_HANDLE_LIST(&ptr, &len, &list)) {
    tpm_free(*resp);
    return TPM_FAIL;
  }
  return TPM_SUCCESS;
}