diff --git a/NearDrop.xcodeproj/project.pbxproj b/NearDrop.xcodeproj/project.pbxproj index 689ca50..155e76b 100644 --- a/NearDrop.xcodeproj/project.pbxproj +++ b/NearDrop.xcodeproj/project.pbxproj @@ -662,7 +662,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -688,7 +688,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 2.0.2; PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -749,7 +749,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -804,7 +804,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -823,7 +823,7 @@ CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 7; + CURRENT_PROJECT_VERSION = 8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSUIElement = YES; @@ -834,8 +834,8 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 2.0.3; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MARKETING_VERSION = 2.0.4; PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -855,7 +855,7 @@ CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 7; + CURRENT_PROJECT_VERSION = 8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSUIElement = YES; @@ -866,8 +866,8 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 2.0.3; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MARKETING_VERSION = 2.0.4; PRODUCT_BUNDLE_IDENTIFIER = me.grishka.NearDrop; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -885,7 +885,7 @@ DYLIB_INSTALL_NAME_BASE = "@executable_path/../Frameworks"; EXECUTABLE_PREFIX = lib; LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; @@ -901,7 +901,7 @@ DYLIB_INSTALL_NAME_BASE = "@executable_path/../Frameworks"; EXECUTABLE_PREFIX = lib; LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)"; - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 10.15; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; diff --git a/NearDrop/AppDelegate.swift b/NearDrop/AppDelegate.swift index b327fef..6f52c20 100644 --- a/NearDrop/AppDelegate.swift +++ b/NearDrop/AppDelegate.swift @@ -34,7 +34,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele } } nc.delegate=self - let incomingTransfersCategory=NDNotificationCenterHackery.hackedNotificationCategory() + let incomingTransfersCategory=UNNotificationCategory(identifier: "INCOMING_TRANSFERS", actions: [ + UNNotificationAction(identifier: "ACCEPT", title: NSLocalizedString("Accept", comment: ""), options: UNNotificationActionOptions.authenticationRequired), + UNNotificationAction(identifier: "DECLINE", title: NSLocalizedString("Decline", comment: "")) + ], intentIdentifiers: []) let errorsCategory=UNNotificationCategory(identifier: "ERRORS", actions: [], intentIdentifiers: []) nc.setNotificationCategories([incomingTransfersCategory, errorsCategory]) NearbyConnectionManager.shared.mainAppDelegate=self @@ -79,9 +82,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele } func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo) { - let notificationContent=UNMutableNotificationContent() - notificationContent.title="NearDrop" - notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!]) let fileStr:String if let textTitle=transfer.textDescription{ fileStr=textTitle @@ -90,14 +90,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele }else{ fileStr=String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count) } + let notificationContent=UNMutableNotificationContent() + notificationContent.title="NearDrop" + notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!]) notificationContent.body=String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr]) notificationContent.sound = .default notificationContent.categoryIdentifier="INCOMING_TRANSFERS" notificationContent.userInfo=["transferID": transfer.id] - NDNotificationCenterHackery.removeDefaultAction(notificationContent) + if #available(macOS 11.0, *){ + NDNotificationCenterHackery.removeDefaultAction(notificationContent) + } let notificationReq=UNNotificationRequest(identifier: "transfer_"+transfer.id, content: notificationContent, trigger: nil) - self.activeIncomingTransfers[transfer.id]=TransferInfo(device: device, transfer: transfer) UNUserNotificationCenter.current().add(notificationReq) + self.activeIncomingTransfers[transfer.id]=TransferInfo(device: device, transfer: transfer) } func incomingTransfer(id: String, didFinishWith error: Error?) { @@ -107,8 +112,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele notificationContent.title=String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [transfer.device.name]) if let ne=(error as? NearbyError){ switch ne{ - case .inputOutput(let er): - notificationContent.body=er.localizedDescription + case .inputOutput: + notificationContent.body="I/O Error"; case .protocolError(_): notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "") case .requiredFieldMissing: diff --git a/NearDrop/MainMenu.xib b/NearDrop/MainMenu.xib index 5e85612..1c336d0 100644 --- a/NearDrop/MainMenu.xib +++ b/NearDrop/MainMenu.xib @@ -1,8 +1,8 @@ - + - + diff --git a/NearDrop/NDNotificationCenterHackery.h b/NearDrop/NDNotificationCenterHackery.h index f108e91..65a4679 100644 --- a/NearDrop/NDNotificationCenterHackery.h +++ b/NearDrop/NDNotificationCenterHackery.h @@ -12,7 +12,6 @@ NS_ASSUME_NONNULL_BEGIN @interface NDNotificationCenterHackery : NSObject -+ (UNNotificationCategory*)hackedNotificationCategory; + (void)removeDefaultAction:(UNMutableNotificationContent*) content; @end diff --git a/NearDrop/NDNotificationCenterHackery.m b/NearDrop/NDNotificationCenterHackery.m index b9c2d0d..5142c93 100644 --- a/NearDrop/NDNotificationCenterHackery.m +++ b/NearDrop/NDNotificationCenterHackery.m @@ -35,13 +35,6 @@ @interface UNMutableNotificationContent (NDPrivateAPIs) @implementation NDNotificationCenterHackery -+ (UNNotificationCategory*)hackedNotificationCategory{ - UNNotificationAction *accept=[UNNotificationAction actionWithIdentifier:@"ACCEPT" title:NSLocalizedString(@"Accept", nil) options:0]; - UNNotificationAction *decline=[UNNotificationAction actionWithIdentifier:@"DECLINE" title:NSLocalizedString(@"Decline", nil) options:0]; - UNMutableNotificationCategory *category=[UNMutableNotificationCategory categoryWithIdentifier:@"INCOMING_TRANSFERS" actions:@[accept, decline] intentIdentifiers:@[] hiddenPreviewsBodyPlaceholder:@"" options: UNNotificationCategoryOptionCustomDismissAction]; - return category; -} - + (void)removeDefaultAction:(UNMutableNotificationContent*) content{ content.hasDefaultAction=false; } diff --git a/NearbyShare/InboundNearbyConnection.swift b/NearbyShare/InboundNearbyConnection.swift index a56da79..c49990a 100644 --- a/NearbyShare/InboundNearbyConnection.swift +++ b/NearbyShare/InboundNearbyConnection.swift @@ -103,7 +103,7 @@ class InboundNearbyConnection: NearbyConnection{ guard frame.payloadChunk.offset==currentOffset else { throw NearbyError.protocolError("Invalid offset into file \(frame.payloadChunk.offset), expected \(currentOffset)") } guard currentOffset+Int64(frame.payloadChunk.body.count)<=fileInfo.meta.size else { throw NearbyError.protocolError("Transferred file size exceeds previously specified value") } if frame.payloadChunk.body.count>0{ - try fileInfo.fileHandle?.write(contentsOf: frame.payloadChunk.body) + fileInfo.fileHandle?.write(frame.payloadChunk.body) transferredFiles[id]!.bytesTransferred+=Int64(frame.payloadChunk.body.count) fileInfo.progress?.completedUnitCount=transferredFiles[id]!.bytesTransferred }else if (frame.payloadChunk.flags & 1)==1{ diff --git a/NearbyShare/NearbyConnection.swift b/NearbyShare/NearbyConnection.swift index 8cc206f..2303aa3 100644 --- a/NearbyShare/NearbyConnection.swift +++ b/NearbyShare/NearbyConnection.swift @@ -319,6 +319,31 @@ class NearbyConnection{ return String(format: "%04d", abs(hash)) } + internal static func hkdfExtract(salt:Data, ikm:Data) -> Data{ + return HMAC.authenticationCode(for: ikm, using: SymmetricKey(data: salt)).withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)}) + } + + internal static func hkdfExpand(prk:Data, info:Data, length:Int) -> Data{ + var okm=Data() + var t=Data() + var i=0 + while okm.count.authenticationCode(for: toDigest, using: SymmetricKey(data: prk)).withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)}) + okm=okm+t + } + return okm.subdata(in: 0.. SymmetricKey{ + if #available(macOS 11.0, *){ + return HKDF.deriveKey(inputKeyMaterial: inputKeyMaterial, salt: salt, info: info, outputByteCount: outputByteCount) + }else{ + return SymmetricKey(data: hkdfExpand(prk: hkdfExtract(salt: salt, ikm: inputKeyMaterial.withUnsafeBytes({return Data(bytes: $0.baseAddress!, count: $0.count)})), info: info, length: outputByteCount)) + } + } + internal func finalizeKeyExchange(peerKey:Securemessage_GenericPublicKey) throws{ guard peerKey.hasEcP256PublicKey else { throw NearbyError.requiredFieldMissing("peerKey.ecP256PublicKey") } @@ -341,8 +366,8 @@ class NearbyConnection{ var ukeyInfo=Data() ukeyInfo.append(ukeyClientInitMsgData!) ukeyInfo.append(ukeyServerInitMsgData!) - let authString=HKDF.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32) - let nextSecret=HKDF.deriveKey(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32) + let authString=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 auth".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32) + let nextSecret=NearbyConnection.hkdf(inputKeyMaterial: SymmetricKey(data: derivedSecretKey), salt: "UKEY2 v1 next".data(using: .utf8)!, info: ukeyInfo, outputByteCount: 32) pinCode=NearbyConnection.pinCodeFromAuthKey(authString) @@ -350,17 +375,17 @@ class NearbyConnection{ 0xEE, 0x8D, 0x39, 0x09, 0xB9, 0x5F, 0x13, 0xFA, 0x7D, 0xEB, 0x1D, 0x4A, 0xB3, 0x83, 0x76, 0xB8, 0x25, 0x6D, 0xA8, 0x55, 0x10]) - let d2dClientKey=HKDF.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "client".data(using: .utf8)!, outputByteCount: 32) - let d2dServerKey=HKDF.deriveKey(inputKeyMaterial: nextSecret, salt: salt, info: "server".data(using: .utf8)!, outputByteCount: 32) + let d2dClientKey=NearbyConnection.hkdf(inputKeyMaterial: nextSecret, salt: salt, info: "client".data(using: .utf8)!, outputByteCount: 32) + let d2dServerKey=NearbyConnection.hkdf(inputKeyMaterial: nextSecret, salt: salt, info: "server".data(using: .utf8)!, outputByteCount: 32) sha=SHA256() sha.update(data: "SecureMessage".data(using: .utf8)!) let smsgSalt=Data(sha.finalize()) - let clientKey=HKDF.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)}) - let clientHmacKey=HKDF.deriveKey(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32) - let serverKey=HKDF.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)}) - let serverHmacKey=HKDF.deriveKey(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32) + let clientKey=NearbyConnection.hkdf(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)}) + let clientHmacKey=NearbyConnection.hkdf(inputKeyMaterial: d2dClientKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32) + let serverKey=NearbyConnection.hkdf(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "ENC:2".data(using: .utf8)!, outputByteCount: 32).withUnsafeBytes({return [UInt8]($0)}) + let serverHmacKey=NearbyConnection.hkdf(inputKeyMaterial: d2dServerKey, salt: smsgSalt, info: "SIG:1".data(using: .utf8)!, outputByteCount: 32) if isServer(){ decryptKey=clientKey diff --git a/NearbyShare/NearbyConnectionManager.swift b/NearbyShare/NearbyConnectionManager.swift index 2874ad0..0fbb222 100644 --- a/NearbyShare/NearbyConnectionManager.swift +++ b/NearbyShare/NearbyConnectionManager.swift @@ -53,7 +53,7 @@ public enum NearbyError:Error{ case protocolError(_ message:String) case requiredFieldMissing(_ message:String) case ukey2 - case inputOutput(cause:Errno) + case inputOutput case canceled(reason:CancellationReason) public enum CancellationReason{ diff --git a/NearbyShare/OutboundNearbyConnection.swift b/NearbyShare/OutboundNearbyConnection.swift index 76214c1..8000a20 100644 --- a/NearbyShare/OutboundNearbyConnection.swift +++ b/NearbyShare/OutboundNearbyConnection.swift @@ -277,9 +277,15 @@ class OutboundNearbyConnection:NearbyConnection{ let typeID=try? url.resourceValues(forKeys: [.typeIdentifierKey]).typeIdentifier meta.mimeType="application/octet-stream" if let typeID=typeID{ - let type=UTType(typeID) - if let type=type, let mimeType=type.preferredMIMEType{ - meta.mimeType=mimeType + if #available(macOS 11.0, *){ + let type=UTType(typeID) + if let type=type, let mimeType=type.preferredMIMEType{ + meta.mimeType=mimeType + } + }else{ + if let mimeType=UTTypeCopyPreferredTagWithClass(typeID as CFString, kUTTagClassMIMEType){ + meta.mimeType=(mimeType.takeRetainedValue() as NSString) as String + } } } if meta.mimeType.starts(with: "image/"){ @@ -358,8 +364,14 @@ class OutboundNearbyConnection:NearbyConnection{ currentTransfer=queue.removeFirst() } - guard let fileBuffer=try currentTransfer!.handle!.read(upToCount: 512*1024) else{ - throw NearbyError.inputOutput(cause: Errno.ioError) + let fileBuffer:Data + if #available(macOS 10.15.4, *) { + guard let _fileBuffer=try currentTransfer!.handle!.read(upToCount: 512*1024) else{ + throw NearbyError.inputOutput + } + fileBuffer=_fileBuffer + } else { + fileBuffer=currentTransfer!.handle!.readData(ofLength: 512*1024) } var transfer=Location_Nearby_Connections_PayloadTransferFrame() diff --git a/ShareExtension/Base.lproj/ShareViewController.xib b/ShareExtension/Base.lproj/ShareViewController.xib index ddb16d4..558acb4 100644 --- a/ShareExtension/Base.lproj/ShareViewController.xib +++ b/ShareExtension/Base.lproj/ShareViewController.xib @@ -1,8 +1,8 @@ - + - + @@ -32,9 +32,6 @@