1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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;
}
|