| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "arc/keymaster/context/chaps_client.h" |
| |
| #include <cstdint> |
| #include <vector> |
| |
| #include <brillo/secure_blob.h> |
| #include <chaps/attributes.h> |
| #include <chaps/chaps_proxy_mock.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "arc/keymaster/context/context_adaptor.h" |
| #include "chaps/pkcs11/pkcs11t.h" |
| |
| using ::testing::_; |
| using ::testing::DoAll; |
| using ::testing::Eq; |
| using ::testing::Invoke; |
| using ::testing::Return; |
| using ::testing::SetArgPointee; |
| |
| namespace arc { |
| namespace keymaster { |
| namespace context { |
| |
| namespace { |
| |
| // Arbitrary non-zero CK_SESSION_HANDLE. |
| constexpr uint64_t kSessionId = 9; |
| // Arbitrary single-element list. |
| const std::vector<uint64_t> kObjectList = {7}; |
| const std::vector<uint64_t> kEmptyObjectList = {}; |
| |
| // Arbitrary 32 byte key. |
| const std::vector<uint8_t> kKeyBlob(32, 99); |
| |
| // Arbitrary blob containing a valid certificate x509 in DER format. |
| const std::vector<uint8_t> kCertificateDer = { |
| 48, 130, 3, 107, 48, 130, 2, 83, 160, 3, 2, 1, 2, 2, 20, |
| 105, 145, 5, 180, 104, 132, 151, 128, 121, 135, 72, 134, 120, 62, 120, |
| 253, 190, 80, 104, 131, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, |
| 1, 1, 11, 5, 0, 48, 69, 49, 11, 48, 9, 6, 3, 85, 4, |
| 6, 19, 2, 65, 85, 49, 19, 48, 17, 6, 3, 85, 4, 8, 12, |
| 10, 83, 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, |
| 6, 3, 85, 4, 10, 12, 24, 73, 110, 116, 101, 114, 110, 101, 116, |
| 32, 87, 105, 100, 103, 105, 116, 115, 32, 80, 116, 121, 32, 76, 116, |
| 100, 48, 30, 23, 13, 50, 48, 49, 50, 48, 51, 49, 48, 53, 49, |
| 48, 49, 90, 23, 13, 50, 49, 49, 50, 48, 51, 49, 48, 53, 49, |
| 48, 49, 90, 48, 69, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, |
| 2, 65, 85, 49, 19, 48, 17, 6, 3, 85, 4, 8, 12, 10, 83, |
| 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, 6, 3, |
| 85, 4, 10, 12, 24, 73, 110, 116, 101, 114, 110, 101, 116, 32, 87, |
| 105, 100, 103, 105, 116, 115, 32, 80, 116, 121, 32, 76, 116, 100, 48, |
| 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, |
| 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, |
| 1, 0, 175, 103, 224, 10, 106, 96, 140, 64, 134, 186, 210, 5, 92, |
| 160, 224, 117, 88, 148, 184, 148, 135, 242, 95, 65, 112, 75, 77, 80, |
| 68, 216, 98, 95, 39, 219, 229, 176, 19, 25, 149, 142, 151, 1, 221, |
| 192, 6, 7, 201, 133, 186, 45, 237, 28, 210, 126, 136, 190, 68, 242, |
| 232, 131, 168, 236, 18, 236, 236, 163, 33, 130, 235, 131, 210, 49, 236, |
| 108, 245, 182, 26, 249, 109, 223, 158, 33, 187, 222, 89, 151, 134, 213, |
| 46, 198, 215, 57, 239, 143, 132, 108, 69, 106, 97, 158, 144, 13, 112, |
| 226, 137, 186, 234, 91, 48, 97, 253, 248, 245, 123, 101, 183, 137, 183, |
| 39, 115, 26, 19, 201, 248, 71, 210, 172, 110, 98, 136, 224, 103, 222, |
| 212, 156, 219, 69, 50, 18, 85, 180, 83, 84, 209, 176, 62, 94, 166, |
| 91, 99, 78, 59, 36, 23, 23, 152, 215, 145, 248, 5, 253, 240, 29, |
| 42, 125, 130, 109, 243, 10, 175, 149, 169, 102, 61, 106, 63, 156, 17, |
| 185, 134, 199, 84, 7, 99, 231, 161, 222, 146, 161, 16, 27, 247, 178, |
| 137, 57, 111, 252, 132, 113, 190, 46, 75, 107, 243, 125, 1, 153, 133, |
| 86, 88, 141, 187, 27, 13, 53, 74, 156, 169, 87, 82, 192, 169, 44, |
| 101, 3, 145, 251, 83, 171, 123, 188, 141, 137, 120, 26, 100, 45, 102, |
| 145, 171, 178, 135, 238, 2, 32, 239, 53, 61, 78, 56, 139, 134, 46, |
| 212, 55, 39, 2, 3, 1, 0, 1, 163, 83, 48, 81, 48, 29, 6, |
| 3, 85, 29, 14, 4, 22, 4, 20, 22, 217, 14, 167, 113, 102, 100, |
| 7, 234, 117, 42, 153, 36, 99, 160, 163, 39, 151, 159, 181, 48, 31, |
| 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 22, 217, 14, 167, |
| 113, 102, 100, 7, 234, 117, 42, 153, 36, 99, 160, 163, 39, 151, 159, |
| 181, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, |
| 1, 1, 255, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, |
| 11, 5, 0, 3, 130, 1, 1, 0, 124, 63, 26, 197, 170, 235, 130, |
| 152, 65, 23, 47, 77, 128, 163, 203, 225, 192, 160, 236, 217, 174, 38, |
| 32, 245, 235, 61, 238, 39, 254, 114, 31, 247, 28, 175, 76, 128, 82, |
| 111, 95, 67, 186, 21, 149, 252, 153, 229, 193, 17, 94, 49, 102, 210, |
| 29, 113, 227, 38, 251, 161, 238, 87, 140, 147, 27, 171, 73, 115, 181, |
| 101, 200, 28, 2, 243, 194, 27, 77, 87, 195, 50, 67, 87, 184, 223, |
| 79, 87, 148, 48, 11, 87, 79, 30, 153, 12, 53, 71, 60, 33, 232, |
| 158, 32, 109, 90, 196, 104, 22, 31, 251, 86, 174, 133, 7, 146, 104, |
| 111, 142, 215, 73, 140, 108, 226, 123, 36, 216, 2, 65, 177, 87, 47, |
| 145, 62, 80, 137, 189, 122, 206, 175, 16, 52, 112, 233, 69, 248, 148, |
| 221, 147, 40, 16, 104, 112, 87, 229, 228, 9, 108, 89, 129, 117, 141, |
| 104, 23, 35, 113, 61, 22, 246, 73, 176, 254, 189, 7, 223, 49, 71, |
| 194, 238, 211, 87, 166, 67, 172, 125, 63, 136, 68, 231, 213, 13, 61, |
| 102, 14, 177, 131, 103, 9, 250, 198, 190, 153, 233, 75, 127, 79, 203, |
| 163, 41, 68, 201, 215, 234, 167, 147, 15, 73, 6, 146, 119, 185, 133, |
| 15, 40, 208, 103, 247, 149, 83, 185, 99, 10, 134, 89, 33, 179, 65, |
| 143, 55, 37, 93, 139, 174, 64, 52, 22, 8, 128, 240, 93, 164, 135, |
| 9, 217, 64, 54, 66, 245, 42, 148, 64}; |
| |
| // The public key of |kCertificateDer|. |
| const std::vector<uint8_t> kCertificateSpkiDer = { |
| 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, |
| 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130, |
| 1, 1, 0, 175, 103, 224, 10, 106, 96, 140, 64, 134, 186, 210, 5, |
| 92, 160, 224, 117, 88, 148, 184, 148, 135, 242, 95, 65, 112, 75, 77, |
| 80, 68, 216, 98, 95, 39, 219, 229, 176, 19, 25, 149, 142, 151, 1, |
| 221, 192, 6, 7, 201, 133, 186, 45, 237, 28, 210, 126, 136, 190, 68, |
| 242, 232, 131, 168, 236, 18, 236, 236, 163, 33, 130, 235, 131, 210, 49, |
| 236, 108, 245, 182, 26, 249, 109, 223, 158, 33, 187, 222, 89, 151, 134, |
| 213, 46, 198, 215, 57, 239, 143, 132, 108, 69, 106, 97, 158, 144, 13, |
| 112, 226, 137, 186, 234, 91, 48, 97, 253, 248, 245, 123, 101, 183, 137, |
| 183, 39, 115, 26, 19, 201, 248, 71, 210, 172, 110, 98, 136, 224, 103, |
| 222, 212, 156, 219, 69, 50, 18, 85, 180, 83, 84, 209, 176, 62, 94, |
| 166, 91, 99, 78, 59, 36, 23, 23, 152, 215, 145, 248, 5, 253, 240, |
| 29, 42, 125, 130, 109, 243, 10, 175, 149, 169, 102, 61, 106, 63, 156, |
| 17, 185, 134, 199, 84, 7, 99, 231, 161, 222, 146, 161, 16, 27, 247, |
| 178, 137, 57, 111, 252, 132, 113, 190, 46, 75, 107, 243, 125, 1, 153, |
| 133, 86, 88, 141, 187, 27, 13, 53, 74, 156, 169, 87, 82, 192, 169, |
| 44, 101, 3, 145, 251, 83, 171, 123, 188, 141, 137, 120, 26, 100, 45, |
| 102, 145, 171, 178, 135, 238, 2, 32, 239, 53, 61, 78, 56, 139, 134, |
| 46, 212, 55, 39, 2, 3, 1, 0, 1}; |
| |
| // Arbitrary blob representing some signature. |
| const std::vector<uint8_t> kSignatureBlob(32, 55); |
| |
| // Arbitrary blob of data. |
| const std::vector<uint8_t> kDataBlob(42, 77); |
| |
| // Valid serialized KeyPermissions protobuf. |
| const std::vector<uint8_t> kArcKeyPermissionTrue = {10, 4, 8, 1, 16, 1}; |
| const std::vector<uint8_t> kArcKeyPermissionFalse = {10, 2, 8, 1}; |
| |
| constexpr char kLabel[] = "object_label"; |
| const brillo::Blob kId(10, 10); |
| |
| } // anonymous namespace |
| |
| // Fixture for chaps client tests. |
| class ChapsClientTest : public ::testing::Test { |
| public: |
| ChapsClientTest() |
| : chaps_mock_(/* is_initialized */ true), |
| chaps_client_(context_adaptor_.GetWeakPtr()) {} |
| |
| uint32_t FakeGetCertificateBlob(const brillo::SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle, |
| const std::vector<uint8_t>& attributes_in, |
| std::vector<uint8_t>* attributes_out) { |
| return ParseAttribute(kCertificateDer, attributes_in, attributes_out); |
| } |
| |
| uint32_t FakeGetAttribute(const brillo::SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle, |
| const std::vector<uint8_t>& attributes_in, |
| std::vector<uint8_t>* attributes_out) { |
| chaps::Attributes input; |
| input.Parse(attributes_in); |
| if (input.attributes()[0].type == CKA_VALUE) |
| return ParseAttribute(kKeyBlob, attributes_in, attributes_out); |
| return ParseAttribute(kArcKeyPermissionTrue, attributes_in, attributes_out); |
| } |
| |
| uint32_t FakeGetAttributeWithoutArcPermission( |
| const brillo::SecureBlob& isolate_credential, |
| uint64_t session_id, |
| uint64_t object_handle, |
| const std::vector<uint8_t>& attributes_in, |
| std::vector<uint8_t>* attributes_out) { |
| chaps::Attributes input; |
| input.Parse(attributes_in); |
| if (input.attributes()[0].type == CKA_VALUE) |
| return ParseAttribute(kKeyBlob, attributes_in, attributes_out); |
| return ParseAttribute(kArcKeyPermissionFalse, attributes_in, |
| attributes_out); |
| } |
| |
| protected: |
| void SetUp() override { |
| context_adaptor_.set_slot_for_tests(1); |
| |
| ON_CALL(chaps_mock_, OpenSession(_, _, _, _)) |
| .WillByDefault(DoAll(SetArgPointee<3>(kSessionId), Return(CKR_OK))); |
| ON_CALL(chaps_mock_, CloseSession(_, _)).WillByDefault(Return(CKR_OK)); |
| ON_CALL(chaps_mock_, FindObjectsInit(_, _, _)) |
| .WillByDefault(Return(CKR_OK)); |
| ON_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillByDefault(DoAll(SetArgPointee<3>(kObjectList), Return(CKR_OK))); |
| ON_CALL(chaps_mock_, FindObjectsFinal(_, _)).WillByDefault(Return(CKR_OK)); |
| ON_CALL(chaps_mock_, GetAttributeValue(_, _, _, _, _)) |
| .WillByDefault( |
| Invoke(/* obj_ptr */ this, &ChapsClientTest::FakeGetAttribute)); |
| } |
| |
| ::testing::NiceMock<::chaps::ChapsProxyMock> chaps_mock_; |
| ContextAdaptor context_adaptor_; |
| ChapsClient chaps_client_; |
| |
| private: |
| uint32_t ParseAttribute(const std::vector<uint8_t>& blob, |
| const std::vector<uint8_t>& attributes_in, |
| std::vector<uint8_t>* attributes_out) { |
| chaps::Attributes parsed; |
| parsed.Parse(attributes_in); |
| parsed.attributes()[0].ulValueLen = blob.size(); |
| if (parsed.attributes()[0].pValue) { |
| memcpy(parsed.attributes()[0].pValue, blob.data(), blob.size()); |
| } |
| parsed.Serialize(attributes_out); |
| return CKR_OK; |
| } |
| }; |
| |
| TEST_F(ChapsClientTest, UsesSlotFromAdaptor) { |
| // Setup a fake slot in the cache. |
| uint64_t slot = 42; |
| context_adaptor_.set_slot_for_tests(slot); |
| |
| // Expect chaps client will use the given slot. |
| EXPECT_CALL(chaps_mock_, OpenSession(_, Eq(slot), _, _)); |
| |
| // Call an operation that triggers slot usage. |
| chaps_client_.session_handle(); |
| } |
| |
| TEST_F(ChapsClientTest, ExportExistingEncryptionKey) { |
| // An existing key is prepared in fixture setup, expect no generation happens. |
| EXPECT_CALL(chaps_mock_, GenerateKey(_, _, _, _, _, _)).Times(0); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify output. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| TEST_F(ChapsClientTest, ExportGeneratedEncryptionKey) { |
| // Expect no existing key is found and generation is called. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<3>(kEmptyObjectList), Return(CKR_OK))); |
| EXPECT_CALL(chaps_mock_, GenerateKey(_, _, _, _, _, _)) |
| .WillOnce(Return(CKR_OK)); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify output. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| TEST_F(ChapsClientTest, CachesExportedEncryptionKey) { |
| // Expect chaps is queried only once. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)).Times(1); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify exported key is cached in adaptor |
| ASSERT_TRUE(context_adaptor_.encryption_key().has_value()); |
| std::vector<uint8_t> key(context_adaptor_.encryption_key()->begin(), |
| context_adaptor_.encryption_key()->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| |
| // Verify exporting key again won't trigger more FindObject calls. |
| for (int i = 0; i < 10; ++i) |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| } |
| |
| TEST_F(ChapsClientTest, ReturnsCachedEncryptionKey) { |
| // Prepare the adaptor cache with a key. |
| brillo::SecureBlob in_key(kKeyBlob.begin(), kKeyBlob.end()); |
| context_adaptor_.set_encryption_key(in_key); |
| |
| // Expect chaps is never asked to find nor generate a key. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)).Times(0); |
| EXPECT_CALL(chaps_mock_, GenerateKey(_, _, _, _, _, _)).Times(0); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify exported key is what we prepared in adaptor cache. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| TEST_F(ChapsClientTest, InitializeSignature) { |
| // Expect the correct parameters are forwarded to chaps. |
| CK_MECHANISM_TYPE mechanism = CKM_RSA_PKCS; |
| CK_OBJECT_HANDLE handle = 42; |
| EXPECT_CALL(chaps_mock_, SignInit(_, _, Eq(mechanism), _, Eq(handle))); |
| |
| bool result = chaps_client_.InitializeSignature(mechanism, handle); |
| ASSERT_TRUE(result); |
| } |
| |
| TEST_F(ChapsClientTest, InitializeSignatureObeysKeyPermissions) { |
| CK_MECHANISM_TYPE mechanism = CKM_RSA_PKCS; |
| CK_OBJECT_HANDLE handle = 42; |
| |
| EXPECT_CALL(chaps_mock_, GetAttributeValue(_, _, _, _, _)) |
| .WillOnce(Invoke(/* obj_ptr */ this, |
| &ChapsClientTest::FakeGetAttributeWithoutArcPermission)) |
| .WillOnce(Invoke(/* obj_ptr */ this, |
| &ChapsClientTest::FakeGetAttributeWithoutArcPermission)) |
| .WillRepeatedly( |
| Invoke(/* obj_ptr */ this, &ChapsClientTest::FakeGetAttribute)); |
| |
| // The first call receives kArcKeyPermissionFalse and should fail. |
| bool result = chaps_client_.InitializeSignature(mechanism, handle); |
| ASSERT_FALSE(result); |
| |
| // Following calls receive kArcKeyPermissionTrue and should work. |
| bool new_result = chaps_client_.InitializeSignature(mechanism, handle); |
| ASSERT_TRUE(new_result); |
| } |
| |
| TEST_F(ChapsClientTest, UpdateSignature) { |
| // Expect the correct parameters are forwarded to chaps. |
| EXPECT_CALL(chaps_mock_, SignUpdate(_, _, Eq(kDataBlob))); |
| |
| bool result = chaps_client_.UpdateSignature(kDataBlob); |
| ASSERT_TRUE(result); |
| } |
| |
| TEST_F(ChapsClientTest, FinalizeSignature) { |
| // Expect the output is forwarded from chaps. |
| EXPECT_CALL(chaps_mock_, SignFinal(_, _, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<4>(kSignatureBlob), Return(CKR_OK))); |
| base::Optional<brillo::Blob> signature = chaps_client_.FinalizeSignature(); |
| ASSERT_EQ(kSignatureBlob, signature); |
| } |
| |
| TEST_F(ChapsClientTest, FindObjectHandlesInvalidSession) { |
| // Expect a retry if FindObjects returns CKR_SESSION_HANDLE_INVALID. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(DoAll(SetArgPointee<3>(kObjectList), Return(CKR_OK))); |
| |
| // Call find object. |
| base::Optional<CK_OBJECT_HANDLE> handle = |
| chaps_client_.FindObject(CKO_CERTIFICATE, std::string(kLabel), kId); |
| |
| // Verify the correct handle is returned. |
| ASSERT_TRUE(handle.has_value()); |
| EXPECT_EQ(handle.value(), kObjectList[0]); |
| } |
| |
| TEST_F(ChapsClientTest, ExportSubjectPublicKeyInfoHandlesInvalidSession) { |
| // Expect a retry if FindObjects returns CKR_SESSION_HANDLE_INVALID. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(DoAll(SetArgPointee<3>(kObjectList), Return(CKR_OK))); |
| EXPECT_CALL(chaps_mock_, GetAttributeValue(_, _, _, _, _)) |
| .WillRepeatedly( |
| Invoke(/* obj_ptr */ this, &ChapsClientTest::FakeGetCertificateBlob)); |
| |
| // Call export SPKI. |
| base::Optional<brillo::Blob> spki = |
| chaps_client_.ExportSubjectPublicKeyInfo(std::string(kLabel), kId); |
| |
| // Verify the correct blob is returned. |
| ASSERT_TRUE(spki.has_value()); |
| EXPECT_EQ(kCertificateSpkiDer, spki.value()); |
| } |
| |
| // base::Optional<brillo::Blob> ExportSubjectPublicKeyInfo( |
| // const std::string& label, const brillo::Blob& id); |
| |
| TEST_F(ChapsClientTest, FindKeyHandlesInvalidSession) { |
| // Expect a retry if FindObjects returns CKR_SESSION_HANDLE_INVALID. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(DoAll(SetArgPointee<3>(kObjectList), Return(CKR_OK))); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify key is exported successfully. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| TEST_F(ChapsClientTest, GenerateKeyHandlesInvalidSession) { |
| // Expect a retry if GenerateKey returns CKR_SESSION_HANDLE_INVALID. |
| EXPECT_CALL(chaps_mock_, FindObjects(_, _, _, _)) |
| .WillOnce(DoAll(SetArgPointee<3>(kEmptyObjectList), Return(CKR_OK))); |
| EXPECT_CALL(chaps_mock_, GenerateKey(_, _, _, _, _, _)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_OK)); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify output. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| TEST_F(ChapsClientTest, GetAttributeHandlesInvalidSession) { |
| // Expect a retry if GetAttribute returns CKR_SESSION_HANDLE_INVALID. |
| EXPECT_CALL(chaps_mock_, GetAttributeValue(_, _, _, _, _)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillOnce(Return(CKR_SESSION_HANDLE_INVALID)) |
| .WillRepeatedly( |
| Invoke(/* obj_ptr */ this, &ChapsClientTest::FakeGetAttribute)); |
| |
| // Call export key. |
| base::Optional<brillo::SecureBlob> encryption_key = |
| chaps_client_.ExportOrGenerateEncryptionKey(); |
| |
| // Verify output. |
| ASSERT_TRUE(encryption_key.has_value()); |
| std::vector<uint8_t> key(encryption_key->begin(), encryption_key->end()); |
| EXPECT_EQ(kKeyBlob, key); |
| } |
| |
| } // namespace context |
| } // namespace keymaster |
| } // namespace arc |