Loading services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +15 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException; Loading @@ -43,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; public class SyntheticPasswordCrypto { public class SyntheticPasswordCrypto { private static final int PROFILE_KEY_IV_SIZE = 12; private static final int PROFILE_KEY_IV_SIZE = 12; private static final int DEFAULT_TAG_LENGTH_BITS = 128; private static final int AES_KEY_LENGTH = 32; // 256-bit AES key private static final int AES_KEY_LENGTH = 32; // 256-bit AES key private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); // Time between the user credential is verified with GK and the decryption of synthetic password // Time between the user credential is verified with GK and the decryption of synthetic password Loading @@ -60,13 +62,14 @@ public class SyntheticPasswordCrypto { byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length); byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length); Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv)); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(DEFAULT_TAG_LENGTH_BITS, iv)); return cipher.doFinal(ciphertext); return cipher.doFinal(ciphertext); } } private static byte[] encrypt(SecretKey key, byte[] blob) private static byte[] encrypt(SecretKey key, byte[] blob) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidParameterSpecException { if (blob == null) { if (blob == null) { return null; return null; } } Loading @@ -79,6 +82,11 @@ public class SyntheticPasswordCrypto { if (iv.length != PROFILE_KEY_IV_SIZE) { if (iv.length != PROFILE_KEY_IV_SIZE) { throw new RuntimeException("Invalid iv length: " + iv.length); throw new RuntimeException("Invalid iv length: " + iv.length); } } final GCMParameterSpec spec = cipher.getParameters().getParameterSpec( GCMParameterSpec.class); if (spec.getTLen() != DEFAULT_TAG_LENGTH_BITS) { throw new RuntimeException("Invalid tag length: " + spec.getTLen()); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(iv); outputStream.write(iv); outputStream.write(ciphertext); outputStream.write(ciphertext); Loading @@ -92,7 +100,8 @@ public class SyntheticPasswordCrypto { try { try { return encrypt(key, message); return encrypt(key, message); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | IOException e) { | IllegalBlockSizeException | BadPaddingException | IOException | InvalidParameterSpecException e) { e.printStackTrace(); e.printStackTrace(); return null; return null; } } Loading Loading @@ -147,7 +156,7 @@ public class SyntheticPasswordCrypto { public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) { public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) { try { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); keyGenerator.init(new SecureRandom()); keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom()); SecretKey secretKey = keyGenerator.generateKey(); SecretKey secretKey = keyGenerator.generateKey(); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); keyStore.load(null); Loading @@ -169,7 +178,8 @@ public class SyntheticPasswordCrypto { } catch (CertificateException | IOException | BadPaddingException } catch (CertificateException | IOException | BadPaddingException | IllegalBlockSizeException | IllegalBlockSizeException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { | InvalidKeyException | InvalidParameterSpecException e) { e.printStackTrace(); e.printStackTrace(); throw new RuntimeException("Failed to encrypt blob", e); throw new RuntimeException("Failed to encrypt blob", e); } } Loading Loading
services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +15 −5 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.security.spec.InvalidParameterSpecException; import java.util.Arrays; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException; Loading @@ -43,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; public class SyntheticPasswordCrypto { public class SyntheticPasswordCrypto { private static final int PROFILE_KEY_IV_SIZE = 12; private static final int PROFILE_KEY_IV_SIZE = 12; private static final int DEFAULT_TAG_LENGTH_BITS = 128; private static final int AES_KEY_LENGTH = 32; // 256-bit AES key private static final int AES_KEY_LENGTH = 32; // 256-bit AES key private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); private static final byte[] APPLICATION_ID_PERSONALIZATION = "application-id".getBytes(); // Time between the user credential is verified with GK and the decryption of synthetic password // Time between the user credential is verified with GK and the decryption of synthetic password Loading @@ -60,13 +62,14 @@ public class SyntheticPasswordCrypto { byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length); byte[] ciphertext = Arrays.copyOfRange(blob, PROFILE_KEY_IV_SIZE, blob.length); Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); + KeyProperties.BLOCK_MODE_GCM + "/" + KeyProperties.ENCRYPTION_PADDING_NONE); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv)); cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(DEFAULT_TAG_LENGTH_BITS, iv)); return cipher.doFinal(ciphertext); return cipher.doFinal(ciphertext); } } private static byte[] encrypt(SecretKey key, byte[] blob) private static byte[] encrypt(SecretKey key, byte[] blob) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidParameterSpecException { if (blob == null) { if (blob == null) { return null; return null; } } Loading @@ -79,6 +82,11 @@ public class SyntheticPasswordCrypto { if (iv.length != PROFILE_KEY_IV_SIZE) { if (iv.length != PROFILE_KEY_IV_SIZE) { throw new RuntimeException("Invalid iv length: " + iv.length); throw new RuntimeException("Invalid iv length: " + iv.length); } } final GCMParameterSpec spec = cipher.getParameters().getParameterSpec( GCMParameterSpec.class); if (spec.getTLen() != DEFAULT_TAG_LENGTH_BITS) { throw new RuntimeException("Invalid tag length: " + spec.getTLen()); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(iv); outputStream.write(iv); outputStream.write(ciphertext); outputStream.write(ciphertext); Loading @@ -92,7 +100,8 @@ public class SyntheticPasswordCrypto { try { try { return encrypt(key, message); return encrypt(key, message); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException | IOException e) { | IllegalBlockSizeException | BadPaddingException | IOException | InvalidParameterSpecException e) { e.printStackTrace(); e.printStackTrace(); return null; return null; } } Loading Loading @@ -147,7 +156,7 @@ public class SyntheticPasswordCrypto { public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) { public static byte[] createBlob(String keyAlias, byte[] data, byte[] applicationId, long sid) { try { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); keyGenerator.init(new SecureRandom()); keyGenerator.init(AES_KEY_LENGTH * 8, new SecureRandom()); SecretKey secretKey = keyGenerator.generateKey(); SecretKey secretKey = keyGenerator.generateKey(); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); keyStore.load(null); Loading @@ -169,7 +178,8 @@ public class SyntheticPasswordCrypto { } catch (CertificateException | IOException | BadPaddingException } catch (CertificateException | IOException | BadPaddingException | IllegalBlockSizeException | IllegalBlockSizeException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) { | InvalidKeyException | InvalidParameterSpecException e) { e.printStackTrace(); e.printStackTrace(); throw new RuntimeException("Failed to encrypt blob", e); throw new RuntimeException("Failed to encrypt blob", e); } } Loading