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

Commit b3ce6d33 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Swap the order of synthetic password wrapping" into oc-mr1-dev

parents 9d3563ad 78acfe71
Loading
Loading
Loading
Loading
+17 −4
Original line number Original line Diff line number Diff line
@@ -112,7 +112,7 @@ public class SyntheticPasswordCrypto {
        }
        }
    }
    }


    public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
    public static byte[] decryptBlobV1(String keyAlias, byte[] blob, byte[] applicationId) {
        try {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            keyStore.load(null);
@@ -120,6 +120,20 @@ public class SyntheticPasswordCrypto {
            SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
            SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
            byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob);
            byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob);
            return decrypt(decryptionKey, intermediate);
            return decrypt(decryptionKey, intermediate);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to decrypt blob", e);
        }
    }

    public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);

            SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
            byte[] intermediate = decrypt(decryptionKey, blob);
            return decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate);
        } catch (CertificateException | IOException | BadPaddingException
        } catch (CertificateException | IOException | BadPaddingException
                | IllegalBlockSizeException
                | IllegalBlockSizeException
                | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
                | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
@@ -150,9 +164,8 @@ public class SyntheticPasswordCrypto {
            keyStore.setEntry(keyAlias,
            keyStore.setEntry(keyAlias,
                    new KeyStore.SecretKeyEntry(secretKey),
                    new KeyStore.SecretKeyEntry(secretKey),
                    builder.build());
                    builder.build());
            byte[] intermediate = encrypt(secretKey, data);
            byte[] intermediate = encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, data);
            return encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate);
            return encrypt(secretKey, intermediate);

        } catch (CertificateException | IOException | BadPaddingException
        } catch (CertificateException | IOException | BadPaddingException
                | IllegalBlockSizeException
                | IllegalBlockSizeException
                | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
                | KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
+21 −6
Original line number Original line Diff line number Diff line
@@ -101,7 +101,8 @@ public class SyntheticPasswordManager {
    private static final byte WEAVER_VERSION = 1;
    private static final byte WEAVER_VERSION = 1;
    private static final int INVALID_WEAVER_SLOT = -1;
    private static final int INVALID_WEAVER_SLOT = -1;


    private static final byte SYNTHETIC_PASSWORD_VERSION = 1;
    private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1;
    private static final byte SYNTHETIC_PASSWORD_VERSION = 2;
    private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
    private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
    private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
    private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;


@@ -792,6 +793,7 @@ public class SyntheticPasswordManager {
        byte[] pwdToken = computePasswordToken(credential, pwd);
        byte[] pwdToken = computePasswordToken(credential, pwd);


        final byte[] applicationId;
        final byte[] applicationId;
        final long sid;
        int weaverSlot = loadWeaverSlot(handle, userId);
        int weaverSlot = loadWeaverSlot(handle, userId);
        if (weaverSlot != INVALID_WEAVER_SLOT) {
        if (weaverSlot != INVALID_WEAVER_SLOT) {
            // Weaver based user password
            // Weaver based user password
@@ -804,6 +806,7 @@ public class SyntheticPasswordManager {
            if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
            if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
                return result;
                return result;
            }
            }
            sid = GateKeeper.INVALID_SECURE_USER_ID;
            applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
            applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
        } else {
        } else {
            byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
            byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
@@ -836,12 +839,13 @@ public class SyntheticPasswordManager {
                result.gkResponse = VerifyCredentialResponse.ERROR;
                result.gkResponse = VerifyCredentialResponse.ERROR;
                return result;
                return result;
            }
            }
            sid = sidFromPasswordHandle(pwd.passwordHandle);
            applicationId = transformUnderSecdiscardable(pwdToken,
            applicationId = transformUnderSecdiscardable(pwdToken,
                    loadSecdiscardable(handle, userId));
                    loadSecdiscardable(handle, userId));
        }
        }


        result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
        result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
                applicationId, userId);
                applicationId, sid, userId);


        // Perform verifyChallenge to refresh auth tokens for GK if user password exists.
        // Perform verifyChallenge to refresh auth tokens for GK if user password exists.
        result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
        result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
@@ -877,7 +881,7 @@ public class SyntheticPasswordManager {
        }
        }
        byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable);
        byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable);
        result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED,
        result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED,
                applicationId, userId);
                applicationId, 0L, userId);
        if (result.authToken != null) {
        if (result.authToken != null) {
            result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
            result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
            if (result.gkResponse == null) {
            if (result.gkResponse == null) {
@@ -892,19 +896,26 @@ public class SyntheticPasswordManager {
    }
    }


    private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type,
    private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type,
            byte[] applicationId, int userId) {
            byte[] applicationId, long sid, int userId) {
        byte[] blob = loadState(SP_BLOB_NAME, handle, userId);
        byte[] blob = loadState(SP_BLOB_NAME, handle, userId);
        if (blob == null) {
        if (blob == null) {
            return null;
            return null;
        }
        }
        if (blob[0] != SYNTHETIC_PASSWORD_VERSION) {
        final byte version = blob[0];
        if (version != SYNTHETIC_PASSWORD_VERSION && version != SYNTHETIC_PASSWORD_VERSION_V1) {
            throw new RuntimeException("Unknown blob version");
            throw new RuntimeException("Unknown blob version");
        }
        }
        if (blob[1] != type) {
        if (blob[1] != type) {
            throw new RuntimeException("Invalid blob type");
            throw new RuntimeException("Invalid blob type");
        }
        }
        byte[] secret = decryptSPBlob(getHandleName(handle),
        final byte[] secret;
        if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
            secret = SyntheticPasswordCrypto.decryptBlobV1(getHandleName(handle),
                    Arrays.copyOfRange(blob, 2, blob.length), applicationId);
        } else {
            secret = decryptSPBlob(getHandleName(handle),
                Arrays.copyOfRange(blob, 2, blob.length), applicationId);
                Arrays.copyOfRange(blob, 2, blob.length), applicationId);
        }
        if (secret == null) {
        if (secret == null) {
            Log.e(TAG, "Fail to decrypt SP for user " + userId);
            Log.e(TAG, "Fail to decrypt SP for user " + userId);
            return null;
            return null;
@@ -919,6 +930,10 @@ public class SyntheticPasswordManager {
        } else {
        } else {
            result.syntheticPassword = new String(secret);
            result.syntheticPassword = new String(secret);
        }
        }
        if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
            Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type);
            createSyntheticPasswordBlob(handle, type, result, applicationId, sid, userId);
        }
        return result;
        return result;
    }
    }