Provide correct version to associated data

This commit is contained in:
Torsten Grote 2021-03-04 17:23:08 -03:00 committed by Chirayu Desai
parent e7a8ad50e8
commit 0aee5cc2aa
4 changed files with 10 additions and 9 deletions

View file

@ -1,7 +1,7 @@
package org.calyxos.backup.storage.crypto package org.calyxos.backup.storage.crypto
import com.google.crypto.tink.subtle.AesGcmHkdfStreaming import com.google.crypto.tink.subtle.AesGcmHkdfStreaming
import org.calyxos.backup.storage.backup.Backup import org.calyxos.backup.storage.backup.Backup.Companion.VERSION
import org.calyxos.backup.storage.crypto.Hkdf.ALGORITHM_HMAC import org.calyxos.backup.storage.crypto.Hkdf.ALGORITHM_HMAC
import org.calyxos.backup.storage.crypto.Hkdf.KEY_SIZE_BYTES import org.calyxos.backup.storage.crypto.Hkdf.KEY_SIZE_BYTES
import org.calyxos.backup.storage.toByteArrayFromHex import org.calyxos.backup.storage.toByteArrayFromHex
@ -29,16 +29,16 @@ public object StreamCrypto {
outLengthBytes = KEY_SIZE_BYTES outLengthBytes = KEY_SIZE_BYTES
) )
internal fun getAssociatedDataForChunk(chunkId: String): ByteArray = internal fun getAssociatedDataForChunk(chunkId: String, version: Byte = VERSION): ByteArray =
ByteBuffer.allocate(2 + KEY_SIZE_BYTES) ByteBuffer.allocate(2 + KEY_SIZE_BYTES)
.put(Backup.VERSION) .put(version)
.put(TYPE_CHUNK) // type ID for chunks .put(TYPE_CHUNK) // type ID for chunks
.put(chunkId.toByteArrayFromHex().apply { check(size == KEY_SIZE_BYTES) }) .put(chunkId.toByteArrayFromHex().apply { check(size == KEY_SIZE_BYTES) })
.array() .array()
internal fun getAssociatedDataForSnapshot(timestamp: Long): ByteArray = internal fun getAssociatedDataForSnapshot(timestamp: Long, version: Byte = VERSION): ByteArray =
ByteBuffer.allocate(2 + 8) ByteBuffer.allocate(2 + 8)
.put(Backup.VERSION) .put(version)
.put(TYPE_SNAPSHOT) // type ID for chunks .put(TYPE_SNAPSHOT) // type ID for chunks
.put(timestamp.toByteArray()) .put(timestamp.toByteArray())
.array() .array()

View file

@ -16,8 +16,8 @@ internal class SnapshotRetriever(
@Throws(IOException::class, GeneralSecurityException::class) @Throws(IOException::class, GeneralSecurityException::class)
suspend fun getSnapshot(streamKey: ByteArray, timestamp: Long): BackupSnapshot { suspend fun getSnapshot(streamKey: ByteArray, timestamp: Long): BackupSnapshot {
return storagePlugin.getBackupSnapshotInputStream(timestamp).use { inputStream -> return storagePlugin.getBackupSnapshotInputStream(timestamp).use { inputStream ->
inputStream.readVersion() val version = inputStream.readVersion()
val ad = streamCrypto.getAssociatedDataForSnapshot(timestamp) val ad = streamCrypto.getAssociatedDataForSnapshot(timestamp, version.toByte())
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream -> streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
BackupSnapshot.parseFrom(decryptedStream) BackupSnapshot.parseFrom(decryptedStream)
} }

View file

@ -24,7 +24,7 @@ internal abstract class AbstractChunkRestore(
) { ) {
storagePlugin.getChunkInputStream(chunkId).use { inputStream -> storagePlugin.getChunkInputStream(chunkId).use { inputStream ->
inputStream.readVersion(version) inputStream.readVersion(version)
val ad = streamCrypto.getAssociatedDataForChunk(chunkId) val ad = streamCrypto.getAssociatedDataForChunk(chunkId, version.toByte())
streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream -> streamCrypto.newDecryptingStream(streamKey, inputStream, ad).use { decryptedStream ->
streamReader(decryptedStream) streamReader(decryptedStream)
} }

View file

@ -116,7 +116,7 @@ internal class Restore(
} }
@Throws(IOException::class, GeneralSecurityException::class) @Throws(IOException::class, GeneralSecurityException::class)
internal fun InputStream.readVersion(expectedVersion: Int? = null) { internal fun InputStream.readVersion(expectedVersion: Int? = null): Int {
val version = read() val version = read()
if (version == -1) throw IOException() if (version == -1) throw IOException()
if (expectedVersion != null && version != expectedVersion) { if (expectedVersion != null && version != expectedVersion) {
@ -126,4 +126,5 @@ internal fun InputStream.readVersion(expectedVersion: Int? = null) {
// TODO maybe throw a different exception here and tell the user? // TODO maybe throw a different exception here and tell the user?
throw IOException() throw IOException()
} }
return version
} }