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

Commit 9ff409c7 authored by Rubin Xu's avatar Rubin Xu Committed by Android (Google) Code Review
Browse files

Merge "Fix AES encryption for SP" into qt-dev

parents 873e0629 01e3a48d
Loading
Loading
Loading
Loading
+15 −5
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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
@@ -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;
        }
        }
@@ -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);
@@ -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;
        }
        }
@@ -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);
@@ -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);
        }
        }