diff options
author | Al Sutton <alsutton@google.com> | 2019-09-13 15:42:09 +0100 |
---|---|---|
committer | Al Sutton <alsutton@google.com> | 2019-09-17 14:50:44 +0100 |
commit | 572df9fff33862f11deb5b707982b2563d82cb6e (patch) | |
tree | 64f5306766e56c4ffca0e295ac5fde49bad0b2cb /packages/BackupEncryption | |
parent | 9f8672db5b9edbb798303bff1da1cfc25217c25b (diff) |
Move chunk proto definitions into the BackupEncrypter APK
Bug: 111386661
Test: make RunBackupEncryptionRoboTests
Change-Id: I3032210e6eec52b0c925baab770a4578ac7ecbf7
Diffstat (limited to 'packages/BackupEncryption')
10 files changed, 143 insertions, 505 deletions
diff --git a/packages/BackupEncryption/proto/backup_chunks_metadata.proto b/packages/BackupEncryption/proto/backup_chunks_metadata.proto new file mode 100644 index 000000000000..2fdedbf70975 --- /dev/null +++ b/packages/BackupEncryption/proto/backup_chunks_metadata.proto @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +syntax = "proto2"; + +package android_backup_crypto; + +option java_package = "com.android.server.backup.encryption.protos"; +option java_outer_classname = "ChunksMetadataProto"; + +// Cipher type with which the chunks are encrypted. For now we only support AES/GCM/NoPadding, but +// this is for backwards-compatibility in case we need to change the default Cipher in the future. +enum CipherType { + UNKNOWN_CIPHER_TYPE = 0; + // Chunk is prefixed with a 12-byte nonce. The tag length is 16 bytes. + AES_256_GCM = 1; +} + +// Checksum type with which the plaintext is verified. +enum ChecksumType { + UNKNOWN_CHECKSUM_TYPE = 0; + SHA_256 = 1; +} + +enum ChunkOrderingType { + CHUNK_ORDERING_TYPE_UNSPECIFIED = 0; + // The chunk ordering contains a list of the start position of each chunk in the encrypted file, + // ordered as in the plaintext file. This allows us to recreate the original plaintext file + // during decryption. We use this mode for full backups where the order of the data in the file + // is important. + EXPLICIT_STARTS = 1; + // The chunk ordering does not contain any start positions, and instead each encrypted chunk in + // the backup file is prefixed with its length. This allows us to decrypt each chunk but does + // not give any information about the order. However, we use this mode for key value backups + // where the order does not matter. + INLINE_LENGTHS = 2; +} + +// Chunk entry (for local state) +message Chunk { + // SHA-256 MAC of the plaintext of the chunk + optional bytes hash = 1; + // Number of bytes in encrypted chunk + optional int32 length = 2; +} + +// List of the chunks in the blob, along with the length of each chunk. From this is it possible to +// extract individual chunks. (i.e., start position is equal to the sum of the lengths of all +// preceding chunks.) +// +// This is local state stored on the device. It is never sent to the backup server. See +// ChunkOrdering for how the device restores the chunks in the correct order. +// Next tag : 6 +message ChunkListing { + repeated Chunk chunks = 1; + + // Cipher algorithm with which the chunks are encrypted. + optional CipherType cipher_type = 2; + + // Defines the type of chunk order used to encode the backup file on the server, so that we can + // consistently use the same type between backups. If unspecified this backup file was created + // before INLINE_LENGTHS was supported, thus assume it is EXPLICIT_STARTS. + optional ChunkOrderingType chunk_ordering_type = 5; + + // The document ID returned from Scotty server after uploading the blob associated with this + // listing. This needs to be sent when uploading new diff scripts. + optional string document_id = 3; + + // Fingerprint mixer salt used for content defined chunking. This is randomly generated for each + // package during the initial non-incremental backup and reused for incremental backups. + optional bytes fingerprint_mixer_salt = 4; +} + +// Ordering information about plaintext and checksum. This is used on restore to reconstruct the +// blob in its correct order. (The chunk order is randomized so as to give the server less +// information about which parts of the backup are changing over time.) This proto is encrypted +// before being uploaded to the server, with a key unknown to the server. +message ChunkOrdering { + // For backups where ChunksMetadata#chunk_ordering_type = EXPLICIT STARTS: + // Ordered start positions of chunks. i.e., the file is the chunk starting at this position, + // followed by the chunk starting at this position, followed by ... etc. You can compute the + // lengths of the chunks by sorting this list then looking at the start position of the next + // chunk after the chunk you care about. This is guaranteed to work as all chunks are + // represented in this list. + // + // For backups where ChunksMetadata#chunk_ordering_type = INLINE_LENGTHS: + // This field is unused. See ChunkOrderingType#INLINE_LENGTHS. + repeated int32 starts = 1 [packed = true]; + + // Checksum of plaintext content. (i.e., in correct order.) + // + // Each chunk also has a MAC, as generated by GCM, so this is NOT Mac-then-Encrypt, which has + // security implications. This is an additional checksum to verify that once the chunks have + // been reordered, that the file matches the expected plaintext. This prevents the device + // restoring garbage data in case of a mismatch between the ChunkOrdering and the backup blob. + optional bytes checksum = 2; +} + +// Additional metadata about a backup blob that needs to be synced to the server. This is used on +// restore to reconstruct the blob in its correct order. (The chunk order is randomized so as to +// give the server less information about which parts of the backup are changing over time.) This +// data structure is only ever uploaded to the server encrypted with a key unknown to the server. +// Next tag : 6 +message ChunksMetadata { + // Cipher algorithm with which the chunk listing and chunks are encrypted. + optional CipherType cipher_type = 1; + + // Defines the type of chunk order this metadata contains. If unspecified this backup file was + // created before INLINE_LENGTHS was supported, thus assume it is EXPLICIT_STARTS. + optional ChunkOrderingType chunk_ordering_type = 5 + [default = CHUNK_ORDERING_TYPE_UNSPECIFIED]; + + // Encrypted bytes of ChunkOrdering + optional bytes chunk_ordering = 2; + + // The type of algorithm used for the checksum of the plaintext. (See ChunkOrdering.) This is + // for forwards compatibility in case we change the algorithm in the future. For now, always + // SHA-256. + optional ChecksumType checksum_type = 3; + + // This used to be the plaintext tertiary key. No longer used. + reserved 4; +}
\ No newline at end of file diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/Chunk.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/Chunk.java deleted file mode 100644 index ba328609a77e..000000000000 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/Chunk.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.backup.encryption.chunk; - -import android.util.proto.ProtoInputStream; - -import java.io.IOException; - -/** - * Information about a chunk entry in a protobuf. Only used for reading from a {@link - * ProtoInputStream}. - */ -public class Chunk { - /** - * Reads a Chunk from a {@link ProtoInputStream}. Expects the message to be of format {@link - * ChunksMetadataProto.Chunk}. - * - * @param inputStream currently at a {@link ChunksMetadataProto.Chunk} message. - * @throws IOException when the message is not structured as expected or a field can not be - * read. - */ - static Chunk readFromProto(ProtoInputStream inputStream) throws IOException { - Chunk result = new Chunk(); - - while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - switch (inputStream.getFieldNumber()) { - case (int) ChunksMetadataProto.Chunk.HASH: - result.mHash = inputStream.readBytes(ChunksMetadataProto.Chunk.HASH); - break; - case (int) ChunksMetadataProto.Chunk.LENGTH: - result.mLength = inputStream.readInt(ChunksMetadataProto.Chunk.LENGTH); - break; - } - } - - return result; - } - - private int mLength; - private byte[] mHash; - - /** Private constructor. This class should only be instantiated by calling readFromProto. */ - private Chunk() { - // Set default values for fields in case they are not available in the proto. - mHash = new byte[]{}; - mLength = 0; - } - - public int getLength() { - return mLength; - } - - public byte[] getHash() { - return mHash; - } -} diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkListingMap.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkListingMap.java deleted file mode 100644 index a44890118717..000000000000 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkListingMap.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.backup.encryption.chunk; - -import android.annotation.Nullable; -import android.util.proto.ProtoInputStream; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * Chunk listing in a format optimized for quick look-up of chunks via their hash keys. This is - * useful when building an incremental backup. After a chunk has been produced, the algorithm can - * quickly look up whether the chunk existed in the previous backup by checking this chunk listing. - * It can then tell the server to use that chunk, through telling it the position and length of the - * chunk in the previous backup's blob. - */ -public class ChunkListingMap { - /** - * Reads a ChunkListingMap from a {@link ProtoInputStream}. Expects the message to be of format - * {@link ChunksMetadataProto.ChunkListing}. - * - * @param inputStream Currently at a {@link ChunksMetadataProto.ChunkListing} message. - * @throws IOException when the message is not structured as expected or a field can not be - * read. - */ - public static ChunkListingMap readFromProto(ProtoInputStream inputStream) throws IOException { - Map<ChunkHash, Entry> entries = new HashMap(); - - long start = 0; - - while (inputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { - if (inputStream.getFieldNumber() == (int) ChunksMetadataProto.ChunkListing.CHUNKS) { - long chunkToken = inputStream.start(ChunksMetadataProto.ChunkListing.CHUNKS); - Chunk chunk = Chunk.readFromProto(inputStream); - entries.put(new ChunkHash(chunk.getHash()), new Entry(start, chunk.getLength())); - start += chunk.getLength(); - inputStream.end(chunkToken); - } - } - - return new ChunkListingMap(entries); - } - - private final Map<ChunkHash, Entry> mChunksByHash; - - private ChunkListingMap(Map<ChunkHash, Entry> chunksByHash) { - mChunksByHash = Collections.unmodifiableMap(new HashMap<>(chunksByHash)); - } - - /** Returns {@code true} if there is a chunk with the given SHA-256 MAC key in the listing. */ - public boolean hasChunk(ChunkHash hash) { - return mChunksByHash.containsKey(hash); - } - - /** - * Returns the entry for the chunk with the given hash. - * - * @param hash The SHA-256 MAC of the plaintext of the chunk. - * @return The entry, containing position and length of the chunk in the backup blob, or null if - * it does not exist. - */ - @Nullable - public Entry getChunkEntry(ChunkHash hash) { - return mChunksByHash.get(hash); - } - - /** Returns the number of chunks in this listing. */ - public int getChunkCount() { - return mChunksByHash.size(); - } - - /** Information about a chunk entry in a backup blob - i.e., its position and length. */ - public static final class Entry { - private final int mLength; - private final long mStart; - - private Entry(long start, int length) { - mStart = start; - mLength = length; - } - - /** Returns the length of the chunk in bytes. */ - public int getLength() { - return mLength; - } - - /** Returns the start position of the chunk in the backup blob, in bytes. */ - public long getStart() { - return mStart; - } - } -} diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java index 8cb028e46e9d..9cda3395f79a 100644 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java @@ -16,9 +16,9 @@ package com.android.server.backup.encryption.chunk; -import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED; -import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.EXPLICIT_STARTS; -import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.INLINE_LENGTHS; +import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.CHUNK_ORDERING_TYPE_UNSPECIFIED; +import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.EXPLICIT_STARTS; +import static com.android.server.backup.encryption.protos.nano.ChunksMetadataProto.INLINE_LENGTHS; import android.annotation.IntDef; diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java index 7b38dd4a1dc3..6b9be9fd91d3 100644 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java @@ -17,7 +17,7 @@ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkOrderingType; -import com.android.server.backup.encryption.chunk.ChunksMetadataProto; +import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto; import java.io.IOException; diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java index 567f75d59513..e707350505fb 100644 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java @@ -17,7 +17,7 @@ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkOrderingType; -import com.android.server.backup.encryption.chunk.ChunksMetadataProto; +import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto; import java.io.IOException; diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java deleted file mode 100644 index 24e5573b891d..000000000000 --- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.backup.encryption.chunk; - -import static com.google.common.truth.Truth.assertThat; - -import android.platform.test.annotations.Presubmit; -import android.util.proto.ProtoInputStream; -import android.util.proto.ProtoOutputStream; - -import com.android.internal.util.Preconditions; - -import com.google.common.base.Charsets; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; - -import java.io.ByteArrayInputStream; -import java.util.Arrays; - -@RunWith(RobolectricTestRunner.class) -@Presubmit -public class ChunkListingMapTest { - private static final String CHUNK_A = "CHUNK_A"; - private static final String CHUNK_B = "CHUNK_B"; - private static final String CHUNK_C = "CHUNK_C"; - - private static final int CHUNK_A_LENGTH = 256; - private static final int CHUNK_B_LENGTH = 1024; - private static final int CHUNK_C_LENGTH = 4055; - - private ChunkHash mChunkHashA; - private ChunkHash mChunkHashB; - private ChunkHash mChunkHashC; - - @Before - public void setUp() throws Exception { - mChunkHashA = getHash(CHUNK_A); - mChunkHashB = getHash(CHUNK_B); - mChunkHashC = getHash(CHUNK_C); - } - - @Test - public void testHasChunk_whenChunkInListing_returnsTrue() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH}); - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - - boolean chunkAInList = chunkListingMap.hasChunk(mChunkHashA); - boolean chunkBInList = chunkListingMap.hasChunk(mChunkHashB); - boolean chunkCInList = chunkListingMap.hasChunk(mChunkHashC); - - assertThat(chunkAInList).isTrue(); - assertThat(chunkBInList).isTrue(); - assertThat(chunkCInList).isTrue(); - } - - @Test - public void testHasChunk_whenChunkNotInListing_returnsFalse() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH}); - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - ChunkHash chunkHashEmpty = getHash(""); - - boolean chunkCInList = chunkListingMap.hasChunk(mChunkHashC); - boolean emptyChunkInList = chunkListingMap.hasChunk(chunkHashEmpty); - - assertThat(chunkCInList).isFalse(); - assertThat(emptyChunkInList).isFalse(); - } - - @Test - public void testGetChunkEntry_returnsEntryWithCorrectLength() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH}); - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - - ChunkListingMap.Entry entryA = chunkListingMap.getChunkEntry(mChunkHashA); - ChunkListingMap.Entry entryB = chunkListingMap.getChunkEntry(mChunkHashB); - ChunkListingMap.Entry entryC = chunkListingMap.getChunkEntry(mChunkHashC); - - assertThat(entryA.getLength()).isEqualTo(CHUNK_A_LENGTH); - assertThat(entryB.getLength()).isEqualTo(CHUNK_B_LENGTH); - assertThat(entryC.getLength()).isEqualTo(CHUNK_C_LENGTH); - } - - @Test - public void testGetChunkEntry_returnsEntryWithCorrectStart() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH}); - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - - ChunkListingMap.Entry entryA = chunkListingMap.getChunkEntry(mChunkHashA); - ChunkListingMap.Entry entryB = chunkListingMap.getChunkEntry(mChunkHashB); - ChunkListingMap.Entry entryC = chunkListingMap.getChunkEntry(mChunkHashC); - - assertThat(entryA.getStart()).isEqualTo(0); - assertThat(entryB.getStart()).isEqualTo(CHUNK_A_LENGTH); - assertThat(entryC.getStart()).isEqualTo(CHUNK_A_LENGTH + CHUNK_B_LENGTH); - } - - @Test - public void testGetChunkEntry_returnsNullForNonExistentChunk() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH}); - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - - ChunkListingMap.Entry chunkEntryNonexistentChunk = - chunkListingMap.getChunkEntry(mChunkHashC); - - assertThat(chunkEntryNonexistentChunk).isNull(); - } - - @Test - public void testReadFromProto_whenEmptyProto_returnsChunkListingMapWith0Chunks() - throws Exception { - ProtoInputStream emptyProto = new ProtoInputStream(new ByteArrayInputStream(new byte[] {})); - - ChunkListingMap chunkListingMap = ChunkListingMap.readFromProto(emptyProto); - - assertThat(chunkListingMap.getChunkCount()).isEqualTo(0); - } - - @Test - public void testReadFromProto_returnsChunkListingWithCorrectSize() throws Exception { - byte[] chunkListingProto = - createChunkListingProto( - new ChunkHash[] {mChunkHashA, mChunkHashB, mChunkHashC}, - new int[] {CHUNK_A_LENGTH, CHUNK_B_LENGTH, CHUNK_C_LENGTH}); - - ChunkListingMap chunkListingMap = - ChunkListingMap.readFromProto( - new ProtoInputStream(new ByteArrayInputStream(chunkListingProto))); - - assertThat(chunkListingMap.getChunkCount()).isEqualTo(3); - } - - private byte[] createChunkListingProto(ChunkHash[] hashes, int[] lengths) { - Preconditions.checkArgument(hashes.length == lengths.length); - ProtoOutputStream outputStream = new ProtoOutputStream(); - - for (int i = 0; i < hashes.length; ++i) { - writeToProtoOutputStream(outputStream, hashes[i], lengths[i]); - } - outputStream.flush(); - - return outputStream.getBytes(); - } - - private void writeToProtoOutputStream(ProtoOutputStream out, ChunkHash chunkHash, int length) { - long token = out.start(ChunksMetadataProto.ChunkListing.CHUNKS); - out.write(ChunksMetadataProto.Chunk.HASH, chunkHash.getHash()); - out.write(ChunksMetadataProto.Chunk.LENGTH, length); - out.end(token); - } - - private ChunkHash getHash(String name) { - return new ChunkHash( - Arrays.copyOf(name.getBytes(Charsets.UTF_8), ChunkHash.HASH_LENGTH_BYTES)); - } -} diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkTest.java deleted file mode 100644 index 1796f56ce17a..000000000000 --- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.backup.encryption.chunk; - -import static com.google.common.truth.Truth.assertThat; - -import android.platform.test.annotations.Presubmit; -import android.util.proto.ProtoInputStream; -import android.util.proto.ProtoOutputStream; - -import com.google.common.base.Charsets; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; - -import java.io.ByteArrayInputStream; -import java.util.Arrays; - -@RunWith(RobolectricTestRunner.class) -@Presubmit -public class ChunkTest { - private static final String CHUNK_A = "CHUNK_A"; - private static final int CHUNK_A_LENGTH = 256; - - private ChunkHash mChunkHashA; - - @Before - public void setUp() throws Exception { - mChunkHashA = getHash(CHUNK_A); - } - - @Test - public void testReadFromProto_readsCorrectly() throws Exception { - ProtoOutputStream out = new ProtoOutputStream(); - out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash()); - out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH); - out.flush(); - byte[] protoBytes = out.getBytes(); - - Chunk chunk = - Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes))); - - assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash()); - assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH); - } - - @Test - public void testReadFromProto_whenFieldsWrittenInReversedOrder_readsCorrectly() - throws Exception { - ProtoOutputStream out = new ProtoOutputStream(); - // Write fields of Chunk proto in reverse order. - out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH); - out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash()); - out.flush(); - byte[] protoBytes = out.getBytes(); - - Chunk chunk = - Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes))); - - assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash()); - assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH); - } - - @Test - public void testReadFromProto_whenEmptyProto_returnsEmptyHash() throws Exception { - ProtoInputStream emptyProto = new ProtoInputStream(new ByteArrayInputStream(new byte[] {})); - - Chunk chunk = Chunk.readFromProto(emptyProto); - - assertThat(chunk.getHash()).asList().hasSize(0); - assertThat(chunk.getLength()).isEqualTo(0); - } - - @Test - public void testReadFromProto_whenOnlyHashSet_returnsChunkWithOnlyHash() throws Exception { - ProtoOutputStream out = new ProtoOutputStream(); - out.write(ChunksMetadataProto.Chunk.HASH, mChunkHashA.getHash()); - out.flush(); - byte[] protoBytes = out.getBytes(); - - Chunk chunk = - Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes))); - - assertThat(chunk.getHash()).isEqualTo(mChunkHashA.getHash()); - assertThat(chunk.getLength()).isEqualTo(0); - } - - @Test - public void testReadFromProto_whenOnlyLengthSet_returnsChunkWithOnlyLength() throws Exception { - ProtoOutputStream out = new ProtoOutputStream(); - out.write(ChunksMetadataProto.Chunk.LENGTH, CHUNK_A_LENGTH); - out.flush(); - byte[] protoBytes = out.getBytes(); - - Chunk chunk = - Chunk.readFromProto(new ProtoInputStream(new ByteArrayInputStream(protoBytes))); - - assertThat(chunk.getHash()).isEqualTo(new byte[] {}); - assertThat(chunk.getLength()).isEqualTo(CHUNK_A_LENGTH); - } - - private ChunkHash getHash(String name) { - return new ChunkHash( - Arrays.copyOf(name.getBytes(Charsets.UTF_8), ChunkHash.HASH_LENGTH_BYTES)); - } -} diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java index 634acdc42eaf..7e1fdedcac80 100644 --- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.mock; import android.platform.test.annotations.Presubmit; import com.android.server.backup.encryption.chunk.ChunkHash; -import com.android.server.backup.encryption.chunk.ChunksMetadataProto; +import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto; import org.junit.Before; import org.junit.Test; diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java index d231603e18b1..6f58ee148b83 100644 --- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.mock; import android.platform.test.annotations.Presubmit; import com.android.server.backup.encryption.chunk.ChunkHash; -import com.android.server.backup.encryption.chunk.ChunksMetadataProto; +import com.android.server.backup.encryption.protos.nano.ChunksMetadataProto; import org.junit.Before; import org.junit.Test; |