Loading camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +187 −3 Original line number Diff line number Diff line Loading @@ -230,10 +230,10 @@ namespace { return false; } int getCameraDeviceVersion(const hidl_string& deviceName, const hidl_string &providerType) { int getCameraDeviceVersionAndId(const hidl_string& deviceName, const hidl_string &providerType, std::string* id) { std::string version; bool match = matchDeviceName(deviceName, providerType, &version, nullptr); bool match = matchDeviceName(deviceName, providerType, &version, id); if (!match) { return -1; } Loading @@ -256,6 +256,11 @@ namespace { return 0; } int getCameraDeviceVersion(const hidl_string& deviceName, const hidl_string &providerType) { return getCameraDeviceVersionAndId(deviceName, providerType, nullptr); } bool parseProviderName(const std::string& name, std::string *type /*out*/, uint32_t *id /*out*/) { if (!type || !id) { Loading Loading @@ -930,6 +935,7 @@ public: camera_metadata_ro_entry* streamConfigs, camera_metadata_ro_entry* maxResolutionStreamConfigs, const camera_metadata_t* staticMetadata); static bool isColorCamera(const camera_metadata_t *metadata); static V3_2::DataspaceFlags getDataspace(PixelFormat format); Loading Loading @@ -6179,6 +6185,167 @@ TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) { } } // Test the multi-camera API requirement for Google Requirement Freeze S // Note that this requirement can only be partially tested. If a vendor // device doesn't expose a physical camera in any shape or form, there is no way // the test can catch it. TEST_P(CameraHidlTest, grfSMultiCameraTest) { const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1); if (socGrfApi < 31 /*S*/) { // Non-GRF devices, or version < 31 Skip ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi); return; } // Test that if more than one color cameras facing the same direction are // supported, there must be at least one logical camera facing that // direction. hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider); // Front and back facing non-logical color cameras std::set<std::string> frontColorCameras, rearColorCameras; // Front and back facing logical cameras' physical camera Id sets std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds; for (const auto& name : cameraDeviceNames) { std::string cameraId; int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId); switch (deviceVersion) { case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: case CAMERA_DEVICE_API_VERSION_3_3: case CAMERA_DEVICE_API_VERSION_3_2: { ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x; ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str()); Return<void> ret; ret = mProvider->getCameraDeviceInterface_V3_x( name, [&](auto status, const auto& device) { ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status); ASSERT_EQ(Status::OK, status); ASSERT_NE(device, nullptr); device3_x = device; }); ASSERT_TRUE(ret.isOk()); ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); // Skip if this is not a color camera. if (!CameraHidlTest::isColorCamera(metadata)) { return; } // Check camera facing. Skip if facing is neither FRONT // nor BACK. If this is not a logical camera, only note down // the camera ID, and skip. camera_metadata_ro_entry entry; int retcode = find_camera_metadata_ro_entry( metadata, ANDROID_LENS_FACING, &entry); ASSERT_EQ(retcode, 0); ASSERT_GT(entry.count, 0); uint8_t facing = entry.data.u8[0]; bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK); if (facing == ANDROID_LENS_FACING_FRONT) { if (!isLogicalCamera) { frontColorCameras.insert(cameraId); return; } } else if (facing == ANDROID_LENS_FACING_BACK) { if (!isLogicalCamera) { rearColorCameras.insert(cameraId); return; } } else { // Not FRONT or BACK facing. Skip. return; } // Check logical camera's physical camera IDs for color // cameras. std::unordered_set<std::string> physicalCameraIds; Status s = getPhysicalCameraIds(metadata, &physicalCameraIds); ASSERT_EQ(Status::OK, s); if (facing == ANDROID_LENS_FACING_FRONT) { frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); } else { rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); } for (const auto& physicalId : physicalCameraIds) { // Skip if the physicalId is publicly available for (auto& deviceName : cameraDeviceNames) { std::string publicVersion, publicId; ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId)); if (physicalId == publicId) { // Skip because public Ids will be iterated in outer loop. return; } } auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x); ASSERT_TRUE(castResult.isOk()); ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = castResult; ASSERT_NE(device3_5, nullptr); // Check camera characteristics for hidden camera id Return<void> ret = device3_5->getPhysicalCameraCharacteristics( physicalId, [&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); const camera_metadata_t* physicalMetadata = (camera_metadata_t*)chars.data(); if (CameraHidlTest::isColorCamera(physicalMetadata)) { if (facing == ANDROID_LENS_FACING_FRONT) { frontColorCameras.insert(physicalId); } else if (facing == ANDROID_LENS_FACING_BACK) { rearColorCameras.insert(physicalId); } } }); ASSERT_TRUE(ret.isOk()); } }); ASSERT_TRUE(ret.isOk()); } break; case CAMERA_DEVICE_API_VERSION_1_0: { // Not applicable } break; default: { ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); ADD_FAILURE(); } break; } } // If there are more than one color cameras facing one direction, a logical // multi-camera must be defined consisting of all color cameras facing that // direction. if (frontColorCameras.size() > 1) { bool hasFrontLogical = false; for (const auto& physicalIds : frontPhysicalIds) { if (std::includes(physicalIds.begin(), physicalIds.end(), frontColorCameras.begin(), frontColorCameras.end())) { hasFrontLogical = true; break; } } ASSERT_TRUE(hasFrontLogical); } if (rearColorCameras.size() > 1) { bool hasRearLogical = false; for (const auto& physicalIds : rearPhysicalIds) { if (std::includes(physicalIds.begin(), physicalIds.end(), rearColorCameras.begin(), rearColorCameras.end())) { hasRearLogical = true; break; } } ASSERT_TRUE(hasRearLogical); } } // Retrieve all valid output stream resolutions from the camera // static characteristics. Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta, Loading Loading @@ -6651,6 +6818,23 @@ Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) { return ret; } bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) { camera_metadata_ro_entry entry; int retcode = find_camera_metadata_ro_entry( metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry); if ((0 == retcode) && (entry.count > 0)) { bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) != entry.data.u8 + entry.count); bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) != entry.data.u8 + entry.count); bool isColor = isBackwardCompatible && !isMonochrome; return isColor; } return false; } // Retrieve the reprocess input-output format map from the static // camera characteristics. Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta, Loading graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,7 @@ TEST_P(GraphicsCompositionTest, ClientComposition) { << " pixel format: PixelFormat::RGBA_8888 dataspace: " << ReadbackHelper::getDataspaceString(clientDataspace) << " unsupported for display" << std::endl; mReader->mCompositionChanges.clear(); continue; } Loading security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,12 @@ parcelable DeviceInfo { * ? "vendor_patch_level" : uint, // YYYYMMDD * "version" : 1, // The CDDL schema version. * "security_level" : "tee" / "strongbox" * "att_id_state": "locked" / "open", // Attestation IDs State. If "locked", this * // indicates a device's attestable IDs are * // factory-locked and immutable. If "open", * // this indicates the device is still in a * // provisionable state and the attestable IDs * // are not yet frozen. * } */ byte[] deviceInfo; Loading security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl +1 −14 Original line number Diff line number Diff line Loading @@ -158,20 +158,7 @@ parcelable ProtectedData { * payload: bstr .cbor BccPayload * ] * * VerifiedDeviceInfo = { * ? "brand" : tstr, * ? "manufacturer" : tstr, * ? "product" : tstr, * ? "model" : tstr, * ? "board" : tstr, * ? "device" : tstr, * ? "vb_state" : "green" / "yellow" / "orange", * ? "bootloader_state" : "locked" / "unlocked", * ? "os_version" : tstr, * ? "system_patch_level" : uint, // YYYYMMDD * ? "boot_patch_level" : uint, // YYYYMMDD * ? "vendor_patch_level" : uint, // YYYYMMDD * } * VerifiedDeviceInfo = DeviceInfo // See DeviceInfo.aidl * * PubKeyX25519 = { // COSE_Key * 1 : 1, // Key type : Octet Key Pair Loading security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +62 −87 Original line number Diff line number Diff line Loading @@ -103,8 +103,8 @@ ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) { return std::move(corruptSig); } ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) { auto [chain, _, parseErr] = cppbor::parse(eek.chain); ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) { auto [chain, _, parseErr] = cppbor::parse(encodedEekChain); if (!chain || !chain->asArray()) { return "EekChain parse failed"; } Loading @@ -126,7 +126,7 @@ ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) { corruptChain.add(eekChain->get(ii)->clone()); } } return EekChain{corruptChain.encode(), eek.last_pubkey, eek.last_privkey}; return corruptChain.encode(); } string device_suffix(const string& name) { Loading Loading @@ -272,14 +272,14 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) { class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { protected: CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) { generateEek(3); generateTestEekChain(3); } void generateEek(size_t eekLength) { void generateTestEekChain(size_t eekLength) { auto chain = generateEekChain(eekLength, eekId_); EXPECT_TRUE(chain) << chain.message(); if (chain) eekChain_ = chain.moveValue(); eekLength_ = eekLength; if (chain) testEekChain_ = chain.moveValue(); testEekLength_ = eekLength; } void generateKeys(bool testMode, size_t numKeys) { Loading Loading @@ -309,7 +309,8 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { ASSERT_TRUE(senderPubkey) << senderPubkey.message(); EXPECT_EQ(senderPubkey->second, eekId_); auto sessionKey = x25519_HKDF_DeriveKey(eekChain_.last_pubkey, eekChain_.last_privkey, auto sessionKey = x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey, senderPubkey->first, false /* senderIsA */); ASSERT_TRUE(sessionKey) << sessionKey.message(); Loading Loading @@ -363,8 +364,8 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { } bytevec eekId_; size_t eekLength_; EekChain eekChain_; size_t testEekLength_; EekChain testEekChain_; bytevec challenge_; std::vector<MacedPublicKey> keysToSign_; cppbor::Array cborKeysToSign_; Loading @@ -378,13 +379,13 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { bool testMode = true; for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); generateTestEekChain(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -400,24 +401,21 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { */ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { constexpr bool testMode = true; constexpr size_t eekLength = 2; generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); std::vector<BccEntryData> firstBcc; checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, &firstBcc); status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -435,28 +433,20 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { } /** * Generate an empty certificate request in prod mode. Generation will fail because we don't have a * valid GEEK. * * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be * able to decrypt. * Generate an empty certificate request in prod mode. This test must be run explicitly, and * is not run by default. Not all devices are GMS devices, and therefore they do not all * trust the Google EEK root. */ TEST_P(CertificateRequestTest, EmptyRequest_prodMode) { TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) { bool testMode = false; for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); EXPECT_FALSE(status.isOk()); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); } EXPECT_TRUE(status.isOk()); } /** Loading @@ -468,13 +458,13 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); generateTestEekChain(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData, testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -483,30 +473,21 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { } /** * Generate a non-empty certificate request in prod mode. Must fail because we don't have a valid * GEEK. * * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be * able to decrypt. * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and * is not run by default. Not all devices are GMS devices, and therefore they do not all * trust the Google EEK root. */ TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) { TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) { bool testMode = false; generateKeys(testMode, 4 /* numKeys */); for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData, testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); EXPECT_FALSE(status.isOk()); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); } EXPECT_TRUE(status.isOk()); } /** Loading @@ -521,8 +502,8 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()) << status.getMessage(); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); } Loading @@ -531,7 +512,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) { * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair. */ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) { bool testMode = true; bool testMode = false; generateKeys(testMode, 1 /* numKeys */); MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue(); Loading @@ -539,38 +520,35 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()) << status.getMessage(); auto rc = status.getServiceSpecificError(); // TODO(drysdale): drop the INVALID_EEK potential error code when a real GEEK is available. EXPECT_TRUE(rc == BnRemotelyProvisionedComponent::STATUS_INVALID_EEK || rc == BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); } /** * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain. * Confirm that the request is rejected. * * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the * implementation is checking signatures. */ TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) { bool testMode = false; generateKeys(testMode, 4 /* numKeys */); for (size_t ii = 0; ii < eekLength_; ii++) { auto chain = corrupt_sig_chain(eekChain_, ii); auto prodEekChain = getProdEekChain(); auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain); ASSERT_NE(parsedChain, nullptr) << parseErr; ASSERT_NE(parsedChain->asArray(), nullptr); for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) { auto chain = corrupt_sig_chain(prodEekChain, ii); ASSERT_TRUE(chain) << chain.message(); EekChain corruptEek = chain.moveValue(); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, corruptEek.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); Loading @@ -580,9 +558,6 @@ TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) { /** * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain. * Confirm that the request is rejected. * * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the * implementation is checking signatures. */ TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) { bool testMode = false; Loading @@ -590,7 +565,7 @@ TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) { // Build an EEK chain that omits the first self-signed cert. auto truncatedChain = cppbor::Array(); auto [chain, _, parseErr] = cppbor::parse(eekChain_.chain); auto [chain, _, parseErr] = cppbor::parse(getProdEekChain()); ASSERT_TRUE(chain); auto eekChain = chain->asArray(); ASSERT_NE(eekChain, nullptr); Loading Loading @@ -619,7 +594,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( true /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), Loading @@ -637,7 +612,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( false /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), Loading Loading
camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +187 −3 Original line number Diff line number Diff line Loading @@ -230,10 +230,10 @@ namespace { return false; } int getCameraDeviceVersion(const hidl_string& deviceName, const hidl_string &providerType) { int getCameraDeviceVersionAndId(const hidl_string& deviceName, const hidl_string &providerType, std::string* id) { std::string version; bool match = matchDeviceName(deviceName, providerType, &version, nullptr); bool match = matchDeviceName(deviceName, providerType, &version, id); if (!match) { return -1; } Loading @@ -256,6 +256,11 @@ namespace { return 0; } int getCameraDeviceVersion(const hidl_string& deviceName, const hidl_string &providerType) { return getCameraDeviceVersionAndId(deviceName, providerType, nullptr); } bool parseProviderName(const std::string& name, std::string *type /*out*/, uint32_t *id /*out*/) { if (!type || !id) { Loading Loading @@ -930,6 +935,7 @@ public: camera_metadata_ro_entry* streamConfigs, camera_metadata_ro_entry* maxResolutionStreamConfigs, const camera_metadata_t* staticMetadata); static bool isColorCamera(const camera_metadata_t *metadata); static V3_2::DataspaceFlags getDataspace(PixelFormat format); Loading Loading @@ -6179,6 +6185,167 @@ TEST_P(CameraHidlTest, configureInjectionStreamsWithSessionParameters) { } } // Test the multi-camera API requirement for Google Requirement Freeze S // Note that this requirement can only be partially tested. If a vendor // device doesn't expose a physical camera in any shape or form, there is no way // the test can catch it. TEST_P(CameraHidlTest, grfSMultiCameraTest) { const int socGrfApi = property_get_int32("ro.board.first_api_level", /*default*/ -1); if (socGrfApi < 31 /*S*/) { // Non-GRF devices, or version < 31 Skip ALOGI("%s: socGrfApi level is %d. Skipping", __FUNCTION__, socGrfApi); return; } // Test that if more than one color cameras facing the same direction are // supported, there must be at least one logical camera facing that // direction. hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider); // Front and back facing non-logical color cameras std::set<std::string> frontColorCameras, rearColorCameras; // Front and back facing logical cameras' physical camera Id sets std::set<std::set<std::string>> frontPhysicalIds, rearPhysicalIds; for (const auto& name : cameraDeviceNames) { std::string cameraId; int deviceVersion = getCameraDeviceVersionAndId(name, mProviderType, &cameraId); switch (deviceVersion) { case CAMERA_DEVICE_API_VERSION_3_7: case CAMERA_DEVICE_API_VERSION_3_6: case CAMERA_DEVICE_API_VERSION_3_5: case CAMERA_DEVICE_API_VERSION_3_4: case CAMERA_DEVICE_API_VERSION_3_3: case CAMERA_DEVICE_API_VERSION_3_2: { ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_x; ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str()); Return<void> ret; ret = mProvider->getCameraDeviceInterface_V3_x( name, [&](auto status, const auto& device) { ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status); ASSERT_EQ(Status::OK, status); ASSERT_NE(device, nullptr); device3_x = device; }); ASSERT_TRUE(ret.isOk()); ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); const camera_metadata_t* metadata = (camera_metadata_t*)chars.data(); // Skip if this is not a color camera. if (!CameraHidlTest::isColorCamera(metadata)) { return; } // Check camera facing. Skip if facing is neither FRONT // nor BACK. If this is not a logical camera, only note down // the camera ID, and skip. camera_metadata_ro_entry entry; int retcode = find_camera_metadata_ro_entry( metadata, ANDROID_LENS_FACING, &entry); ASSERT_EQ(retcode, 0); ASSERT_GT(entry.count, 0); uint8_t facing = entry.data.u8[0]; bool isLogicalCamera = (isLogicalMultiCamera(metadata) == Status::OK); if (facing == ANDROID_LENS_FACING_FRONT) { if (!isLogicalCamera) { frontColorCameras.insert(cameraId); return; } } else if (facing == ANDROID_LENS_FACING_BACK) { if (!isLogicalCamera) { rearColorCameras.insert(cameraId); return; } } else { // Not FRONT or BACK facing. Skip. return; } // Check logical camera's physical camera IDs for color // cameras. std::unordered_set<std::string> physicalCameraIds; Status s = getPhysicalCameraIds(metadata, &physicalCameraIds); ASSERT_EQ(Status::OK, s); if (facing == ANDROID_LENS_FACING_FRONT) { frontPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); } else { rearPhysicalIds.emplace(physicalCameraIds.begin(), physicalCameraIds.end()); } for (const auto& physicalId : physicalCameraIds) { // Skip if the physicalId is publicly available for (auto& deviceName : cameraDeviceNames) { std::string publicVersion, publicId; ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId)); if (physicalId == publicId) { // Skip because public Ids will be iterated in outer loop. return; } } auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x); ASSERT_TRUE(castResult.isOk()); ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 = castResult; ASSERT_NE(device3_5, nullptr); // Check camera characteristics for hidden camera id Return<void> ret = device3_5->getPhysicalCameraCharacteristics( physicalId, [&](auto status, const auto& chars) { ASSERT_EQ(Status::OK, status); const camera_metadata_t* physicalMetadata = (camera_metadata_t*)chars.data(); if (CameraHidlTest::isColorCamera(physicalMetadata)) { if (facing == ANDROID_LENS_FACING_FRONT) { frontColorCameras.insert(physicalId); } else if (facing == ANDROID_LENS_FACING_BACK) { rearColorCameras.insert(physicalId); } } }); ASSERT_TRUE(ret.isOk()); } }); ASSERT_TRUE(ret.isOk()); } break; case CAMERA_DEVICE_API_VERSION_1_0: { // Not applicable } break; default: { ALOGE("%s: Unsupported device version %d", __func__, deviceVersion); ADD_FAILURE(); } break; } } // If there are more than one color cameras facing one direction, a logical // multi-camera must be defined consisting of all color cameras facing that // direction. if (frontColorCameras.size() > 1) { bool hasFrontLogical = false; for (const auto& physicalIds : frontPhysicalIds) { if (std::includes(physicalIds.begin(), physicalIds.end(), frontColorCameras.begin(), frontColorCameras.end())) { hasFrontLogical = true; break; } } ASSERT_TRUE(hasFrontLogical); } if (rearColorCameras.size() > 1) { bool hasRearLogical = false; for (const auto& physicalIds : rearPhysicalIds) { if (std::includes(physicalIds.begin(), physicalIds.end(), rearColorCameras.begin(), rearColorCameras.end())) { hasRearLogical = true; break; } } ASSERT_TRUE(hasRearLogical); } } // Retrieve all valid output stream resolutions from the camera // static characteristics. Status CameraHidlTest::getAvailableOutputStreams(const camera_metadata_t* staticMeta, Loading Loading @@ -6651,6 +6818,23 @@ Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) { return ret; } bool CameraHidlTest::isColorCamera(const camera_metadata_t *metadata) { camera_metadata_ro_entry entry; int retcode = find_camera_metadata_ro_entry( metadata, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, &entry); if ((0 == retcode) && (entry.count > 0)) { bool isBackwardCompatible = (std::find(entry.data.u8, entry.data.u8 + entry.count, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) != entry.data.u8 + entry.count); bool isMonochrome = (std::find(entry.data.u8, entry.data.u8 + entry.count, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) != entry.data.u8 + entry.count); bool isColor = isBackwardCompatible && !isMonochrome; return isColor; } return false; } // Retrieve the reprocess input-output format map from the static // camera characteristics. Status CameraHidlTest::getZSLInputOutputMap(camera_metadata_t *staticMeta, Loading
graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -458,6 +458,7 @@ TEST_P(GraphicsCompositionTest, ClientComposition) { << " pixel format: PixelFormat::RGBA_8888 dataspace: " << ReadbackHelper::getDataspaceString(clientDataspace) << " unsupported for display" << std::endl; mReader->mCompositionChanges.clear(); continue; } Loading
security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl +6 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,12 @@ parcelable DeviceInfo { * ? "vendor_patch_level" : uint, // YYYYMMDD * "version" : 1, // The CDDL schema version. * "security_level" : "tee" / "strongbox" * "att_id_state": "locked" / "open", // Attestation IDs State. If "locked", this * // indicates a device's attestable IDs are * // factory-locked and immutable. If "open", * // this indicates the device is still in a * // provisionable state and the attestable IDs * // are not yet frozen. * } */ byte[] deviceInfo; Loading
security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl +1 −14 Original line number Diff line number Diff line Loading @@ -158,20 +158,7 @@ parcelable ProtectedData { * payload: bstr .cbor BccPayload * ] * * VerifiedDeviceInfo = { * ? "brand" : tstr, * ? "manufacturer" : tstr, * ? "product" : tstr, * ? "model" : tstr, * ? "board" : tstr, * ? "device" : tstr, * ? "vb_state" : "green" / "yellow" / "orange", * ? "bootloader_state" : "locked" / "unlocked", * ? "os_version" : tstr, * ? "system_patch_level" : uint, // YYYYMMDD * ? "boot_patch_level" : uint, // YYYYMMDD * ? "vendor_patch_level" : uint, // YYYYMMDD * } * VerifiedDeviceInfo = DeviceInfo // See DeviceInfo.aidl * * PubKeyX25519 = { // COSE_Key * 1 : 1, // Key type : Octet Key Pair Loading
security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +62 −87 Original line number Diff line number Diff line Loading @@ -103,8 +103,8 @@ ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) { return std::move(corruptSig); } ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) { auto [chain, _, parseErr] = cppbor::parse(eek.chain); ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) { auto [chain, _, parseErr] = cppbor::parse(encodedEekChain); if (!chain || !chain->asArray()) { return "EekChain parse failed"; } Loading @@ -126,7 +126,7 @@ ErrMsgOr<EekChain> corrupt_sig_chain(const EekChain& eek, int which) { corruptChain.add(eekChain->get(ii)->clone()); } } return EekChain{corruptChain.encode(), eek.last_pubkey, eek.last_privkey}; return corruptChain.encode(); } string device_suffix(const string& name) { Loading Loading @@ -272,14 +272,14 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) { class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { protected: CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) { generateEek(3); generateTestEekChain(3); } void generateEek(size_t eekLength) { void generateTestEekChain(size_t eekLength) { auto chain = generateEekChain(eekLength, eekId_); EXPECT_TRUE(chain) << chain.message(); if (chain) eekChain_ = chain.moveValue(); eekLength_ = eekLength; if (chain) testEekChain_ = chain.moveValue(); testEekLength_ = eekLength; } void generateKeys(bool testMode, size_t numKeys) { Loading Loading @@ -309,7 +309,8 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { ASSERT_TRUE(senderPubkey) << senderPubkey.message(); EXPECT_EQ(senderPubkey->second, eekId_); auto sessionKey = x25519_HKDF_DeriveKey(eekChain_.last_pubkey, eekChain_.last_privkey, auto sessionKey = x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey, senderPubkey->first, false /* senderIsA */); ASSERT_TRUE(sessionKey) << sessionKey.message(); Loading Loading @@ -363,8 +364,8 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { } bytevec eekId_; size_t eekLength_; EekChain eekChain_; size_t testEekLength_; EekChain testEekChain_; bytevec challenge_; std::vector<MacedPublicKey> keysToSign_; cppbor::Array cborKeysToSign_; Loading @@ -378,13 +379,13 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { bool testMode = true; for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); generateTestEekChain(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -400,24 +401,21 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { */ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { constexpr bool testMode = true; constexpr size_t eekLength = 2; generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); std::vector<BccEntryData> firstBcc; checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, &firstBcc); status = provisionable_->generateCertificateRequest(testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -435,28 +433,20 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { } /** * Generate an empty certificate request in prod mode. Generation will fail because we don't have a * valid GEEK. * * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be * able to decrypt. * Generate an empty certificate request in prod mode. This test must be run explicitly, and * is not run by default. Not all devices are GMS devices, and therefore they do not all * trust the Google EEK root. */ TEST_P(CertificateRequestTest, EmptyRequest_prodMode) { TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) { bool testMode = false; for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {} /* keysToSign */, eekChain_.chain, challenge_, &deviceInfo, testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); EXPECT_FALSE(status.isOk()); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); } EXPECT_TRUE(status.isOk()); } /** Loading @@ -468,13 +458,13 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); generateTestEekChain(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData, testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getMessage(); Loading @@ -483,30 +473,21 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { } /** * Generate a non-empty certificate request in prod mode. Must fail because we don't have a valid * GEEK. * * TODO(swillden): Get a valid GEEK and use it so the generation can succeed, though we won't be * able to decrypt. * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and * is not run by default. Not all devices are GMS devices, and therefore they do not all * trust the Google EEK root. */ TEST_P(CertificateRequestTest, NonEmptyRequest_prodMode) { TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) { bool testMode = false; generateKeys(testMode, 4 /* numKeys */); for (size_t eekLength : {2, 3, 7}) { SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength); generateEek(eekLength); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, &protectedData, testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); EXPECT_FALSE(status.isOk()); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); } EXPECT_TRUE(status.isOk()); } /** Loading @@ -521,8 +502,8 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()) << status.getMessage(); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); } Loading @@ -531,7 +512,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) { * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair. */ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) { bool testMode = true; bool testMode = false; generateKeys(testMode, 1 /* numKeys */); MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue(); Loading @@ -539,38 +520,35 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, {keyWithCorruptMac}, eekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()) << status.getMessage(); auto rc = status.getServiceSpecificError(); // TODO(drysdale): drop the INVALID_EEK potential error code when a real GEEK is available. EXPECT_TRUE(rc == BnRemotelyProvisionedComponent::STATUS_INVALID_EEK || rc == BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); } /** * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain. * Confirm that the request is rejected. * * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the * implementation is checking signatures. */ TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) { bool testMode = false; generateKeys(testMode, 4 /* numKeys */); for (size_t ii = 0; ii < eekLength_; ii++) { auto chain = corrupt_sig_chain(eekChain_, ii); auto prodEekChain = getProdEekChain(); auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain); ASSERT_NE(parsedChain, nullptr) << parseErr; ASSERT_NE(parsedChain->asArray(), nullptr); for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) { auto chain = corrupt_sig_chain(prodEekChain, ii); ASSERT_TRUE(chain) << chain.message(); EekChain corruptEek = chain.moveValue(); bytevec keysToSignMac; DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( testMode, keysToSign_, corruptEek.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK); Loading @@ -580,9 +558,6 @@ TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) { /** * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain. * Confirm that the request is rejected. * * TODO(drysdale): Update to use a valid GEEK, so that the test actually confirms that the * implementation is checking signatures. */ TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) { bool testMode = false; Loading @@ -590,7 +565,7 @@ TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) { // Build an EEK chain that omits the first self-signed cert. auto truncatedChain = cppbor::Array(); auto [chain, _, parseErr] = cppbor::parse(eekChain_.chain); auto [chain, _, parseErr] = cppbor::parse(getProdEekChain()); ASSERT_TRUE(chain); auto eekChain = chain->asArray(); ASSERT_NE(eekChain, nullptr); Loading Loading @@ -619,7 +594,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( true /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), Loading @@ -637,7 +612,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) { DeviceInfo deviceInfo; ProtectedData protectedData; auto status = provisionable_->generateCertificateRequest( false /* testMode */, keysToSign_, eekChain_.chain, challenge_, &deviceInfo, false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); ASSERT_FALSE(status.isOk()); ASSERT_EQ(status.getServiceSpecificError(), Loading