Skip to content

Commit

Permalink
Auto-format code style of all files to match official style
Browse files Browse the repository at this point in the history
This also adds a note to the README
and the Android Studio coding style files.
  • Loading branch information
grote authored and chirayudesai committed Oct 7, 2020
1 parent 55909ce commit 53937bd
Show file tree
Hide file tree
Showing 72 changed files with 1,781 additions and 1,171 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ out/
lib/
.idea/*
!.idea/runConfigurations*
!.idea/codeStyles*
*.ipr
*.iws
*.iml
Expand Down
139 changes: 139 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ It uses the same internal APIs as `adb backup` which is deprecated and thus need
* `android.permission.INSTALL_PACKAGES` to re-install apps when restoring from backup.

## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/stevesoltys/seedvault.
Bug reports and pull requests are welcome on GitHub at https://github.com/stevesoltys/seedvault.

This project aims to adhere to the [official Kotlin coding style](https://developer.android.com/kotlin/style-guide).

## License
This application is available as open source under the terms of the [Apache-2.0 License](https://opensource.org/licenses/Apache-2.0).
2 changes: 1 addition & 1 deletion app/src/main/java/com/stevesoltys/seedvault/Base64Utils.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.stevesoltys.seedvault

import java.nio.charset.Charset
import java.util.*
import java.util.Base64

val Utf8: Charset = Charset.forName("UTF-8")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import java.util.concurrent.TimeUnit.HOURS

private val TAG = UsbIntentReceiver::class.java.simpleName

private const val HOURS_AUTO_BACKUP: Long = 24

class UsbIntentReceiver : UsbMonitor() {

// using KoinComponent would crash robolectric tests :(
Expand All @@ -37,7 +39,8 @@ class UsbIntentReceiver : UsbMonitor() {
val attachedFlashDrive = FlashDrive.from(device)
return if (savedFlashDrive == attachedFlashDrive) {
Log.d(TAG, "Matches stored device, checking backup time...")
if (System.currentTimeMillis() - metadataManager.getLastBackupTime() >= HOURS.toMillis(24)) {
val backupMillis = System.currentTimeMillis() - metadataManager.getLastBackupTime()
if (backupMillis >= HOURS.toMillis(HOURS_AUTO_BACKUP)) {
Log.d(TAG, "Last backup older than 24 hours, requesting a backup...")
true
} else {
Expand Down Expand Up @@ -101,6 +104,7 @@ internal fun UsbDevice.isMassStorage(): Boolean {
}

private fun UsbInterface.isMassStorage(): Boolean {
@Suppress("MagicNumber")
return interfaceClass == 8 && interfaceProtocol == 80 && interfaceSubclass == 6
}

Expand Down
33 changes: 24 additions & 9 deletions app/src/main/java/com/stevesoltys/seedvault/crypto/Crypto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,12 @@ interface Crypto {
* @return The read [VersionHeader] present in the beginning of the given [InputStream].
*/
@Throws(IOException::class, SecurityException::class)
fun decryptHeader(inputStream: InputStream, expectedVersion: Byte, expectedPackageName: String,
expectedKey: String? = null): VersionHeader
fun decryptHeader(
inputStream: InputStream,
expectedVersion: Byte,
expectedPackageName: String,
expectedKey: String? = null
): VersionHeader

