Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c79c4525 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 7537076 from f569528b to sc-release

Change-Id: I979b6365c1887525f6345ba2430b9ea86731f607
parents 3f4e3417 f569528b
Loading
Loading
Loading
Loading
+187 −3
Original line number Diff line number Diff line
@@ -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;
        }
@@ -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) {
@@ -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);

@@ -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,
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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;
            }

+6 −0
Original line number Diff line number Diff line
@@ -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;
+1 −14
Original line number Diff line number Diff line
@@ -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
+62 −87
Original line number Diff line number Diff line
@@ -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";
    }
@@ -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) {
@@ -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) {
@@ -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();

@@ -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_;
@@ -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();

@@ -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();

@@ -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());
}

/**
@@ -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();

@@ -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());
}

/**
@@ -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);
}
@@ -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();

@@ -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);
@@ -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;
@@ -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);
@@ -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(),
@@ -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(),