diff options
Diffstat (limited to 'openpgp-ktx/src/main/java/org')
4 files changed, 633 insertions, 0 deletions
diff --git a/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpDecryptionResult.kt b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpDecryptionResult.kt new file mode 100644 index 00000000..0e294ba1 --- /dev/null +++ b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpDecryptionResult.kt @@ -0,0 +1,126 @@ +/* + * Copyright © 2019 The Android Password Authors. All Rights Reserved. + * SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception + */ +@file:JvmName("OpenPgpDecryptionResult") + +package org.openintents.openpgp + +import android.os.Parcel +import android.os.Parcelable +import android.os.Parcelable.Creator + +public class OpenPgpDecryptionResult() : Parcelable { + + private var result = 0 + private var sessionKey: ByteArray? = null + private var decryptedSessionKey: ByteArray? = null + + private constructor(result: Int) : this() { + this.result = result + sessionKey = null + decryptedSessionKey = null + } + + private constructor( + result: Int, + sessionKey: ByteArray?, + decryptedSessionKey: ByteArray? + ) : this() { + this.result = result + if (sessionKey == null != (decryptedSessionKey == null)) { + throw AssertionError("sessionkey must be null iff decryptedSessionKey is null") + } + this.sessionKey = sessionKey + this.decryptedSessionKey = decryptedSessionKey + } + + public fun getResult(): Int { + return result + } + + public fun hasDecryptedSessionKey(): Boolean { + return sessionKey != null + } + + public fun getSessionKey(): ByteArray? { + return if (sessionKey == null) { + null + } else sessionKey!!.copyOf(sessionKey!!.size) + } + + public fun getDecryptedSessionKey(): ByteArray? { + return if (sessionKey == null || decryptedSessionKey == null) { + null + } else decryptedSessionKey!!.copyOf(decryptedSessionKey!!.size) + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) { + /** + * NOTE: When adding fields in the process of updating this API, make sure to bump + * [.PARCELABLE_VERSION]. + */ + dest.writeInt(PARCELABLE_VERSION) + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + val sizePosition = dest.dataPosition() + dest.writeInt(0) + val startPosition = dest.dataPosition() + // version 1 + dest.writeInt(result) + // version 2 + dest.writeByteArray(sessionKey) + dest.writeByteArray(decryptedSessionKey) + // Go back and write the size + val parcelableSize = dest.dataPosition() - startPosition + dest.setDataPosition(sizePosition) + dest.writeInt(parcelableSize) + dest.setDataPosition(startPosition + parcelableSize) + } + + override fun toString(): String { + return "\nresult: $result" + } + + public companion object CREATOR : Creator<OpenPgpDecryptionResult> { + + /** + * Since there might be a case where new versions of the client using the library getting + * old versions of the protocol (and thus old versions of this class), we need a versioning + * system for the parcels sent between the clients and the providers. + */ + private const val PARCELABLE_VERSION = 2 + + // content not encrypted + public const val RESULT_NOT_ENCRYPTED: Int = -1 + + // insecure! + public const val RESULT_INSECURE: Int = 0 + + // encrypted + public const val RESULT_ENCRYPTED: Int = 1 + + override fun createFromParcel(source: Parcel): OpenPgpDecryptionResult? { + val version = source.readInt() // parcelableVersion + val parcelableSize = source.readInt() + val startPosition = source.dataPosition() + val result = source.readInt() + val sessionKey = if (version > 1) source.createByteArray() else null + val decryptedSessionKey = + if (version > 1) source.createByteArray() else null + val vr = + OpenPgpDecryptionResult(result, sessionKey, decryptedSessionKey) + // skip over all fields added in future versions of this parcel + source.setDataPosition(startPosition + parcelableSize) + return vr + } + + override fun newArray(size: Int): Array<OpenPgpDecryptionResult?> { + return arrayOfNulls(size) + } + } +} diff --git a/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpError.kt b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpError.kt new file mode 100644 index 00000000..7cef34aa --- /dev/null +++ b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpError.kt @@ -0,0 +1,91 @@ +/* + * Copyright © 2019 The Android Password Authors. All Rights Reserved. + * SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception + */ +@file:JvmName("OpenPgpError") + +package org.openintents.openpgp + +import android.os.Parcel +import android.os.Parcelable +import android.os.Parcelable.Creator + +public class OpenPgpError() : Parcelable { + + public var errorId: Int = 0 + public var message: String? = null + + private constructor(parcel: Parcel) : this() { + errorId = parcel.readInt() + message = parcel.readString() + } + + internal constructor(errorId: Int, message: String?) : this() { + this.errorId = errorId + this.message = message + } + + internal constructor(b: OpenPgpError) : this() { + errorId = b.errorId + message = b.message + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) { + /** + * NOTE: When adding fields in the process of updating this API, make sure to bump + * [PARCELABLE_VERSION]. + */ + dest.writeInt(PARCELABLE_VERSION) + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + val sizePosition = dest.dataPosition() + dest.writeInt(0) + val startPosition = dest.dataPosition() + // version 1 + dest.writeInt(errorId) + dest.writeString(message) + // Go back and write the size + val parcelableSize = dest.dataPosition() - startPosition + dest.setDataPosition(sizePosition) + dest.writeInt(parcelableSize) + dest.setDataPosition(startPosition + parcelableSize) + } + + public companion object CREATOR : Creator<OpenPgpError> { + + /** + * Since there might be a case where new versions of the client using the library getting + * old versions of the protocol (and thus old versions of this class), we need a versioning + * system for the parcels sent between the clients and the providers. + */ + private const val PARCELABLE_VERSION = 1 + + // possible values for errorId + public const val CLIENT_SIDE_ERROR: Int = -1 + public const val GENERIC_ERROR: Int = 0 + public const val INCOMPATIBLE_API_VERSIONS: Int = 1 + public const val NO_OR_WRONG_PASSPHRASE: Int = 2 + public const val NO_USER_IDS: Int = 3 + public const val OPPORTUNISTIC_MISSING_KEYS: Int = 4 + + override fun createFromParcel(source: Parcel): OpenPgpError? { + source.readInt() // parcelableVersion + val parcelableSize = source.readInt() + val startPosition = source.dataPosition() + val error = OpenPgpError() + error.errorId = source.readInt() + error.message = source.readString() + // skip over all fields added in future versions of this parcel + source.setDataPosition(startPosition + parcelableSize) + return error + } + + override fun newArray(size: Int): Array<OpenPgpError?> { + return arrayOfNulls(size) + } + } +} diff --git a/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpMetadata.kt b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpMetadata.kt new file mode 100644 index 00000000..65497e1f --- /dev/null +++ b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpMetadata.kt @@ -0,0 +1,122 @@ +/* + * Copyright © 2019 The Android Password Authors. All Rights Reserved. + * SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception + */ +@file:JvmName("OpenPgpMetadata") + +package org.openintents.openpgp + +import android.os.Parcel +import android.os.Parcelable +import android.os.Parcelable.Creator + +public class OpenPgpMetadata() : Parcelable { + + public var filename: String? = null + public var mimeType: String? = null + public var charset: String? = null + public var modificationTime: Long = 0 + public var originalSize: Long = 0 + + private constructor( + filename: String?, + mimeType: String?, + modificationTime: Long, + originalSize: Long, + charset: String? + ) : this() { + this.filename = filename + this.mimeType = mimeType + this.modificationTime = modificationTime + this.originalSize = originalSize + this.charset = charset + } + + private constructor( + filename: String?, + mimeType: String?, + modificationTime: Long, + originalSize: Long + ) : this() { + this.filename = filename + this.mimeType = mimeType + this.modificationTime = modificationTime + this.originalSize = originalSize + } + + private constructor(b: OpenPgpMetadata) : this() { + filename = b.filename + mimeType = b.mimeType + modificationTime = b.modificationTime + originalSize = b.originalSize + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) { + /** + * NOTE: When adding fields in the process of updating this API, make sure to bump + * [PARCELABLE_VERSION]. + */ + dest.writeInt(PARCELABLE_VERSION) + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + val sizePosition = dest.dataPosition() + dest.writeInt(0) + val startPosition = dest.dataPosition() + // version 1 + dest.writeString(filename) + dest.writeString(mimeType) + dest.writeLong(modificationTime) + dest.writeLong(originalSize) + // version 2 + dest.writeString(charset) + // Go back and write the size + val parcelableSize = dest.dataPosition() - startPosition + dest.setDataPosition(sizePosition) + dest.writeInt(parcelableSize) + dest.setDataPosition(startPosition + parcelableSize) + } + + public companion object CREATOR : Creator<OpenPgpMetadata> { + + /** + * Since there might be a case where new versions of the client using the library getting + * old versions of the protocol (and thus old versions of this class), we need a versioning + * system for the parcels sent between the clients and the providers. + */ + private const val PARCELABLE_VERSION = 2 + + override fun createFromParcel(source: Parcel): OpenPgpMetadata? { + val version = source.readInt() // parcelableVersion + val parcelableSize = source.readInt() + val startPosition = source.dataPosition() + val vr = OpenPgpMetadata() + vr.filename = source.readString() + vr.mimeType = source.readString() + vr.modificationTime = source.readLong() + vr.originalSize = source.readLong() + if (version >= 2) { + vr.charset = source.readString() + } + // skip over all fields added in future versions of this parcel + source.setDataPosition(startPosition + parcelableSize) + return vr + } + + override fun newArray(size: Int): Array<OpenPgpMetadata?> { + return arrayOfNulls(size) + } + } + + override fun toString(): String { + var out = "\nfilename: $filename" + out += "\nmimeType: $mimeType" + out += "\nmodificationTime: $modificationTime" + out += "\noriginalSize: $originalSize" + out += "\ncharset: $charset" + return out + } +} diff --git a/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.kt b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.kt new file mode 100644 index 00000000..e318ebe8 --- /dev/null +++ b/openpgp-ktx/src/main/java/org/openintents/openpgp/OpenPgpSignatureResult.kt @@ -0,0 +1,294 @@ +/* + * Copyright © 2019 The Android Password Authors. All Rights Reserved. + * SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception + */ +@file:JvmName("OpenPgpSignatureResult") + +package org.openintents.openpgp + +import android.os.Parcel +import android.os.Parcelable +import android.os.Parcelable.Creator +import java.util.Date +import me.msfjarvis.openpgpktx.util.OpenPgpUtils + +public class OpenPgpSignatureResult : Parcelable { + + private val result: Int + private val keyId: Long + private val primaryUserId: String? + private val userIds: ArrayList<String>? + private val confirmedUserIds: ArrayList<String>? + private val senderStatusResult: SenderStatusResult? + private val signatureTimestamp: Date? + private val autocryptPeerentityResult: AutocryptPeerResult? + + private constructor( + signatureStatus: Int, + signatureUserId: String?, + keyId: Long, + userIds: ArrayList<String>?, + confirmedUserIds: ArrayList<String>?, + senderStatusResult: SenderStatusResult?, + signatureOnly: Boolean?, + signatureTimestamp: Date?, + autocryptPeerentityResult: AutocryptPeerResult? + ) { + result = signatureStatus + primaryUserId = signatureUserId + this.keyId = keyId + this.userIds = userIds + this.confirmedUserIds = confirmedUserIds + this.senderStatusResult = senderStatusResult + this.signatureTimestamp = signatureTimestamp + this.autocryptPeerentityResult = autocryptPeerentityResult + } + + private constructor(source: Parcel, version: Int) { + result = source.readInt() + // we dropped support for signatureOnly, but need to skip the value for compatibility + source.readByte() + primaryUserId = source.readString() + keyId = source.readLong() + userIds = if (version > 1) { + source.createStringArrayList() + } else { + null + } + // backward compatibility for this exact version + if (version > 2) { + senderStatusResult = readEnumWithNullAndFallback( + source, + SenderStatusResult.values(), + SenderStatusResult.UNKNOWN + ) + confirmedUserIds = source.createStringArrayList() + } else { + senderStatusResult = SenderStatusResult.UNKNOWN + confirmedUserIds = null + } + signatureTimestamp = if (version > 3) { + if (source.readInt() > 0) Date(source.readLong()) else null + } else { + null + } + autocryptPeerentityResult = if (version > 4) { + readEnumWithNullAndFallback( + source, + AutocryptPeerResult.values(), + null + ) + } else { + null + } + } + + public fun getUserIds(): List<String> { + return (userIds ?: arrayListOf()).toList() + } + + public fun getConfirmedUserIds(): List<String> { + return (confirmedUserIds ?: arrayListOf()).toList() + } + + override fun describeContents(): Int { + return 0 + } + + override fun writeToParcel(dest: Parcel, flags: Int) { + /** + * NOTE: When adding fields in the process of updating this API, make sure to bump + * [.PARCELABLE_VERSION]. + */ + dest.writeInt(PARCELABLE_VERSION) + // Inject a placeholder that will store the parcel size from this point on + // (not including the size itself). + val sizePosition = dest.dataPosition() + dest.writeInt(0) + val startPosition = dest.dataPosition() + // version 1 + dest.writeInt(result) + // signatureOnly is deprecated since version 3. we pass a dummy value for compatibility + dest.writeByte(0.toByte()) + dest.writeString(primaryUserId) + dest.writeLong(keyId) + // version 2 + dest.writeStringList(userIds) + // version 3 + writeEnumWithNull(dest, senderStatusResult) + dest.writeStringList(confirmedUserIds) + // version 4 + if (signatureTimestamp != null) { + dest.writeInt(1) + dest.writeLong(signatureTimestamp.time) + } else { + dest.writeInt(0) + } + // version 5 + writeEnumWithNull(dest, autocryptPeerentityResult) + // Go back and write the size + val parcelableSize = dest.dataPosition() - startPosition + dest.setDataPosition(sizePosition) + dest.writeInt(parcelableSize) + dest.setDataPosition(startPosition + parcelableSize) + } + + override fun toString(): String { + var out = "\nresult: $result" + out += "\nprimaryUserId: $primaryUserId" + out += "\nuserIds: $userIds" + out += "\nkeyId: " + OpenPgpUtils.convertKeyIdToHex(keyId) + return out + } + + @Deprecated("") + public fun withSignatureOnlyFlag(signatureOnly: Boolean): OpenPgpSignatureResult { + return OpenPgpSignatureResult( + result, primaryUserId, keyId, userIds, confirmedUserIds, + senderStatusResult, signatureOnly, signatureTimestamp, autocryptPeerentityResult + ) + } + + public fun withAutocryptPeerResult(autocryptPeerentityResult: AutocryptPeerResult?): OpenPgpSignatureResult { + return OpenPgpSignatureResult( + result, primaryUserId, keyId, userIds, confirmedUserIds, + senderStatusResult, null, signatureTimestamp, autocryptPeerentityResult + ) + } + + public enum class SenderStatusResult { + UNKNOWN, USER_ID_CONFIRMED, USER_ID_UNCONFIRMED, USER_ID_MISSING; + } + + public enum class AutocryptPeerResult { + OK, NEW, MISMATCH; + } + + public companion object CREATOR : Creator<OpenPgpSignatureResult> { + + /** + * Since there might be a case where new versions of the client using the library getting + * old versions of the protocol (and thus old versions of this class), we need a versioning + * system for the parcels sent between the clients and the providers. + */ + private const val PARCELABLE_VERSION = 5 + + // content not signed + public const val RESULT_NO_SIGNATURE: Int = -1 + + // invalid signature! + public const val RESULT_INVALID_SIGNATURE: Int = 0 + + // successfully verified signature, with confirmed key + public const val RESULT_VALID_KEY_CONFIRMED: Int = 1 + + // no key was found for this signature verification + public const val RESULT_KEY_MISSING: Int = 2 + + // successfully verified signature, but with unconfirmed key + public const val RESULT_VALID_KEY_UNCONFIRMED: Int = 3 + + // key has been revoked -> invalid signature! + public const val RESULT_INVALID_KEY_REVOKED: Int = 4 + + // key is expired -> invalid signature! + public const val RESULT_INVALID_KEY_EXPIRED: Int = 5 + + // insecure cryptographic algorithms/protocol -> invalid signature! + public const val RESULT_INVALID_KEY_INSECURE: Int = 6 + + override fun createFromParcel(source: Parcel): OpenPgpSignatureResult? { + val version = source.readInt() // parcelableVersion + val parcelableSize = source.readInt() + val startPosition = source.dataPosition() + val vr = OpenPgpSignatureResult(source, version) + // skip over all fields added in future versions of this parcel + source.setDataPosition(startPosition + parcelableSize) + return vr + } + + override fun newArray(size: Int): Array<OpenPgpSignatureResult?> { + return arrayOfNulls(size) + } + + public fun createWithValidSignature( + signatureStatus: Int, + primaryUserId: String?, + keyId: Long, + userIds: ArrayList<String>?, + confirmedUserIds: ArrayList<String>?, + senderStatusResult: SenderStatusResult?, + signatureTimestamp: Date? + ): OpenPgpSignatureResult { + require(!(signatureStatus == RESULT_NO_SIGNATURE || signatureStatus == RESULT_KEY_MISSING || signatureStatus == RESULT_INVALID_SIGNATURE)) { "can only use this method for valid types of signatures" } + return OpenPgpSignatureResult( + signatureStatus, primaryUserId, keyId, userIds, confirmedUserIds, + senderStatusResult, null, signatureTimestamp, null + ) + } + + public fun createWithNoSignature(): OpenPgpSignatureResult { + return OpenPgpSignatureResult( + RESULT_NO_SIGNATURE, + null, + 0L, + null, + null, + null, + null, + null, + null + ) + } + + public fun createWithKeyMissing(keyId: Long, signatureTimestamp: Date?): OpenPgpSignatureResult { + return OpenPgpSignatureResult( + RESULT_KEY_MISSING, + null, + keyId, + null, + null, + null, + null, + signatureTimestamp, + null + ) + } + + public fun createWithInvalidSignature(): OpenPgpSignatureResult { + return OpenPgpSignatureResult( + RESULT_INVALID_SIGNATURE, + null, + 0L, + null, + null, + null, + null, + null, + null + ) + } + + private fun <T : Enum<T>?> readEnumWithNullAndFallback( + source: Parcel, + enumValues: Array<T>, + fallback: T? + ): T? { + val valueOrdinal = source.readInt() + if (valueOrdinal == -1) { + return null + } + return if (valueOrdinal >= enumValues.size) { + fallback + } else enumValues[valueOrdinal] + } + + private fun writeEnumWithNull(dest: Parcel, enumValue: Enum<*>?) { + if (enumValue == null) { + dest.writeInt(-1) + return + } + dest.writeInt(enumValue.ordinal) + } + } +} |
