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

Commit 572df9ff authored by Al Sutton's avatar Al Sutton
Browse files

Move chunk proto definitions into the BackupEncrypter APK

Bug: 111386661
Test: make RunBackupEncryptionRoboTests
Change-Id: I3032210e6eec52b0c925baab770a4578ac7ecbf7
parent 9f8672db
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -15,8 +15,10 @@
 */

syntax = "proto2";
package com.android.server.backup.encryption.chunk;

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
+0 −70
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+0 −109
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -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;

+1 −1
Original line number Diff line number Diff line
@@ -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;

Loading