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 #include <string>
18
19 #include <gtest/gtest.h>
20
21 #include "trunks/hmac_authorization_delegate.h"
22
23 namespace trunks {
24
TEST(HmacAuthorizationDelegateTest,UninitializedSessionTest)25 TEST(HmacAuthorizationDelegateTest, UninitializedSessionTest) {
26 HmacAuthorizationDelegate delegate;
27 std::string dummy;
28 std::string p_hash("test");
29 EXPECT_FALSE(delegate.GetCommandAuthorization(p_hash, false, false, &dummy));
30 EXPECT_EQ(0u, dummy.size());
31 EXPECT_FALSE(delegate.CheckResponseAuthorization(p_hash, dummy));
32 EXPECT_FALSE(delegate.EncryptCommandParameter(&dummy));
33 EXPECT_FALSE(delegate.DecryptResponseParameter(&dummy));
34 }
35
TEST(HmacAuthorizationDelegateTest,SessionKeyTest)36 TEST(HmacAuthorizationDelegateTest, SessionKeyTest) {
37 HmacAuthorizationDelegate delegate;
38 TPM2B_NONCE nonce;
39 nonce.size = kAesKeySize;
40 memset(nonce.buffer, 0, nonce.size);
41 TPM_HANDLE dummy_handle = HMAC_SESSION_FIRST;
42 EXPECT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, std::string(),
43 std::string(), false));
44 EXPECT_EQ(0u, delegate.session_key_.size());
45
46 std::string dummy_auth = std::string("authorization");
47 std::string dummy_salt = std::string("salt");
48 EXPECT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, dummy_salt,
49 dummy_auth, false));
50 EXPECT_EQ(kHashDigestSize, delegate.session_key_.size());
51 // TODO(usanghi): Use TCG TPM2.0 test vectors when available.
52 std::string expected_key(
53 "\xfb\x2f\x3c\x33\x65\x3e\xdc\x47"
54 "\xda\xbe\x4e\xb7\xf4\x6c\x19\x4d"
55 "\xea\x50\xb2\x11\x54\x45\x32\x73"
56 "\x47\x38\xef\xb3\x4a\x82\x29\x94",
57 kHashDigestSize);
58 EXPECT_EQ(0, expected_key.compare(delegate.session_key_));
59 }
60
TEST(HmacAuthorizationDelegateTest,EncryptDecryptTest)61 TEST(HmacAuthorizationDelegateTest, EncryptDecryptTest) {
62 HmacAuthorizationDelegate delegate;
63 std::string plaintext_parameter("parameter");
64 std::string encrypted_parameter(plaintext_parameter);
65 // Test with session not initialized.
66 EXPECT_FALSE(delegate.EncryptCommandParameter(&encrypted_parameter));
67 EXPECT_FALSE(delegate.DecryptResponseParameter(&encrypted_parameter));
68 // Test with encryption not enabled.
69 TPM_HANDLE dummy_handle = HMAC_SESSION_FIRST;
70 TPM2B_NONCE nonce;
71 nonce.size = kAesKeySize;
72 std::string salt("salt");
73 ASSERT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, salt,
74 std::string(), false));
75 EXPECT_TRUE(delegate.EncryptCommandParameter(&encrypted_parameter));
76 EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
77 EXPECT_TRUE(delegate.DecryptResponseParameter(&encrypted_parameter));
78 EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
79 // Test with encryption enabled.
80 ASSERT_TRUE(delegate.InitSession(dummy_handle, nonce, nonce, salt,
81 std::string(), true));
82 EXPECT_TRUE(delegate.EncryptCommandParameter(&encrypted_parameter));
83 EXPECT_NE(0, plaintext_parameter.compare(encrypted_parameter));
84 // Calling EncryptCommandParameter regenerated the caller_nonce.
85 // We need to manually switch tpm_nonce and caller_nonce to ensure
86 // that DecryptResponseParameter has the correct nonces.
87 delegate.tpm_nonce_ = delegate.caller_nonce_;
88 delegate.caller_nonce_ = nonce;
89 EXPECT_TRUE(delegate.DecryptResponseParameter(&encrypted_parameter));
90 EXPECT_EQ(0, plaintext_parameter.compare(encrypted_parameter));
91 }
92
93 class HmacAuthorizationDelegateFixture : public testing::Test {
94 public:
HmacAuthorizationDelegateFixture()95 HmacAuthorizationDelegateFixture() {}
~HmacAuthorizationDelegateFixture()96 ~HmacAuthorizationDelegateFixture() override {}
97
SetUp()98 void SetUp() override {
99 session_handle_ = HMAC_SESSION_FIRST;
100 session_nonce_.size = kAesKeySize;
101 memset(session_nonce_.buffer, 0, kAesKeySize);
102 ASSERT_TRUE(delegate_.InitSession(session_handle_,
103 session_nonce_, // TPM nonce.
104 session_nonce_, // Caller nonce.
105 std::string(), // Salt.
106 std::string(), // Bind auth value.
107 false)); // Enable encryption.
108 }
109
110 protected:
111 TPM_HANDLE session_handle_;
112 TPM2B_NONCE session_nonce_;
113 HmacAuthorizationDelegate delegate_;
114 };
115
TEST_F(HmacAuthorizationDelegateFixture,NonceRegenerationTest)116 TEST_F(HmacAuthorizationDelegateFixture, NonceRegenerationTest) {
117 ASSERT_TRUE(delegate_.InitSession(session_handle_,
118 session_nonce_, // TPM nonce.
119 session_nonce_, // Caller nonce.
120 std::string(), // Salt.
121 std::string(), // Bind auth value.
122 true)); // Enable encryption.
123 TPM2B_NONCE original_nonce = session_nonce_;
124 EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
125 EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer, original_nonce.buffer,
126 original_nonce.size));
127 // First we check that performing GetCommandAuthorization resets the nonce.
128 std::string command_hash;
129 std::string authorization;
130 TPMS_AUTH_COMMAND auth_command;
131 EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
132 &authorization));
133 EXPECT_EQ(TPM_RC_SUCCESS,
134 Parse_TPMS_AUTH_COMMAND(&authorization, &auth_command, nullptr));
135 EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
136 EXPECT_EQ(auth_command.nonce.size, original_nonce.size);
137 EXPECT_NE(0, memcmp(delegate_.caller_nonce_.buffer, original_nonce.buffer,
138 original_nonce.size));
139 EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer, auth_command.nonce.buffer,
140 auth_command.nonce.size));
141 // Now we check that GetCommandAuthorization does not reset nonce
142 // when EncryptCommandParameter is called first.
143 original_nonce = delegate_.caller_nonce_;
144 std::string parameter;
145 EXPECT_TRUE(delegate_.EncryptCommandParameter(¶meter));
146 EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
147 EXPECT_NE(0, memcmp(delegate_.caller_nonce_.buffer, original_nonce.buffer,
148 original_nonce.size));
149 EXPECT_TRUE(delegate_.nonce_generated_);
150 original_nonce = delegate_.caller_nonce_;
151 EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
152 &authorization));
153 EXPECT_EQ(TPM_RC_SUCCESS,
154 Parse_TPMS_AUTH_COMMAND(&authorization, &auth_command, nullptr));
155 EXPECT_EQ(delegate_.caller_nonce_.size, original_nonce.size);
156 EXPECT_EQ(auth_command.nonce.size, original_nonce.size);
157 EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer, original_nonce.buffer,
158 original_nonce.size));
159 EXPECT_EQ(0, memcmp(delegate_.caller_nonce_.buffer, auth_command.nonce.buffer,
160 auth_command.nonce.size));
161 }
162
TEST_F(HmacAuthorizationDelegateFixture,CommandAuthTest)163 TEST_F(HmacAuthorizationDelegateFixture, CommandAuthTest) {
164 std::string command_hash;
165 std::string authorization;
166 EXPECT_TRUE(delegate_.GetCommandAuthorization(command_hash, false, false,
167 &authorization));
168 TPMS_AUTH_COMMAND auth_command;
169 std::string auth_bytes;
170 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
171 &authorization, &auth_command, &auth_bytes));
172 EXPECT_EQ(auth_command.session_handle, session_handle_);
173 EXPECT_EQ(auth_command.nonce.size, session_nonce_.size);
174 EXPECT_EQ(kContinueSession, auth_command.session_attributes);
175 EXPECT_EQ(kHashDigestSize, auth_command.hmac.size);
176 }
177
TEST_F(HmacAuthorizationDelegateFixture,ResponseAuthTest)178 TEST_F(HmacAuthorizationDelegateFixture, ResponseAuthTest) {
179 TPMS_AUTH_RESPONSE auth_response;
180 auth_response.session_attributes = kContinueSession;
181 auth_response.nonce.size = kAesKeySize;
182 memset(auth_response.nonce.buffer, 0, kAesKeySize);
183 auth_response.hmac.size = kHashDigestSize;
184 // TODO(usanghi): Use TCG TPM2.0 test vectors when available.
185 uint8_t hmac_buffer[kHashDigestSize] = {
186 0x37, 0x69, 0xaf, 0x12, 0xff, 0x4d, 0xbf, 0x44, 0xe5, 0x16, 0xa2,
187 0x2d, 0x1d, 0x05, 0x12, 0xe8, 0xbc, 0x42, 0x51, 0x6d, 0x59, 0xe8,
188 0xbf, 0x40, 0x1e, 0xa3, 0x46, 0xa4, 0xd6, 0x0d, 0xcc, 0xf7};
189 memcpy(auth_response.hmac.buffer, hmac_buffer, kHashDigestSize);
190 std::string response_hash;
191 std::string authorization;
192 EXPECT_EQ(TPM_RC_SUCCESS,
193 Serialize_TPMS_AUTH_RESPONSE(auth_response, &authorization));
194 EXPECT_TRUE(
195 delegate_.CheckResponseAuthorization(response_hash, authorization));
196 }
197
TEST_F(HmacAuthorizationDelegateFixture,SessionAttributes)198 TEST_F(HmacAuthorizationDelegateFixture, SessionAttributes) {
199 const uint8_t kDecryptSession = 1 << 5;
200 const uint8_t kEncryptSession = 1 << 6;
201
202 // Encryption disabled and not possible for command.
203 std::string authorization;
204 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, false,
205 &authorization));
206 TPMS_AUTH_COMMAND auth_command;
207 std::string auth_bytes;
208 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
209 &authorization, &auth_command, &auth_bytes));
210 EXPECT_EQ(kContinueSession, auth_command.session_attributes);
211
212 // Encryption disabled and possible for command.
213 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, true,
214 &authorization));
215 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
216 &authorization, &auth_command, &auth_bytes));
217 EXPECT_EQ(kContinueSession, auth_command.session_attributes);
218
219 // Encryption enabled and not possible for command.
220 ASSERT_TRUE(delegate_.InitSession(session_handle_,
221 session_nonce_, // TPM nonce.
222 session_nonce_, // Caller nonce.
223 std::string(), // Salt.
224 std::string(), // Bind auth value.
225 true)); // Enable encryption.
226 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, false,
227 &authorization));
228 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
229 &authorization, &auth_command, &auth_bytes));
230 EXPECT_EQ(kContinueSession, auth_command.session_attributes);
231
232 // Encryption enabled and possible only for command input.
233 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, false,
234 &authorization));
235 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
236 &authorization, &auth_command, &auth_bytes));
237 EXPECT_EQ(kContinueSession | kDecryptSession,
238 auth_command.session_attributes);
239
240 // Encryption enabled and possible only for command output.
241 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), false, true,
242 &authorization));
243 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
244 &authorization, &auth_command, &auth_bytes));
245 EXPECT_EQ(kContinueSession | kEncryptSession,
246 auth_command.session_attributes);
247
248 // Encryption enabled and possible for command input and output.
249 EXPECT_TRUE(delegate_.GetCommandAuthorization(std::string(), true, true,
250 &authorization));
251 EXPECT_EQ(TPM_RC_SUCCESS, Parse_TPMS_AUTH_COMMAND(
252 &authorization, &auth_command, &auth_bytes));
253 EXPECT_EQ(kContinueSession | kEncryptSession | kDecryptSession,
254 auth_command.session_attributes);
255 }
256
257 } // namespace trunks
258