From 5b02f298ba11d40520481c4549b3c29edd7fd142 Mon Sep 17 00:00:00 2001 From: quh4gko8 <88831734+quh4gko8@users.noreply.github.com> Date: Mon, 31 Jul 2023 05:20:24 +0000 Subject: [PATCH] Migration to new data structure --- .../server/AttestationProtocol.java | 74 +++++++------ .../attestation/server/AttestationServer.java | 101 +++++++++++++----- 2 files changed, 121 insertions(+), 54 deletions(-) diff --git a/src/main/java/app/attestation/server/AttestationProtocol.java b/src/main/java/app/attestation/server/AttestationProtocol.java index 893010a1..e70637d6 100644 --- a/src/main/java/app/attestation/server/AttestationProtocol.java +++ b/src/main/java/app/attestation/server/AttestationProtocol.java @@ -1683,6 +1683,8 @@ private static void verify(final byte[] fingerprint, Certificate[] pinnedCertificates = null; byte[] pinnedVerifiedBootKey = null; + String pinnedDeviceManufacturer = null; + String pinnedDeviceModel = null; int pinnedOsVersion = Integer.MAX_VALUE; int pinnedOsPatchLevel = Integer.MAX_VALUE; int pinnedVendorPatchLevel = 0; @@ -1692,7 +1694,8 @@ private static void verify(final byte[] fingerprint, int pinnedSecurityLevel = 1; if (hasPersistentKey) { final SQLiteStatement st = conn.prepare("SELECT pinnedCertificates, " + - "pinnedVerifiedBootKey, pinnedOsVersion, pinnedOsPatchLevel, " + + "pinnedVerifiedBootKey, pinnedDeviceManufacturer, pinnedDeviceModel, " + + "pinnedOsVersion, pinnedOsPatchLevel, " + "pinnedVendorPatchLevel, pinnedBootPatchLevel, pinnedAppVersion, pinnedAppVariant, " + "pinnedSecurityLevel, userId " + "FROM Devices WHERE fingerprint = ?"); @@ -1705,14 +1708,16 @@ private static void verify(final byte[] fingerprint, throw new IOException(e); } pinnedVerifiedBootKey = st.columnBlob(1); - pinnedOsVersion = st.columnInt(2); - pinnedOsPatchLevel = st.columnInt(3); - pinnedVendorPatchLevel = st.columnInt(4); - pinnedBootPatchLevel = st.columnInt(5); - pinnedAppVersion = st.columnInt(6); - pinnedAppVariant = st.columnInt(7); - pinnedSecurityLevel = st.columnInt(8); - if (userId != st.columnLong(9)) { + pinnedDeviceManufacturer = st.columnString(2); + pinnedDeviceModel = st.columnString(3); + pinnedOsVersion = st.columnInt(4); + pinnedOsPatchLevel = st.columnInt(5); + pinnedVendorPatchLevel = st.columnInt(6); + pinnedBootPatchLevel = st.columnInt(7); + pinnedAppVersion = st.columnInt(8); + pinnedAppVariant = st.columnInt(9); + pinnedSecurityLevel = st.columnInt(10); + if (userId != st.columnLong(11)) { throw new GeneralSecurityException("wrong userId"); } } else { @@ -1821,41 +1826,50 @@ private static void verify(final byte[] fingerprint, final SQLiteStatement insert = conn.prepare("INSERT INTO Devices " + "(fingerprint, pinnedCertificates, attestKey, pinnedVerifiedBootKey, " + - "verifiedBootHash, pinnedOsVersion, pinnedOsPatchLevel, " + + "verifiedBootHash, pinnedDeviceManufacturer, pinnedDeviceModel, " + + "pinnedOsVersion, pinnedOsPatchLevel, " + "pinnedVendorPatchLevel, pinnedBootPatchLevel, pinnedAppVersion, pinnedAppVariant, pinnedSecurityLevel, " + "userProfileSecure, enrolledBiometrics, accessibility, deviceAdmin, " + "adbEnabled, addUsersWhenLocked, denyNewUsb, oemUnlockAllowed, systemUser, " + "verifiedTimeFirst, verifiedTimeLast, userId) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); try { insert.bind(1, fingerprint); + if (!verified.device.startsWith(DEVICE_GENERIC_UNKNOWN)) { + String[] deviceInfo = verified.device.split(" ", 2); + if (deviceInfo.length != 2) { + throw new GeneralSecurityException("device name must contain both manufacturer and model"); + } + insert.bind(6, deviceInfo[0]); + insert.bind(7, deviceInfo[1]); + } insert.bind(2, encodeChain(DEFLATE_DICTIONARY_2, attestationCertificates)); insert.bind(3, verified.attestKey ? 1 : 0); insert.bind(4, verifiedBootKey); insert.bind(5, verified.verifiedBootHash); - insert.bind(6, verified.osVersion); - insert.bind(7, verified.osPatchLevel); + insert.bind(8, verified.osVersion); + insert.bind(9, verified.osPatchLevel); if (verified.vendorPatchLevel != 0) { - insert.bind(8, verified.vendorPatchLevel); + insert.bind(10, verified.vendorPatchLevel); } if (verified.bootPatchLevel != 0) { - insert.bind(9, verified.bootPatchLevel); + insert.bind(11, verified.bootPatchLevel); } - insert.bind(10, verified.appVersion); - insert.bind(11, verified.appVariant); - insert.bind(12, verified.securityLevel); - insert.bind(13, userProfileSecure ? 1 : 0); - insert.bind(14, enrolledBiometrics ? 1 : 0); - insert.bind(15, accessibility ? 1 : 0); - insert.bind(16, deviceAdmin ? (deviceAdminNonSystem ? 2 : 1) : 0); - insert.bind(17, adbEnabled ? 1 : 0); - insert.bind(18, addUsersWhenLocked ? 1 : 0); - insert.bind(19, denyNewUsb ? 1 : 0); - insert.bind(20, oemUnlockAllowed ? 1 : 0); - insert.bind(21, systemUser ? 1 : 0); - insert.bind(22, now); - insert.bind(23, now); - insert.bind(24, userId); + insert.bind(12, verified.appVersion); + insert.bind(13, verified.appVariant); + insert.bind(14, verified.securityLevel); + insert.bind(15, userProfileSecure ? 1 : 0); + insert.bind(16, enrolledBiometrics ? 1 : 0); + insert.bind(17, accessibility ? 1 : 0); + insert.bind(18, deviceAdmin ? (deviceAdminNonSystem ? 2 : 1) : 0); + insert.bind(19, adbEnabled ? 1 : 0); + insert.bind(20, addUsersWhenLocked ? 1 : 0); + insert.bind(21, denyNewUsb ? 1 : 0); + insert.bind(22, oemUnlockAllowed ? 1 : 0); + insert.bind(23, systemUser ? 1 : 0); + insert.bind(24, now); + insert.bind(25, now); + insert.bind(26, userId); insert.step(); } finally { insert.dispose(); diff --git a/src/main/java/app/attestation/server/AttestationServer.java b/src/main/java/app/attestation/server/AttestationServer.java index e72d2164..d1a4f0ad 100644 --- a/src/main/java/app/attestation/server/AttestationServer.java +++ b/src/main/java/app/attestation/server/AttestationServer.java @@ -174,6 +174,8 @@ private static void createAttestationTables(final SQLiteConnection conn) throws "attestKey INTEGER NOT NULL CHECK (attestKey in (0, 1)),\n" + "pinnedVerifiedBootKey BLOB NOT NULL,\n" + "verifiedBootHash BLOB,\n" + + "pinnedDeviceManufacturer TEXT,\n" + + "pinnedDeviceModel TEXT,\n" + "pinnedOsVersion INTEGER NOT NULL,\n" + "pinnedOsPatchLevel INTEGER NOT NULL,\n" + "pinnedVendorPatchLevel INTEGER,\n" + @@ -291,7 +293,7 @@ public static void main(final String[] args) throws Exception { try { final SQLiteStatement selectCreated = attestationConn.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='Configuration'"); if (!selectCreated.step()) { - attestationConn.exec("PRAGMA user_version = 11"); + attestationConn.exec("PRAGMA user_version = 12"); } selectCreated.dispose(); @@ -305,6 +307,50 @@ public static void main(final String[] args) throws Exception { "supported. Use an older AttestationServer revision to upgrade."); } + if (userVersion < 12) { + attestationConn.exec("PRAGMA foreign_keys = OFF"); + attestationConn.exec("BEGIN IMMEDIATE TRANSACTION"); + + attestationConn.exec("ALTER TABLE Devices RENAME TO OldDevices"); + attestationConn.exec("ALTER TABLE Attestations RENAME TO OldAttestations"); + createAttestationTables(attestationConn); + + attestationConn.exec("INSERT INTO Devices " + + "(fingerprint, pinnedCertificates, attestKey, pinnedVerifiedBootKey, verifiedBootHash, pinnedDeviceManufacturer, pinnedDeviceModel, " + + "pinnedOsVersion, pinnedOsPatchLevel, pinnedVendorPatchLevel, pinnedBootPatchLevel, pinnedAppVersion, " + + "pinnedAppVariant, pinnedSecurityLevel, userProfileSecure, enrolledBiometrics, accessibility, " + + "deviceAdmin, adbEnabled, addUsersWhenLocked, denyNewUsb, oemUnlockAllowed, systemUser, verifiedTimeFirst, " + + "verifiedTimeLast, expiredTimeLast, failureTimeLast, userId, deletionTime) " + + "SELECT " + + "fingerprint, pinnedCertificates, attestKey, pinnedVerifiedBootKey, verifiedBootHash, " + + "NULL, NULL, " + + "pinnedOsVersion, pinnedOsPatchLevel, pinnedVendorPatchLevel, pinnedBootPatchLevel, pinnedAppVersion, " + + "pinnedAppVariant, pinnedSecurityLevel, userProfileSecure, enrolledBiometrics, accessibility, deviceAdmin, adbEnabled, " + + "addUsersWhenLocked, denyNewUsb, oemUnlockAllowed, systemUser, verifiedTimeFirst, verifiedTimeLast, " + + "expiredTimeLast, failureTimeLast, userId, deletionTime " + + "FROM OldDevices"); + + attestationConn.exec("INSERT INTO Attestations " + + "(id, fingerprint, time, strong, osVersion, osPatchLevel, vendorPatchLevel, " + + "bootPatchLevel, verifiedBootHash, appVersion, userProfileSecure, enrolledBiometrics, " + + "accessibility, deviceAdmin, adbEnabled, addUsersWhenLocked, denyNewUsb, oemUnlockAllowed, systemUser) " + + "SELECT " + + "id, fingerprint, time, strong, osVersion, osPatchLevel, vendorPatchLevel, " + + "bootPatchLevel, verifiedBootHash, appVersion, userProfileSecure, enrolledBiometrics," + + " accessibility, deviceAdmin, adbEnabled, addUsersWhenLocked, denyNewUsb, oemUnlockAllowed, systemUser " + + "FROM OldAttestations"); + + attestationConn.exec("DROP TABLE OldDevices"); + attestationConn.exec("DROP TABLE OldAttestations"); + + createAttestationIndices(attestationConn); + attestationConn.exec("PRAGMA user_version = 12"); + attestationConn.exec("COMMIT TRANSACTION"); + userVersion = 12; + attestationConn.exec("PRAGMA foreign_keys = ON"); + logger.info("Migrated to schema version: " + userVersion); + } + logger.info("Finished database setup for " + ATTESTATION_DATABASE); } finally { attestationConn.dispose(); @@ -1078,6 +1124,7 @@ private static void writeDevicesJson(final HttpExchange exchange, final long use final SQLiteStatement select = conn.prepare("SELECT fingerprint, " + "pinnedCertificates, attestKey, hex(pinnedVerifiedBootKey), " + "(SELECT hex(verifiedBootHash) WHERE verifiedBootHash IS NOT NULL), " + + "pinnedDeviceManufacturer, pinnedDeviceModel , " + "pinnedOsVersion, pinnedOsPatchLevel, pinnedVendorPatchLevel, " + "pinnedBootPatchLevel, pinnedAppVersion, pinnedAppVariant, pinnedSecurityLevel, " + "userProfileSecure, enrolledBiometrics, accessibility, deviceAdmin, " + @@ -1107,7 +1154,7 @@ private static void writeDevicesJson(final HttpExchange exchange, final long use final String verifiedBootKey = select.columnString(3); device.add("verifiedBootKey", verifiedBootKey); DeviceInfo info; - final int pinnedSecurityLevel = select.columnInt(11); + final int pinnedSecurityLevel = select.columnInt(13); if (pinnedSecurityLevel == ParsedAttestationRecord.securityLevelToInt(ParsedAttestationRecord.SecurityLevel.STRONG_BOX)) { info = fingerprintsStrongBoxCustomOS.get(verifiedBootKey); if (info == null) { @@ -1126,34 +1173,40 @@ private static void writeDevicesJson(final HttpExchange exchange, final long use } } device.add("osName", info.osName); - device.add("name", info.name); + if (!select.columnNull(5) && !select.columnNull(6)) { + device.add("name", select.columnString(5) + " " + select.columnString(6)); + } else if (info.isGeneric()) { + device.add("name", AttestationProtocol.DEVICE_GENERIC_UNKNOWN); + } else { + device.add("name", info.name); + } if (!select.columnNull(4)) { device.add("verifiedBootHash", select.columnString(4)); } - device.add("pinnedOsVersion", select.columnInt(5)); - device.add("pinnedOsPatchLevel", select.columnInt(6)); - if (!select.columnNull(7)) { - device.add("pinnedVendorPatchLevel", select.columnInt(7)); + device.add("pinnedOsVersion", select.columnInt(7)); + device.add("pinnedOsPatchLevel", select.columnInt(8)); + if (!select.columnNull(9)) { + device.add("pinnedVendorPatchLevel", select.columnInt(9)); } - if (!select.columnNull(8)) { - device.add("pinnedBootPatchLevel", select.columnInt(8)); + if (!select.columnNull(10)) { + device.add("pinnedBootPatchLevel", select.columnInt(10)); } - device.add("pinnedAppVersion", select.columnInt(9)); - device.add("pinnedAppVariant", select.columnInt(10)); + device.add("pinnedAppVersion", select.columnInt(11)); + device.add("pinnedAppVariant", select.columnInt(12)); device.add("pinnedSecurityLevel", pinnedSecurityLevel); - device.add("userProfileSecure", select.columnInt(12)); - device.add("enrolledBiometrics", select.columnInt(13)); - device.add("accessibility", select.columnInt(14)); - device.add("deviceAdmin", select.columnInt(15)); - device.add("adbEnabled", select.columnInt(16)); - device.add("addUsersWhenLocked", select.columnInt(17)); - device.add("denyNewUsb", select.columnInt(18)); - device.add("oemUnlockAllowed", select.columnInt(19)); - device.add("systemUser", select.columnInt(20)); - device.add("verifiedTimeFirst", select.columnLong(21)); - device.add("verifiedTimeLast", select.columnLong(22)); - device.add("minId", select.columnLong(23)); - device.add("maxId", select.columnLong(24)); + device.add("userProfileSecure", select.columnInt(14)); + device.add("enrolledBiometrics", select.columnInt(15)); + device.add("accessibility", select.columnInt(16)); + device.add("deviceAdmin", select.columnInt(17)); + device.add("adbEnabled", select.columnInt(18)); + device.add("addUsersWhenLocked", select.columnInt(19)); + device.add("denyNewUsb", select.columnInt(20)); + device.add("oemUnlockAllowed", select.columnInt(21)); + device.add("systemUser", select.columnInt(22)); + device.add("verifiedTimeFirst", select.columnLong(23)); + device.add("verifiedTimeLast", select.columnLong(24)); + device.add("minId", select.columnLong(25)); + device.add("maxId", select.columnLong(26)); devices.add(device); } } finally {