/* * 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; }