/* 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_context.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"
#include <crypto/rc4.h>
#include <crypto/hmac.h>

/*
 * Session Management ([TPM_Part3], Section 21)
 */

UINT32 tpm_get_free_session(BYTE type)
{
  UINT32 i;
  for (i = 0; i < TPM_MAX_SESSIONS; i++) {
    if (tpmData.stany.data.sessions[i].type == TPM_ST_INVALID) {
      tpmData.stany.data.sessions[i].type = type;
      if (type == TPM_ST_TRANSPORT) return INDEX_TO_TRANS_HANDLE(i);
      else return INDEX_TO_AUTH_HANDLE(i);
    }
  }
  return TPM_INVALID_HANDLE;
}

void tpm_invalidate_sessions(TPM_HANDLE handle)
{
  TPM_SESSION_DATA *session;
  int i;

  for (i = 0; i < TPM_MAX_SESSIONS; i++) {
    session = &tpmData.stany.data.sessions[i];
    if ((session->type == TPM_ST_OSAP && session->handle == handle)
        || (session->type == TPM_ST_DSAP && session->handle == handle)
        || (session->type == TPM_ST_TRANSPORT && session->handle == handle))
      memset(session, 0, sizeof(*session));
  }
}

TPM_RESULT TPM_KeyControlOwner(TPM_KEY_HANDLE keyHandle, TPM_PUBKEY pubKey,
                               UINT32 bitName, BOOL bitValue, TPM_AUTH *auth1)
{
  TPM_RESULT res;
  TPM_KEY_DATA *key;
  TPM_PUBKEY pubKey2;
  TPM_DIGEST keyDigest, keyDigest2;
  info("TPM_KeyControlOwner()");
  /* get key */
  key = tpm_get_key(keyHandle);
  if (key == NULL) return TPM_INVALID_KEYHANDLE;
  /* verify authorization */
  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
  if (res != TPM_SUCCESS) return res;
  /* verify public key */
  if (tpm_compute_pubkey_digest(&pubKey, &keyDigest)) {
    debug("tpm_compute_pubkey_digest() failed");
    return TPM_FAIL;
  }
  if (tpm_extract_pubkey(key, &pubKey2)) {
    debug("tpm_extraxt_pubkey() failed.");
    return TPM_FAIL;
  }
  if (tpm_compute_pubkey_digest(&pubKey2, &keyDigest2)) {
    debug("tpm_compute_pubkey_digest() failed");
    free_TPM_PUBKEY(pubKey2);
    return TPM_FAIL;
  }
  free_TPM_PUBKEY(pubKey2);
  if (memcmp(&keyDigest, &keyDigest2, sizeof(TPM_DIGEST)) != 0)
    return TPM_BAD_PARAMETER;
  /* get bit name */
  debug("bitName = %d", bitName);
  if (bitName & TPM_KEY_CONTROL_OWNER_EVICT) {
    if (bitValue) {
      int i, num = 0;
      for (i = 0; i < TPM_MAX_KEYS; i++) {
        if (!tpmData.permanent.data.keys[i].payload ||
            !(tpmData.permanent.data.keys[i].keyControl
              & TPM_KEY_CONTROL_OWNER_EVICT)) num++;
      }
      if (num < 2) return TPM_NOSPACE;
      if (key->parentPCRStatus || (key->keyFlags & TPM_KEY_FLAG_VOLATILE))
        return TPM_BAD_PARAMETER;
      key->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT;
    } else {
      key->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT;
    }
  } else {
    return TPM_BAD_MODE;
  }
  return TPM_SUCCESS;
}

static int encrypt_context(BYTE *iv, UINT32 iv_size, TPM_CONTEXT_SENSITIVE *context, 
                           BYTE **enc, UINT32 *enc_size)
{
  UINT32 len;
  BYTE *ptr;
  tpm_rc4_ctx_t rc4_ctx;
  BYTE key[TPM_SYM_KEY_SIZE + iv_size];
  /* marshal context */
  *enc_size = len = sizeof_TPM_CONTEXT_SENSITIVE((*context));
  *enc = ptr = tpm_malloc(len);
  if (*enc == NULL) return -1;
  if (tpm_marshal_TPM_CONTEXT_SENSITIVE(&ptr, &len, context)) {
    tpm_free(*enc);
    return -1;
  }
  /* encrypt context */
  memcpy(key, tpmData.permanent.data.contextKey, TPM_SYM_KEY_SIZE);
  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);
  tpm_rc4_init(&rc4_ctx, key, sizeof(key));
  tpm_rc4_crypt(&rc4_ctx, *enc, *enc, *enc_size);
  return 0;
}

