Skip to content
Merged

E2ee21 #3950

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Nextcloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -6143,7 +6143,7 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/nextcloud/NextcloudKit";
requirement = {
branch = "declarative-ui";
branch = main;
kind = branch;
};
};
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Data/NCManageDatabase+E2EE.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class tableE2eMetadataV2: Object {
@Persisted var keyChecksums = List<String>()
@Persisted var ocIdServerUrl: String = ""
@Persisted var serverUrl: String = ""
@Persisted var version: String = NCGlobal.shared.e2eeVersionV20
@Persisted var version: String = "2.0"

convenience init(account: String, ocIdServerUrl: String) {
self.init()
Expand Down
14 changes: 4 additions & 10 deletions iOSClient/Files/NCFiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,7 @@ class NCFiles: NCCollectionViewCommon {
}
} else {
// show error
Task {
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}

return(metadatas, error, reloadRequired)
Expand All @@ -338,25 +336,21 @@ class NCFiles: NCCollectionViewCommon {

if errorDecodeMetadata == .success {
let capabilities = await NKCapabilities.shared.getCapabilities(for: self.session.account)
if version == "v1", capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if version == "v1", NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
NCContentPresenter().showInfo(description: "Conversion metadata v1 to v2 required, please wait...")
nkLog(tag: self.global.logTagE2EE, message: "Conversion v1 to v2")
NCActivityIndicator.shared.start()

let error = await NCNetworkingE2EE().uploadMetadata(serverUrl: serverUrl, updateVersionV1V2: true, account: account)
if error != .success {
Task {
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}
NCActivityIndicator.shared.stop()
}
} else {
// Client Diagnostic
await self.database.addDiagnosticAsync(account: account, issue: NCGlobal.shared.diagnosticIssueE2eeErrors)
Task {
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}
await showErrorBanner(controller: self.controller, errorDescription: error.errorDescription)
}

return (metadatas, error, reloadRequired)
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Menu/NCShare+Menu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ extension NCShare {
sender: sender,
action: { _ in
Task {
if share.shareType != NKShare.ShareType.publicLink.rawValue, let metadata = self.metadata, metadata.e2eEncrypted && capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if share.shareType != NKShare.ShareType.publicLink.rawValue, let metadata = self.metadata, metadata.e2eEncrypted && NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
if await NCNetworkingE2EE().isInUpload(account: metadata.account, serverUrl: metadata.serverUrlFileName) {
let error = NKError(errorCode: NCGlobal.shared.errorE2EEUploadInProgress, errorDescription: NSLocalizedString("_e2e_in_upload_", comment: ""))
return NCContentPresenter().showInfo(error: error)
Expand Down
12 changes: 8 additions & 4 deletions iOSClient/NCGlobal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,14 @@ final class NCGlobal: Sendable {
// E2EE
//
let e2eePassphraseTest = "more over television factory tendency independence international intellectual impress interest sentence pony"
let e2eeVersions = ["1.1", "1.2", "2.0"]
let e2eeVersionV11 = "1.1"
let e2eeVersionV12 = "1.2"
let e2eeVersionV20 = "2.0"
let e2eeCompatibleVersions = ["1.1", "1.2", "2.0", "2.1"]

func isE2eeVersion2(_ version: String) -> Bool {
if version == "2.0" || version == "2.1" {
return true
}
return false
}

// CHUNK
let chunkSizeMBCellular = 10000000
Expand Down
10 changes: 5 additions & 5 deletions iOSClient/Networking/E2EE/NCEndToEndMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class NCEndToEndMetadata: NSObject {
}
let capabilities = await NKCapabilities.shared.getCapabilities(for: session.account)

if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 && NCGlobal.shared.e2eeVersions.contains(NCGlobal.shared.e2eeVersionV12) {
if capabilities.e2EEApiVersion == "1.2" {
return await encodeMetadataV12(account: session.account, serverUrl: serverUrl, ocIdServerUrl: directory.ocId)
} else if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 && NCGlobal.shared.e2eeVersions.contains(NCGlobal.shared.e2eeVersionV20) {
} else if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
return await encodeMetadataV20(serverUrl: serverUrl, ocIdServerUrl: directory.ocId, addUserId: addUserId, addCertificate: addCertificate, removeUserId: removeUserId, session: session)
} else {
return (nil, nil, 0, NKError(errorCode: NCGlobal.shared.errorE2EEVersion, errorDescription: "Server E2EE version " + capabilities.e2EEApiVersion + ", not compatible"))
Expand All @@ -40,11 +40,11 @@ class NCEndToEndMetadata: NSObject {

data.printJson()

if (try? JSONDecoder().decode(E2eeV1.self, from: data)) != nil && NCGlobal.shared.e2eeVersions.contains(NCGlobal.shared.e2eeVersionV11) {
if (try? JSONDecoder().decode(E2eeV1.self, from: data)) != nil {
return await decodeMetadataV1(metadata, serverUrl: serverUrl, ocIdServerUrl: directory.ocId, session: session)
} else if (try? JSONDecoder().decode(E2eeV12.self, from: data)) != nil && NCGlobal.shared.e2eeVersions.contains(NCGlobal.shared.e2eeVersionV12) {
} else if (try? JSONDecoder().decode(E2eeV12.self, from: data)) != nil {
return await decodeMetadataV12(metadata, serverUrl: serverUrl, ocIdServerUrl: directory.ocId, session: session)
} else if (try? JSONDecoder().decode(E2eeV20.self, from: data)) != nil && NCGlobal.shared.e2eeVersions.contains(NCGlobal.shared.e2eeVersionV20) {
} else if (try? JSONDecoder().decode(E2eeV20.self, from: data)) != nil {
return await decodeMetadataV20(metadata, signature: signature, serverUrl: serverUrl, ocIdServerUrl: directory.ocId, session: session)
} else {
return NKError(errorCode: NCGlobal.shared.errorE2EEVersion, errorDescription: "Unable to decode the metadata file")
Expand Down
8 changes: 4 additions & 4 deletions iOSClient/Networking/E2EE/NCEndToEndMetadataV20.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,12 @@
ciphertextMetadata = ciphertextMetadata + "|" + initializationVector

let metadataCodable = E2eeV20.Metadata(ciphertext: ciphertextMetadata, nonce: initializationVector, authenticationTag: authenticationTag)
let e2eeCodable = E2eeV20(metadata: metadataCodable, users: usersCodable, filedrop: nil, version: NCGlobal.shared.e2eeVersionV20)
let e2eeCodable = E2eeV20(metadata: metadataCodable, users: usersCodable, filedrop: nil, version: "2.0")
let e2eeData = try JSONEncoder().encode(e2eeCodable)
e2eeData.printJson()

let e2eeJson = String(data: e2eeData, encoding: .utf8)
let signature = createSignature(metadata: metadataCodable, users: usersCodable, version: NCGlobal.shared.e2eeVersionV20, certificate: certificate, session: session)
let signature = createSignature(metadata: metadataCodable, users: usersCodable, version: "2.0", certificate: certificate, session: session)

return (e2eeJson, signature, counter, NKError())

Expand Down Expand Up @@ -226,7 +226,7 @@
object.metadataKey = metadataKey
object.mimeType = mimetype
object.serverUrl = serverUrl
object.version = NCGlobal.shared.e2eeVersionV20
object.version = "2.0"

// Write file parameter for decrypted on DB
await self.database.addE2eEncryptionAsync(object)
Expand All @@ -250,7 +250,7 @@
let metadata = json.metadata
let users = json.users
let filesdrop = json.filedrop
let version = json.version as String? ?? NCGlobal.shared.e2eeVersionV20
let version = json.version as String? ?? "2.0"

if isDirectoryTop {

Expand Down Expand Up @@ -281,7 +281,7 @@

// SIGNATURE CHECK
//
// TODO: if null exit with error

Check warning on line 284 in iOSClient/Networking/E2EE/NCEndToEndMetadataV20.swift

View workflow job for this annotation

GitHub Actions / Lint

Todo Violation: TODOs should be resolved (if null exit with error) (todo)
if let signature, !signature.isEmpty {
if !verifySignature(account: session.account, signature: signature, userId: tableUser.userId, metadata: metadata, users: users, version: version, certificate: tableUser.certificate) {
nkLog(tag: global.logTagE2EE, message: "Error verify signature")
Expand Down Expand Up @@ -330,7 +330,7 @@

// CHECKSUM CHECK
//
// TODO: if null exit with error

Check warning on line 333 in iOSClient/Networking/E2EE/NCEndToEndMetadataV20.swift

View workflow job for this annotation

GitHub Actions / Lint

Todo Violation: TODOs should be resolved (if null exit with error) (todo)
if let keyChecksums = jsonCiphertextMetadata.keyChecksums, !keyChecksums.isEmpty {
guard let hash = NCEndToEndEncryption.shared().createSHA256(decryptedMetadataKey),
keyChecksums.contains(hash) else {
Expand All @@ -347,7 +347,7 @@
if let resultCounter = await self.database.getCounterE2eMetadataAsync(account: session.account, ocIdServerUrl: ocIdServerUrl) {
nkLog(tag: global.logTagE2EE, message: "COUNTER CHECK: counter saved \(resultCounter), counter UPDATED: \(jsonCiphertextMetadata.counter)")
await self.database.updateCounterE2eMetadataAsync(account: session.account, ocIdServerUrl: ocIdServerUrl, counter: jsonCiphertextMetadata.counter)
// TODO: whats happen with < ?

Check warning on line 350 in iOSClient/Networking/E2EE/NCEndToEndMetadataV20.swift

View workflow job for this annotation

GitHub Actions / Lint

Todo Violation: TODOs should be resolved (whats happen with < ?) (todo)
/*
if jsonCiphertextMetadata.counter < resultCounter {
//NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EECounter, errorDescription: NSLocalizedString("_e2e_error_", comment: "")))
Expand All @@ -364,7 +364,7 @@
// DELETE CHECK
//
if let deleted = jsonCiphertextMetadata.deleted, deleted {
// TODO: We need to check deleted, id yes ???

Check warning on line 367 in iOSClient/Networking/E2EE/NCEndToEndMetadataV20.swift

View workflow job for this annotation

GitHub Actions / Lint

Todo Violation: TODOs should be resolved (We need to check deleted, id y...) (todo)
}

await self.database.addE2eMetadataAsync(account: session.account,
Expand Down
13 changes: 8 additions & 5 deletions iOSClient/Networking/E2EE/NCNetworkingE2EE.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ class NCNetworkingE2EE: NSObject {
}

func getOptions(account: String, capabilities: NKCapabilities.Capabilities) -> NKRequestOptions {
let version = capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 ? e2EEApiVersion2 : e2EEApiVersion1
var version = e2EEApiVersion1
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
version = e2EEApiVersion2
}
return NKRequestOptions(version: version)
}

Expand All @@ -44,7 +47,7 @@ class NCNetworkingE2EE: NSObject {
let capabilities = await NKCapabilities.shared.getCapabilities(for: account)

switch capabilities.e2EEApiVersion {
case NCGlobal.shared.e2eeVersionV11, NCGlobal.shared.e2eeVersionV12:
case "1.1", "1.2":
let options = NKRequestOptions(version: e2EEApiVersion1)
let results = await NextcloudKit.shared.getE2EEMetadataAsync(fileId: fileId, e2eToken: e2eToken, account: account, options: options) { task in
Task {
Expand All @@ -55,7 +58,7 @@ class NCNetworkingE2EE: NSObject {
}
}
return (results.account, self.e2EEApiVersion1, results.e2eMetadata, results.signature, results.responseData, results.error)
case NCGlobal.shared.e2eeVersionV20:
case "2.0", "2.1":
var options = NKRequestOptions(version: e2EEApiVersion2)
let results = await NextcloudKit.shared.getE2EEMetadataAsync(fileId: fileId, e2eToken: e2eToken, account: account, options: options) { task in
Task {
Expand Down Expand Up @@ -204,7 +207,7 @@ class NCNetworkingE2EE: NSObject {

// COUNTER
//
if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
await self.database.updateCounterE2eMetadataAsync(account: session.account, ocIdServerUrl: ocIdServerUrl, counter: resultsEncodeMetadata.counter)
}

Expand Down Expand Up @@ -247,7 +250,7 @@ class NCNetworkingE2EE: NSObject {
e2eToken = tableLock.e2eToken
}

if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20,
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion),
var counter = await self.database.getCounterE2eMetadataAsync(account: account, ocIdServerUrl: directory.ocId) {
counter += 1
e2eCounter = "\(counter)"
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Networking/E2EE/NCNetworkingE2EEMarkFolder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class NCNetworkingE2EEMarkFolder: NSObject {
await self.database.createDirectory(metadata: metadata)

await self.database.deleteE2eEncryptionAsync(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", metadata.account, serverUrlFileName))
if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
await self.database.updateCounterE2eMetadataAsync(account: account, ocIdServerUrl: metadata.ocId, counter: 0)
}

Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Settings/E2EE/NCManageE2EEModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class NCManageE2EE: NSObject, ObservableObject, ViewOnAppearHandling, NCEndToEnd

/// Triggered when the view appears.
func onViewAppear() {
if capabilities.e2EEEnabled && NCGlobal.shared.e2eeVersions.contains(capabilities.e2EEApiVersion) {
if capabilities.e2EEEnabled && NCGlobal.shared.e2eeCompatibleVersions.contains(capabilities.e2EEApiVersion) {
isEndToEndEnabled = NCPreferences().isEndToEndEnabled(account: session.account)
if isEndToEndEnabled {
statusOfService = NSLocalizedString("_status_e2ee_configured_", comment: "")
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Settings/NCPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ final class NCPreferences: NSObject {
let publicKey = getEndToEndPublicKey(account: account), !publicKey.isEmpty,
let privateKey = getEndToEndPrivateKey(account: account), !privateKey.isEmpty,
let passphrase = getEndToEndPassphrase(account: account), !passphrase.isEmpty,
NCGlobal.shared.e2eeVersions.contains(capabilities.e2EEApiVersion) else {
NCGlobal.shared.e2eeCompatibleVersions.contains(capabilities.e2EEApiVersion) else {
return false
}
return true
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Settings/Settings/NCSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ struct NCSettingsView: View {
Text(NSLocalizedString("_users_footer_", comment: ""))
})
// E2EEncryption` Section
if capabilities.e2EEEnabled && NCGlobal.shared.e2eeVersions.contains(capabilities.e2EEApiVersion) {
if capabilities.e2EEEnabled && NCGlobal.shared.e2eeCompatibleVersions.contains(capabilities.e2EEApiVersion) {
E2EESection(model: model)
}
// `Advanced` Section
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Share/Advanced/NCShareAdvancePermission.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ class NCShareAdvancePermission: UITableViewController, NCShareAdvanceFotterDeleg
let capabilities = await NKCapabilities.shared.getCapabilities(for: metadata.account)

if share.shareType != NKShare.ShareType.publicLink.rawValue, metadata.e2eEncrypted,
capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {

if await NCNetworkingE2EE().isInUpload(account: metadata.account, serverUrl: metadata.serverUrlFileName) {
let error = NKError(errorCode: NCGlobal.shared.errorE2EEUploadInProgress, errorDescription: NSLocalizedString("_e2e_in_upload_", comment: ""))
Expand Down
4 changes: 2 additions & 2 deletions iOSClient/Share/Advanced/NCShareCells.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ enum NCUserPermission: CaseIterable, NCPermission {

static func forDirectoryE2EE(account: String) -> [NCPermission] {
let capabilities = NCNetworking.shared.capabilities[account] ?? NKCapabilities.Capabilities()
if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
return NCUserPermission.allCases
}
return []
Expand All @@ -107,7 +107,7 @@ enum NCUserPermission: CaseIterable, NCPermission {
enum NCLinkEmailPermission: CaseIterable, NCPermission {
static func forDirectoryE2EE(account: String) -> [any NCPermission] {
let capabilities = NCNetworking.shared.capabilities[account] ?? NKCapabilities.Capabilities()
if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 {
if NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) {
return NCUserPermission.allCases
}
return []
Expand Down
8 changes: 4 additions & 4 deletions iOSClient/Share/NCShare.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ class NCShare: UIViewController, NCSharePagingContent {
self.capabilities = await NKCapabilities.shared.getCapabilities(for: metadata.account)
if metadata.e2eEncrypted {
let metadataDirectory = await self.database.getMetadataDirectoryAsync(serverUrl: metadata.serverUrl, account: metadata.account)
if capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 ||
(capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV20 && metadataDirectory?.e2eEncrypted ?? false) {
if capabilities.e2EEApiVersion == "1.2" ||
(NCGlobal.shared.isE2eeVersion2(capabilities.e2EEApiVersion) && metadataDirectory?.e2eEncrypted ?? false) {
searchFieldTopConstraint.constant = -50
searchField.alpha = 0
btnContact.alpha = 0
Expand Down Expand Up @@ -341,7 +341,7 @@ extension NCShare: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numRows = shares.share?.count ?? 0
if section == 0 {
if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 {
if metadata.e2eEncrypted, capabilities.e2EEApiVersion == "1.2" {
numRows = 1
} else {
// don't allow link creation if reshare is disabled
Expand All @@ -357,7 +357,7 @@ extension NCShare: UITableViewDataSource {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cellLink", for: indexPath) as? NCShareLinkCell
else { return UITableViewCell() }
cell.delegate = self
if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 {
if metadata.e2eEncrypted, capabilities.e2EEApiVersion == "1.2" {
cell.tableShare = shares.firstShareLink
} else {
if indexPath.row == 0 {
Expand Down
2 changes: 1 addition & 1 deletion iOSClient/Share/TransientShare.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class TransientShare: Shareable {
private init(shareType: Int, metadata: tableMetadata, password: String?) {
let capabilities = NCNetworking.shared.capabilities[metadata.account] ?? NKCapabilities.Capabilities()

if metadata.e2eEncrypted, capabilities.e2EEApiVersion == NCGlobal.shared.e2eeVersionV12 {
if metadata.e2eEncrypted, capabilities.e2EEApiVersion == "1.2" {
self.permissions = NKShare.Permission.create.rawValue
} else {
self.permissions = capabilities.fileSharingDefaultPermission & metadata.sharePermissionsCollaborationServices
Expand Down
Loading