Home | History | Annotate | Download | only in trunks
      1 //
      2 // Copyright (C) 2014 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
     18 #define TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
     19 
     20 #include <string>
     21 
     22 #include <base/gtest_prod_util.h>
     23 #include <crypto/secure_hash.h>
     24 #include <gtest/gtest_prod.h>
     25 
     26 #include "trunks/authorization_delegate.h"
     27 #include "trunks/tpm_generated.h"
     28 #include "trunks/trunks_export.h"
     29 
     30 namespace trunks {
     31 
     32 const uint8_t kContinueSession = 1;
     33 const size_t kAesKeySize = 16;      // 128 bits is minimum AES key size.
     34 const size_t kHashDigestSize = 32;  // 256 bits is SHA256 digest size.
     35 
     36 // HmacAuthorizationDelegate is an implementation of the AuthorizationDelegate
     37 // interface. It provides the necessary Auth data for HMAC sessions.
     38 // This delegate also does parameter encryption on sessions that support it.
     39 
     40 // Usage:
     41 // 1) After running the StartAuthSession command on the TPM2.0, we declare this
     42 // delegate using the constructor. We can specify if we want parameter
     43 // obfuscation enabled or not.
     44 // 2) We initialize the session using |InitSession|. We feed in the handle and
     45 // tpm_nonce returned by StartAuthSession. Additionally we inject the
     46 // caller_nonce, salt and auth_value of the bound entity we fed into
     47 // StartAuthSession.
     48 // 3) Pass a pointer to this delegate to any TPM command that needs
     49 // authorization using this delegate.
     50 
     51 // Sample control flow:
     52 //  TrunksProxy proxy;
     53 //  proxy.Init();
     54 //  Tpm tpm(&proxy);
     55 //  tpm.StartAuthSession(...);
     56 //  HmacAuthorizationDelegate hmac();
     57 //  hmac.InitSession(...);
     58 //  tpm.Create(..., &hmac);
     59 //  hmac.set_entity_authorization_value(...);
     60 //  tpm.Load(..., &hmac);
     61 class TRUNKS_EXPORT HmacAuthorizationDelegate : public AuthorizationDelegate {
     62  public:
     63   HmacAuthorizationDelegate();
     64   ~HmacAuthorizationDelegate() override;
     65 
     66   // AuthorizationDelegate methods.
     67   bool GetCommandAuthorization(const std::string& command_hash,
     68                                bool is_command_parameter_encryption_possible,
     69                                bool is_response_parameter_encryption_possible,
     70                                std::string* authorization) override;
     71   bool CheckResponseAuthorization(const std::string& response_hash,
     72                                   const std::string& authorization) override;
     73   bool EncryptCommandParameter(std::string* parameter) override;
     74   bool DecryptResponseParameter(std::string* parameter) override;
     75 
     76   // This function is called with the return data of |StartAuthSession|. It
     77   // will initialize the session to start providing auth information. It can
     78   // only be called once per delegate, and must be called before the delegate
     79   // is used for any operation. The boolean arg |enable_parameter_encryption|
     80   // specifies if parameter encryption should be enabled for this delegate.
     81   // |salt| and |bind_auth_value| specify the injected auth values into this
     82   // delegate.
     83   bool InitSession(TPM_HANDLE session_handle,
     84                    const TPM2B_NONCE& tpm_nonce,
     85                    const TPM2B_NONCE& caller_nonce,
     86                    const std::string& salt,
     87                    const std::string& bind_auth_value,
     88                    bool enable_parameter_encryption);
     89 
     90   // This method sets the FutureAuthorizationValue. This value is used in
     91   // computing the HMAC response of TPM2_HierarchyChangeAuth.
     92   void set_future_authorization_value(const std::string& auth_value);
     93 
     94   std::string future_authorization_value() {
     95     return future_authorization_value_;
     96   }
     97 
     98   // This method is used to inject an auth_value associated with an entity.
     99   // This auth_value is then used when generating HMACs and encryption keys.
    100   // Note: This value will be used for all commands until explicitly reset.
    101   void set_entity_authorization_value(const std::string& auth_value) {
    102     entity_authorization_value_ = auth_value;
    103   }
    104 
    105   std::string entity_authorization_value() const {
    106     return entity_authorization_value_;
    107   }
    108 
    109   TPM_HANDLE session_handle() const { return session_handle_; }
    110 
    111   void set_use_entity_authorization_for_encryption_only(bool value) {
    112     use_entity_authorization_for_encryption_only_ = value;
    113   }
    114 
    115  protected:
    116   FRIEND_TEST(HmacAuthorizationDelegateFixture, NonceRegenerationTest);
    117   FRIEND_TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest);
    118   FRIEND_TEST(HmacAuthorizationDelegateTest, SessionKeyTest);
    119 
    120  private:
    121   // This method implements the key derivation function used in the TPM.
    122   // NOTE: It only returns 32 byte keys.
    123   std::string CreateKey(const std::string& hmac_key,
    124                         const std::string& label,
    125                         const TPM2B_NONCE& nonce_newer,
    126                         const TPM2B_NONCE& nonce_older);
    127   // This method performs a FIPS198 HMAC operation on |data| using |key|
    128   std::string HmacSha256(const std::string& key, const std::string& data);
    129   // This method performs an AES operation using a 128 bit key.
    130   // |operation_type| can be either AES_ENCRYPT or AES_DECRYPT and it
    131   // determines if the operation is an encryption or decryption.
    132   void AesOperation(std::string* parameter,
    133                     const TPM2B_NONCE& nonce_newer,
    134                     const TPM2B_NONCE& nonce_older,
    135                     int operation_type);
    136   // This method regenerates the caller nonce. The new nonce is the same
    137   // length as the previous nonce. The buffer is filled with random data using
    138   // openssl's |RAND_bytes| function.
    139   // NOTE: This operation is DESTRUCTIVE, and rewrites the caller_nonce_ field.
    140   void RegenerateCallerNonce();
    141 
    142   TPM_HANDLE session_handle_;
    143   TPM2B_NONCE caller_nonce_;
    144   TPM2B_NONCE tpm_nonce_;
    145   bool is_parameter_encryption_enabled_;
    146   bool nonce_generated_;
    147   std::string session_key_;
    148   std::string entity_authorization_value_;
    149   bool future_authorization_value_set_;
    150   std::string future_authorization_value_;
    151   // This boolean flag determines if the entity_authorization_value_ is needed
    152   // when computing the hmac_key to create the authorization hmac. Defaults
    153   // to false, but policy sessions may set this flag to true.
    154   bool use_entity_authorization_for_encryption_only_;
    155 
    156   DISALLOW_COPY_AND_ASSIGN(HmacAuthorizationDelegate);
    157 };
    158 
    159 }  // namespace trunks
    160 
    161 #endif  // TRUNKS_HMAC_AUTHORIZATION_DELEGATE_H_
    162