static int decrypt_context(BYTE *iv, UINT32 iv_size, BYTE *enc, UINT32 enc_size, 
                           TPM_CONTEXT_SENSITIVE *context, BYTE **buf) 
{
  UINT32 len;
  BYTE *ptr;
  tpm_rc4_ctx_t rc4_ctx;
  BYTE key[TPM_SYM_KEY_SIZE + iv_size];
  len = enc_size;
  *buf = ptr = tpm_malloc(len);
  if (*buf == NULL) return -1;
  /* decrypt context */
  memcpy(key, tpmData.permanent.data.contextKey, TPM_SYM_KEY_SIZE);
  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);
  tpm_rc4_init(&rc4_ctx, key, sizeof(key));  
  tpm_rc4_crypt(&rc4_ctx, enc, *buf, enc_size);
  /* unmarshal context */
  if (tpm_unmarshal_TPM_CONTEXT_SENSITIVE(&ptr, &len, context)) {
    tpm_free(*buf);
    return -1;
  }
  return 0;
}

static int compute_context_digest(TPM_CONTEXT_BLOB *contextBlob, TPM_DIGEST *digest)
{
  BYTE *buf, *ptr;
  UINT32 len;
  tpm_hmac_ctx_t hmac_ctx;
  len = sizeof_TPM_CONTEXT_BLOB((*contextBlob));
  buf = ptr = tpm_malloc(len);
  if (buf == NULL) return -1;
  if (tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, contextBlob)) {
    tpm_free(buf);
    return -1;
  }
  memset(&buf[30], 0, 20);
  tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, 
    sizeof(tpmData.permanent.data.tpmProof.nonce));
  tpm_hmac_update(&hmac_ctx, buf, sizeof_TPM_CONTEXT_BLOB((*contextBlob)));
  tpm_hmac_final(&hmac_ctx, digest->digest);
  tpm_free(buf);
  return 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;
}

