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

Commit 8b09c50e authored by Max Bires's avatar Max Bires
Browse files

Changing DeviceInfo fields to be mandatory.

This change removes the optionality ("?") from all of the device info
fields, now that DeviceIDs are mandatory. It also changes att_id_state
to the broader "fused" category. It may not convey exactly the same
meaning, but it seems better to avoid proliferating a lot of fields that
all speak to some technical detail of the factory provisioning status of
the device.

Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: Iaf3de6a7a7a9b8af7d2e9673d7f1320858b95617
parent c96879a0
Loading
Loading
Loading
Loading
+16 −20
Original line number Diff line number Diff line
@@ -30,26 +30,22 @@ parcelable DeviceInfo {
     * DeviceInfo is a CBOR Map structure described by the following CDDL.
     *
     *     DeviceInfo = {
     *         ? "brand" : tstr,
     *         ? "manufacturer" : tstr,
     *         ? "product" : tstr,
     *         ? "model" : tstr,
     *         ? "board" : tstr,
     *         ? "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
     *         ? "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
     *         ? "vbmeta_digest": bstr,                         // Taken from the AVB values
     *         ? "os_version" : tstr,                    // Same as android.os.Build.VERSION.release
     *         ? "system_patch_level" : uint,                   // YYYYMMDD
     *         ? "boot_patch_level" : uint,                     // YYYYMMDD
     *         ? "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.
     *         "brand" : tstr,
     *         "manufacturer" : tstr,
     *         "product" : tstr,
     *         "model" : tstr,
     *         "device" : tstr,
     *         "vb_state" : "green" / "yellow" / "orange",    // Taken from the AVB values
     *         "bootloader_state" : "locked" / "unlocked",    // Taken from the AVB values
     *         "vbmeta_digest": bstr,                         // Taken from the AVB values
     *         "os_version" : tstr,                      // Same as android.os.Build.VERSION.release
     *         "system_patch_level" : uint,                   // YYYYMMDD
     *         "boot_patch_level" : uint,                     // YYYYMMDD
     *         "vendor_patch_level" : uint,                   // YYYYMMDD
     *         "version" : 2,                                 // The CDDL schema version.
     *         "security_level" : "tee" / "strongbox",
     *         "fused": 1 / 0,  // 1 if secure boot is enforced for the processor that the IRPC
     *                          // implementation is contained in. 0 otherwise.
     *     }
     */
    byte[] deviceInfo;
+88 −0
Original line number Diff line number Diff line
@@ -52,6 +52,22 @@ using testing::MatchesRegex;
using namespace remote_prov;
using namespace keymaster;

std::set<std::string> getAllowedVbStates() {
    return {"green", "yellow", "orange"};
}

std::set<std::string> getAllowedBootloaderStates() {
    return {"locked", "unlocked"};
}

std::set<std::string> getAllowedSecurityLevels() {
    return {"tee", "strongbox"};
}

std::set<std::string> getAllowedAttIdStates() {
    return {"locked", "open"};
}

bytevec string_to_bytevec(const char* s) {
    const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
    return bytevec(p, p + strlen(s));
@@ -340,6 +356,8 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
        ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
        ASSERT_TRUE(deviceInfoMap->asMap());

        checkDeviceInfo(deviceInfoMap->asMap());

        auto& signingKey = bccContents->back().pubKey;
        auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
                                              cppbor::Array()  // SignedMacAad
@@ -366,6 +384,76 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
        }
    }

    void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
        const auto& val = devInfo->get(entryName);
        ASSERT_TRUE(val) << entryName << " does not exist";
        ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
        switch (majorType) {
            case cppbor::TSTR:
                ASSERT_GT(val->asTstr()->value().size(), 0);
                break;
            case cppbor::BSTR:
                ASSERT_GT(val->asBstr()->value().size(), 0);
                break;
            default:
                break;
        }
    }

    void checkDeviceInfo(const cppbor::Map* deviceInfo) {
        const auto& version = deviceInfo->get("version");
        ASSERT_TRUE(version);
        ASSERT_TRUE(version->asUint());
        RpcHardwareInfo info;
        provisionable_->getHardwareInfo(&info);
        ASSERT_EQ(version->asUint()->value(), info.versionNumber);
        std::set<std::string> allowList;
        switch (version->asUint()->value()) {
            // These fields became mandated in version 2.
            case 2:
                checkType(deviceInfo, cppbor::TSTR, "brand");
                checkType(deviceInfo, cppbor::TSTR, "manufacturer");
                checkType(deviceInfo, cppbor::TSTR, "product");
                checkType(deviceInfo, cppbor::TSTR, "model");
                checkType(deviceInfo, cppbor::TSTR, "device");
                // TODO: Refactor the KeyMint code that validates these fields and include it here.
                checkType(deviceInfo, cppbor::TSTR, "vb_state");
                allowList = getAllowedVbStates();
                ASSERT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
                          allowList.end());
                checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
                allowList = getAllowedBootloaderStates();
                ASSERT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
                          allowList.end());
                checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
                checkType(deviceInfo, cppbor::TSTR, "os_version");
                checkType(deviceInfo, cppbor::UINT, "system_patch_level");
                checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
                checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
                checkType(deviceInfo, cppbor::UINT, "fused");
                ASSERT_LT(deviceInfo->get("fused")->asUint()->value(), 2);  // Must be 0 or 1.
                checkType(deviceInfo, cppbor::TSTR, "security_level");
                allowList = getAllowedSecurityLevels();
                ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
                          allowList.end());
                break;
            case 1:
                checkType(deviceInfo, cppbor::TSTR, "security_level");
                allowList = getAllowedSecurityLevels();
                ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
                          allowList.end());
                if (version->asUint()->value() == 1) {
                    checkType(deviceInfo, cppbor::TSTR, "att_id_state");
                    allowList = getAllowedAttIdStates();
                    ASSERT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
                              allowList.end());
                }
                break;
            default:
                FAIL() << "Unrecognized version: " << version->asUint()->value();
        }
    }

    bytevec eekId_;
    size_t testEekLength_;
    EekChain testEekChain_;