diff --git a/app/src/main/java/app/attestation/auditor/AttestationProtocol.java b/app/src/main/java/app/attestation/auditor/AttestationProtocol.java index 54e6295d..ae4d9309 100644 --- a/app/src/main/java/app/attestation/auditor/AttestationProtocol.java +++ b/app/src/main/java/app/attestation/auditor/AttestationProtocol.java @@ -107,7 +107,7 @@ class AttestationProtocol { private static final String KEY_VERIFIED_TIME_FIRST = "verified_time_first"; private static final String KEY_VERIFIED_TIME_LAST = "verified_time_last"; - private static final int CHALLENGE_LENGTH = 32; + private static final int RANDOM_TOKEN_LENGTH = 32; static final String EC_CURVE = "secp256r1"; private static final String SIGNATURE_ALGORITHM = "SHA256WithECDSA"; static final String KEY_DIGEST = DIGEST_SHA256; @@ -119,8 +119,8 @@ class AttestationProtocol { // Challenge message: // // byte maxVersion = PROTOCOL_VERSION - // byte[] challenge index (length: CHALLENGE_LENGTH) - // byte[] challenge (length: CHALLENGE_LENGTH) + // byte[] challenge index (length: RANDOM_TOKEN_LENGTH) + // byte[] challenge (length: RANDOM_TOKEN_LENGTH) // // The challenge index is randomly generated by Auditor and used for all future challenge // messages from that Auditor. It's used on the Auditee as an index to choose the correct @@ -193,7 +193,7 @@ class AttestationProtocol { private static final byte PROTOCOL_VERSION = 5; private static final byte PROTOCOL_VERSION_MINIMUM = 5; // can become longer in the future, but this is the minimum length - static final byte CHALLENGE_MESSAGE_LENGTH = 1 + CHALLENGE_LENGTH * 2; + static final byte CHALLENGE_MESSAGE_LENGTH = 1 + RANDOM_TOKEN_LENGTH * 2; private static final int MAX_ENCODED_CHAIN_LENGTH = 5000; private static final int MAX_MESSAGE_SIZE = 2953; @@ -511,7 +511,7 @@ private static byte[] getChallengeIndex(final Context context) { if (challengeIndexSerialized != null) { return BaseEncoding.base64().decode(challengeIndexSerialized); } else { - final byte[] challengeIndex = getChallenge(); + final byte[] challengeIndex = generateRandomToken(); global.edit() .putString(KEY_CHALLENGE_INDEX, BaseEncoding.base64().encode(challengeIndex)) .apply(); @@ -519,15 +519,16 @@ private static byte[] getChallengeIndex(final Context context) { } } - private static byte[] getChallenge() { - final SecureRandom random = new SecureRandom(); - final byte[] challenge = new byte[CHALLENGE_LENGTH]; + private static final SecureRandom random = new SecureRandom(); + + private static byte[] generateRandomToken() { + final byte[] challenge = new byte[RANDOM_TOKEN_LENGTH]; random.nextBytes(challenge); return challenge; } static byte[] getChallengeMessage(final Context context) { - return Bytes.concat(new byte[]{PROTOCOL_VERSION}, getChallengeIndex(context), getChallenge()); + return Bytes.concat(new byte[]{PROTOCOL_VERSION}, getChallengeIndex(context), generateRandomToken()); } private static byte[] getFingerprint(final Certificate certificate) @@ -1233,7 +1234,7 @@ static VerificationResult verifySerialized(final Context context, final byte[] a deserializer.rewind(); deserializer.limit(deserializer.capacity() - signature.length); - final byte[] challenge = Arrays.copyOfRange(challengeMessage, 1 + CHALLENGE_LENGTH, 1 + CHALLENGE_LENGTH * 2); + final byte[] challenge = Arrays.copyOfRange(challengeMessage, 1 + RANDOM_TOKEN_LENGTH, 1 + RANDOM_TOKEN_LENGTH * 2); return verify(context, fingerprint, challenge, deserializer.asReadOnlyBuffer(), signature, certificates, userProfileSecure, accessibility, deviceAdmin, deviceAdminNonSystem, adbEnabled, addUsersWhenLocked, enrolledBiometrics, denyNewUsb, oemUnlockAllowed, @@ -1314,8 +1315,8 @@ static AttestationResult generateSerialized(final Context context, final byte[] throw new GeneralSecurityException("Auditor protocol version too old: " + maxVersion); } final byte version = (byte) Math.min(PROTOCOL_VERSION, maxVersion); - final byte[] challengeIndex = Arrays.copyOfRange(challengeMessage, 1, 1 + CHALLENGE_LENGTH); - final byte[] challenge = Arrays.copyOfRange(challengeMessage, 1 + CHALLENGE_LENGTH, 1 + CHALLENGE_LENGTH * 2); + final byte[] challengeIndex = Arrays.copyOfRange(challengeMessage, 1, 1 + RANDOM_TOKEN_LENGTH); + final byte[] challenge = Arrays.copyOfRange(challengeMessage, 1 + RANDOM_TOKEN_LENGTH, 1 + RANDOM_TOKEN_LENGTH * 2); final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null);