TPM_RESULT TPM_LoadContext(BOOL keepHandle, TPM_HANDLE hintHandle,
                           UINT32 contextSize, TPM_CONTEXT_BLOB *contextBlob,
                           TPM_HANDLE *handle)
{
  TPM_CONTEXT_SENSITIVE context;
  BYTE *context_buf;
  TPM_SESSION_DATA *session;
  TPM_DAA_SESSION_DATA *sessionDAA;
  TPM_KEY_DATA *key;
  TPM_DIGEST digest;
  int i = 0;
  info("TPM_LoadContext()");
  if (decrypt_context(contextBlob->additionalData, contextBlob->additionalSize,
      contextBlob->sensitiveData, contextBlob->sensitiveSize, 
      &context, &context_buf)) return TPM_DECRYPT_ERROR;
  /* validate structure */
  if (compute_context_digest(contextBlob, &digest)
      || memcmp(&digest, &contextBlob->integrityDigest, sizeof(TPM_DIGEST))) {
    tpm_free(context_buf);
    return TPM_BADCONTEXT;
  }
  if (contextBlob->resourceType == TPM_RT_KEY) {
   /* check contextNonce */
    if (context.internalData.key.parentPCRStatus 
        || (context.internalData.key.keyFlags & TPM_KEY_FLAG_VOLATILE)) {
      if (memcmp(&context.contextNonce, &tpmData.stclear.data.contextNonceKey,
          sizeof(TPM_NONCE)) != 0) {
        tpm_free(context_buf);
        return TPM_BADCONTEXT;
      }
    }
    /* check handle */
    key = tpm_get_key_slot(hintHandle);
    if (key == NULL || !key->payload) {
      if (keepHandle) {
        tpm_free(context_buf);
        return TPM_BAD_HANDLE;
      }    
      *handle = tpm_get_free_key();
      if (*handle == TPM_INVALID_HANDLE) {
        tpm_free(context_buf);
        return TPM_RESOURCES;
      }
      key = &tpmData.permanent.data.keys[HANDLE_TO_INDEX(*handle)];
    } else {
      *handle = hintHandle;
    }
    /* reload resource */
    memcpy(key, &context.internalData.key, sizeof(TPM_KEY_DATA));
    tpm_rsa_copy_key(&key->key, &context.internalData.key.key);
  } else if (contextBlob->resourceType == TPM_RT_DAA_TPM) {
    /* check contextNonce */
    if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, 
        sizeof(TPM_NONCE)) != 0) {
      tpm_free(context_buf);
      return TPM_BADCONTEXT;
    }
    /* check context list */
    for (i = 0; i < TPM_MAX_SESSION_LIST; i++)
      if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break;
    if (i >= TPM_MAX_SESSION_LIST) {
      tpm_free(context_buf);
      return TPM_BADCONTEXT;
    }
    tpmData.stany.data.contextList[i] = 0;
    /* check handle */
    info("keepHandle = %d, hintHandle = %.8x", keepHandle, hintHandle);
    sessionDAA = tpm_get_daa_slot(hintHandle);
    if (sessionDAA == NULL) {
      if (keepHandle) {
        tpm_free(context_buf);
        return TPM_BAD_HANDLE;
      }
      *handle = tpm_get_free_daa_session();
      if (*handle == TPM_INVALID_HANDLE) {
        tpm_free(context_buf);
        return TPM_RESOURCES;
      }
      sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];
    } else if (sessionDAA->type != TPM_ST_INVALID) {
      if (keepHandle) {
        tpm_free(context_buf);
        return TPM_BAD_HANDLE;
      }
      *handle = tpm_get_free_daa_session();
      if (*handle == TPM_INVALID_HANDLE) {
        tpm_free(context_buf);
        return TPM_RESOURCES;
      }
      sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];
    } else {
      if (HANDLE_TO_RT(hintHandle) != TPM_RT_DAA_TPM) {
        if (keepHandle) {
          tpm_free(context_buf);
          return TPM_BAD_HANDLE;
        }
        *handle = tpm_get_free_daa_session();
        if (*handle == TPM_INVALID_HANDLE) {
          tpm_free(context_buf);
          return TPM_RESOURCES;
        }
        sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];
      } else
        *handle = hintHandle;
    }
    /* reload resource */
    tpmData.stany.data.currentDAA = *handle;
    info("stany.data.currentDAA := %.8x", *handle);
    memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA));
    memcpy(sessionDAA, &context.internalData.sessionDAA, context.internalSize);
  } else {
    /* check contextNonce */
    if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, 
        sizeof(TPM_NONCE)) != 0) {
      tpm_free(context_buf);
      return TPM_BADCONTEXT;
    }
    if (context.internalData.session.type == TPM_ST_OSAP
        && tpm_get_key(context.internalData.session.handle) == NULL) {
      tpm_free(context_buf);
      return TPM_RESOURCEMISSING;
    }
    /* check context list */
    for (i = 0; i < TPM_MAX_SESSION_LIST; i++)
      if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break;
    if (i >= TPM_MAX_SESSION_LIST) {
      tpm_free(context_buf);
      return TPM_BADCONTEXT;
    }
    tpmData.stany.data.contextList[i] = 0;
    /* check handle */
    session = tpm_get_session_slot(hintHandle);
    if (session == NULL || session->type != TPM_ST_INVALID) {
      if (keepHandle) {
        tpm_free(context_buf);
        return TPM_BAD_HANDLE;
      }
      *handle = tpm_get_free_session(context.internalData.session.type);
      if (*handle == TPM_INVALID_HANDLE) {
        tpm_free(context_buf);
        return TPM_RESOURCES;
      }
      session = &tpmData.stany.data.sessions[HANDLE_TO_INDEX(*handle)];
    } else {
      *handle = hintHandle;
    }
    /* reload resource */
    memcpy(session, &context.internalData.session, sizeof(TPM_SESSION_DATA));
  }
  tpm_free(context_buf);
  return TPM_SUCCESS;
}