/**
* Reads and decrypts a segment from the given [InputStream].
Expand All @@ -94,9 +98,10 @@ interface Crypto {
}

internal class CryptoImpl(
private val cipherFactory: CipherFactory,
private val headerWriter: HeaderWriter,
private val headerReader: HeaderReader) : Crypto {
private val cipherFactory: CipherFactory,
private val headerWriter: HeaderWriter,
private val headerReader: HeaderReader
) : Crypto {

@Throws(IOException::class)
override fun encryptHeader(outputStream: OutputStream, versionHeader: VersionHeader) {
Expand Down Expand Up @@ -136,16 +141,26 @@ internal class CryptoImpl(
}

@Throws(IOException::class, SecurityException::class)
override fun decryptHeader(inputStream: InputStream, expectedVersion: Byte,
expectedPackageName: String, expectedKey: String?): VersionHeader {
override fun decryptHeader(
inputStream: InputStream,
expectedVersion: Byte,
expectedPackageName: String,
expectedKey: String?
): VersionHeader {
val decrypted = decryptSegment(inputStream, MAX_VERSION_HEADER_SIZE)
val header = headerReader.getVersionHeader(decrypted)

if (header.version != expectedVersion) {
throw SecurityException("Invalid version '${header.version.toInt()}' in header, expected '${expectedVersion.toInt()}'.")
throw SecurityException(
"Invalid version '${header.version.toInt()}' in header, " +
"expected '${expectedVersion.toInt()}'."
)
}
if (header.packageName != expectedPackageName) {
throw SecurityException("Invalid package name '${header.packageName}' in header, expected '$expectedPackageName'.")
throw SecurityException(
"Invalid package name '${header.packageName}' in header, " +
"expected '$expectedPackageName'."
)
}
if (header.key != expectedKey) {
throw SecurityException("Invalid key '${header.key}' in header, expected '$expectedKey'.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ internal class KeyManagerImpl : KeyManager {
}

override fun hasBackupKey() = keyStore.containsAlias(KEY_ALIAS) &&
keyStore.entryInstanceOf(KEY_ALIAS, SecretKeyEntry::class.java)
keyStore.entryInstanceOf(KEY_ALIAS, SecretKeyEntry::class.java)

override fun getBackupKey(): SecretKey {
val ksEntry = keyStore.getEntry(KEY_ALIAS, null) as SecretKeyEntry
Expand All @@ -63,9 +63,9 @@ internal class KeyManagerImpl : KeyManager {

private fun getKeyProtection(): KeyProtection {
val builder = KeyProtection.Builder(PURPOSE_ENCRYPT or PURPOSE_DECRYPT)
.setBlockModes(BLOCK_MODE_GCM)
.setEncryptionPaddings(ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(true)
.setBlockModes(BLOCK_MODE_GCM)
.setEncryptionPaddings(ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(true)
// unlocking is required only for decryption, so when restoring from backup
builder.setUnlockedDeviceRequired(true)
return builder.build()
Expand Down
17 changes: 9 additions & 8 deletions app/src/main/java/com/stevesoltys/seedvault/header/Header.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import com.stevesoltys.seedvault.crypto.GCM_AUTHENTICATION_TAG_LENGTH
internal const val VERSION: Byte = 0
internal const val MAX_PACKAGE_LENGTH_SIZE = 255
internal const val MAX_KEY_LENGTH_SIZE = MAX_PACKAGE_LENGTH_SIZE
internal const val MAX_VERSION_HEADER_SIZE = 1 + Short.SIZE_BYTES * 2 + MAX_PACKAGE_LENGTH_SIZE + MAX_KEY_LENGTH_SIZE
internal const val MAX_VERSION_HEADER_SIZE =
1 + Short.SIZE_BYTES * 2 + MAX_PACKAGE_LENGTH_SIZE + MAX_KEY_LENGTH_SIZE

/**
* After the first version byte of each backup stream
* must follow followed this header encrypted with authentication.
*/
data class VersionHeader(
internal val version: Byte = VERSION, // 1 byte
internal val packageName: String, // ?? bytes (max 255)
internal val key: String? = null // ?? bytes
internal val version: Byte = VERSION, // 1 byte
internal val packageName: String, // ?? bytes (max 255)
internal val key: String? = null // ?? bytes
) {
init {
check(packageName.length <= MAX_PACKAGE_LENGTH_SIZE) {
Expand All @@ -26,19 +27,19 @@ data class VersionHeader(
}
}


internal const val SEGMENT_LENGTH_SIZE: Int = Short.SIZE_BYTES
internal const val MAX_SEGMENT_LENGTH: Int = Short.MAX_VALUE.toInt()
internal const val MAX_SEGMENT_CLEARTEXT_LENGTH: Int = MAX_SEGMENT_LENGTH - GCM_AUTHENTICATION_TAG_LENGTH / 8
internal const val MAX_SEGMENT_CLEARTEXT_LENGTH: Int =
MAX_SEGMENT_LENGTH - GCM_AUTHENTICATION_TAG_LENGTH / 8
internal const val IV_SIZE: Int = 12
internal const val SEGMENT_HEADER_SIZE = SEGMENT_LENGTH_SIZE + IV_SIZE

/**
* Each data segment must start with this header
*/
class SegmentHeader(
internal val segmentLength: Short, // 2 bytes
internal val nonce: ByteArray // 12 bytes
internal val segmentLength: Short, // 2 bytes
internal val nonce: ByteArray // 12 bytes
) {
init {
check(nonce.size == IV_SIZE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ internal class HeaderReaderImpl : HeaderReader {
if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException("Too large package length: $packageLength")
if (packageLength > buffer.remaining()) throw SecurityException("Not enough bytes for package name")
val packageName = ByteArray(packageLength)
.apply { buffer.get(this) }
.toString(Utf8)
.apply { buffer.get(this) }
.toString(Utf8)

val keyLength = buffer.short.toInt()
if (keyLength < 0) throw SecurityException("Invalid key length: $keyLength")
if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException("Too large key length: $keyLength")
if (keyLength > buffer.remaining()) throw SecurityException("Not enough bytes for key")
val key = if (keyLength == 0) null else ByteArray(keyLength)
.apply { buffer.get(this) }
.toString(Utf8)
.apply { buffer.get(this) }
.toString(Utf8)

if (buffer.remaining() != 0) throw SecurityException("Found extra bytes in header")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ internal class HeaderWriterImpl : HeaderWriter {

override fun writeSegmentHeader(outputStream: OutputStream, header: SegmentHeader) {
val buffer = ByteBuffer.allocate(SEGMENT_HEADER_SIZE)
.putShort(header.segmentLength)
.put(header.nonce)
.putShort(header.segmentLength)
.put(header.nonce)
outputStream.write(buffer.array())
}

Expand Down
Loading

0 comments on commit 53937bd

Please sign in to comment.