blob: 1e590f0d24455edb5c76b8a31da3e6d8c2c27b20
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 <algorithm> |
18 | |
19 | #include <gtest/gtest.h> |
20 | |
21 | #include <openssl/engine.h> |
22 | #include <openssl/rand.h> |
23 | |
24 | #include <keymaster/authorization_set.h> |
25 | #include <keymaster/android_keymaster_utils.h> |
26 | #include <keymaster/keymaster_tags.h> |
27 | |
28 | #include "android_keymaster_test_utils.h" |
29 | #include "auth_encrypted_key_blob.h" |
30 | #include "integrity_assured_key_blob.h" |
31 | #include "ocb_utils.h" |
32 | |
33 | namespace keymaster { |
34 | |
35 | namespace test { |
36 | |
37 | const uint8_t master_key_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
38 | const uint8_t key_data[5] = {21, 22, 23, 24, 25}; |
39 | |
40 | class KeyBlobTest : public testing::Test { |
41 | protected: |
42 | KeyBlobTest() |
43 | : master_key_(master_key_data, array_length(master_key_data)), |
44 | key_material_(key_data, array_length(key_data)) { |
45 | hw_enforced_.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA); |
46 | hw_enforced_.push_back(TAG_KEY_SIZE, 256); |
47 | hw_enforced_.push_back(TAG_BLOB_USAGE_REQUIREMENTS, KM_BLOB_STANDALONE); |
48 | hw_enforced_.push_back(TAG_MIN_SECONDS_BETWEEN_OPS, 10); |
49 | hw_enforced_.push_back(TAG_ALL_USERS); |
50 | hw_enforced_.push_back(TAG_NO_AUTH_REQUIRED); |
51 | hw_enforced_.push_back(TAG_ORIGIN, KM_ORIGIN_GENERATED); |
52 | |
53 | sw_enforced_.push_back(TAG_ACTIVE_DATETIME, 10); |
54 | sw_enforced_.push_back(TAG_ORIGINATION_EXPIRE_DATETIME, 100); |
55 | sw_enforced_.push_back(TAG_CREATION_DATETIME, 10); |
56 | |
57 | hidden_.push_back(TAG_ROOT_OF_TRUST, "foo", 3); |
58 | hidden_.push_back(TAG_APPLICATION_ID, "my_app", 6); |
59 | |
60 | nonce_.reserve(OCB_NONCE_LENGTH); |
61 | EXPECT_EQ(1, RAND_bytes(nonce_.peek_write(), OCB_NONCE_LENGTH)); |
62 | nonce_.advance_write(OCB_NONCE_LENGTH); |
63 | |
64 | tag_.reserve(OCB_TAG_LENGTH); |
65 | } |
66 | |
67 | keymaster_error_t Encrypt() { |
68 | return OcbEncryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, key_material_, |
69 | nonce_, &ciphertext_, &tag_); |
70 | } |
71 | |
72 | keymaster_error_t Decrypt() { |
73 | return OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_, nonce_, |
74 | tag_, &decrypted_plaintext_); |
75 | } |
76 | |
77 | keymaster_error_t Serialize() { |
78 | return SerializeAuthEncryptedBlob(ciphertext_, hw_enforced_, sw_enforced_, nonce_, tag_, |
79 | &serialized_blob_); |
80 | } |
81 | |
82 | keymaster_error_t Deserialize() { |
83 | return DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw_enforced_, |
84 | &sw_enforced_, &nonce_, &tag_); |
85 | } |
86 | |
87 | AuthorizationSet hw_enforced_; |
88 | AuthorizationSet sw_enforced_; |
89 | AuthorizationSet hidden_; |
90 | Buffer nonce_, tag_; |
91 | |
92 | KeymasterKeyBlob master_key_; |
93 | KeymasterKeyBlob key_material_; |
94 | KeymasterKeyBlob ciphertext_; |
95 | KeymasterKeyBlob decrypted_plaintext_; |
96 | KeymasterKeyBlob serialized_blob_; |
97 | }; |
98 | |
99 | TEST_F(KeyBlobTest, EncryptDecrypt) { |
100 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
101 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
102 | |
103 | // key_data shouldn't be anywhere in the blob, ciphertext should. |
104 | EXPECT_EQ(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(), |
105 | key_material_.begin(), key_material_.end())); |
106 | EXPECT_NE(serialized_blob_.end(), std::search(serialized_blob_.begin(), serialized_blob_.end(), |
107 | ciphertext_.begin(), ciphertext_.end())); |
108 | |
109 | ciphertext_.Clear(); |
110 | nonce_.Clear(); |
111 | tag_.Clear(); |
112 | AuthorizationSet hw2; |
113 | AuthorizationSet sw2; |
114 | |
115 | ASSERT_EQ(KM_ERROR_OK, DeserializeAuthEncryptedBlob(serialized_blob_, &ciphertext_, &hw2, &sw2, |
116 | &nonce_, &tag_)); |
117 | KeymasterKeyBlob plaintext; |
118 | OcbDecryptKey(hw2, sw2, hidden_, master_key_, ciphertext_, nonce_, tag_, &plaintext); |
119 | |
120 | EXPECT_EQ(hw_enforced_, hw2); |
121 | EXPECT_EQ(sw_enforced_, sw2); |
122 | |
123 | ASSERT_EQ(key_material_.key_material_size, plaintext.key_material_size); |
124 | EXPECT_EQ(0, memcmp(plaintext.begin(), key_material_.begin(), plaintext.key_material_size)); |
125 | } |
126 | |
127 | TEST_F(KeyBlobTest, WrongKeyLength) { |
128 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
129 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
130 | |
131 | // Modify the key length, shouldn't be able to parse. |
132 | serialized_blob_.writable_data()[1 /* version */ + 4 /* nonce len */ + 12 /* nonce */ + 3]++; |
133 | |
134 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Deserialize()); |
135 | } |
136 | |
137 | TEST_F(KeyBlobTest, WrongNonce) { |
138 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
139 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
140 | |
141 | // Find the nonce, then modify it. |
142 | auto nonce_ptr = |
143 | std::search(serialized_blob_.begin(), serialized_blob_.end(), nonce_.begin(), nonce_.end()); |
144 | ASSERT_NE(nonce_ptr, serialized_blob_.end()); |
145 | EXPECT_EQ(serialized_blob_.end(), |
146 | std::search(nonce_ptr + 1, serialized_blob_.end(), nonce_.begin(), nonce_.end())); |
147 | (*const_cast<uint8_t*>(nonce_ptr))++; |
148 | |
149 | // Deserialization shouldn't be affected, but decryption should fail. |
150 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
151 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt()); |
152 | } |
153 | |
154 | TEST_F(KeyBlobTest, WrongTag) { |
155 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
156 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
157 | |
158 | // Find the tag, them modify it. |
159 | auto tag_ptr = |
160 | std::search(serialized_blob_.begin(), serialized_blob_.end(), tag_.begin(), tag_.end()); |
161 | ASSERT_NE(tag_ptr, serialized_blob_.end()); |
162 | EXPECT_EQ(serialized_blob_.end(), |
163 | std::search(tag_ptr + 1, serialized_blob_.end(), tag_.begin(), tag_.end())); |
164 | (*const_cast<uint8_t*>(tag_ptr))++; |
165 | |
166 | // Deserialization shouldn't be affected, but decryption should fail. |
167 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
168 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt()); |
169 | } |
170 | |
171 | TEST_F(KeyBlobTest, WrongCiphertext) { |
172 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
173 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
174 | |
175 | // Find the ciphertext, them modify it. |
176 | auto ciphertext_ptr = std::search(serialized_blob_.begin(), serialized_blob_.end(), |
177 | ciphertext_.begin(), ciphertext_.end()); |
178 | ASSERT_NE(ciphertext_ptr, serialized_blob_.end()); |
179 | EXPECT_EQ(serialized_blob_.end(), std::search(ciphertext_ptr + 1, serialized_blob_.end(), |
180 | ciphertext_.begin(), ciphertext_.end())); |
181 | (*const_cast<uint8_t*>(ciphertext_ptr))++; |
182 | |
183 | // Deserialization shouldn't be affected, but decryption should fail. |
184 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
185 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt()); |
186 | } |
187 | |
188 | TEST_F(KeyBlobTest, WrongMasterKey) { |
189 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
190 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
191 | |
192 | uint8_t wrong_master_data[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
193 | KeymasterKeyBlob wrong_master(wrong_master_data, array_length(wrong_master_data)); |
194 | |
195 | // Decrypting with wrong master key should fail. |
196 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
197 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
198 | OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, wrong_master, ciphertext_, nonce_, |
199 | tag_, &decrypted_plaintext_)); |
200 | } |
201 | |
202 | TEST_F(KeyBlobTest, WrongHwEnforced) { |
203 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
204 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
205 | |
206 | // Find enforced serialization data and modify it. |
207 | size_t hw_enforced_size = hw_enforced_.SerializedSize(); |
208 | UniquePtr<uint8_t[]> hw_enforced_data(new uint8_t[hw_enforced_size]); |
209 | hw_enforced_.Serialize(hw_enforced_data.get(), hw_enforced_data.get() + hw_enforced_size); |
210 | |
211 | auto hw_enforced_ptr = |
212 | std::search(serialized_blob_.begin(), serialized_blob_.end(), hw_enforced_data.get(), |
213 | hw_enforced_data.get() + hw_enforced_size); |
214 | ASSERT_NE(serialized_blob_.end(), hw_enforced_ptr); |
215 | EXPECT_EQ(serialized_blob_.end(), |
216 | std::search(hw_enforced_ptr + 1, serialized_blob_.end(), hw_enforced_data.get(), |
217 | hw_enforced_data.get() + hw_enforced_size)); |
218 | (*(const_cast<uint8_t*>(hw_enforced_ptr) + hw_enforced_size - 1))++; |
219 | |
220 | // Deserialization shouldn't be affected, but decryption should fail. |
221 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
222 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt()); |
223 | } |
224 | |
225 | TEST_F(KeyBlobTest, WrongSwEnforced) { |
226 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
227 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
228 | |
229 | // Find enforced serialization data and modify it. |
230 | size_t sw_enforced_size = sw_enforced_.SerializedSize(); |
231 | UniquePtr<uint8_t[]> sw_enforced_data(new uint8_t[sw_enforced_size]); |
232 | sw_enforced_.Serialize(sw_enforced_data.get(), sw_enforced_data.get() + sw_enforced_size); |
233 | |
234 | auto sw_enforced_ptr = |
235 | std::search(serialized_blob_.begin(), serialized_blob_.end(), sw_enforced_data.get(), |
236 | sw_enforced_data.get() + sw_enforced_size); |
237 | ASSERT_NE(serialized_blob_.end(), sw_enforced_ptr); |
238 | EXPECT_EQ(serialized_blob_.end(), |
239 | std::search(sw_enforced_ptr + 1, serialized_blob_.end(), sw_enforced_data.get(), |
240 | sw_enforced_data.get() + sw_enforced_size)); |
241 | (*(const_cast<uint8_t*>(sw_enforced_ptr) + sw_enforced_size - 1))++; |
242 | |
243 | // Deserialization shouldn't be affected, but decryption should fail. |
244 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
245 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, Decrypt()); |
246 | } |
247 | |
248 | TEST_F(KeyBlobTest, EmptyHidden) { |
249 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
250 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
251 | |
252 | AuthorizationSet wrong_hidden; |
253 | |
254 | // Deserialization shouldn't be affected, but decryption should fail. |
255 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
256 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
257 | OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_, |
258 | nonce_, tag_, &decrypted_plaintext_)); |
259 | } |
260 | |
261 | TEST_F(KeyBlobTest, WrongRootOfTrust) { |
262 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
263 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
264 | |
265 | AuthorizationSet wrong_hidden; |
266 | wrong_hidden.push_back(TAG_ROOT_OF_TRUST, "bar", 2); |
267 | wrong_hidden.push_back(TAG_APPLICATION_ID, "my_app", 6); |
268 | |
269 | // Deserialization shouldn't be affected, but decryption should fail. |
270 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
271 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
272 | OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_, |
273 | nonce_, tag_, &decrypted_plaintext_)); |
274 | } |
275 | |
276 | TEST_F(KeyBlobTest, WrongAppId) { |
277 | ASSERT_EQ(KM_ERROR_OK, Encrypt()); |
278 | ASSERT_EQ(KM_ERROR_OK, Serialize()); |
279 | |
280 | AuthorizationSet wrong_hidden; |
281 | wrong_hidden.push_back(TAG_ROOT_OF_TRUST, "foo", 3); |
282 | wrong_hidden.push_back(TAG_APPLICATION_ID, "your_app", 7); |
283 | |
284 | // Deserialization shouldn't be affected, but decryption should fail. |
285 | ASSERT_EQ(KM_ERROR_OK, Deserialize()); |
286 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
287 | OcbDecryptKey(hw_enforced_, sw_enforced_, wrong_hidden, master_key_, ciphertext_, |
288 | nonce_, tag_, &decrypted_plaintext_)); |
289 | } |
290 | |
291 | // This test is especially useful when compiled for 32-bit mode and run under valgrind. |
292 | TEST_F(KeyBlobTest, FuzzTest) { |
293 | time_t now = time(NULL); |
294 | std::cout << "Seeding rand() with " << now << " for fuzz test." << std::endl; |
295 | srand(now); |
296 | |
297 | // Fill large buffer with random bytes. |
298 | const int kBufSize = 10000; |
299 | UniquePtr<uint8_t[]> buf(new uint8_t[kBufSize]); |
300 | for (size_t i = 0; i < kBufSize; ++i) |
301 | buf[i] = static_cast<uint8_t>(rand()); |
302 | |
303 | // Try to deserialize every offset with multiple methods. |
304 | size_t deserialize_auth_encrypted_success = 0; |
305 | for (size_t i = 0; i < kBufSize; ++i) { |
306 | keymaster_key_blob_t blob = {buf.get() + i, kBufSize - i}; |
307 | KeymasterKeyBlob key_blob(blob); |
308 | |
309 | // Integrity-assured blob. |
310 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
311 | DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_, |
312 | &sw_enforced_)); |
313 | |
314 | // Auth-encrypted OCB blob. |
315 | keymaster_error_t error = DeserializeAuthEncryptedBlob( |
316 | key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_, &nonce_, &tag_); |
317 | if (error == KM_ERROR_OK) { |
318 | // It's possible to deserialize successfully. Decryption should always fail. |
319 | ++deserialize_auth_encrypted_success; |
320 | error = OcbDecryptKey(hw_enforced_, sw_enforced_, hidden_, master_key_, ciphertext_, |
321 | nonce_, tag_, &decrypted_plaintext_); |
322 | } |
323 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, error) |
324 | << "Somehow sucessfully parsed a blob with seed " << now << " at offset " << i; |
325 | } |
326 | } |
327 | |
328 | TEST_F(KeyBlobTest, UnderflowTest) { |
329 | uint8_t buf[0]; |
330 | keymaster_key_blob_t blob = {buf, 0}; |
331 | KeymasterKeyBlob key_blob(blob); |
332 | EXPECT_NE(nullptr, key_blob.key_material); |
333 | EXPECT_EQ(0U, key_blob.key_material_size); |
334 | |
335 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
336 | DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_, |
337 | &sw_enforced_)); |
338 | |
339 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
340 | DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_, |
341 | &nonce_, &tag_)); |
342 | } |
343 | |
344 | TEST_F(KeyBlobTest, DupBufferToolarge) { |
345 | uint8_t buf[0]; |
346 | keymaster_key_blob_t blob = {buf, 0}; |
347 | blob.key_material_size = 16 * 1024 * 1024 + 1; |
348 | KeymasterKeyBlob key_blob(blob); |
349 | EXPECT_EQ(nullptr, key_blob.key_material); |
350 | EXPECT_EQ(0U, key_blob.key_material_size); |
351 | |
352 | ASSERT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
353 | DeserializeIntegrityAssuredBlob(key_blob, hidden_, &key_material_, &hw_enforced_, |
354 | &sw_enforced_)); |
355 | |
356 | EXPECT_EQ(KM_ERROR_INVALID_KEY_BLOB, |
357 | DeserializeAuthEncryptedBlob(key_blob, &ciphertext_, &hw_enforced_, &sw_enforced_, |
358 | &nonce_, &tag_)); |
359 | } |
360 | |
361 | } // namespace test |
362 | } // namespace keymaster |
363 |