Loading core/java/android/util/ByteStringUtils.java +2 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ public final class ByteStringUtils { * @param bytes Byte array to encode. * @return Hex encoded string representation of bytes. */ public static String toString(byte[] bytes) { public static String toHexString(byte[] bytes) { if (bytes == null || bytes.length == 0 || bytes.length % 2 != 0) { return null; } Loading @@ -55,7 +55,7 @@ public final class ByteStringUtils { * @param str Hex encoded string to decode. * @return Decoded byte array representation of str. */ public static byte[] toByteArray(String str) { public static byte[] fromHexToByteArray(String str) { if (str == null || str.length() == 0 || str.length() % 2 != 0) { return null; } Loading core/java/android/util/PackageUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,6 @@ public final class PackageUtils { messageDigest.update(data); return ByteStringUtils.toString(messageDigest.digest()); return ByteStringUtils.toHexString(messageDigest.digest()); } } packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +36 −16 Original line number Diff line number Diff line Loading @@ -80,16 +80,20 @@ import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import static android.os.Process.ROOT_UID; import static android.os.Process.SHELL_UID; Loading Loading @@ -996,7 +1000,7 @@ public class SettingsProvider extends ContentProvider { continue; } // As of Android O (API 24), the SSAID is read from an app-specific entry in table // As of Android O, the SSAID is read from an app-specific entry in table // SETTINGS_FILE_SSAID, unless accessed by a system process. final Setting setting; if (isNewSsaidSetting(name)) { Loading Loading @@ -1035,7 +1039,7 @@ public class SettingsProvider extends ContentProvider { // Get the value. synchronized (mLock) { // As of Android O (API 24), the SSAID is read from an app-specific entry in table // As of Android O, the SSAID is read from an app-specific entry in table // SETTINGS_FILE_SSAID, unless accessed by a system process. if (isNewSsaidSetting(name)) { return getSsaidSettingLocked(owningUserId); Loading Loading @@ -1978,12 +1982,12 @@ public class SettingsProvider extends ContentProvider { private void generateUserKeyLocked(int userId) { // Generate a random key for each user used for creating a new ssaid. final byte[] keyBytes = new byte[16]; final byte[] keyBytes = new byte[32]; final SecureRandom rand = new SecureRandom(); rand.nextBytes(keyBytes); // Convert to string for storage in settings table. final String userKey = ByteStringUtils.toString(keyBytes); final String userKey = ByteStringUtils.toHexString(keyBytes); // Store the key in the ssaid table. final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId); Loading @@ -1995,6 +1999,10 @@ public class SettingsProvider extends ContentProvider { } } private byte[] getLengthPrefix(byte[] data) { return ByteBuffer.allocate(4).putInt(data.length).array(); } public Setting generateSsaidLocked(String packageName, int userId) { final PackageInfo packageInfo; try { Loading @@ -2019,25 +2027,37 @@ public class SettingsProvider extends ContentProvider { final String userKey = userKeySetting.getValue(); // Convert the user's key back to a byte array. final byte[] keyBytes = ByteStringUtils.toByteArray(userKey); if (keyBytes == null || keyBytes.length != 16) { final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey); // Validate that the key is of expected length. // Keys are currently 32 bytes, but were once 16 bytes during Android O development. if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) { throw new IllegalStateException("User key invalid"); } final MessageDigest md; final Mac m; try { // Hash package name and signature. md = MessageDigest.getInstance("SHA-256"); m = Mac.getInstance("HmacSHA256"); m.init(new SecretKeySpec(keyBytes, m.getAlgorithm())); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("HmacSHA256 is not available"); throw new IllegalStateException("HmacSHA256 is not available", e); } catch (InvalidKeyException e) { throw new IllegalStateException("Key is corrupted", e); } // Mac the package name and each of the signatures. byte[] packageNameBytes = packageInfo.packageName.getBytes(StandardCharsets.UTF_8); m.update(getLengthPrefix(packageNameBytes), 0, 4); m.update(packageNameBytes); for (int i = 0; i < packageInfo.signatures.length; i++) { byte[] sig = packageInfo.signatures[i].toByteArray(); m.update(getLengthPrefix(sig), 0, 4); m.update(sig); } md.update(keyBytes); md.update(packageInfo.packageName.getBytes(StandardCharsets.UTF_8)); md.update(packageInfo.signatures[0].toByteArray()); // Convert result to a string for storage in settings table. Only want first 64 bits. final String ssaid = ByteStringUtils.toString(md.digest()).substring(0, 16) .toLowerCase(); final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16) .toLowerCase(Locale.US); // Save the ssaid in the ssaid table. final String uid = Integer.toString(packageInfo.applicationInfo.uid); Loading Loading
core/java/android/util/ByteStringUtils.java +2 −2 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ public final class ByteStringUtils { * @param bytes Byte array to encode. * @return Hex encoded string representation of bytes. */ public static String toString(byte[] bytes) { public static String toHexString(byte[] bytes) { if (bytes == null || bytes.length == 0 || bytes.length % 2 != 0) { return null; } Loading @@ -55,7 +55,7 @@ public final class ByteStringUtils { * @param str Hex encoded string to decode. * @return Decoded byte array representation of str. */ public static byte[] toByteArray(String str) { public static byte[] fromHexToByteArray(String str) { if (str == null || str.length() == 0 || str.length() % 2 != 0) { return null; } Loading
core/java/android/util/PackageUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -80,6 +80,6 @@ public final class PackageUtils { messageDigest.update(data); return ByteStringUtils.toString(messageDigest.digest()); return ByteStringUtils.toHexString(messageDigest.digest()); } }
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +36 −16 Original line number Diff line number Diff line Loading @@ -80,16 +80,20 @@ import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import static android.os.Process.ROOT_UID; import static android.os.Process.SHELL_UID; Loading Loading @@ -996,7 +1000,7 @@ public class SettingsProvider extends ContentProvider { continue; } // As of Android O (API 24), the SSAID is read from an app-specific entry in table // As of Android O, the SSAID is read from an app-specific entry in table // SETTINGS_FILE_SSAID, unless accessed by a system process. final Setting setting; if (isNewSsaidSetting(name)) { Loading Loading @@ -1035,7 +1039,7 @@ public class SettingsProvider extends ContentProvider { // Get the value. synchronized (mLock) { // As of Android O (API 24), the SSAID is read from an app-specific entry in table // As of Android O, the SSAID is read from an app-specific entry in table // SETTINGS_FILE_SSAID, unless accessed by a system process. if (isNewSsaidSetting(name)) { return getSsaidSettingLocked(owningUserId); Loading Loading @@ -1978,12 +1982,12 @@ public class SettingsProvider extends ContentProvider { private void generateUserKeyLocked(int userId) { // Generate a random key for each user used for creating a new ssaid. final byte[] keyBytes = new byte[16]; final byte[] keyBytes = new byte[32]; final SecureRandom rand = new SecureRandom(); rand.nextBytes(keyBytes); // Convert to string for storage in settings table. final String userKey = ByteStringUtils.toString(keyBytes); final String userKey = ByteStringUtils.toHexString(keyBytes); // Store the key in the ssaid table. final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId); Loading @@ -1995,6 +1999,10 @@ public class SettingsProvider extends ContentProvider { } } private byte[] getLengthPrefix(byte[] data) { return ByteBuffer.allocate(4).putInt(data.length).array(); } public Setting generateSsaidLocked(String packageName, int userId) { final PackageInfo packageInfo; try { Loading @@ -2019,25 +2027,37 @@ public class SettingsProvider extends ContentProvider { final String userKey = userKeySetting.getValue(); // Convert the user's key back to a byte array. final byte[] keyBytes = ByteStringUtils.toByteArray(userKey); if (keyBytes == null || keyBytes.length != 16) { final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey); // Validate that the key is of expected length. // Keys are currently 32 bytes, but were once 16 bytes during Android O development. if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) { throw new IllegalStateException("User key invalid"); } final MessageDigest md; final Mac m; try { // Hash package name and signature. md = MessageDigest.getInstance("SHA-256"); m = Mac.getInstance("HmacSHA256"); m.init(new SecretKeySpec(keyBytes, m.getAlgorithm())); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("HmacSHA256 is not available"); throw new IllegalStateException("HmacSHA256 is not available", e); } catch (InvalidKeyException e) { throw new IllegalStateException("Key is corrupted", e); } // Mac the package name and each of the signatures. byte[] packageNameBytes = packageInfo.packageName.getBytes(StandardCharsets.UTF_8); m.update(getLengthPrefix(packageNameBytes), 0, 4); m.update(packageNameBytes); for (int i = 0; i < packageInfo.signatures.length; i++) { byte[] sig = packageInfo.signatures[i].toByteArray(); m.update(getLengthPrefix(sig), 0, 4); m.update(sig); } md.update(keyBytes); md.update(packageInfo.packageName.getBytes(StandardCharsets.UTF_8)); md.update(packageInfo.signatures[0].toByteArray()); // Convert result to a string for storage in settings table. Only want first 64 bits. final String ssaid = ByteStringUtils.toString(md.digest()).substring(0, 16) .toLowerCase(); final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16) .toLowerCase(Locale.US); // Save the ssaid in the ssaid table. final String uid = Integer.toString(packageInfo.applicationInfo.uid); Loading