trunks: Made it possible to reinitialize AuthorizationSession

this commit allows us to call StartUnboundSession/StartBoundSession
multiple times in the same AuthorizationSession. This is useful because
session resources are now freed correctly when a session is
reinitialized.

BUG=None
TEST=unit and manual

Change-Id: I32f4ec6750719d9f6a402ec5f0b49484c76d60bf
Reviewed-on: https://chromium-review.googlesource.com/239200
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: Utkarsh Sanghi <usanghi@chromium.org>
Tested-by: Utkarsh Sanghi <usanghi@chromium.org>
diff --git a/authorization_session_impl.cc b/authorization_session_impl.cc
index 99c88b2..8103d14 100644
--- a/authorization_session_impl.cc
+++ b/authorization_session_impl.cc
@@ -21,30 +21,23 @@
 namespace {
 
 const size_t kWellKnownExponent = 0x10001;
+const trunks::TPM_HANDLE kUninitializedHandle = 0;
 
 }  // namespace
 
 namespace trunks {
 
 AuthorizationSessionImpl::AuthorizationSessionImpl(
-    const TrunksFactory& factory) : factory_(factory) {}
+    const TrunksFactory& factory)
+    : factory_(factory),
+      hmac_handle_(kUninitializedHandle) {}
 
 AuthorizationSessionImpl::~AuthorizationSessionImpl() {
-  if (!hmac_handle_) {
-    return;
-  }
-  Tpm* tpm = factory_.GetTpm();
-  TPM_RC result = tpm->FlushContextSync(hmac_handle_,
-                                        "",
-                                        NULL);
-  if (result != TPM_RC_SUCCESS) {
-    LOG(WARNING) << "Error closing authorization session: "
-                 << GetErrorString(result);
-  }
+  CloseSession();
 }
 
 AuthorizationDelegate* AuthorizationSessionImpl::GetDelegate() {
-  if (!hmac_handle_) {
+  if (hmac_handle_ == kUninitializedHandle) {
     return NULL;
   }
   return &hmac_delegate_;
@@ -54,6 +47,8 @@
     TPMI_DH_ENTITY bind_entity,
     const std::string& bind_authorization_value,
     bool enable_encryption) {
+  // If we already have an active session, close it.
+  CloseSession();
   // First we generate a cryptographically secure salt and encrypt it using
   // PKCS1_OAEP padded RSA public key encryption. This is specified in TPM2.0
   // Part1 Architecture, Appendix B.10.2.
@@ -217,4 +212,19 @@
   return TPM_RC_SUCCESS;
 }
 
+void AuthorizationSessionImpl::CloseSession() {
+  if (hmac_handle_ == kUninitializedHandle) {
+    return;
+  }
+  Tpm* tpm = factory_.GetTpm();
+  TPM_RC result = tpm->FlushContextSync(hmac_handle_,
+                                        "",
+                                        NULL);
+  if (result != TPM_RC_SUCCESS) {
+    LOG(WARNING) << "Error closing authorization session: "
+                 << GetErrorString(result);
+  }
+  hmac_handle_ = kUninitializedHandle;
+}
+
 }  // namespace trunks
diff --git a/authorization_session_impl.h b/authorization_session_impl.h
index ec51ad0..d53136c 100644
--- a/authorization_session_impl.h
+++ b/authorization_session_impl.h
@@ -58,6 +58,10 @@
   // The encrypted salt is stored in the out parameter |encrypted_salt|.
   TPM_RC EncryptSalt(const std::string& salt, std::string* encrypted_salt);
 
+  // This method tries to flush all TPM context associated with the current
+  // AuthorizationSession.
+  void CloseSession();
+
   // This factory is only set in the constructor and is used to instantiate
   // The TPM class to forward commands to the TPM chip.
   const TrunksFactory& factory_;