diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 284577fc8..3c1e7a29a 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -114,6 +114,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLECallConfirmationStatus.h', 'SmartDeviceLink/SDLECallInfo.h', 'SmartDeviceLink/SDLElectronicParkBrakeStatus.h', +'SmartDeviceLink/SDLEncryptionConfiguration.h', 'SmartDeviceLink/SDLEmergencyEvent.h', 'SmartDeviceLink/SDLEmergencyEventType.h', 'SmartDeviceLink/SDLEncodedSyncPData.h', @@ -279,6 +280,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLPrimaryAudioSource.h', 'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLProtocolConstants.h', 'SmartDeviceLink/SDLPublishAppService.h', 'SmartDeviceLink/SDLPublishAppServiceResponse.h', 'SmartDeviceLink/SDLPutFile.h', @@ -329,6 +331,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLSendHapticDataResponse.h', 'SmartDeviceLink/SDLSendLocation.h', 'SmartDeviceLink/SDLSendLocationResponse.h', +'SmartDeviceLink/SDLServiceEncryptionDelegate.h', 'SmartDeviceLink/SDLServiceUpdateReason.h', 'SmartDeviceLink/SDLSetAppIcon.h', 'SmartDeviceLink/SDLSetAppIconResponse.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 7e98d9a5b..3531abab7 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 000DD57222EF063F005AB7A7 /* SDLGetInteriorVehicleDataConsentResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 000DD57122EF063F005AB7A7 /* SDLGetInteriorVehicleDataConsentResponseSpec.m */; }; 000DD57422EF0957005AB7A7 /* SDLReleaseInteriorVehicleDataModuleSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 000DD57322EF0957005AB7A7 /* SDLReleaseInteriorVehicleDataModuleSpec.m */; }; 000DD57622EF0971005AB7A7 /* SDLReleaseInteriorVehicleDataModuleResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 000DD57522EF0971005AB7A7 /* SDLReleaseInteriorVehicleDataModuleResponseSpec.m */; }; + 001A08B52321ADD30078A31E /* SDLServiceEncryptionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 001A08B32321ADD30078A31E /* SDLServiceEncryptionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0055412622D40DAB003194D3 /* SDLModuleInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0055412422D40DAB003194D3 /* SDLModuleInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0055412722D40DAB003194D3 /* SDLModuleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0055412522D40DAB003194D3 /* SDLModuleInfo.m */; }; 0055412A22D5DC0B003194D3 /* SDLGrid.h in Headers */ = {isa = PBXBuildFile; fileRef = 0055412822D5DC0B003194D3 /* SDLGrid.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -21,6 +22,10 @@ 0055412F22D759BD003194D3 /* SDLSeatLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 0055412D22D759BC003194D3 /* SDLSeatLocation.m */; }; 0055413222D75A7B003194D3 /* SDLSeatLocationCapability.h in Headers */ = {isa = PBXBuildFile; fileRef = 0055413022D75A7A003194D3 /* SDLSeatLocationCapability.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0055413322D75A7B003194D3 /* SDLSeatLocationCapability.m in Sources */ = {isa = PBXBuildFile; fileRef = 0055413122D75A7B003194D3 /* SDLSeatLocationCapability.m */; }; + 005DF3C522C59191006E01A9 /* SDLEncryptionLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 005DF3C322C59191006E01A9 /* SDLEncryptionLifecycleManager.h */; }; + 005DF3C622C59191006E01A9 /* SDLEncryptionLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 005DF3C422C59191006E01A9 /* SDLEncryptionLifecycleManager.m */; }; + 005DF3CA22C62E00006E01A9 /* SDLEncryptionManagerConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 005DF3C822C62E00006E01A9 /* SDLEncryptionManagerConstants.h */; }; + 005DF3CB22C62E00006E01A9 /* SDLEncryptionManagerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 005DF3C922C62E00006E01A9 /* SDLEncryptionManagerConstants.m */; }; 008DB36122EA7482003F458C /* SDLGetInteriorVehicleDataConsent.h in Headers */ = {isa = PBXBuildFile; fileRef = 008DB35F22EA7481003F458C /* SDLGetInteriorVehicleDataConsent.h */; settings = {ATTRIBUTES = (Public, ); }; }; 008DB36222EA7482003F458C /* SDLGetInteriorVehicleDataConsent.m in Sources */ = {isa = PBXBuildFile; fileRef = 008DB36022EA7481003F458C /* SDLGetInteriorVehicleDataConsent.m */; }; 008DB36522EA7F6F003F458C /* SDLGetInteriorVehicleDataConsentResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 008DB36322EA7F6F003F458C /* SDLGetInteriorVehicleDataConsentResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -29,6 +34,10 @@ 008DB36A22EA8261003F458C /* SDLReleaseInteriorVehicleDataModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 008DB36822EA8261003F458C /* SDLReleaseInteriorVehicleDataModule.m */; }; 008DB36D22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 008DB36B22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; 008DB36E22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 008DB36C22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.m */; }; + 00E22CEC22C2F1B300BC6B08 /* SDLEncryptionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E22CEA22C2F1B200BC6B08 /* SDLEncryptionConfiguration.m */; }; + 00E22CED22C2F1B300BC6B08 /* SDLEncryptionConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 00E22CEB22C2F1B300BC6B08 /* SDLEncryptionConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 00EADD3322DFE54B0088B608 /* SDLEncryptionLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 00EADD3222DFE54B0088B608 /* SDLEncryptionLifecycleManagerSpec.m */; }; + 00EADD3522DFE5670088B608 /* SDLEncryptionConfigurationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 00EADD3422DFE5670088B608 /* SDLEncryptionConfigurationSpec.m */; }; 162E82CA1A9BDE8A00906325 /* SDLAmbientLightStatusSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 162E81E21A9BDE8A00906325 /* SDLAmbientLightStatusSpec.m */; }; 162E82CB1A9BDE8A00906325 /* SDLAppHMITypeSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 162E81E31A9BDE8A00906325 /* SDLAppHMITypeSpec.m */; }; 162E82CC1A9BDE8A00906325 /* SDLAppInterfaceUnregisteredReasonSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 162E81E41A9BDE8A00906325 /* SDLAppInterfaceUnregisteredReasonSpec.m */; }; @@ -1152,7 +1161,7 @@ 5DA8A0EA1E955FE00039C50D /* SDLLogModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBF06301E64A9C600A5CF03 /* SDLLogModel.m */; }; 5DAB5F512098994C00A020C8 /* SDLMenuCellSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F502098994C00A020C8 /* SDLMenuCellSpec.m */; }; 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F5220989A8300A020C8 /* SDLVoiceCommandSpec.m */; }; - 5DAB5F562098E5D100A020C8 /* SDLProtocolConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAB5F542098E5D100A020C8 /* SDLProtocolConstants.h */; }; + 5DAB5F562098E5D100A020C8 /* SDLProtocolConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAB5F542098E5D100A020C8 /* SDLProtocolConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5DAB5F572098E5D100A020C8 /* SDLProtocolConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAB5F552098E5D100A020C8 /* SDLProtocolConstants.m */; }; 5DAD5F7F204DEDEB0025624C /* SDLScreenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DAD5F7D204DEDEB0025624C /* SDLScreenManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5DAD5F80204DEDEB0025624C /* SDLScreenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DAD5F7E204DEDEB0025624C /* SDLScreenManager.m */; }; @@ -1709,6 +1718,7 @@ 000DD57122EF063F005AB7A7 /* SDLGetInteriorVehicleDataConsentResponseSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLGetInteriorVehicleDataConsentResponseSpec.m; sourceTree = ""; }; 000DD57322EF0957005AB7A7 /* SDLReleaseInteriorVehicleDataModuleSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLReleaseInteriorVehicleDataModuleSpec.m; sourceTree = ""; }; 000DD57522EF0971005AB7A7 /* SDLReleaseInteriorVehicleDataModuleResponseSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLReleaseInteriorVehicleDataModuleResponseSpec.m; sourceTree = ""; }; + 001A08B32321ADD30078A31E /* SDLServiceEncryptionDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLServiceEncryptionDelegate.h; sourceTree = ""; }; 0055412422D40DAB003194D3 /* SDLModuleInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLModuleInfo.h; sourceTree = ""; }; 0055412522D40DAB003194D3 /* SDLModuleInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLModuleInfo.m; sourceTree = ""; }; 0055412822D5DC0B003194D3 /* SDLGrid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLGrid.h; sourceTree = ""; }; @@ -1717,6 +1727,10 @@ 0055412D22D759BC003194D3 /* SDLSeatLocation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLSeatLocation.m; sourceTree = ""; }; 0055413022D75A7A003194D3 /* SDLSeatLocationCapability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLSeatLocationCapability.h; sourceTree = ""; }; 0055413122D75A7B003194D3 /* SDLSeatLocationCapability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLSeatLocationCapability.m; sourceTree = ""; }; + 005DF3C322C59191006E01A9 /* SDLEncryptionLifecycleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLEncryptionLifecycleManager.h; sourceTree = ""; }; + 005DF3C422C59191006E01A9 /* SDLEncryptionLifecycleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLEncryptionLifecycleManager.m; sourceTree = ""; }; + 005DF3C822C62E00006E01A9 /* SDLEncryptionManagerConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLEncryptionManagerConstants.h; sourceTree = ""; }; + 005DF3C922C62E00006E01A9 /* SDLEncryptionManagerConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLEncryptionManagerConstants.m; sourceTree = ""; }; 008DB35F22EA7481003F458C /* SDLGetInteriorVehicleDataConsent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLGetInteriorVehicleDataConsent.h; sourceTree = ""; }; 008DB36022EA7481003F458C /* SDLGetInteriorVehicleDataConsent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLGetInteriorVehicleDataConsent.m; sourceTree = ""; }; 008DB36322EA7F6F003F458C /* SDLGetInteriorVehicleDataConsentResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLGetInteriorVehicleDataConsentResponse.h; sourceTree = ""; }; @@ -1725,6 +1739,10 @@ 008DB36822EA8261003F458C /* SDLReleaseInteriorVehicleDataModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLReleaseInteriorVehicleDataModule.m; sourceTree = ""; }; 008DB36B22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLReleaseInteriorVehicleDataModuleResponse.h; sourceTree = ""; }; 008DB36C22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLReleaseInteriorVehicleDataModuleResponse.m; sourceTree = ""; }; + 00E22CEA22C2F1B200BC6B08 /* SDLEncryptionConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLEncryptionConfiguration.m; sourceTree = ""; }; + 00E22CEB22C2F1B300BC6B08 /* SDLEncryptionConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLEncryptionConfiguration.h; sourceTree = ""; }; + 00EADD3222DFE54B0088B608 /* SDLEncryptionLifecycleManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLEncryptionLifecycleManagerSpec.m; sourceTree = ""; }; + 00EADD3422DFE5670088B608 /* SDLEncryptionConfigurationSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLEncryptionConfigurationSpec.m; sourceTree = ""; }; 162E81E21A9BDE8A00906325 /* SDLAmbientLightStatusSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAmbientLightStatusSpec.m; sourceTree = ""; }; 162E81E31A9BDE8A00906325 /* SDLAppHMITypeSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAppHMITypeSpec.m; sourceTree = ""; }; 162E81E41A9BDE8A00906325 /* SDLAppInterfaceUnregisteredReasonSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAppInterfaceUnregisteredReasonSpec.m; sourceTree = ""; }; @@ -3403,6 +3421,60 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 001A08B22321ACE90078A31E /* Delegates */ = { + isa = PBXGroup; + children = ( + 001A08B32321ADD30078A31E /* SDLServiceEncryptionDelegate.h */, + ); + name = Delegates; + sourceTree = ""; + }; + 005DF3BE22C590FB006E01A9 /* Lifecycle */ = { + isa = PBXGroup; + children = ( + 005DF3C322C59191006E01A9 /* SDLEncryptionLifecycleManager.h */, + 005DF3C422C59191006E01A9 /* SDLEncryptionLifecycleManager.m */, + ); + name = Lifecycle; + sourceTree = ""; + }; + 005DF3C722C62DDA006E01A9 /* Utilities */ = { + isa = PBXGroup; + children = ( + 005DF3C822C62E00006E01A9 /* SDLEncryptionManagerConstants.h */, + 005DF3C922C62E00006E01A9 /* SDLEncryptionManagerConstants.m */, + ); + name = Utilities; + sourceTree = ""; + }; + 00E22CE822C2F19700BC6B08 /* Encryption */ = { + isa = PBXGroup; + children = ( + 00E22CE922C2F1A400BC6B08 /* Configuration */, + 001A08B22321ACE90078A31E /* Delegates */, + 005DF3BE22C590FB006E01A9 /* Lifecycle */, + 005DF3C722C62DDA006E01A9 /* Utilities */, + ); + name = Encryption; + sourceTree = ""; + }; + 00E22CE922C2F1A400BC6B08 /* Configuration */ = { + isa = PBXGroup; + children = ( + 00E22CEB22C2F1B300BC6B08 /* SDLEncryptionConfiguration.h */, + 00E22CEA22C2F1B200BC6B08 /* SDLEncryptionConfiguration.m */, + ); + name = Configuration; + sourceTree = ""; + }; + 00EADD3122DFDF680088B608 /* Encryption */ = { + isa = PBXGroup; + children = ( + 00EADD3222DFE54B0088B608 /* SDLEncryptionLifecycleManagerSpec.m */, + ); + name = Encryption; + sourceTree = ""; + }; 162E81E01A9BDE8A00906325 /* RPCSpecs */ = { isa = PBXGroup; children = ( @@ -5783,6 +5855,7 @@ 5DB1BCDC1D243DC3002FFC37 /* SDLLifecycleConfigurationSpec.m */, 5DB1BCDE1D243DD3002FFC37 /* SDLLockScreenConfigurationSpec.m */, 5DBEFA531F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m */, + 00EADD3422DFE5670088B608 /* SDLEncryptionConfigurationSpec.m */, ); name = Configurations; sourceTree = ""; @@ -5873,6 +5946,7 @@ 5DBAE0A61D355EF200CE00BF /* Managers */ = { isa = PBXGroup; children = ( + 00E22CE822C2F19700BC6B08 /* Encryption */, 5DA3F36E1BC4489A0026F2D0 /* SDLManager.h */, 5DA3F36F1BC4489A0026F2D0 /* SDLManager.m */, 5D82041C1BCD8E6100D0A41B /* SDLConfiguration.h */, @@ -5902,6 +5976,7 @@ 5DBAE0A81D35886E00CE00BF /* Managers */ = { isa = PBXGroup; children = ( + 00EADD3122DFDF680088B608 /* Encryption */, 5DAD5F8120507DE40025624C /* Screen */, DA8966ED1E5693D100413EAB /* Streaming */, 880E35B62088F77C00181259 /* System Capabilities */, @@ -6638,6 +6713,7 @@ 880D267D220DE5DF00B3F496 /* SDLWeatherServiceManifest.h in Headers */, DAA41D551DF66B2000BC7337 /* SDLH264VideoEncoder.h in Headers */, 8B7B319A1F2F7B5700BDC38D /* SDLVideoStreamingCodec.h in Headers */, + 005DF3CA22C62E00006E01A9 /* SDLEncryptionManagerConstants.h in Headers */, 5D61FCAF1A84238C00846EE7 /* SDLGenericResponse.h in Headers */, 885468352225C1F800994D8D /* SDLCloudAppProperties.h in Headers */, 5D61FC4F1A84238C00846EE7 /* SDLBodyInformation.h in Headers */, @@ -6812,6 +6888,7 @@ 880E35B52088F75A00181259 /* SDLSystemCapabilityManager.h in Headers */, 5D61FC611A84238C00846EE7 /* SDLChoice.h in Headers */, 5D92937420B5EEA200FCC775 /* SDLPreloadChoicesOperation.h in Headers */, + 00E22CED22C2F1B300BC6B08 /* SDLEncryptionConfiguration.h in Headers */, 5D7F87F31CE3C29E002DD7C4 /* SDLFileWrapper.h in Headers */, 5D61FC7C1A84238C00846EE7 /* SDLDeleteInteractionChoiceSetResponse.h in Headers */, 5D61FDB91A84238C00846EE7 /* SDLSyncPDataResponse.h in Headers */, @@ -6827,6 +6904,7 @@ 008DB36D22EA83E4003F458C /* SDLReleaseInteriorVehicleDataModuleResponse.h in Headers */, 5D61FDE31A84238C00846EE7 /* SDLUnregisterAppInterface.h in Headers */, 5D61FD331A84238C00846EE7 /* SDLPowerModeQualificationStatus.h in Headers */, + 005DF3C522C59191006E01A9 /* SDLEncryptionLifecycleManager.h in Headers */, 5D92937020B5E0E500FCC775 /* SDLDeleteChoicesOperation.h in Headers */, 5DA150CD2271FE180032928D /* SDLSoftButtonReplaceOperation.h in Headers */, 5D61FE011A84238C00846EE7 /* SDLVehicleDataNotificationStatus.h in Headers */, @@ -6935,6 +7013,7 @@ 5D9FDA941F2A7D3400A495C8 /* bson_util.h in Headers */, 5D61FD771A84238C00846EE7 /* SDLSamplingRate.h in Headers */, 5DF40B22208E761A00DD6FDA /* SDLVoiceCommandManager.h in Headers */, + 001A08B52321ADD30078A31E /* SDLServiceEncryptionDelegate.h in Headers */, 5D61FCBB1A84238C00846EE7 /* SDLGPSData.h in Headers */, 5D61FDA31A84238C00846EE7 /* SDLSoftButtonType.h in Headers */, 5D61FC431A84238C00846EE7 /* SDLAppInterfaceUnregisteredReason.h in Headers */, @@ -7279,6 +7358,7 @@ 5D61FC9D1A84238C00846EE7 /* SDLEmergencyEventType.m in Sources */, 5D61FCAC1A84238C00846EE7 /* SDLFuelCutoffStatus.m in Sources */, 5D61FC871A84238C00846EE7 /* SDLDeviceStatus.m in Sources */, + 005DF3CB22C62E00006E01A9 /* SDLEncryptionManagerConstants.m in Sources */, 5D61FD561A84238C00846EE7 /* SDLPutFile.m in Sources */, 1EAA474E20356B2D000FE74B /* SDLDisplayMode.m in Sources */, 5D61FCE71A84238C00846EE7 /* SDLKeypressMode.m in Sources */, @@ -7409,6 +7489,7 @@ 0055412B22D5DC0B003194D3 /* SDLGrid.m in Sources */, 8815D0F122330781000F24E6 /* SDLRPCRequestNotification.m in Sources */, 5D3E48CC1D7722FE0000BFEF /* NSBundle+SDLBundle.m in Sources */, + 005DF3C622C59191006E01A9 /* SDLEncryptionLifecycleManager.m in Sources */, 5D61FCBC1A84238C00846EE7 /* SDLGPSData.m in Sources */, 5D61FD341A84238C00846EE7 /* SDLPowerModeQualificationStatus.m in Sources */, 5D61FC891A84238C00846EE7 /* SDLDiagnosticMessage.m in Sources */, @@ -7704,6 +7785,7 @@ 1E5AD0851F20B9290029B8AF /* SDLButtonPressResponse.m in Sources */, 9FE2470E22D77A5A00F8D2FC /* SDLDeleteWindowResponse.m in Sources */, 5D82041F1BCD8E6100D0A41B /* SDLConfiguration.m in Sources */, + 00E22CEC22C2F1B300BC6B08 /* SDLEncryptionConfiguration.m in Sources */, 5D61FD381A84238C00846EE7 /* SDLPredefinedLayout.m in Sources */, 5D3E487C1D6F888E0000BFEF /* SDLRPCResponseNotification.m in Sources */, 5D61FD0E1A84238C00846EE7 /* SDLOnHashChange.m in Sources */, @@ -7831,6 +7913,7 @@ 5DBEFA581F436132009EE295 /* SDLFakeSecurityManager.m in Sources */, 9FA0D00022DF06A0009CF344 /* SDLWindowCapabilitySpec.m in Sources */, 162E82D91A9BDE8A00906325 /* SDLDisplayTypeSpec.m in Sources */, + 00EADD3522DFE5670088B608 /* SDLEncryptionConfigurationSpec.m in Sources */, 162E83871A9BDE8B00906325 /* SDLPermissionItemSpec.m in Sources */, 5DAB5F5320989A8300A020C8 /* SDLVoiceCommandSpec.m in Sources */, 162E82E31A9BDE8B00906325 /* SDLIgnitionStatusSpec.m in Sources */, @@ -7941,6 +8024,7 @@ 162E82DC1A9BDE8B00906325 /* SDLEmergencyEventTypeSpec.m in Sources */, 162E82CE1A9BDE8A00906325 /* SDLAudioTypeSpec.m in Sources */, 162E831C1A9BDE8B00906325 /* SDLOnSyncPDataSpec.m in Sources */, + 00EADD3322DFE54B0088B608 /* SDLEncryptionLifecycleManagerSpec.m in Sources */, 5D9F50871BED412E00FEF399 /* TestConnectionManager.m in Sources */, 1EAA47802036C2C9000FE74B /* SDLStationIDNumberSpec.m in Sources */, 162E83341A9BDE8B00906325 /* SDLPutFileSpec.m in Sources */, diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 84841ee6e..9abd77a7b 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -115,6 +115,7 @@ sdefault.public_header_files = [ 'SmartDeviceLink/SDLECallConfirmationStatus.h', 'SmartDeviceLink/SDLECallInfo.h', 'SmartDeviceLink/SDLElectronicParkBrakeStatus.h', +'SmartDeviceLink/SDLEncryptionConfiguration.h', 'SmartDeviceLink/SDLEmergencyEvent.h', 'SmartDeviceLink/SDLEmergencyEventType.h', 'SmartDeviceLink/SDLEncodedSyncPData.h', @@ -280,6 +281,7 @@ sdefault.public_header_files = [ 'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLPrimaryAudioSource.h', 'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLProtocolConstants.h', 'SmartDeviceLink/SDLPublishAppService.h', 'SmartDeviceLink/SDLPublishAppServiceResponse.h', 'SmartDeviceLink/SDLPutFile.h', @@ -330,6 +332,7 @@ sdefault.public_header_files = [ 'SmartDeviceLink/SDLSendHapticDataResponse.h', 'SmartDeviceLink/SDLSendLocation.h', 'SmartDeviceLink/SDLSendLocationResponse.h', +'SmartDeviceLink/SDLServiceEncryptionDelegate.h', 'SmartDeviceLink/SDLServiceUpdateReason.h', 'SmartDeviceLink/SDLSetAppIcon.h', 'SmartDeviceLink/SDLSetAppIconResponse.h', diff --git a/SmartDeviceLink/SDLConfiguration.h b/SmartDeviceLink/SDLConfiguration.h index 2cd6420fd..fcb871870 100644 --- a/SmartDeviceLink/SDLConfiguration.h +++ b/SmartDeviceLink/SDLConfiguration.h @@ -13,6 +13,7 @@ @class SDLLockScreenConfiguration; @class SDLLogConfiguration; @class SDLStreamingMediaConfiguration; +@class SDLEncryptionConfiguration; NS_ASSUME_NONNULL_BEGIN @@ -43,6 +44,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (copy, nonatomic, readonly) SDLFileManagerConfiguration *fileManagerConfig; +/** + * The encryption configuration. + */ +@property (copy, nonatomic, readonly) SDLEncryptionConfiguration *encryptionConfig; + /** * Creates a new configuration to be passed to the SDLManager with custom lifecycle, lock screen and logging configurations. * @@ -62,7 +68,19 @@ NS_ASSUME_NONNULL_BEGIN * @param fileManagerConfig The file manager configuration to be used or `defaultConfiguration` if nil. * @return The configuration */ -- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig; +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig __deprecated_msg("Use initWithLifecycle:lockScreen:logging:fileManager:encryption: instead"); + +/** + * Creates a new configuration to be passed to the SDLManager with custom lifecycle, lock screen, logging, file manager and encryption configurations. + * + * @param lifecycleConfig The lifecycle configuration to be used. + * @param lockScreenConfig The lockscreen configuration to be used. If nil, the `enabledConfiguration` will be used. + * @param logConfig The logging configuration to be used. If nil, the `defaultConfiguration` will be used. + * @param fileManagerConfig The file manager configuration to be used or `defaultConfiguration` if nil. + * @param encryptionConfig The encryption configuration to be used. If nil, the `defaultConfiguration` will be used. + * @return The configuration + */ +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig encryption:(nullable SDLEncryptionConfiguration *)encryptionConfig; /** * Creates a new configuration to be passed to the SDLManager with custom lifecycle, lock screen and logging configurations. @@ -106,7 +124,20 @@ NS_ASSUME_NONNULL_BEGIN * @param fileManagerConfig The file manager configuration to be used or `defaultConfiguration` if nil. * @return The configuration */ -- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig; +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig __deprecated_msg("Use initWithLifecycle:lockScreen:logging:streamingMedia:fileManager:encryption: instead"); + +/** + * Creates a new configuration to be passed to the SDLManager with custom lifecycle, lock screen, logging, streaming media, file manager and encryption configurations. + * + * @param lifecycleConfig The lifecycle configuration to be used. + * @param lockScreenConfig The lockscreen configuration to be used. If nil, the `enabledConfiguration` will be used. + * @param logConfig The logging configuration to be used. If nil, the `defaultConfiguration` will be used. + * @param streamingMediaConfig The streaming media configuration to be used or nil if not used. + * @param fileManagerConfig The file manager configuration to be used or `defaultConfiguration` if nil. + * @param encryptionConfig The encryption configuration to be used. If nil, the `defaultConfiguration` will be used. + * @return The configuration + */ +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig encryption:(nullable SDLEncryptionConfiguration *)encryptionConfig; /** * Creates a new configuration to be passed to the SDLManager with custom lifecycle, lock screen, logging and streaming media configurations. diff --git a/SmartDeviceLink/SDLConfiguration.m b/SmartDeviceLink/SDLConfiguration.m index a96b27d68..626b25d03 100644 --- a/SmartDeviceLink/SDLConfiguration.m +++ b/SmartDeviceLink/SDLConfiguration.m @@ -13,6 +13,7 @@ #import "SDLLockScreenConfiguration.h" #import "SDLLogConfiguration.h" #import "SDLStreamingMediaConfiguration.h" +#import "SDLEncryptionConfiguration.h" NS_ASSUME_NONNULL_BEGIN @@ -23,14 +24,18 @@ - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfigur } - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig { - return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:nil fileManager:nil]; + return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:nil fileManager:nil encryption: nil]; } - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig { - return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig fileManager:nil]; + return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig fileManager:nil encryption: nil]; } - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig { + return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig fileManager:fileManagerConfig encryption:nil]; +} + +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig encryption:(nullable SDLEncryptionConfiguration *)encryptionConfig { self = [super init]; if (!self) { return nil; @@ -40,6 +45,7 @@ - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig l _lockScreenConfig = lockScreenConfig ?: [SDLLockScreenConfiguration enabledConfiguration]; _loggingConfig = logConfig ?: [SDLLogConfiguration defaultConfiguration]; _fileManagerConfig = fileManagerConfig ?: [SDLFileManagerConfiguration defaultConfiguration]; + _encryptionConfig = encryptionConfig ?: [SDLEncryptionConfiguration defaultConfiguration]; return self; } @@ -57,14 +63,18 @@ + (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycl } + (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig { - return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig fileManager:fileManagerConfig]; + return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig fileManager:fileManagerConfig encryption: nil]; } - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig { - return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig fileManager:nil]; + return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig fileManager:nil encryption:nil]; } - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig { + return [self initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig fileManager:fileManagerConfig encryption:nil]; +} + +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig encryption:(nullable SDLEncryptionConfiguration *)encryptionConfig { self = [super init]; if (!self) { return nil; @@ -85,6 +95,7 @@ - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig l } _fileManagerConfig = fileManagerConfig ?: [SDLFileManagerConfiguration defaultConfiguration]; + _encryptionConfig = encryptionConfig ?: [SDLEncryptionConfiguration defaultConfiguration]; return self; } @@ -94,13 +105,13 @@ + (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycl } + (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig fileManager:(nullable SDLFileManagerConfiguration *)fileManagerConfig { - return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig fileManager:fileManagerConfig]; + return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig fileManager:fileManagerConfig encryption:nil]; } #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { - SDLConfiguration *new = [[SDLConfiguration allocWithZone:zone] initWithLifecycle:_lifecycleConfig lockScreen:_lockScreenConfig logging:_loggingConfig streamingMedia:_streamingMediaConfig fileManager:_fileManagerConfig]; + SDLConfiguration *new = [[SDLConfiguration allocWithZone:zone] initWithLifecycle:_lifecycleConfig lockScreen:_lockScreenConfig logging:_loggingConfig streamingMedia:_streamingMediaConfig fileManager:_fileManagerConfig encryption:_encryptionConfig]; return new; } diff --git a/SmartDeviceLink/SDLEncryptionConfiguration.h b/SmartDeviceLink/SDLEncryptionConfiguration.h new file mode 100644 index 000000000..c116ceb22 --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionConfiguration.h @@ -0,0 +1,47 @@ +// +// SDLEncryptionConfiguration.h +// SmartDeviceLink +// +// Created by standa1 on 6/17/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import + +#import "SDLServiceEncryptionDelegate.h" + +@protocol SDLSecurityType; + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLEncryptionConfiguration : NSObject + +/** + * A set of security managers used to encrypt traffic data. Each OEM has their own proprietary security manager. + */ +@property (copy, nonatomic, nullable) NSArray> *securityManagers; + +/** + * A delegate callback that will tell you when an acknowledgement has occurred for starting as secure service. + */ +@property (copy, nonatomic, nullable) id delegate; + +/** + * Creates a default encryption configuration. + * + * @return A default configuration that may be customized. + */ ++ (instancetype)defaultConfiguration; + +/** + Creates a secure configuration for each of the security managers provided. + + @param securityManagers The security managers to be used. + @param delegate The delegate callback. + @return The configuration + */ +- (instancetype)initWithSecurityManagers:(nullable NSArray> *)securityManagers delegate:(nullable id)delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLEncryptionConfiguration.m b/SmartDeviceLink/SDLEncryptionConfiguration.m new file mode 100644 index 000000000..dbb26b6d7 --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionConfiguration.m @@ -0,0 +1,45 @@ +// +// SDLEncryptionConfiguration.m +// SmartDeviceLink +// +// Created by standa1 on 6/17/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLEncryptionConfiguration.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation SDLEncryptionConfiguration + ++ (instancetype)defaultConfiguration { + return [[self.class alloc] initWithSecurityManagers:nil delegate:nil]; +} + +- (instancetype)initWithSecurityManagers:(nullable NSArray> *)securityManagers delegate:(nullable id)delegate { + self = [super init]; + if (!self) { + return nil; + } + + _securityManagers = securityManagers; + _delegate = delegate; + + return self; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + SDLEncryptionConfiguration *newConfig = [[self.class allocWithZone:zone] init]; + + newConfig.securityManagers = self.securityManagers; + newConfig.delegate = self.delegate; + + return newConfig; +} + + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLEncryptionLifecycleManager.h b/SmartDeviceLink/SDLEncryptionLifecycleManager.h new file mode 100644 index 000000000..eb6aa951e --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionLifecycleManager.h @@ -0,0 +1,59 @@ +// +// SDLEncryptionLifecycleManager.h +// SmartDeviceLink +// +// Created by standa1 on 6/27/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import +#import "SDLConnectionManagerType.h" +#import "SDLProtocolListener.h" + +@class SDLEncryptionConfiguration; +@class SDLProtocol; + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLEncryptionLifecycleManager : NSObject + +/** + * Whether or not the encryption session is connected. + */ +@property (assign, nonatomic, readonly, getter=isEncryptionReady) BOOL encryptionReady; + + +- (instancetype)init NS_UNAVAILABLE; + +/** + Create a new encryption lifecycle manager for apps that need encryption. + + @param connectionManager The pass-through for RPCs + @param configuration This session's configuration + @return A new encryption lifecycle manager + */ +- (instancetype)initWithConnectionManager:(id)connectionManager configuration:(SDLEncryptionConfiguration *)configuration; + +/** + * Start the manager. This is used internally to get notified of the ACK message. + */ +- (void)startWithProtocol:(SDLProtocol *)protocol; + +/** + * Stop the manager. This method is used internally. + */ +- (void)stop; + +/** + * Check whether or not an RPC needs encryption. + */ +- (BOOL)rpcRequiresEncryption:(__kindof SDLRPCMessage *)rpc; + +/** + * Attempt to manually start a secure service. + */ +- (void)startEncryptionService; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLEncryptionLifecycleManager.m b/SmartDeviceLink/SDLEncryptionLifecycleManager.m new file mode 100644 index 000000000..dcbf773db --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionLifecycleManager.m @@ -0,0 +1,274 @@ +// +// SDLEncryptionLifecycleManager.m +// SmartDeviceLink +// +// Created by standa1 on 6/27/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLEncryptionLifecycleManager.h" +#import "SDLEncryptionManagerConstants.h" +#import "SDLEncryptionConfiguration.h" +#import "SDLServiceEncryptionDelegate.h" +#import "SDLAsynchronousRPCRequestOperation.h" +#import "SDLLogMacros.h" +#import "SDLStateMachine.h" +#import "SDLProtocolMessage.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLOnHMIStatus.h" +#import "SDLOnPermissionsChange.h" +#import "SDLPermissionItem.h" +#import "SDLPermissionConstants.h" +#import "SDLProtocol.h" +#import "SDLError.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLEncryptionLifecycleManager() + +@property (weak, nonatomic) id connectionManager; +@property (weak, nonatomic) SDLProtocol *protocol; + +@property (strong, nonatomic, readwrite) SDLStateMachine *encryptionStateMachine; +@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; +@property (strong, nonatomic, nullable) NSMutableDictionary *permissions; +@property (assign, nonatomic) BOOL requiresEncryption; +@property (weak, nonatomic, nullable) id delegate; + +@end + +@implementation SDLEncryptionLifecycleManager + +- (instancetype)initWithConnectionManager:(id)connectionManager configuration:(SDLEncryptionConfiguration *)configuration { + self = [super init]; + if (!self) { + return nil; + } + + SDLLogV(@"Creating EncryptionLifecycleManager"); + _connectionManager = connectionManager; + _currentHMILevel = nil; + _requiresEncryption = NO; + _encryptionStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLEncryptionLifecycleManagerStateStopped states:[self.class sdl_encryptionStateTransitionDictionary]]; + _permissions = [NSMutableDictionary dictionary]; + _delegate = configuration.delegate; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_permissionsDidChange:) name:SDLDidChangePermissionsNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiLevelDidChange:) name:SDLDidChangeHMIStatusNotification object:nil]; + + return self; +} + +- (void)startWithProtocol:(SDLProtocol *)protocol { + SDLLogD(@"Starting encryption manager"); + _protocol = protocol; + + @synchronized(self.protocol.protocolDelegateTable) { + if (![self.protocol.protocolDelegateTable containsObject:self]) { + [self.protocol.protocolDelegateTable addObject:self]; + } + } +} + +- (void)stop { + _permissions = nil; + _protocol = nil; + _currentHMILevel = nil; + _requiresEncryption = NO; + _delegate = nil; + + SDLLogD(@"Stopping encryption manager"); +} + +- (BOOL)isEncryptionReady { + return [self.encryptionStateMachine isCurrentState:SDLEncryptionLifecycleManagerStateReady]; +} + +- (void)startEncryptionService { + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStarting]; +} + +- (void)sdl_startEncryptionService { + SDLLogV(@"Attempting to start Encryption Service"); + if (!self.protocol || !self.currentHMILevel) { + SDLLogV(@"Encryption manager is not yet started"); + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_notReadyError]]; + return; + } + + if (![self.currentHMILevel isEqualToEnum:SDLHMILevelNone]) { + if ([self sdl_appRequiresEncryption]) { + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStarting]; + } else { + SDLLogE(@"Encryption Manager is not ready to encrypt."); + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_notReadyError]]; + } + } +} + +- (void)sdl_sendEncryptionStartService { + SDLLogD(@"Sending secure rpc start service"); + [self.protocol startSecureServiceWithType:SDLServiceTypeRPC payload:nil tlsInitializationHandler:^(BOOL success, NSError *error) { + if (error) { + SDLLogE(@"TLS setup error: %@", error); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStopped]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:error]; + } + }]; +} + +#pragma mark Encryption ++ (NSDictionary *)sdl_encryptionStateTransitionDictionary { + return @{ + SDLEncryptionLifecycleManagerStateStopped : @[SDLEncryptionLifecycleManagerStateStarting], + SDLEncryptionLifecycleManagerStateStarting : @[SDLEncryptionLifecycleManagerStateStopped, SDLEncryptionLifecycleManagerStateReady], + SDLEncryptionLifecycleManagerStateReady : @[SDLEncryptionLifecycleManagerStateStopped] + }; +} + +#pragma mark - State Machine +- (void)didEnterStateEncryptionStarting { + SDLLogD(@"Encryption manager is starting"); + [self sdl_sendEncryptionStartService]; +} + +- (void)didEnterStateEncryptionReady { + SDLLogD(@"Encryption manager is ready"); +} + +- (void)didEnterStateEncryptionStopped { + SDLLogD(@"Encryption manager stopped"); +} + +#pragma mark - SDLProtocolListener +#pragma mark Encryption Start Service ACK + +- (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK { + switch (startServiceACK.header.serviceType) { + case SDLServiceTypeRPC: { + [self sdl_handleEncryptionStartServiceACK:startServiceACK]; + } break; + default: break; + } +} + +- (void)sdl_handleEncryptionStartServiceACK:(SDLProtocolMessage *)encryptionStartServiceAck { + if (encryptionStartServiceAck.header.encrypted) { + SDLLogD(@"Encryption service started"); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateReady]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:YES error:nil]; + } else { + SDLLogD(@"Encryption service ACK received encryption = OFF"); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStopped]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_encryption_off]]; + } +} + +#pragma mark Encryption Start Service NAK + +- (void)handleProtocolStartServiceNAKMessage:(SDLProtocolMessage *)startServiceNAK { + switch (startServiceNAK.header.serviceType) { + case SDLServiceTypeRPC: { + [self sdl_handleEncryptionStartServiceNAK:startServiceNAK]; + } break; + default: break; + } +} + +- (void)sdl_handleEncryptionStartServiceNAK:(SDLProtocolMessage *)audioStartServiceNak { + SDLLogW(@"Encryption service failed to start due to NAK"); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStopped]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_nak]]; +} + +#pragma mark Encryption End Service + +- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK { + switch (endServiceACK.header.serviceType) { + case SDLServiceTypeRPC: { + SDLLogW(@"Encryption RPC service ended with end service ACK"); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStopped]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_notReadyError]]; + } break; + default: break; + } +} + +- (void)handleProtocolEndServiceNAKMessage:(SDLProtocolMessage *)endServiceNAK { + switch (endServiceNAK.header.serviceType) { + case SDLServiceTypeRPC: { + SDLLogW(@"Encryption RPC service ended with end service NAK"); + [self.encryptionStateMachine transitionToState:SDLEncryptionLifecycleManagerStateStopped]; + [self.delegate serviceEncryptionUpdatedOnService:SDLServiceTypeRPC encrypted:NO error:[NSError sdl_encryption_lifecycle_notReadyError]]; + } break; + default: break; + } +} + +#pragma mark - SDL RPC Notification callbacks +- (void)sdl_hmiLevelDidChange:(SDLRPCNotificationNotification *)notification { + if (![notification isNotificationMemberOfClass:[SDLOnHMIStatus class]]) { + return; + } + + SDLOnHMIStatus *hmiStatus = notification.notification; + + self.currentHMILevel = hmiStatus.hmiLevel; + + // if startWithProtocol has not been called yet, abort here + if (!self.protocol) { return; } + + if ([self.encryptionStateMachine isCurrentState:SDLEncryptionLifecycleManagerStateStopped]) { + [self sdl_startEncryptionService]; + } +} + +- (void)sdl_permissionsDidChange:(SDLRPCNotificationNotification *)notification { + if (![notification isNotificationMemberOfClass:[SDLOnPermissionsChange class]]) { + return; + } + + SDLOnPermissionsChange *onPermissionChange = notification.notification; + NSArray *permissionItems = onPermissionChange.permissionItem; + [self.permissions removeAllObjects]; + + for (SDLPermissionItem *item in permissionItems) { + self.permissions[item.rpcName] = item; + } + + self.requiresEncryption = (onPermissionChange.requireEncryption != nil) ? onPermissionChange.requireEncryption.boolValue : [self sdl_containsAtLeastOneRPCThatRequiresEncryption]; + + // if startWithProtocol has not been called yet, abort here + if (!self.protocol) { return; } + + if ([self.encryptionStateMachine isCurrentState:SDLEncryptionLifecycleManagerStateStopped]) { + [self sdl_startEncryptionService]; + } +} + +- (BOOL)sdl_appRequiresEncryption { + if (self.requiresEncryption && [self sdl_containsAtLeastOneRPCThatRequiresEncryption]) { + return YES; + } + return NO; +} + +- (BOOL)rpcRequiresEncryption:(__kindof SDLRPCMessage *)rpc { + if (self.permissions[rpc.name].requireEncryption != nil) { + return self.permissions[rpc.name].requireEncryption.boolValue; + } + return NO; +} + +- (BOOL)sdl_containsAtLeastOneRPCThatRequiresEncryption { + for (SDLPermissionItem *item in self.permissions.allValues) { + if (item.requireEncryption) { + return YES; + } + } + return NO; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLEncryptionManagerConstants.h b/SmartDeviceLink/SDLEncryptionManagerConstants.h new file mode 100644 index 000000000..43e00c365 --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionManagerConstants.h @@ -0,0 +1,18 @@ +// +// SDLEncryptionManagerConstants.h +// SmartDeviceLink +// +// Created by standa1 on 6/28/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString SDLEncryptionLifecycleManagerState; +extern SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateStopped; +extern SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateStarting; +extern SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateReady; + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLEncryptionManagerConstants.m b/SmartDeviceLink/SDLEncryptionManagerConstants.m new file mode 100644 index 000000000..80181d729 --- /dev/null +++ b/SmartDeviceLink/SDLEncryptionManagerConstants.m @@ -0,0 +1,13 @@ +// +// SDLEncryptionManagerConstants.m +// SmartDeviceLink +// +// Created by standa1 on 6/28/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import "SDLEncryptionManagerConstants.h" + +SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateStopped = @"EncryptionStopped"; +SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateStarting = @"EncryptionStarting"; +SDLEncryptionLifecycleManagerState *const SDLEncryptionLifecycleManagerStateReady = @"EncryptionReady"; diff --git a/SmartDeviceLink/SDLError.h b/SmartDeviceLink/SDLError.h index 715305a24..89cf49208 100644 --- a/SmartDeviceLink/SDLError.h +++ b/SmartDeviceLink/SDLError.h @@ -28,6 +28,11 @@ extern SDLErrorDomain *const SDLErrorDomainRPCStore; @interface NSError (SDLErrors) +#pragma mark SDLEncryptionLifecycleManager ++ (NSError *)sdl_encryption_lifecycle_notReadyError; ++ (NSError *)sdl_encryption_lifecycle_encryption_off; ++ (NSError *)sdl_encryption_lifecycle_nak; + #pragma mark SDLManager + (NSError *)sdl_lifecycle_rpcErrorWithDescription:(NSString *)description andReason:(NSString *)reason; diff --git a/SmartDeviceLink/SDLError.m b/SmartDeviceLink/SDLError.m index 8a716c5b0..efe518cb8 100644 --- a/SmartDeviceLink/SDLError.m +++ b/SmartDeviceLink/SDLError.m @@ -15,6 +15,7 @@ #pragma mark Error Domains SDLErrorDomain *const SDLErrorDomainLifecycleManager = @"com.sdl.lifecyclemanager.error"; +SDLErrorDomain *const SDLErrorDomainEncryptionLifecycleManager = @"com.sdl.encryptionlifecyclemanager.error"; SDLErrorDomain *const SDLErrorDomainFileManager = @"com.sdl.filemanager.error"; SDLErrorDomain *const SDLErrorDomainTextAndGraphicManager = @"com.sdl.textandgraphicmanager.error"; SDLErrorDomain *const SDLErrorDomainSoftButtonManager = @"com.sdl.softbuttonmanager.error"; @@ -25,6 +26,44 @@ @implementation NSError (SDLErrors) +#pragma mark - SDLEncryptionLifecycleManager ++ (NSError *)sdl_encryption_lifecycle_notReadyError { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Encryption Lifecycle manager not ready", nil), + NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The SDL library is not finished setting up the connection, please wait until the encryption lifecycleState is SDLEncryptionLifecycleStateReady", nil), + NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Make sure HMI is not NONE and at least one RPC requires encryption in permissions?", nil) + }; + + return [NSError errorWithDomain:SDLErrorDomainEncryptionLifecycleManager + code:SDLEncryptionLifecycleManagerErrorNotConnected + userInfo:userInfo]; +} + ++ (NSError *)sdl_encryption_lifecycle_encryption_off { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Encryption Lifecycle received a ACK with encryption bit = 0", nil), + NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The SDL library received ACK with encryption = OFF.", nil), + NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Make sure you are on a supported remote head unit with proper policies and your app id is approved.", nil) + }; + + return [NSError errorWithDomain:SDLErrorDomainEncryptionLifecycleManager + code:SDLEncryptionLifecycleManagerErrorEncryptionOff + userInfo:userInfo]; +} + ++ (NSError *)sdl_encryption_lifecycle_nak { + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: NSLocalizedString(@"Encryption Lifecycle received a negative acknowledgement", nil), + NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The remote head unit sent a NAK. Encryption service failed to start due to NAK.", nil), + NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Make sure your certificates are valid.", nil) + }; + + return [NSError errorWithDomain:SDLErrorDomainEncryptionLifecycleManager + code:SDLEncryptionLifecycleManagerErrorNAK + userInfo:userInfo]; + +} + #pragma mark - SDLManager + (NSError *)sdl_lifecycle_rpcErrorWithDescription:(NSString *)description andReason:(NSString *)reason { diff --git a/SmartDeviceLink/SDLErrorConstants.h b/SmartDeviceLink/SDLErrorConstants.h index f7c7bcc2a..66a9c2a70 100644 --- a/SmartDeviceLink/SDLErrorConstants.h +++ b/SmartDeviceLink/SDLErrorConstants.h @@ -8,6 +8,24 @@ #import +/** + * Errors associated with the SDLManager class. + */ +typedef NS_ENUM(NSInteger, SDLEncryptionLifecycleManagerError) { + /** + * Some action was attempted that requires a connection to the remote head unit. + */ + SDLEncryptionLifecycleManagerErrorNotConnected = -1, + /** + * Received ACK with encryption bit set to false from the remote head unit + */ + SDLEncryptionLifecycleManagerErrorEncryptionOff = -2, + /** + * Received NAK from the remote head unit. + */ + SDLEncryptionLifecycleManagerErrorNAK = -3 +}; + /** * Errors associated with the SDLManager class. */ diff --git a/SmartDeviceLink/SDLLifecycleManager.h b/SmartDeviceLink/SDLLifecycleManager.h index 067cd6af5..519cdbf8f 100644 --- a/SmartDeviceLink/SDLLifecycleManager.h +++ b/SmartDeviceLink/SDLLifecycleManager.h @@ -118,6 +118,11 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error); */ - (void)stop; +/** + * Start the encryption lifecycle manager, which will attempt to open a secure service. + * + */ +- (void)startRPCEncryption; #pragma mark Send RPC Requests diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index f3628a809..6fc6f5b0d 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -16,8 +16,10 @@ #import "SDLChangeRegistration.h" #import "SDLConfiguration.h" #import "SDLConnectionManagerType.h" +#import "SDLEncryptionConfiguration.h" #import "SDLLogMacros.h" #import "SDLError.h" +#import "SDLEncryptionLifecycleManager.h" #import "SDLFile.h" #import "SDLFileManager.h" #import "SDLFileManagerConfiguration.h" @@ -91,6 +93,7 @@ @interface SDLLifecycleManager () *)sdl_getNextCorrelationId { if (self.lastCorrelationId == INT32_MAX) { @@ -718,11 +754,13 @@ - (nullable NSString *)authToken { #pragma mark SDL notification observers - (void)transportDidConnect { - SDLLogD(@"Transport connected"); + if (![self.lifecycleStateMachine isCurrentState:SDLLifecycleStateReady]) { + SDLLogD(@"Transport connected"); - dispatch_async(self.lifecycleQueue, ^{ - [self sdl_transitionToState:SDLLifecycleStateConnected]; - }); + dispatch_async(self.lifecycleQueue, ^{ + [self sdl_transitionToState:SDLLifecycleStateConnected]; + }); + } } - (void)transportDidDisconnect { diff --git a/SmartDeviceLink/SDLLogFileModuleMap.m b/SmartDeviceLink/SDLLogFileModuleMap.m index 53efda21e..4e8ed5808 100644 --- a/SmartDeviceLink/SDLLogFileModuleMap.m +++ b/SmartDeviceLink/SDLLogFileModuleMap.m @@ -19,6 +19,7 @@ @implementation SDLLogFileModuleMap [self sdl_rpcModule], [self sdl_dispatcherModule], [self sdl_fileManagerModule], + [self sdl_encryptionLifecycleManagerModule], [self sdl_lifecycleManagerModule], [self sdl_systemCapabilityModule], [self sdl_lockscreenManagerModule], @@ -59,6 +60,10 @@ + (SDLLogFileModule *)sdl_fileManagerModule { return [SDLLogFileModule moduleWithName:@"File" files:[NSSet setWithArray:@[@"SDLFileManager", @"SDLFile", @"SDLArtwork", @"SDLListFilesOperation", @"SDLUploadFileOperation", @"SDLDeleteFileOperation"]]]; } ++ (SDLLogFileModule *)sdl_encryptionLifecycleManagerModule { + return [SDLLogFileModule moduleWithName:@"Encryption" files:[NSSet setWithArray:@[@"SDLEncryptionLifecycleManager", @"SDLEncryptionConfiguration", @"SDLEncryptionManagerConstants"]]]; +} + + (SDLLogFileModule *)sdl_lifecycleManagerModule { return [SDLLogFileModule moduleWithName:@"Lifecycle" files:[NSSet setWithArray:@[@"SDLLifecycleManager", @"SDLManager", @"SDLAsynchronousOperation", @"SDLBackgroundTaskManager"]]]; } diff --git a/SmartDeviceLink/SDLManager.h b/SmartDeviceLink/SDLManager.h index 9764f3f3a..0e3f22f3e 100644 --- a/SmartDeviceLink/SDLManager.h +++ b/SmartDeviceLink/SDLManager.h @@ -135,6 +135,12 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error); */ - (void)stop; +/** + * Start the encryption lifecycle manager, which will attempt to open a secure service. + * + * Please call this method in the successful callback of startWithReadyHandler. If you do call this method, you must wait for SDLServiceEncryptionDelegate's serviceEncryptionUpdatedOnService delegate method before you send any encrypted RPCs. + */ +- (void)startRPCEncryption; #pragma mark Manually Send RPC Requests diff --git a/SmartDeviceLink/SDLManager.m b/SmartDeviceLink/SDLManager.m index b198f7e52..e9cb1c5c3 100644 --- a/SmartDeviceLink/SDLManager.m +++ b/SmartDeviceLink/SDLManager.m @@ -65,6 +65,9 @@ - (void)stop { [self.lifecycleManager stop]; } +- (void)startRPCEncryption { + [self.lifecycleManager startRPCEncryption]; +} #pragma mark - Passthrough getters / setters diff --git a/SmartDeviceLink/SDLOnPermissionsChange.h b/SmartDeviceLink/SDLOnPermissionsChange.h index 60fb9329c..244bbc08f 100644 --- a/SmartDeviceLink/SDLOnPermissionsChange.h +++ b/SmartDeviceLink/SDLOnPermissionsChange.h @@ -22,6 +22,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, nonatomic) NSArray *permissionItem; +/** + Describes whether or not the app needs the encryption permission + + Optional, Boolean, since SDL 6.0 + */ +@property (strong, nonatomic, nullable) NSNumber *requireEncryption; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLOnPermissionsChange.m b/SmartDeviceLink/SDLOnPermissionsChange.m index 11250c209..a067e084c 100644 --- a/SmartDeviceLink/SDLOnPermissionsChange.m +++ b/SmartDeviceLink/SDLOnPermissionsChange.m @@ -30,6 +30,14 @@ - (void)setPermissionItem:(NSArray *)permissionItem { return [self.parameters sdl_objectsForName:SDLRPCParameterNamePermissionItem ofClass:SDLPermissionItem.class error:&error]; } +- (void)setRequireEncryption:(nullable NSNumber *)requireEncryption { + [self.parameters sdl_setObject:requireEncryption forName:SDLRPCParameterNameRequireEncryption]; +} + +- (nullable NSNumber *)requireEncryption { + return [self.parameters sdl_objectForName:SDLRPCParameterNameRequireEncryption ofClass:NSNumber.class error:nil]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLPermissionItem.h b/SmartDeviceLink/SDLPermissionItem.h index 990e84581..1b363b068 100644 --- a/SmartDeviceLink/SDLPermissionItem.h +++ b/SmartDeviceLink/SDLPermissionItem.h @@ -31,6 +31,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (strong, nonatomic) SDLParameterPermissions *parameterPermissions; +/** + Describes whether or not the RPC needs encryption + + Optional, Boolean, since SDL 6.0 + */ +@property (strong, nonatomic, nullable) NSNumber *requireEncryption; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLPermissionItem.m b/SmartDeviceLink/SDLPermissionItem.m index 501ad20f5..b4c749b59 100644 --- a/SmartDeviceLink/SDLPermissionItem.m +++ b/SmartDeviceLink/SDLPermissionItem.m @@ -39,6 +39,15 @@ - (SDLParameterPermissions *)parameterPermissions { return [self.store sdl_objectForName:SDLRPCParameterNameParameterPermissions ofClass:SDLParameterPermissions.class error:&error]; } +- (void)setRequireEncryption:(nullable NSNumber *)requireEncryption { + [self.store sdl_setObject:requireEncryption forName:SDLRPCParameterNameRequireEncryption]; +} + +- (nullable NSNumber *)requireEncryption { + NSError *error = nil; + return [self.store sdl_objectForName:SDLRPCParameterNameRequireEncryption ofClass:NSNumber.class error:&error]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLPermissionManager.h b/SmartDeviceLink/SDLPermissionManager.h index 99ace1b2a..90dcb8680 100644 --- a/SmartDeviceLink/SDLPermissionManager.h +++ b/SmartDeviceLink/SDLPermissionManager.h @@ -12,12 +12,17 @@ #import "SDLPermissionConstants.h" @class SDLPermissionItem; - +@class SDLRPCMessage; NS_ASSUME_NONNULL_BEGIN @interface SDLPermissionManager : NSObject +/** + * Flag indicating if the app requires an encryption service to be active. + */ +@property (assign, nonatomic, readonly) BOOL requiresEncryption; + /** * Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLPermissionManager, you should use the manager found on `SDLManager`. * @@ -84,6 +89,12 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)removeObserverForIdentifier:(SDLPermissionObserverIdentifier)identifier; + +/** + * Check whether or not an RPC needs encryption. + */ +- (BOOL)rpcRequiresEncryption:(SDLPermissionRPCName)rpcName; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLPermissionManager.m b/SmartDeviceLink/SDLPermissionManager.m index e68990faa..cdb08e135 100644 --- a/SmartDeviceLink/SDLPermissionManager.m +++ b/SmartDeviceLink/SDLPermissionManager.m @@ -26,6 +26,7 @@ @interface SDLPermissionManager () @property (strong, nonatomic) NSMutableDictionary *permissions; @property (strong, nonatomic) NSMutableArray *filters; @property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; +@property (assign, nonatomic) BOOL requiresEncryption; @end @@ -182,6 +183,7 @@ - (void)sdl_permissionsDidChange:(SDLRPCNotificationNotification *)notification } SDLOnPermissionsChange *onPermissionChange = notification.notification; + NSArray *newPermissionItems = [onPermissionChange.permissionItem copy]; NSArray *currentFilters = [self.filters copy]; @@ -217,6 +219,8 @@ - (void)sdl_permissionsDidChange:(SDLRPCNotificationNotification *)notification for (SDLPermissionFilter *filter in filtersToCall) { [self sdl_callFilterObserver:filter]; } + + self.requiresEncryption = (onPermissionChange.requireEncryption != nil) ? onPermissionChange.requireEncryption.boolValue : [self sdl_containsAtLeastOneRPCThatRequiresEncryption]; } - (void)sdl_hmiLevelDidChange:(SDLRPCNotificationNotification *)notification { @@ -354,6 +358,22 @@ - (BOOL)sdl_didFilterChange:(SDLPermissionFilter *)filter fromHMILevel:(SDLHMILe return [modifiedPermissions copy]; } +- (BOOL)sdl_containsAtLeastOneRPCThatRequiresEncryption { + for (SDLPermissionItem *item in self.permissions.allValues) { + if (item.requireEncryption) { + return YES; + } + } + return NO; +} + +- (BOOL)rpcRequiresEncryption:(SDLPermissionRPCName)rpcName { + if (self.permissions[rpcName].requireEncryption != nil) { + return self.permissions[rpcName].requireEncryption.boolValue; + } + return NO; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLProtocol.h b/SmartDeviceLink/SDLProtocol.h index 82777f167..4f8954026 100644 --- a/SmartDeviceLink/SDLProtocol.h +++ b/SmartDeviceLink/SDLProtocol.h @@ -9,6 +9,7 @@ #import "SDLSecurityType.h" #import "SDLTransportDelegate.h" +@class SDLEncryptionLifecycleManager; @class SDLProtocolHeader; @class SDLProtocolRecievedMessageRouter; @class SDLRPCMessage; @@ -61,6 +62,16 @@ extern NSString *const SDLProtocolSecurityErrorDomain; */ @property (strong, nonatomic, readonly, nullable) NSString *authToken; +#pragma mark - Init +/** + * Initialize the protocol with an encryption lifecycle manager. + * + * @param encryptionLifecycleManager An encryption lifecycle manager. + * + * @return An instance of SDLProtocol + */ +- (instancetype)initWithEncryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager; + #pragma mark - Sending /** @@ -87,9 +98,9 @@ extern NSString *const SDLProtocolSecurityErrorDomain; * * @param serviceType A SDLServiceType object * @param payload The data to send in the message - * @param completionHandler The handler is called when the secure service is started. If a secure service can not be started, an error message is also returned + * @param tlsInitializationHandler Handler called when the app is authenticated via TLS handshake and a secure service has started. If a secure service can not be started an error message is returned. */ -- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload completionHandler:(void (^)(BOOL success, NSError *error))completionHandler; +- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload tlsInitializationHandler:(void (^)(BOOL success, NSError *error))tlsInitializationHandler; /** * Sends an end service message to Core @@ -110,16 +121,6 @@ extern NSString *const SDLProtocolSecurityErrorDomain; */ - (void)sendRPC:(SDLRPCMessage *)message; -/** - * Sends an RPC to Core - * - * @param message A SDLRPCMessage message - * @param encryption Whether or not the message should be encrypted - * @param error A pointer to a NSError object - * @return YES if the message was created successfully, NO if not - */ -- (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSError **)error; - /** * Sends an unencrypted message to Core * diff --git a/SmartDeviceLink/SDLProtocol.m b/SmartDeviceLink/SDLProtocol.m index 5adfd5b88..f71da8354 100644 --- a/SmartDeviceLink/SDLProtocol.m +++ b/SmartDeviceLink/SDLProtocol.m @@ -11,6 +11,7 @@ #import "SDLControlFramePayloadRegisterSecondaryTransportNak.h" #import "SDLControlFramePayloadRPCStartService.h" #import "SDLControlFramePayloadRPCStartServiceAck.h" +#import "SDLEncryptionLifecycleManager.h" #import "SDLLogMacros.h" #import "SDLGlobals.h" #import "SDLPrioritizedObjectCollection.h" @@ -46,6 +47,7 @@ @interface SDLProtocol () { @property (nullable, strong, nonatomic) SDLProtocolReceivedMessageRouter *messageRouter; @property (strong, nonatomic) NSMutableDictionary *serviceHeaders; @property (assign, nonatomic) int32_t hashId; +@property (nonatomic, strong) SDLEncryptionLifecycleManager *encryptionLifecycleManager; // Readonly public properties @property (strong, nonatomic, readwrite, nullable) NSString *authToken; @@ -73,6 +75,20 @@ - (instancetype)init { return self; } +- (instancetype)initWithEncryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager { + if (self = [super init]) { + _messageID = 0; + _hashId = SDLControlFrameInt32NotFound; + _prioritizedCollection = [[SDLPrioritizedObjectCollection alloc] init]; + _protocolDelegateTable = [NSHashTable weakObjectsHashTable]; + _serviceHeaders = [[NSMutableDictionary alloc] init]; + _messageRouter = [[SDLProtocolReceivedMessageRouter alloc] init]; + _messageRouter.delegate = self; + _encryptionLifecycleManager = encryptionLifecycleManager; + } + + return self; +} #pragma mark - Service metadata - (BOOL)storeHeader:(SDLProtocolHeader *)header forServiceType:(SDLServiceType)serviceType { @@ -140,11 +156,11 @@ - (void)startServiceWithType:(SDLServiceType)serviceType payload:(nullable NSDat [self sdl_sendDataToTransport:message.data onService:serviceType]; } -- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload completionHandler:(void (^)(BOOL success, NSError *error))completionHandler { +- (void)startSecureServiceWithType:(SDLServiceType)serviceType payload:(nullable NSData *)payload tlsInitializationHandler:(void (^)(BOOL success, NSError *error))tlsInitializationHandler { [self sdl_initializeTLSEncryptionWithCompletionHandler:^(BOOL success, NSError *error) { if (!success) { // We can't start the service because we don't have encryption, return the error - completionHandler(success, error); + tlsInitializationHandler(success, error); BLOCK_RETURN; } @@ -161,7 +177,6 @@ - (SDLProtocolMessage *)sdl_createStartServiceMessageWithType:(SDLServiceType)se switch (serviceType) { case SDLServiceTypeRPC: { // Need a different header for starting the RPC service, we get the session Id from the HU, or its the same as the RPC service's - header = [SDLProtocolHeader headerForVersion:1]; if ([self sdl_retrieveSessionIDforServiceType:SDLServiceTypeRPC]) { header.sessionID = [self sdl_retrieveSessionIDforServiceType:SDLServiceTypeRPC]; } else { @@ -257,7 +272,16 @@ - (void)registerSecondaryTransport { #pragma mark - Send Data - (void)sendRPC:(SDLRPCMessage *)message { - [self sendRPC:message encrypted:NO error:nil]; + if (!message.isPayloadProtected && [self.encryptionLifecycleManager rpcRequiresEncryption:message]) { + message.payloadProtected = YES; + } + + if (message.isPayloadProtected && !self.encryptionLifecycleManager.isEncryptionReady) { + SDLLogW(@"Encryption Manager not ready, request not sent (%@)", message); + return; + } + + [self sendRPC:message encrypted:message.isPayloadProtected error:nil]; } - (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSError *__autoreleasing *)error { @@ -309,10 +333,22 @@ - (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSErr // If we're trying to encrypt, try to have the security manager encrypt it. Return if it fails. // TODO: (Joel F.)[2016-02-09] We should assert if the service isn't setup for encryption. See [#350](https://github.com/smartdevicelink/sdl_ios/issues/350) - messagePayload = encryption ? [self.securityManager encryptData:rpcPayload.data withError:error] : rpcPayload.data; + if (encryption) { + NSError *encryptError = nil; + + messagePayload = [self.securityManager encryptData:rpcPayload.data withError:&encryptError]; + + if (encryptError) { + SDLLogE(@"Error encrypting request! %@", encryptError); + } + } else { + messagePayload = rpcPayload.data; + } + if (!messagePayload) { return NO; } + } break; default: { NSAssert(NO, @"Attempting to send an RPC based on an unknown version number: %@, message: %@", @([SDLGlobals sharedGlobals].protocolVersion.major), message); diff --git a/SmartDeviceLink/SDLProtocolMessage.m b/SmartDeviceLink/SDLProtocolMessage.m index 81fc23e82..eddd2288e 100644 --- a/SmartDeviceLink/SDLProtocolMessage.m +++ b/SmartDeviceLink/SDLProtocolMessage.m @@ -50,6 +50,10 @@ - (NSData *)data { } - (NSString *)description { + if (_header.encrypted) { + return @"Encrypted header, description overflows"; + } + // Print the header data. NSMutableString *description = [[NSMutableString alloc] init]; [description appendString:self.header.description]; diff --git a/SmartDeviceLink/SDLProxy.h b/SmartDeviceLink/SDLProxy.h index 9049cf93f..60a68f44c 100644 --- a/SmartDeviceLink/SDLProxy.h +++ b/SmartDeviceLink/SDLProxy.h @@ -1,6 +1,7 @@ // SDLProxy.h // +@class SDLEncryptionLifecycleManager; @class SDLProtocol; @class SDLPutFile; @class SDLRPCMessage; @@ -61,9 +62,10 @@ NS_ASSUME_NONNULL_BEGIN * * @param delegate The subscriber * @param secondaryTransportManager The secondary transport manager + * @param encryptionLifecycleManager The encryption life cycle manager * @return A SDLProxy object */ -+ (SDLProxy *)iapProxyWithListener:(id)delegate secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager; ++ (SDLProxy *)iapProxyWithListener:(id)delegate secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager encryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager; /** * Creates a SDLProxy object with a TCP (WiFi) transport network connection. @@ -72,9 +74,10 @@ NS_ASSUME_NONNULL_BEGIN * @param ipaddress The IP address of Core * @param port The port address of Core * @param secondaryTransportManager The secondary transport manager + * @param encryptionLifecycleManager The encryption life cycle manager * @return A SDLProxy object */ -+ (SDLProxy *)tcpProxyWithListener:(id)delegate tcpIPAddress:(NSString *)ipaddress tcpPort:(NSString *)port secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager; ++ (SDLProxy *)tcpProxyWithListener:(id)delegate tcpIPAddress:(NSString *)ipaddress tcpPort:(NSString *)port secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager encryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager; /** * Adds a delegate. diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m index f32b3de94..ae65a2e39 100644 --- a/SmartDeviceLink/SDLProxy.m +++ b/SmartDeviceLink/SDLProxy.m @@ -8,6 +8,7 @@ #import "SDLAudioStreamingState.h" #import "SDLLogMacros.h" #import "SDLEncodedSyncPData.h" +#import "SDLEncryptionLifecycleManager.h" #import "SDLFileType.h" #import "SDLFunctionID.h" #import "SDLGlobals.h" @@ -107,6 +108,42 @@ - (instancetype)initWithTransport:(id)transport delegate:(id)transport delegate:(id)delegate secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager encryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager { + if (self = [super init]) { + SDLLogD(@"Framework Version: %@", self.proxyVersion); + _lsm = [[SDLLockScreenStatusManager alloc] init]; + _mutableProxyListeners = [NSMutableSet setWithObject:delegate]; + _securityManagers = [NSMutableDictionary dictionary]; + + _protocol = [[SDLProtocol alloc] initWithEncryptionLifecycleManager:encryptionLifecycleManager]; + _transport = transport; + _transport.delegate = _protocol; + + [_protocol.protocolDelegateTable addObject:self]; + _protocol.transport = transport; + + // make sure that secondary transport manager is started prior to starting protocol + if (secondaryTransportManager != nil) { + [secondaryTransportManager startWithPrimaryProtocol:_protocol]; + } + + [self.transport connect]; + + SDLLogV(@"Proxy transport initialization"); + + NSURLSessionConfiguration* configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + configuration.timeoutIntervalForRequest = DefaultConnectionTimeout; + configuration.timeoutIntervalForResource = DefaultConnectionTimeout; + configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; + + _urlSession = [NSURLSession sessionWithConfiguration:configuration]; + + } + + return self; +} + + + (SDLProxy *)iapProxyWithListener:(id)delegate secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager { SDLIAPTransport *transport = [[SDLIAPTransport alloc] init]; SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport delegate:delegate secondaryTransportManager:secondaryTransportManager]; @@ -122,6 +159,21 @@ + (SDLProxy *)tcpProxyWithListener:(id)delegate tcpIPAddress:( return ret; } ++ (SDLProxy *)iapProxyWithListener:(id)delegate secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager encryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager { + SDLIAPTransport *transport = [[SDLIAPTransport alloc] init]; + SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport delegate:delegate secondaryTransportManager:secondaryTransportManager encryptionLifecycleManager:encryptionLifecycleManager]; + + return ret; +} + ++ (SDLProxy *)tcpProxyWithListener:(id)delegate tcpIPAddress:(NSString *)ipaddress tcpPort:(NSString *)port secondaryTransportManager:(nullable SDLSecondaryTransportManager *)secondaryTransportManager encryptionLifecycleManager:(SDLEncryptionLifecycleManager *)encryptionLifecycleManager { + SDLTCPTransport *transport = [[SDLTCPTransport alloc] initWithHostName:ipaddress portNumber:port]; + + SDLProxy *ret = [[SDLProxy alloc] initWithTransport:transport delegate:delegate secondaryTransportManager:secondaryTransportManager encryptionLifecycleManager:encryptionLifecycleManager]; + + return ret; +} + - (void)dealloc { if (self.protocol.securityManager != nil) { [self.protocol.securityManager stop]; diff --git a/SmartDeviceLink/SDLRPCParameterNames.h b/SmartDeviceLink/SDLRPCParameterNames.h index 718d42bfc..e6541968a 100644 --- a/SmartDeviceLink/SDLRPCParameterNames.h +++ b/SmartDeviceLink/SDLRPCParameterNames.h @@ -517,6 +517,7 @@ extern SDLRPCParameterName const SDLRPCParameterNameRequest; extern SDLRPCParameterName const SDLRPCParameterNameRequestServiceActive; extern SDLRPCParameterName const SDLRPCParameterNameRequestSubType; extern SDLRPCParameterName const SDLRPCParameterNameRequestType; +extern SDLRPCParameterName const SDLRPCParameterNameRequireEncryption; extern SDLRPCParameterName const SDLRPCParameterNameReserved; extern SDLRPCParameterName const SDLRPCParameterNameResolution; extern SDLRPCParameterName const SDLRPCParameterNameResolutionHeight; diff --git a/SmartDeviceLink/SDLRPCParameterNames.m b/SmartDeviceLink/SDLRPCParameterNames.m index c928fcb30..85a88b1d4 100644 --- a/SmartDeviceLink/SDLRPCParameterNames.m +++ b/SmartDeviceLink/SDLRPCParameterNames.m @@ -511,6 +511,7 @@ SDLRPCParameterName const SDLRPCParameterNameRequestServiceActive = @"requestServiceActive"; SDLRPCParameterName const SDLRPCParameterNameRequestSubType = @"requestSubType"; SDLRPCParameterName const SDLRPCParameterNameRequestType = @"requestType"; +SDLRPCParameterName const SDLRPCParameterNameRequireEncryption = @"requireEncryption"; SDLRPCParameterName const SDLRPCParameterNameReserved = @"reserved"; SDLRPCParameterName const SDLRPCParameterNameSecondaryColor = @"secondaryColor"; SDLRPCParameterName const SDLRPCParameterNameResolution = @"resolution"; diff --git a/SmartDeviceLink/SDLRPCStruct.h b/SmartDeviceLink/SDLRPCStruct.h index 7813c960b..25db21f16 100644 --- a/SmartDeviceLink/SDLRPCStruct.h +++ b/SmartDeviceLink/SDLRPCStruct.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN @interface SDLRPCStruct : NSObject @property (strong, nonatomic, readonly) NSMutableDictionary *store; - +@property (assign, nonatomic, getter=isPayloadProtected) BOOL payloadProtected; /** * Convenience init * diff --git a/SmartDeviceLink/SDLRPCStruct.m b/SmartDeviceLink/SDLRPCStruct.m index 4a634959a..e3de83f73 100644 --- a/SmartDeviceLink/SDLRPCStruct.m +++ b/SmartDeviceLink/SDLRPCStruct.m @@ -18,6 +18,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict { } _store = [dict mutableCopy]; + _payloadProtected = NO; return self; } @@ -29,6 +30,7 @@ - (instancetype)init { } _store = [NSMutableDictionary dictionary]; + _payloadProtected = NO; return self; } @@ -84,6 +86,7 @@ - (NSString *)description { - (id)copyWithZone:(nullable NSZone *)zone { SDLRPCStruct *newStruct = [[[self class] allocWithZone:zone] initWithDictionary:_store]; + newStruct.payloadProtected = self.payloadProtected; return newStruct; } diff --git a/SmartDeviceLink/SDLResult.h b/SmartDeviceLink/SDLResult.h index fe9820475..dd966102e 100644 --- a/SmartDeviceLink/SDLResult.h +++ b/SmartDeviceLink/SDLResult.h @@ -208,3 +208,8 @@ extern SDLResult const SDLResultDataNotAvailable; The requested data is read only thus cannot be change via remote control . */ extern SDLResult const SDLResultReadOnly; + +/** + The RPC request needs to be encrypted. + */ +extern SDLResult const SDLResultEncryptionNeeded; diff --git a/SmartDeviceLink/SDLResult.m b/SmartDeviceLink/SDLResult.m index 5e169c3a2..234fb4eea 100644 --- a/SmartDeviceLink/SDLResult.m +++ b/SmartDeviceLink/SDLResult.m @@ -40,4 +40,4 @@ SDLResult const SDLResultResumeFailed = @"RESUME_FAILED"; SDLResult const SDLResultDataNotAvailable = @"DATA_NOT_AVAILABLE"; SDLResult const SDLResultReadOnly = @"READ_ONLY"; - +SDLResult const SDLResultEncryptionNeeded = @"ENCRYPTION_NEEDED"; diff --git a/SmartDeviceLink/SDLServiceEncryptionDelegate.h b/SmartDeviceLink/SDLServiceEncryptionDelegate.h new file mode 100644 index 000000000..aa63cf12a --- /dev/null +++ b/SmartDeviceLink/SDLServiceEncryptionDelegate.h @@ -0,0 +1,28 @@ +// +// SDLServiceEncryptionDelegate.h +// SmartDeviceLink +// +// Created by Tanda, Satbir (S.S.) on 9/5/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import + +#import "SDLProtocolConstants.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol SDLServiceEncryptionDelegate + +/** + * Called when the encryption service has been. + * + * @param type will return whichever type had an encryption update (for now probably only SDLServiceTypeRPC), but it could also apply to video / audio in the future. + * @param encrypted return true if the the encryption service was setup successfully, will return false if the service is presently not encrypted. + * @param error will return any error that happens or nil if there is no error. + */ +- (void)serviceEncryptionUpdatedOnService:(SDLServiceType)type encrypted:(BOOL)encrypted error:(NSError *__nullable)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h index 0ec3cc5bf..1d034ef97 100644 --- a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h @@ -17,6 +17,7 @@ @class SDLProtocol; @class SDLStateMachine; @class SDLStreamingMediaConfiguration; +@class SDLEncryptionConfiguration; @protocol SDLConnectionManagerType; @@ -64,10 +65,11 @@ NS_ASSUME_NONNULL_BEGIN Create a new streaming media manager for navigation and VPM apps with a specified configuration @param connectionManager The pass-through for RPCs - @param configuration The configuration of this streaming media session + @param streamingConfiguration The configuration of this streaming media session + @param encryptionConfiguration The encryption configuration with security managers @return A new streaming manager */ -- (instancetype)initWithConnectionManager:(id)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithConnectionManager:(id)connectionManager streamingConfiguration:(SDLStreamingMediaConfiguration *)streamingConfiguration encryptionConfiguration:(SDLEncryptionConfiguration *)encryptionConfiguration NS_DESIGNATED_INITIALIZER; /** * Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLStreamingMediaManager, you should use the manager found on `SDLManager`. diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m index 2f1faf28f..7f1fa6ba6 100644 --- a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m @@ -26,6 +26,7 @@ #import "SDLRPCResponseNotification.h" #import "SDLStateMachine.h" #import "SDLStreamingMediaConfiguration.h" +#import "SDLEncryptionConfiguration.h" #import "SDLVehicleType.h" @@ -46,7 +47,7 @@ @interface SDLStreamingAudioLifecycleManager() @implementation SDLStreamingAudioLifecycleManager -- (instancetype)initWithConnectionManager:(id)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration { +- (instancetype)initWithConnectionManager:(id)connectionManager streamingConfiguration:(SDLStreamingMediaConfiguration *)streamingConfiguration encryptionConfiguration:(SDLEncryptionConfiguration *)encryptionConfiguration { self = [super init]; if (!self) { return nil; @@ -58,13 +59,20 @@ - (instancetype)initWithConnectionManager:(id)connecti _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self]; - _requestedEncryptionType = configuration.maximumDesiredEncryption; + _requestedEncryptionType = streamingConfiguration.maximumDesiredEncryption; NSMutableArray *tempMakeArray = [NSMutableArray array]; - for (Class securityManagerClass in configuration.securityManagers) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + for (Class securityManagerClass in streamingConfiguration.securityManagers) { + [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects]; + } +#pragma clang diagnostic pop + for (Class securityManagerClass in encryptionConfiguration.securityManagers) { [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects]; } - _secureMakes = [tempMakeArray copy]; + NSOrderedSet *tempMakeSet = [NSOrderedSet orderedSetWithArray:tempMakeArray]; + _secureMakes = [tempMakeSet.array copy]; _audioStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLAudioStreamManagerStateStopped states:[self.class sdl_audioStreamingStateTransitionDictionary]]; @@ -140,7 +148,7 @@ - (void)didEnterStateAudioStreamStopped { - (void)didEnterStateAudioStreamStarting { SDLLogD(@"Audio stream starting"); if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) { - [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil completionHandler:^(BOOL success, NSError * _Nonnull error) { + [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil tlsInitializationHandler:^(BOOL success, NSError * _Nonnull error) { if (error) { SDLLogE(@"TLS setup error: %@", error); [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped]; diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h index 3e4f91849..b000b6ba8 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.h +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h @@ -34,7 +34,7 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { /** * Set security managers which could be used. This is primarily used with video streaming applications to authenticate and perhaps encrypt traffic data. */ -@property (copy, nonatomic, nullable) NSArray> *securityManagers; +@property (copy, nonatomic, nullable) NSArray> *securityManagers __deprecated_msg("This is now unused, the security managers are taken in from SDLEncryptionConfiguration"); /** * What encryption level video/audio streaming should be. The default is SDLStreamingEncryptionFlagAuthenticateAndEncrypt. @@ -92,6 +92,13 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { */ - (instancetype)init; +/** + Create a secure video streaming configuration. Security managers will be provided from SDLEncryptionConfiguration and the encryption flag will be set to SDLStreamingEncryptionFlagAuthenticateAndEncrypt. If you'd like custom video encoder settings, you can set the property manually. + + @return The configuration + */ ++ (instancetype)secureConfiguration; + /** Manually set all the properties to the streaming media configuration @@ -101,7 +108,17 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { @param rootViewController The UIViewController wih the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews) @return The configuration */ -- (instancetype)initWithSecurityManagers:(nullable NSArray> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary *)videoSettings dataSource:(nullable id)dataSource rootViewController:(nullable UIViewController *)rootViewController; +- (instancetype)initWithSecurityManagers:(nullable NSArray> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary *)videoSettings dataSource:(nullable id)dataSource rootViewController:(nullable UIViewController *)rootViewController __deprecated_msg("Use initWithEncryptionFlag:videoSettings:dataSource:rootViewController: instead"); + +/** + Manually set all the properties to the streaming media configuration + + @param encryptionFlag The maximum encrpytion supported. If the connected head unit supports less than set here, it will still connect, but if it supports more than set here, it will not connect. + @param videoSettings Custom video encoder settings to be used in video streaming. + @param rootViewController The UIViewController wih the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews) + @return The configuration + */ +- (instancetype)initWithEncryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary *)videoSettings dataSource:(nullable id)dataSource rootViewController:(nullable UIViewController *)rootViewController; /** Create a secure configuration for each of the security managers provided. @@ -109,7 +126,7 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. @return The configuration */ -- (instancetype)initWithSecurityManagers:(NSArray> *)securityManagers; +- (instancetype)initWithSecurityManagers:(NSArray> *)securityManagers __deprecated_msg("Use secureConfiguration instead"); /** Create a secure configuration for each of the security managers provided. @@ -117,7 +134,7 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. @return The configuration */ -+ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers NS_SWIFT_UNAVAILABLE("Use an initializer instead"); ++ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers NS_SWIFT_UNAVAILABLE("Use an initializer instead") __deprecated_msg("Use secureConfiguration instead"); /** Create an insecure video streaming configuration. No security managers will be provided and the encryption flag will be set to None. If you'd like custom video encoder settings, you can set the property manually. This is equivalent to `init`. @@ -141,7 +158,15 @@ typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) { @param initialViewController The initial view controller that will be streamed, this can be a basic `UIViewController` if you need to set your actual streaming view controller at a later time on `SDLManager.streamingManager.rootViewController`. @return The configuration */ -+ (instancetype)autostreamingSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers initialViewController:(UIViewController *)initialViewController; ++ (instancetype)autostreamingSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers initialViewController:(UIViewController *)initialViewController __deprecated_msg("Use autostreamingSecureConfigurationWithInitialViewController: instead"); + +/** + Create a CarWindow secure configuration with a view controller. + + @param initialViewController The initial view controller that will be streamed, this can be a basic `UIViewController` if you need to set your actual streaming view controller at a later time on `SDLManager.streamingManager.rootViewController`. + @return The configuration + */ ++ (instancetype)autostreamingSecureConfigurationWithInitialViewController:(UIViewController *)initialViewController; @end diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m index 41c7df822..4c82ddcfd 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.m +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m @@ -16,7 +16,14 @@ @implementation SDLStreamingMediaConfiguration - (instancetype)init { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [self initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil dataSource:nil rootViewController:nil]; +#pragma clang diagnostic pop +} + ++ (instancetype)secureConfiguration { + return [[self alloc] initWithEncryptionFlag:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoSettings:nil dataSource:nil rootViewController:nil]; } + (instancetype)insecureConfiguration { @@ -41,6 +48,23 @@ - (instancetype)initWithSecurityManagers:(nullable NSArray *)videoSettings dataSource:(nullable id)dataSource rootViewController:(nullable UIViewController *)rootViewController { + if (!self) { + return nil; + } + + _securityManagers = nil; + _maximumDesiredEncryption = encryptionFlag; + _customVideoEncoderSettings = videoSettings; + _dataSource = dataSource; + _rootViewController = rootViewController; + _carWindowRenderingType = SDLCarWindowRenderingTypeLayer; + _enableForcedFramerateSync = YES; + _allowMultipleViewControllerOrientations = NO; + + return self; +} + - (instancetype)initWithSecurityManagers:(NSArray> *)securityManagers { NSAssert(securityManagers.count > 0, @"A secure streaming media configuration requires security managers to be passed."); SDLStreamingEncryptionFlag encryptionFlag = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; @@ -49,21 +73,34 @@ - (instancetype)initWithSecurityManagers:(NSArray> *)secu } + (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [[self alloc] initWithSecurityManagers:securityManagers]; +#pragma clang diagnostic pop } + (instancetype)autostreamingInsecureConfigurationWithInitialViewController:(UIViewController *)initialViewController { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [[self alloc] initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil dataSource:nil rootViewController:initialViewController]; +#pragma clang diagnostic pop } + (instancetype)autostreamingSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers initialViewController:(UIViewController *)initialViewController { return [[self alloc] initWithSecurityManagers:securityManagers encryptionFlag:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoSettings:nil dataSource:nil rootViewController:initialViewController]; } ++ (instancetype)autostreamingSecureConfigurationWithInitialViewController:(UIViewController *)initialViewController { + return [[self alloc] initWithEncryptionFlag:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoSettings:nil dataSource:nil rootViewController:initialViewController]; +} + #pragma mark NSCopying - (id)copyWithZone:(nullable NSZone *)zone { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLStreamingMediaConfiguration *newConfig = [[self.class allocWithZone:zone] initWithSecurityManagers:_securityManagers encryptionFlag:_maximumDesiredEncryption videoSettings:_customVideoEncoderSettings dataSource:_dataSource rootViewController:_rootViewController]; +#pragma clang diagnostic pop newConfig.carWindowRenderingType = self.carWindowRenderingType; newConfig.enableForcedFramerateSync = self.enableForcedFramerateSync; diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 9b7258824..a1c81facc 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -40,7 +40,7 @@ - (instancetype)initWithConnectionManager:(id)connecti return nil; } - _audioLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration.streamingMediaConfig]; + _audioLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:connectionManager streamingConfiguration: configuration.streamingMediaConfig encryptionConfiguration:configuration.encryptionConfig]; _videoLifecycleManager = [[SDLStreamingVideoLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration]; return self; diff --git a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m index 613583312..92801dc8e 100644 --- a/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m @@ -38,6 +38,7 @@ #import "SDLScreenParams.h" #import "SDLStateMachine.h" #import "SDLStreamingMediaConfiguration.h" +#import "SDLEncryptionConfiguration.h" #import "SDLStreamingMediaManagerDataSource.h" #import "SDLStreamingVideoScaleManager.h" #import "SDLSystemCapability.h" @@ -137,10 +138,17 @@ - (instancetype)initWithConnectionManager:(id)connecti _videoStreamingState = SDLVideoStreamingStateNotStreamable; NSMutableArray *tempMakeArray = [NSMutableArray array]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" for (Class securityManagerClass in configuration.streamingMediaConfig.securityManagers) { [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects]; } - _secureMakes = [tempMakeArray copy]; +#pragma clang diagnostic pop + for (Class securityManagerClass in configuration.encryptionConfig.securityManagers) { + [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects]; + } + NSOrderedSet *tempMakeSet = [NSOrderedSet orderedSetWithArray:tempMakeArray]; + _secureMakes = [tempMakeSet.array copy]; SDLAppState *initialState = SDLAppStateInactive; switch ([[UIApplication sharedApplication] applicationState]) { @@ -772,7 +780,7 @@ - (void)sdl_sendVideoStartService { // Decide if we need to start a secure service or not if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) { SDLLogD(@"Sending secure video start service with payload: %@", startVideoPayload); - [self.protocol startSecureServiceWithType:SDLServiceTypeVideo payload:startVideoPayload.data completionHandler:^(BOOL success, NSError *error) { + [self.protocol startSecureServiceWithType:SDLServiceTypeVideo payload:startVideoPayload.data tlsInitializationHandler:^(BOOL success, NSError *error) { if (error) { SDLLogE(@"TLS setup error: %@", error); [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped]; diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index efa4f8b2d..0f0bde4e2 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -393,12 +393,17 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; // Developer API // Configurations #import "SDLConfiguration.h" +#import "SDLEncryptionConfiguration.h" #import "SDLFileManagerConfiguration.h" #import "SDLLifecycleConfiguration.h" #import "SDLLifecycleConfigurationUpdate.h" #import "SDLLockScreenConfiguration.h" #import "SDLStreamingMediaConfiguration.h" +// Encryption +#import "SDLProtocolConstants.h" +#import "SDLServiceEncryptionDelegate.h" + // Streaming #import "SDLAudioFile.h" #import "SDLAudioStreamManager.h" diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m index cdfef4f4d..38fb36ec9 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m @@ -7,6 +7,7 @@ #import "SDLLogConfiguration.h" #import "SDLLockScreenConfiguration.h" #import "SDLStreamingMediaConfiguration.h" +#import "SDLEncryptionConfiguration.h" QuickSpecBegin(SDLConfigurationSpec) @@ -19,7 +20,8 @@ __block SDLLogConfiguration *someLogConfig = nil; __block SDLStreamingMediaConfiguration *someStreamingConfig = nil; __block SDLFileManagerConfiguration *someFileManagerConfig = nil; - + __block SDLEncryptionConfiguration *someEncryptionConfig = nil; + __block NSString *someAppName = nil; __block NSString *someAppId = nil; __block UIColor *someBackgroundColor = nil; @@ -36,6 +38,7 @@ someLogConfig = [SDLLogConfiguration defaultConfiguration]; someStreamingConfig = [SDLStreamingMediaConfiguration insecureConfiguration]; someFileManagerConfig = [SDLFileManagerConfiguration defaultConfiguration]; + someEncryptionConfig = [SDLEncryptionConfiguration defaultConfiguration]; }); it(@"initWithLifecycle:lockScreen:logging:", ^{ @@ -52,13 +55,14 @@ }); it(@"initWithLifecycle:lockScreen:logging:fileManager:", ^{ - testConfig = [[SDLConfiguration alloc] initWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig fileManager:someFileManagerConfig]; + testConfig = [[SDLConfiguration alloc] initWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig fileManager:someFileManagerConfig encryption: someEncryptionConfig]; expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); expect(testConfig.lockScreenConfig).to(equal(someLockscreenConfig)); expect(testConfig.loggingConfig).to(equal(someLogConfig)); expect(testConfig.streamingMediaConfig).to(beNil()); expect(testConfig.fileManagerConfig).to(equal(someFileManagerConfig)); + expect(testConfig.encryptionConfig).to(equal(someEncryptionConfig)); }); it(@"configurationWithLifecycle:lockScreen:logging:", ^{ @@ -104,7 +108,7 @@ }); it(@"initWithLifecycle:lockScreen:logging:streamingMedia:fileManager:", ^{ - testConfig = [[SDLConfiguration alloc] initWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig streamingMedia:someStreamingConfig fileManager:someFileManagerConfig]; + testConfig = [[SDLConfiguration alloc] initWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig streamingMedia:someStreamingConfig fileManager:someFileManagerConfig encryption:[SDLEncryptionConfiguration defaultConfiguration]]; expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); expect(testConfig.lockScreenConfig).to(equal(someLockscreenConfig)); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index 8e0d85c5b..4328d3af3 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -102,7 +102,7 @@ @interface SDLLifecycleManager () }; beforeEach(^{ - OCMStub([proxyMock iapProxyWithListener:[OCMArg any] secondaryTransportManager:[OCMArg any]]).andReturn(proxyMock); + OCMStub([proxyMock iapProxyWithListener:[OCMArg any] secondaryTransportManager:[OCMArg any] encryptionLifecycleManager:[OCMArg any]]).andReturn(proxyMock); OCMStub([(SDLProxy*)proxyMock protocol]).andReturn(protocolMock); SDLLifecycleConfiguration *testLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test App" appId:@"Test Id"]; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m index 05d70a6db..eaf657595 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLPermissionsManagerSpec.m @@ -19,6 +19,7 @@ @interface SDLPermissionManager () @property (strong, nonatomic) NSMutableDictionary *permissions; @property (strong, nonatomic) NSMutableArray *filters; @property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; +@property (assign, nonatomic) BOOL requiresEncryption; @end @@ -127,6 +128,7 @@ @interface SDLPermissionManager () expect(testPermissionsManager.filters).to(beEmpty()); expect(testPermissionsManager.permissions).to(beEmpty()); expect(testPermissionsManager.currentHMILevel).to(beNil()); + expect(testPermissionsManager.requiresEncryption).to(beFalse()); }); describe(@"checking if a permission is allowed", ^{ diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m index c8d9a9301..cfcb62aea 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m @@ -15,6 +15,7 @@ #import "SDLStateMachine.h" #import "SDLStreamingAudioLifecycleManager.h" #import "SDLStreamingMediaConfiguration.h" +#import "SDLEncryptionConfiguration.h" #import "SDLV2ProtocolHeader.h" #import "SDLV2ProtocolMessage.h" #import "TestConnectionManager.h" @@ -24,6 +25,7 @@ describe(@"the streaming audio manager", ^{ __block SDLStreamingAudioLifecycleManager *streamingLifecycleManager = nil; __block SDLStreamingMediaConfiguration *testConfiguration = [SDLStreamingMediaConfiguration insecureConfiguration]; + __block SDLEncryptionConfiguration *encryptionConfiguration = [SDLEncryptionConfiguration defaultConfiguration]; __block TestConnectionManager *testConnectionManager = nil; __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILevel hmiLevel) { @@ -37,7 +39,7 @@ __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILeve beforeEach(^{ testConnectionManager = [[TestConnectionManager alloc] init]; - streamingLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration]; + streamingLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:testConnectionManager streamingConfiguration:testConfiguration encryptionConfiguration:encryptionConfiguration]; }); it(@"should initialize properties", ^{ diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLResultSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLResultSpec.m index c90ece5d3..e0e46eeec 100644 --- a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLResultSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLResultSpec.m @@ -50,7 +50,7 @@ expect(SDLResultResumeFailed).to(equal(@"RESUME_FAILED")); expect(SDLResultDataNotAvailable).to(equal(@"DATA_NOT_AVAILABLE")); expect(SDLResultReadOnly).to(equal(@"READ_ONLY")); - + expect(SDLResultEncryptionNeeded).to(equal(@"ENCRYPTION_NEEDED")); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnPermissionsChangeSpec.m b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnPermissionsChangeSpec.m index d0d8e07d5..7b316929c 100644 --- a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnPermissionsChangeSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnPermissionsChangeSpec.m @@ -15,34 +15,42 @@ QuickSpecBegin(SDLOnPermissionsChangeSpec) -SDLPermissionItem* item = [[SDLPermissionItem alloc] init]; - describe(@"Getter/Setter Tests", ^ { + __block SDLPermissionItem *testPermissionItem = nil; + + beforeEach(^{ + testPermissionItem = [[SDLPermissionItem alloc] init]; + }); + it(@"Should set and get correctly", ^ { - SDLOnPermissionsChange* testNotification = [[SDLOnPermissionsChange alloc] init]; - - testNotification.permissionItem = [@[item] mutableCopy]; + SDLOnPermissionsChange *testNotification = [[SDLOnPermissionsChange alloc] init]; - expect(testNotification.permissionItem).to(equal([@[item] mutableCopy])); + testNotification.permissionItem = [@[testPermissionItem] mutableCopy]; + testNotification.requireEncryption = @YES; + + expect(testNotification.permissionItem).to(equal([@[testPermissionItem] mutableCopy])); + expect(testNotification.requireEncryption.boolValue).to(beTrue()); }); it(@"Should get correctly when initialized", ^ { NSMutableDictionary *dict = [@{SDLRPCParameterNameNotification: @{SDLRPCParameterNameParameters: - @{SDLRPCParameterNamePermissionItem:[@[item] mutableCopy]}, - SDLRPCParameterNameOperationName:SDLRPCFunctionNameOnPermissionsChange}} mutableCopy]; + @{SDLRPCParameterNamePermissionItem:@[testPermissionItem], + SDLRPCParameterNameRequireEncryption:@YES}, SDLRPCParameterNameOperationName:SDLRPCFunctionNameOnPermissionsChange}} mutableCopy]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" SDLOnPermissionsChange* testNotification = [[SDLOnPermissionsChange alloc] initWithDictionary:dict]; #pragma clang diagnostic pop - expect(testNotification.permissionItem).to(equal([@[item] mutableCopy])); + expect(testNotification.permissionItem).to(equal([@[testPermissionItem] mutableCopy])); + expect(testNotification.requireEncryption.boolValue).to(beTrue()); }); it(@"Should return nil if not set", ^ { - SDLOnPermissionsChange* testNotification = [[SDLOnPermissionsChange alloc] init]; + SDLOnPermissionsChange *testNotification = [[SDLOnPermissionsChange alloc] init]; expect(testNotification.permissionItem).to(beNil()); + expect(testNotification.requireEncryption.boolValue).to(beFalse()); }); }); diff --git a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLPermissionItemSpec.m b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLPermissionItemSpec.m index 83b7f57cc..5c6cfabb3 100644 --- a/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLPermissionItemSpec.m +++ b/SmartDeviceLinkTests/RPCSpecs/StructSpecs/SDLPermissionItemSpec.m @@ -15,42 +15,47 @@ QuickSpecBegin(SDLPermissionItemSpec) -SDLHMIPermissions* hmiPermissions = [[SDLHMIPermissions alloc] init]; -SDLParameterPermissions* parameterPermissions = [[SDLParameterPermissions alloc] init]; +SDLHMIPermissions *hmiPermissions = [[SDLHMIPermissions alloc] init]; +SDLParameterPermissions *parameterPermissions = [[SDLParameterPermissions alloc] init]; describe(@"Getter/Setter Tests", ^ { it(@"Should set and get correctly", ^ { - SDLPermissionItem* testStruct = [[SDLPermissionItem alloc] init]; + SDLPermissionItem *testStruct = [[SDLPermissionItem alloc] init]; testStruct.rpcName = @"RPCNameThing"; testStruct.hmiPermissions = hmiPermissions; testStruct.parameterPermissions = parameterPermissions; + testStruct.requireEncryption = @YES; expect(testStruct.rpcName).to(equal(@"RPCNameThing")); expect(testStruct.hmiPermissions).to(equal(hmiPermissions)); expect(testStruct.parameterPermissions).to(equal(parameterPermissions)); + expect(testStruct.requireEncryption.boolValue).to(beTrue()); }); it(@"Should get correctly when initialized", ^ { NSMutableDictionary *dict = [@{SDLRPCParameterNameRPCName:@"RPCNameThing", SDLRPCParameterNameHMIPermissions:hmiPermissions, - SDLRPCParameterNameParameterPermissions:parameterPermissions} mutableCopy]; + SDLRPCParameterNameParameterPermissions:parameterPermissions, + SDLRPCParameterNameRequireEncryption:@YES} mutableCopy]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - SDLPermissionItem* testStruct = [[SDLPermissionItem alloc] initWithDictionary:dict]; + SDLPermissionItem *testStruct = [[SDLPermissionItem alloc] initWithDictionary:dict]; #pragma clang diagnostic pop expect(testStruct.rpcName).to(equal(@"RPCNameThing")); expect(testStruct.hmiPermissions).to(equal(hmiPermissions)); expect(testStruct.parameterPermissions).to(equal(parameterPermissions)); + expect(testStruct.requireEncryption.boolValue).to(beTrue()); }); it(@"Should return nil if not set", ^ { - SDLPermissionItem* testStruct = [[SDLPermissionItem alloc] init]; + SDLPermissionItem *testStruct = [[SDLPermissionItem alloc] init]; expect(testStruct.rpcName).to(beNil()); expect(testStruct.hmiPermissions).to(beNil()); expect(testStruct.parameterPermissions).to(beNil()); + expect(testStruct.requireEncryption).to(beNil()); }); }); diff --git a/SmartDeviceLinkTests/SDLEncryptionConfigurationSpec.m b/SmartDeviceLinkTests/SDLEncryptionConfigurationSpec.m new file mode 100644 index 000000000..84904e8ad --- /dev/null +++ b/SmartDeviceLinkTests/SDLEncryptionConfigurationSpec.m @@ -0,0 +1,47 @@ +// +// SDLEncryptionConfigurationSpec.m +// SmartDeviceLinkTests +// +// Created by standa1 on 7/17/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import +#import +#import + +#import "SDLEncryptionConfiguration.h" + +#import "SDLFakeSecurityManager.h" + +QuickSpecBegin(SDLEncryptionConfigurationSpec) + +describe(@"a streaming media configuration", ^{ + __block SDLEncryptionConfiguration *testConfig = nil; + + context(@"That is created with a full initializer", ^{ + __block SDLFakeSecurityManager *testFakeSecurityManager = nil; + + beforeEach(^{ + testFakeSecurityManager = [[SDLFakeSecurityManager alloc] init]; + + testConfig = [[SDLEncryptionConfiguration alloc] initWithSecurityManagers:@[testFakeSecurityManager.class] delegate:nil]; + }); + + it(@"should have properly set properties", ^{ + expect(testConfig.securityManagers).to(contain(testFakeSecurityManager.class)); + }); + }); + + context(@"That is created with init", ^{ + beforeEach(^{ + testConfig = [[SDLEncryptionConfiguration alloc] init]; + }); + + it(@"should have all properties nil", ^{ + expect(testConfig.securityManagers).to(beNil()); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/SDLEncryptionLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLEncryptionLifecycleManagerSpec.m new file mode 100644 index 000000000..5ae9101a3 --- /dev/null +++ b/SmartDeviceLinkTests/SDLEncryptionLifecycleManagerSpec.m @@ -0,0 +1,163 @@ +// +// SDLEncryptionLifecycleManagerSpec.m +// SmartDeviceLinkTests +// +// Created by standa1 on 7/17/19. +// Copyright © 2019 smartdevicelink. All rights reserved. +// + +#import +#import +#import + +#import "SDLDisplayCapabilities.h" +#import "SDLGlobals.h" +#import "SDLOnHMIStatus.h" +#import "SDLProtocol.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLRPCResponseNotification.h" +#import "SDLStateMachine.h" +#import "SDLEncryptionConfiguration.h" +#import "SDLEncryptionLifecycleManager.h" +#import "SDLV2ProtocolHeader.h" +#import "SDLV2ProtocolMessage.h" +#import "TestConnectionManager.h" +#import "SDLFakeSecurityManager.h" +#import "SDLEncryptionManagerConstants.h" + +@interface SDLEncryptionLifecycleManager() +@property (strong, nonatomic, readwrite) SDLStateMachine *encryptionStateMachine; +@end + +QuickSpecBegin(SDLEncryptionLifecycleManagerSpec) + +describe(@"the encryption lifecycle manager", ^{ + __block SDLEncryptionLifecycleManager *encryptionLifecycleManager = nil; + __block SDLEncryptionConfiguration *testConfiguration = nil; + __block TestConnectionManager *testConnectionManager = nil; + __block SDLFakeSecurityManager *testFakeSecurityManager = nil; + __block NSOperationQueue *testRPCOperationQueue = nil; + + beforeEach(^{ + testConnectionManager = [[TestConnectionManager alloc] init]; + testFakeSecurityManager = [[SDLFakeSecurityManager alloc] init]; + testConfiguration = [[SDLEncryptionConfiguration alloc] initWithSecurityManagers:@[testFakeSecurityManager.class] delegate:nil]; + testRPCOperationQueue = OCMClassMock([NSOperationQueue class]); + + encryptionLifecycleManager = [[SDLEncryptionLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration]; + }); + + it(@"should initialize properties", ^{ + expect(@(encryptionLifecycleManager.isEncryptionReady)).to(equal(@NO)); + }); + + describe(@"when started", ^{ + __block BOOL readyHandlerSuccess = NO; + __block NSError *readyHandlerError = nil; + + __block SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]); + + beforeEach(^{ + readyHandlerSuccess = NO; + readyHandlerError = nil; + + [encryptionLifecycleManager startWithProtocol:protocolMock]; + }); + + it(@"should not be ready to stream", ^{ + expect(@(encryptionLifecycleManager.isEncryptionReady)).to(equal(@NO)); + }); + + describe(@"after receiving an RPC Start ACK", ^{ + __block SDLProtocolHeader *testRPCHeader = nil; + __block SDLProtocolMessage *testRPCMessage = nil; + + beforeEach(^{ + [encryptionLifecycleManager.encryptionStateMachine setToState:SDLEncryptionLifecycleManagerStateStarting fromOldState:nil callEnterTransition:YES]; + + testRPCHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testRPCHeader.frameType = SDLFrameTypeSingle; + testRPCHeader.frameData = SDLFrameInfoStartServiceACK; + testRPCHeader.encrypted = YES; + testRPCHeader.serviceType = SDLServiceTypeRPC; + + testRPCMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testRPCHeader andPayload:nil]; + [encryptionLifecycleManager handleProtocolStartServiceACKMessage:testRPCMessage]; + }); + + it(@"should have set all the right properties", ^{ + expect(encryptionLifecycleManager.isEncryptionReady).to(equal(YES)); + expect(encryptionLifecycleManager.encryptionStateMachine.currentState).to(equal(SDLEncryptionLifecycleManagerStateReady)); + }); + }); + + describe(@"after receiving an RPC Start NAK", ^{ + __block SDLProtocolHeader *testRPCHeader = nil; + __block SDLProtocolMessage *testRPCMessage = nil; + + beforeEach(^{ + [encryptionLifecycleManager.encryptionStateMachine setToState:SDLEncryptionLifecycleManagerStateStarting fromOldState:nil callEnterTransition:NO]; + + testRPCHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testRPCHeader.frameType = SDLFrameTypeSingle; + testRPCHeader.frameData = SDLFrameInfoStartServiceNACK; + testRPCHeader.encrypted = NO; + testRPCHeader.serviceType = SDLServiceTypeRPC; + + testRPCMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testRPCHeader andPayload:nil]; + [encryptionLifecycleManager handleProtocolEndServiceACKMessage:testRPCMessage]; + }); + + it(@"should have set all the right properties", ^{ + expect(encryptionLifecycleManager.encryptionStateMachine.currentState).to(equal(SDLEncryptionLifecycleManagerStateStopped)); + }); + }); + + describe(@"after receiving a RPC end ACK", ^{ + __block SDLProtocolHeader *testRPCHeader = nil; + __block SDLProtocolMessage *testRPCMessage = nil; + + beforeEach(^{ + [encryptionLifecycleManager.encryptionStateMachine setToState:SDLEncryptionLifecycleManagerStateStopped fromOldState:nil callEnterTransition:NO]; + + testRPCHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testRPCHeader.frameType = SDLFrameTypeSingle; + testRPCHeader.frameData = SDLFrameInfoEndServiceACK; + testRPCHeader.encrypted = NO; + testRPCHeader.serviceType = SDLServiceTypeRPC; + + testRPCMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testRPCHeader andPayload:nil]; + [encryptionLifecycleManager handleProtocolEndServiceACKMessage:testRPCMessage]; + }); + + it(@"should have set all the right properties", ^{ + expect(encryptionLifecycleManager.encryptionStateMachine.currentState).to(equal(SDLEncryptionLifecycleManagerStateStopped)); + }); + }); + + describe(@"after receiving a RPC end NAK", ^{ + __block SDLProtocolHeader *testRPCHeader = nil; + __block SDLProtocolMessage *testRPCMessage = nil; + + beforeEach(^{ + [encryptionLifecycleManager.encryptionStateMachine setToState:SDLEncryptionLifecycleManagerStateStopped fromOldState:nil callEnterTransition:NO]; + + testRPCHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5]; + testRPCHeader.frameType = SDLFrameTypeSingle; + testRPCHeader.frameData = SDLFrameInfoEndServiceNACK; + testRPCHeader.encrypted = NO; + testRPCHeader.serviceType = SDLServiceTypeRPC; + + testRPCMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testRPCHeader andPayload:nil]; + [encryptionLifecycleManager handleProtocolEndServiceNAKMessage:testRPCMessage]; + }); + + it(@"should have set all the right properties", ^{ + expect(encryptionLifecycleManager.encryptionStateMachine.currentState).to(equal(SDLEncryptionLifecycleManagerStateStopped)); + }); + }); + }); +}); + +QuickSpecEnd