From b8d256b73dd91b971307584c5d1e94ecd4c4ca08 Mon Sep 17 00:00:00 2001 From: Diego Waxemberg Date: Mon, 20 Oct 2014 02:59:16 -0400 Subject: [PATCH] pairing works! --- Limelight.xcodeproj/project.pbxproj | 284 +--------------------------- Limelight/CryptoManager.h | 9 + Limelight/CryptoManager.m | 142 ++++++++++++++ Limelight/HttpManager.h | 17 +- Limelight/HttpManager.m | 194 +++++++++++++------ Limelight/MainFrameViewController.m | 33 ++-- Limelight/PairManager.h | 17 ++ Limelight/PairManager.m | 158 ++++++++++++++++ 8 files changed, 500 insertions(+), 354 deletions(-) create mode 100644 Limelight/PairManager.h create mode 100644 Limelight/PairManager.m diff --git a/Limelight.xcodeproj/project.pbxproj b/Limelight.xcodeproj/project.pbxproj index ce4644e..fba1b39 100644 --- a/Limelight.xcodeproj/project.pbxproj +++ b/Limelight.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ FB290DC419B2E98F004C83CF /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290DC319B2E98F004C83CF /* libxml2.dylib */; }; FB290E7919B37D81004C83CF /* MainFrame-iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7819B37D81004C83CF /* MainFrame-iPad.storyboard */; }; FB290E7B19B38036004C83CF /* MainFrame-iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB290E7A19B38036004C83CF /* MainFrame-iPhone.storyboard */; }; + FB63FCF219F43EBC00227761 /* PairManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB63FCF119F43EBC00227761 /* PairManager.m */; }; FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; }; FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F119EDB08B00929691 /* MDNSManager.m */; }; FBAB29F619EDE0F800929691 /* Computer.m in Sources */ = {isa = PBXBuildFile; fileRef = FBAB29F519EDE0F800929691 /* Computer.m */; }; @@ -117,6 +118,8 @@ FB290DC319B2E98F004C83CF /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; }; FB290E7819B37D81004C83CF /* MainFrame-iPad.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "MainFrame-iPad.storyboard"; sourceTree = SOURCE_ROOT; }; FB290E7A19B38036004C83CF /* MainFrame-iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "MainFrame-iPhone.storyboard"; sourceTree = SOURCE_ROOT; }; + FB63FCF019F43EBC00227761 /* PairManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PairManager.h; sourceTree = ""; }; + FB63FCF119F43EBC00227761 /* PairManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PairManager.m; sourceTree = ""; }; FB7E794319C8B71B00A15F68 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; FBAB29F119EDB08B00929691 /* MDNSManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDNSManager.m; sourceTree = ""; }; FBAB29F319EDB0C400929691 /* MDNSManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDNSManager.h; sourceTree = ""; }; @@ -206,101 +209,6 @@ FBCC0E9919EF9703009729EB /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libssl.a; sourceTree = ""; }; FBCC0E9C19F00659009729EB /* mkcert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mkcert.c; sourceTree = ""; }; FBCC0E9E19F00697009729EB /* mkcert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mkcert.h; sourceTree = ""; }; - FBD8B3FD19C906230032E027 /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavcodec.a; sourceTree = ""; }; - FBD8B3FE19C906230032E027 /* libavdevice.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavdevice.a; sourceTree = ""; }; - FBD8B3FF19C906230032E027 /* libavfilter.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavfilter.a; sourceTree = ""; }; - FBD8B40019C906230032E027 /* libavformat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavformat.a; sourceTree = ""; }; - FBD8B40119C906230032E027 /* libavresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavresample.a; sourceTree = ""; }; - FBD8B40219C906230032E027 /* libavutil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libavutil.a; sourceTree = ""; }; - FBD8B40319C906230032E027 /* libswresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libswresample.a; sourceTree = ""; }; - FBD8B40419C906230032E027 /* libswscale.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libswscale.a; sourceTree = ""; }; - FBD8B40F19C9064B0032E027 /* avcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avcodec.h; sourceTree = ""; }; - FBD8B41019C9064B0032E027 /* avfft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfft.h; sourceTree = ""; }; - FBD8B41119C9064B0032E027 /* dv_profile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dv_profile.h; sourceTree = ""; }; - FBD8B41219C9064B0032E027 /* dxva2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxva2.h; sourceTree = ""; }; - FBD8B41319C9064B0032E027 /* old_codec_ids.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = old_codec_ids.h; sourceTree = ""; }; - FBD8B41419C9064B0032E027 /* vaapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vaapi.h; sourceTree = ""; }; - FBD8B41519C9064B0032E027 /* vda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vda.h; sourceTree = ""; }; - FBD8B41619C9064B0032E027 /* vdpau.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdpau.h; sourceTree = ""; }; - FBD8B41719C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B41819C9064B0032E027 /* xvmc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xvmc.h; sourceTree = ""; }; - FBD8B41A19C9064B0032E027 /* avdevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avdevice.h; sourceTree = ""; }; - FBD8B41B19C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B41D19C9064B0032E027 /* asrc_abuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asrc_abuffer.h; sourceTree = ""; }; - FBD8B41E19C9064B0032E027 /* avcodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avcodec.h; sourceTree = ""; }; - FBD8B41F19C9064B0032E027 /* avfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfilter.h; sourceTree = ""; }; - FBD8B42019C9064B0032E027 /* avfiltergraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avfiltergraph.h; sourceTree = ""; }; - FBD8B42119C9064B0032E027 /* buffersink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffersink.h; sourceTree = ""; }; - FBD8B42219C9064B0032E027 /* buffersrc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffersrc.h; sourceTree = ""; }; - FBD8B42319C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B42519C9064B0032E027 /* avformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avformat.h; sourceTree = ""; }; - FBD8B42619C9064B0032E027 /* avio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avio.h; sourceTree = ""; }; - FBD8B42719C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B42919C9064B0032E027 /* avresample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avresample.h; sourceTree = ""; }; - FBD8B42A19C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B42C19C9064B0032E027 /* adler32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adler32.h; sourceTree = ""; }; - FBD8B42D19C9064B0032E027 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; }; - FBD8B42E19C9064B0032E027 /* attributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attributes.h; sourceTree = ""; }; - FBD8B42F19C9064B0032E027 /* audio_fifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio_fifo.h; sourceTree = ""; }; - FBD8B43019C9064B0032E027 /* audioconvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audioconvert.h; sourceTree = ""; }; - FBD8B43119C9064B0032E027 /* avassert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avassert.h; sourceTree = ""; }; - FBD8B43219C9064B0032E027 /* avconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avconfig.h; sourceTree = ""; }; - FBD8B43319C9064B0032E027 /* avstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avstring.h; sourceTree = ""; }; - FBD8B43419C9064B0032E027 /* avutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = avutil.h; sourceTree = ""; }; - FBD8B43519C9064B0032E027 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = ""; }; - FBD8B43619C9064B0032E027 /* blowfish.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blowfish.h; sourceTree = ""; }; - FBD8B43719C9064B0032E027 /* bprint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bprint.h; sourceTree = ""; }; - FBD8B43819C9064B0032E027 /* bswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bswap.h; sourceTree = ""; }; - FBD8B43919C9064B0032E027 /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = ""; }; - FBD8B43A19C9064B0032E027 /* channel_layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = channel_layout.h; sourceTree = ""; }; - FBD8B43B19C9064B0032E027 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; - FBD8B43C19C9064B0032E027 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = ""; }; - FBD8B43D19C9064B0032E027 /* crc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc.h; sourceTree = ""; }; - FBD8B43E19C9064B0032E027 /* dict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dict.h; sourceTree = ""; }; - FBD8B43F19C9064B0032E027 /* display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = display.h; sourceTree = ""; }; - FBD8B44019C9064B0032E027 /* downmix_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = downmix_info.h; sourceTree = ""; }; - FBD8B44119C9064B0032E027 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; - FBD8B44219C9064B0032E027 /* eval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eval.h; sourceTree = ""; }; - FBD8B44319C9064B0032E027 /* ffversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffversion.h; sourceTree = ""; }; - FBD8B44419C9064B0032E027 /* fifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fifo.h; sourceTree = ""; }; - FBD8B44519C9064B0032E027 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; - FBD8B44619C9064B0032E027 /* frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = frame.h; sourceTree = ""; }; - FBD8B44719C9064B0032E027 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; - FBD8B44819C9064B0032E027 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = ""; }; - FBD8B44919C9064B0032E027 /* imgutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgutils.h; sourceTree = ""; }; - FBD8B44A19C9064B0032E027 /* intfloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intfloat.h; sourceTree = ""; }; - FBD8B44B19C9064B0032E027 /* intfloat_readwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intfloat_readwrite.h; sourceTree = ""; }; - FBD8B44C19C9064B0032E027 /* intreadwrite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = intreadwrite.h; sourceTree = ""; }; - FBD8B44D19C9064B0032E027 /* lfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lfg.h; sourceTree = ""; }; - FBD8B44E19C9064B0032E027 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; - FBD8B44F19C9064B0032E027 /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macros.h; sourceTree = ""; }; - FBD8B45019C9064B0032E027 /* mathematics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mathematics.h; sourceTree = ""; }; - FBD8B45119C9064B0032E027 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = ""; }; - FBD8B45219C9064B0032E027 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; }; - FBD8B45319C9064B0032E027 /* murmur3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = murmur3.h; sourceTree = ""; }; - FBD8B45419C9064B0032E027 /* old_pix_fmts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = old_pix_fmts.h; sourceTree = ""; }; - FBD8B45519C9064B0032E027 /* opt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opt.h; sourceTree = ""; }; - FBD8B45619C9064B0032E027 /* parseutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parseutils.h; sourceTree = ""; }; - FBD8B45719C9064B0032E027 /* pixdesc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixdesc.h; sourceTree = ""; }; - FBD8B45819C9064B0032E027 /* pixfmt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixfmt.h; sourceTree = ""; }; - FBD8B45919C9064B0032E027 /* random_seed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = random_seed.h; sourceTree = ""; }; - FBD8B45A19C9064B0032E027 /* rational.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rational.h; sourceTree = ""; }; - FBD8B45B19C9064B0032E027 /* replaygain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = replaygain.h; sourceTree = ""; }; - FBD8B45C19C9064B0032E027 /* ripemd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ripemd.h; sourceTree = ""; }; - FBD8B45D19C9064B0032E027 /* samplefmt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplefmt.h; sourceTree = ""; }; - FBD8B45E19C9064B0032E027 /* sha.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha.h; sourceTree = ""; }; - FBD8B45F19C9064B0032E027 /* sha512.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha512.h; sourceTree = ""; }; - FBD8B46019C9064B0032E027 /* stereo3d.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stereo3d.h; sourceTree = ""; }; - FBD8B46119C9064B0032E027 /* threadmessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = threadmessage.h; sourceTree = ""; }; - FBD8B46219C9064B0032E027 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; - FBD8B46319C9064B0032E027 /* timecode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timecode.h; sourceTree = ""; }; - FBD8B46419C9064B0032E027 /* timestamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timestamp.h; sourceTree = ""; }; - FBD8B46519C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B46619C9064B0032E027 /* xtea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xtea.h; sourceTree = ""; }; - FBD8B46819C9064B0032E027 /* swresample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swresample.h; sourceTree = ""; }; - FBD8B46919C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - FBD8B46B19C9064B0032E027 /* swscale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = swscale.h; sourceTree = ""; }; - FBD8B46C19C9064B0032E027 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -386,6 +294,8 @@ FB290CF919B2C406004C83CF /* Limelight */ = { isa = PBXGroup; children = ( + FB63FCF019F43EBC00227761 /* PairManager.h */, + FB63FCF119F43EBC00227761 /* PairManager.m */, FB290D3019B2C6E3004C83CF /* Video */, FB290D2619B2C6E3004C83CF /* Connection.h */, FB290D2719B2C6E3004C83CF /* Connection.m */, @@ -458,7 +368,6 @@ isa = PBXGroup; children = ( FBCC0E4919EF9703009729EB /* openssl */, - FB2C87FA19B8F0B300F7655B /* FFmpeg */, FB290DA719B2C814004C83CF /* limelight-common */, FB290DAC19B2C814004C83CF /* opus */, ); @@ -526,15 +435,6 @@ path = lib; sourceTree = ""; }; - FB2C87FA19B8F0B300F7655B /* FFmpeg */ = { - isa = PBXGroup; - children = ( - FBD8B40D19C9064B0032E027 /* include */, - FBD8B3FC19C906230032E027 /* lib */, - ); - path = FFmpeg; - sourceTree = ""; - }; FBC8622F19F346A60087327B /* Products */ = { isa = PBXGroup; children = ( @@ -651,179 +551,6 @@ path = lib; sourceTree = ""; }; - FBD8B3FC19C906230032E027 /* lib */ = { - isa = PBXGroup; - children = ( - FBD8B3FD19C906230032E027 /* libavcodec.a */, - FBD8B3FE19C906230032E027 /* libavdevice.a */, - FBD8B3FF19C906230032E027 /* libavfilter.a */, - FBD8B40019C906230032E027 /* libavformat.a */, - FBD8B40119C906230032E027 /* libavresample.a */, - FBD8B40219C906230032E027 /* libavutil.a */, - FBD8B40319C906230032E027 /* libswresample.a */, - FBD8B40419C906230032E027 /* libswscale.a */, - ); - path = lib; - sourceTree = ""; - }; - FBD8B40D19C9064B0032E027 /* include */ = { - isa = PBXGroup; - children = ( - FBD8B40E19C9064B0032E027 /* libavcodec */, - FBD8B41919C9064B0032E027 /* libavdevice */, - FBD8B41C19C9064B0032E027 /* libavfilter */, - FBD8B42419C9064B0032E027 /* libavformat */, - FBD8B42819C9064B0032E027 /* libavresample */, - FBD8B42B19C9064B0032E027 /* libavutil */, - FBD8B46719C9064B0032E027 /* libswresample */, - FBD8B46A19C9064B0032E027 /* libswscale */, - ); - path = include; - sourceTree = ""; - }; - FBD8B40E19C9064B0032E027 /* libavcodec */ = { - isa = PBXGroup; - children = ( - FBD8B40F19C9064B0032E027 /* avcodec.h */, - FBD8B41019C9064B0032E027 /* avfft.h */, - FBD8B41119C9064B0032E027 /* dv_profile.h */, - FBD8B41219C9064B0032E027 /* dxva2.h */, - FBD8B41319C9064B0032E027 /* old_codec_ids.h */, - FBD8B41419C9064B0032E027 /* vaapi.h */, - FBD8B41519C9064B0032E027 /* vda.h */, - FBD8B41619C9064B0032E027 /* vdpau.h */, - FBD8B41719C9064B0032E027 /* version.h */, - FBD8B41819C9064B0032E027 /* xvmc.h */, - ); - path = libavcodec; - sourceTree = ""; - }; - FBD8B41919C9064B0032E027 /* libavdevice */ = { - isa = PBXGroup; - children = ( - FBD8B41A19C9064B0032E027 /* avdevice.h */, - FBD8B41B19C9064B0032E027 /* version.h */, - ); - path = libavdevice; - sourceTree = ""; - }; - FBD8B41C19C9064B0032E027 /* libavfilter */ = { - isa = PBXGroup; - children = ( - FBD8B41D19C9064B0032E027 /* asrc_abuffer.h */, - FBD8B41E19C9064B0032E027 /* avcodec.h */, - FBD8B41F19C9064B0032E027 /* avfilter.h */, - FBD8B42019C9064B0032E027 /* avfiltergraph.h */, - FBD8B42119C9064B0032E027 /* buffersink.h */, - FBD8B42219C9064B0032E027 /* buffersrc.h */, - FBD8B42319C9064B0032E027 /* version.h */, - ); - path = libavfilter; - sourceTree = ""; - }; - FBD8B42419C9064B0032E027 /* libavformat */ = { - isa = PBXGroup; - children = ( - FBD8B42519C9064B0032E027 /* avformat.h */, - FBD8B42619C9064B0032E027 /* avio.h */, - FBD8B42719C9064B0032E027 /* version.h */, - ); - path = libavformat; - sourceTree = ""; - }; - FBD8B42819C9064B0032E027 /* libavresample */ = { - isa = PBXGroup; - children = ( - FBD8B42919C9064B0032E027 /* avresample.h */, - FBD8B42A19C9064B0032E027 /* version.h */, - ); - path = libavresample; - sourceTree = ""; - }; - FBD8B42B19C9064B0032E027 /* libavutil */ = { - isa = PBXGroup; - children = ( - FBD8B42C19C9064B0032E027 /* adler32.h */, - FBD8B42D19C9064B0032E027 /* aes.h */, - FBD8B42E19C9064B0032E027 /* attributes.h */, - FBD8B42F19C9064B0032E027 /* audio_fifo.h */, - FBD8B43019C9064B0032E027 /* audioconvert.h */, - FBD8B43119C9064B0032E027 /* avassert.h */, - FBD8B43219C9064B0032E027 /* avconfig.h */, - FBD8B43319C9064B0032E027 /* avstring.h */, - FBD8B43419C9064B0032E027 /* avutil.h */, - FBD8B43519C9064B0032E027 /* base64.h */, - FBD8B43619C9064B0032E027 /* blowfish.h */, - FBD8B43719C9064B0032E027 /* bprint.h */, - FBD8B43819C9064B0032E027 /* bswap.h */, - FBD8B43919C9064B0032E027 /* buffer.h */, - FBD8B43A19C9064B0032E027 /* channel_layout.h */, - FBD8B43B19C9064B0032E027 /* common.h */, - FBD8B43C19C9064B0032E027 /* cpu.h */, - FBD8B43D19C9064B0032E027 /* crc.h */, - FBD8B43E19C9064B0032E027 /* dict.h */, - FBD8B43F19C9064B0032E027 /* display.h */, - FBD8B44019C9064B0032E027 /* downmix_info.h */, - FBD8B44119C9064B0032E027 /* error.h */, - FBD8B44219C9064B0032E027 /* eval.h */, - FBD8B44319C9064B0032E027 /* ffversion.h */, - FBD8B44419C9064B0032E027 /* fifo.h */, - FBD8B44519C9064B0032E027 /* file.h */, - FBD8B44619C9064B0032E027 /* frame.h */, - FBD8B44719C9064B0032E027 /* hash.h */, - FBD8B44819C9064B0032E027 /* hmac.h */, - FBD8B44919C9064B0032E027 /* imgutils.h */, - FBD8B44A19C9064B0032E027 /* intfloat.h */, - FBD8B44B19C9064B0032E027 /* intfloat_readwrite.h */, - FBD8B44C19C9064B0032E027 /* intreadwrite.h */, - FBD8B44D19C9064B0032E027 /* lfg.h */, - FBD8B44E19C9064B0032E027 /* log.h */, - FBD8B44F19C9064B0032E027 /* macros.h */, - FBD8B45019C9064B0032E027 /* mathematics.h */, - FBD8B45119C9064B0032E027 /* md5.h */, - FBD8B45219C9064B0032E027 /* mem.h */, - FBD8B45319C9064B0032E027 /* murmur3.h */, - FBD8B45419C9064B0032E027 /* old_pix_fmts.h */, - FBD8B45519C9064B0032E027 /* opt.h */, - FBD8B45619C9064B0032E027 /* parseutils.h */, - FBD8B45719C9064B0032E027 /* pixdesc.h */, - FBD8B45819C9064B0032E027 /* pixfmt.h */, - FBD8B45919C9064B0032E027 /* random_seed.h */, - FBD8B45A19C9064B0032E027 /* rational.h */, - FBD8B45B19C9064B0032E027 /* replaygain.h */, - FBD8B45C19C9064B0032E027 /* ripemd.h */, - FBD8B45D19C9064B0032E027 /* samplefmt.h */, - FBD8B45E19C9064B0032E027 /* sha.h */, - FBD8B45F19C9064B0032E027 /* sha512.h */, - FBD8B46019C9064B0032E027 /* stereo3d.h */, - FBD8B46119C9064B0032E027 /* threadmessage.h */, - FBD8B46219C9064B0032E027 /* time.h */, - FBD8B46319C9064B0032E027 /* timecode.h */, - FBD8B46419C9064B0032E027 /* timestamp.h */, - FBD8B46519C9064B0032E027 /* version.h */, - FBD8B46619C9064B0032E027 /* xtea.h */, - ); - path = libavutil; - sourceTree = ""; - }; - FBD8B46719C9064B0032E027 /* libswresample */ = { - isa = PBXGroup; - children = ( - FBD8B46819C9064B0032E027 /* swresample.h */, - FBD8B46919C9064B0032E027 /* version.h */, - ); - path = libswresample; - sourceTree = ""; - }; - FBD8B46A19C9064B0032E027 /* libswscale */ = { - isa = PBXGroup; - children = ( - FBD8B46B19C9064B0032E027 /* swscale.h */, - FBD8B46C19C9064B0032E027 /* version.h */, - ); - path = libswscale; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -950,6 +677,7 @@ buildActionMask = 2147483647; files = ( FBAB29FC19EE13AA00929691 /* CryptoManager.m in Sources */, + FB63FCF219F43EBC00227761 /* PairManager.m in Sources */, 98A03B5019F3598400861ACA /* VideoDecoderRenderer.m in Sources */, FBAB29F219EDB08B00929691 /* MDNSManager.m in Sources */, FBC8622D19F0BEFB0087327B /* HttpManager.m in Sources */, diff --git a/Limelight/CryptoManager.h b/Limelight/CryptoManager.h index 73f5195..78187a2 100644 --- a/Limelight/CryptoManager.h +++ b/Limelight/CryptoManager.h @@ -15,4 +15,13 @@ + (NSData*) readCertFromFile; + (NSData*) readKeyFromFile; + (NSData*) readP12FromFile; ++ (NSData*) getSignatureFromCert:(NSData*)cert; + +- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN; +- (NSData*) SHA1HashData:(NSData*)data; +- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key; +- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key; +- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert; +- (NSData*) signData:(NSData*)data withKey:(NSData*)key; + @end diff --git a/Limelight/CryptoManager.m b/Limelight/CryptoManager.m index 5adc135..b480a42 100644 --- a/Limelight/CryptoManager.m +++ b/Limelight/CryptoManager.m @@ -10,7 +10,135 @@ #import "mkcert.h" #import +#include +#include +#include +#include +#include + @implementation CryptoManager +static const int SHA1_DIGEST_LENGTH = 20; + +- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN { + return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)]; +} + +- (NSData*) SHA1HashData:(NSData*)data { + unsigned char sha1[SHA1_DIGEST_LENGTH]; + SHA1([data bytes], [data length], sha1); + NSData* bytes = [NSData dataWithBytes:sha1 length:20]; + return bytes; +} + +- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key { + AES_KEY aesKey; + AES_set_encrypt_key([key bytes], 128, &aesKey); + int size = [self getEncryptSize:data]; + unsigned char* buffer = malloc(size); + unsigned char* blockRoundedBuffer = calloc(1, size); + memcpy(blockRoundedBuffer, [data bytes], [data length]); + + // AES_encrypt only encrypts the first 16 bytes so iterate the entire buffer + int blockOffset = 0; + while (blockOffset < size) { + AES_encrypt(blockRoundedBuffer + blockOffset, buffer + blockOffset, &aesKey); + blockOffset += 16; + } + + NSData* encryptedData = [NSData dataWithBytes:buffer length:size]; + free(buffer); + free(blockRoundedBuffer); + return encryptedData; +} + +- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key { + AES_KEY aesKey; + AES_set_decrypt_key([key bytes], 128, &aesKey); + unsigned char* buffer = malloc([data length]); + + // AES_decrypt only decrypts the first 16 bytes so iterate the entire buffer + int blockOffset = 0; + while (blockOffset < [data length]) { + AES_decrypt([data bytes] + blockOffset, buffer + blockOffset, &aesKey); + blockOffset += 16; + } + + NSData* decryptedData = [NSData dataWithBytes:buffer length:[data length]]; + free(buffer); + return decryptedData; +} + +- (int) getEncryptSize:(NSData*)data { + // the size is the length of the data ceiling to the nearest 16 bytes + return (([data length] + 15) / 16) * 16; +} + +- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert { + const char* buffer = [cert bytes]; + X509* x509; + BIO* bio = BIO_new(BIO_s_mem()); + BIO_puts(bio, buffer); + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + + BIO_free(bio); + + if (!x509) { + fprintf(stderr, "unable to parse certificate in memory\n"); + return NULL; + } + + EVP_PKEY* pubKey = X509_get_pubkey(x509); + EVP_MD_CTX *mdctx = NULL; + mdctx = EVP_MD_CTX_create(); + EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pubKey); + EVP_DigestVerifyUpdate(mdctx, [data bytes], [data length]); + int result = EVP_DigestVerifyFinal(mdctx, (unsigned char*)[signature bytes], [signature length]); + + X509_free(x509); + EVP_PKEY_free(pubKey); + EVP_MD_CTX_destroy(mdctx); + + return result > 0; +} + +- (NSData *)signData:(NSData *)data withKey:(NSData *)key { + const char* buffer = [key bytes]; + BIO* bio = BIO_new(BIO_s_mem()); + BIO_puts(bio, buffer); + + EVP_PKEY* pkey; + pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + + BIO_free(bio); + + if (!pkey) { + fprintf(stderr, "unable to parse private key in memory\n"); + return NULL; + } + + int ret = -1; + EVP_MD_CTX *mdctx = NULL; + mdctx = EVP_MD_CTX_create(); + ret = EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey); + ret = EVP_DigestSignUpdate(mdctx, [data bytes], [data length]); + size_t slen; + ret = EVP_DigestSignFinal(mdctx, NULL, &slen); + unsigned char* signature = malloc(slen); + int result = EVP_DigestSignFinal(mdctx, signature, &slen); + + EVP_PKEY_free(pkey); + EVP_MD_CTX_destroy(mdctx); + + if (result <= 0) { + free(signature); + return NULL; + } + + NSData* signedData = [NSData dataWithBytes:signature length:slen]; + free(signature); + + return signedData; +} // TODO: these three methods are almost identical, fix the copy-pasta + (NSData*) readCertFromFile { @@ -34,6 +162,20 @@ return [NSData dataWithContentsOfFile:keyFile]; } ++ (NSData *)getSignatureFromCert:(NSData *)cert { + const char* buffer = [cert bytes]; + X509* x509; + BIO* bio = BIO_new(BIO_s_mem()); + BIO_puts(bio, buffer); + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + + if (!x509) { + fprintf(stderr, "unable to parse certificate in memory\n"); + return NULL; + } + return [NSData dataWithBytes:x509->signature->data length:x509->signature->length]; +} + + (void) generateKeyPairUsingSSl { NSLog(@"Generating Certificate... "); CertKeyPair certKeyPair = generateCertKeyPair(); diff --git a/Limelight/HttpManager.h b/Limelight/HttpManager.h index dec7757..defa3df 100644 --- a/Limelight/HttpManager.h +++ b/Limelight/HttpManager.h @@ -9,8 +9,19 @@ #import @interface HttpManager : NSObject + ++ (NSString*) getStringFromXML:(NSData*)xml tag:(NSString*)tag; + - (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert; -- (NSString*) generatePIN; -- (NSData*) saltPIN:(NSString*)PIN; -- (NSURL*) newPairRequest; +- (NSURLRequest*) newPairRequest:(NSData*)salt; +- (NSURLRequest*) newUnpairRequest; +- (NSURLRequest*) newChallengeRequest:(NSData*)challenge; +- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp; +- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret; +- (NSURLRequest*) newPairChallenge; +- (NSURLRequest*) newAppListRequest; +- (NSURLRequest*) newServerInfoRequest; +- (NSData*) executeRequestSynchronously:(NSURLRequest*)request; @end + + diff --git a/Limelight/HttpManager.m b/Limelight/HttpManager.m index 0551d96..1df5794 100644 --- a/Limelight/HttpManager.m +++ b/Limelight/HttpManager.m @@ -9,17 +9,70 @@ #import "HttpManager.h" #import "CryptoManager.h" +#include +#include + @implementation HttpManager { NSString* _baseURL; NSString* _host; NSString* _uniqueId; NSString* _deviceName; - NSData* _salt; NSData* _cert; + NSMutableData* _respData; + NSData* _requestResp; + dispatch_semaphore_t _requestLock; } static const NSString* PORT = @"47984"; ++ (NSString*) getStringFromXML:(NSData*)xml tag:(NSString*)tag { + xmlDocPtr docPtr = xmlParseMemory([xml bytes], [xml length]); + + if (docPtr == NULL) { + NSLog(@"ERROR: An error occured trying to parse xml."); + return NULL; + } + NSString* value; + xmlNodePtr node; + xmlNodePtr rootNode = node = xmlDocGetRootElement(docPtr); + + // Check root status_code + if (![HttpManager verifyStatus: rootNode]) { + //TODO: handle error + } + + // Skip the root node + node = node->children; + + while (node != NULL) { + //NSLog(@"node: %s", node->name); + if (!xmlStrcmp(node->name, (const xmlChar*)[tag UTF8String])) { + xmlChar* nodeVal = xmlNodeListGetString(docPtr, node->xmlChildrenNode, 1); + value = [[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding]; + xmlFree(nodeVal); + } + node = node->next; + } + //NSLog(@"xmlValue: %@", value); + xmlFree(rootNode); + xmlFree(docPtr); + + return value; +} + ++ (bool) verifyStatus:(xmlNodePtr)docRoot { + xmlChar* statusStr = xmlGetProp(docRoot, (const xmlChar*)"status_code"); + NSLog(@"status: %s", statusStr); + int status = [[NSString stringWithUTF8String:(const char*)statusStr] intValue]; + xmlFree(statusStr); + return status == 200; +} + ++ (NSData*) fixXmlVersion:(NSData*) xmlData { + NSString* xmlString = [[[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"UTF-16" withString:@"UTF-8" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [xmlData length])]; + //NSLog(@"xmlString: %@", xmlString); + return [NSData dataWithBytes:[xmlString UTF8String] length:[xmlString length]]; +} - (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert { self = [super init]; @@ -29,15 +82,72 @@ static const NSString* PORT = @"47984"; _cert = cert; _baseURL = [[NSString stringWithFormat:@"https://%@:%@", host, PORT] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + _requestLock = dispatch_semaphore_create(0); + _respData = [[NSMutableData alloc] init]; return self; } -- (NSURL*) newPairRequest { - //NSLog(@"host: %@ \nport: %@ \nuniqueID: %@ \ndeviceName: %@ \nsalt: %@ \ncert: %@", _host, PORT, _uniqueId, _deviceName, salt, cert); - NSString* urlString = [[NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@", _baseURL, _uniqueId, _deviceName, [self bytesToHex:_salt], [self bytesToHex:_cert]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSURL* url = [[NSURL alloc] initWithString:urlString]; - //NSLog(@"pair url: %@", url); - return url; +- (NSData*) executeRequestSynchronously:(NSURLRequest*)request { + NSLog(@"Making Request: %@", request); + [_respData setLength:0]; + dispatch_sync(dispatch_get_main_queue(), ^{ + [NSURLConnection connectionWithRequest:request delegate:self]; + }); + dispatch_semaphore_wait(_requestLock, DISPATCH_TIME_FOREVER); + return _requestResp; +} + +- (void) executeRequest:(NSURLRequest*)request { + [NSURLConnection connectionWithRequest:request delegate:self]; +} + +- (NSURLRequest*) createRequestFromString:(NSString*) urlString { + NSString* escapedUrl = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSURL* url = [[NSURL alloc] initWithString:escapedUrl]; + return [NSURLRequest requestWithURL:url]; +} + +- (NSURLRequest*) newPairRequest:(NSData*)salt { + NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@", + _baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest*) newUnpairRequest { + NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseURL, _uniqueId]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest*) newChallengeRequest:(NSData*)challenge { + NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@", + _baseURL, _uniqueId, _deviceName, [self bytesToHex:challenge]]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp { + NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@", + _baseURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret { + NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseURL, _uniqueId, _deviceName, clientPairSecret]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest*) newPairChallenge { + NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=pairchallenge", _baseURL, _uniqueId, _deviceName]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest *)newAppListRequest { + NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseURL, _uniqueId]; + return [self createRequestFromString:urlString]; +} + +- (NSURLRequest *)newServerInfoRequest { + NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseURL, _uniqueId]; + return [self createRequestFromString:urlString]; } - (NSString*) bytesToHex:(NSData*)data { @@ -49,50 +159,27 @@ static const NSString* PORT = @"47984"; return hex; } -- (NSString*) generatePIN { - NSString* PIN = [NSString stringWithFormat:@"%d%d%d%d", - arc4random() % 10, arc4random() % 10, - arc4random() % 10, arc4random() % 10]; - NSLog(@"PIN: %@", PIN); - return PIN; -} - -- (NSData*) saltPIN:(NSString*)PIN { - NSMutableData* saltedPIN = [[NSMutableData alloc] initWithCapacity:20]; - [saltedPIN appendData:[self randomBytes:16]]; - [saltedPIN appendBytes:[PIN UTF8String] length:4]; - - //NSLog(@"Salted PIN: %@", [saltedPIN description]); - _salt = saltedPIN; - return saltedPIN; -} - -- (NSData*) randomBytes:(NSInteger)length { - char* bytes = malloc(length); - arc4random_buf(bytes, length); - NSData* randomData = [NSData dataWithBytes:bytes length:length]; - free(bytes); - return randomData; -} - - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"Received response: %@", response); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - NSLog(@"Received data: %@", data); + NSLog(@"Received data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + [_respData appendData:data]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + _requestResp = [HttpManager fixXmlVersion:_respData]; + dispatch_semaphore_signal(_requestLock); } - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { SecIdentityRef identity = [self getClientCertificate]; // Go get a SecIdentityRef CFArrayRef certs = [self getCertificate:identity]; // Get an array of certificates - // Convert the CFArrayRef to a NSArray - NSArray *myArray = (__bridge NSArray *)certs; + NSArray *certArray = (__bridge NSArray *)certs; - // Create the NSURLCredential - NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:myArray persistence:NSURLCredentialPersistencePermanent]; + NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent]; - // Send [challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge]; } @@ -103,35 +190,32 @@ static const NSString* PORT = @"47984"; SecIdentityCopyCertificate(identity, &certificate); SecCertificateRef certs[1] = { certificate }; - CFArrayRef array = CFArrayCreate(NULL, (const void **) certs, 1, NULL); + CFArrayRef certArray = CFArrayCreate(NULL, (const void **) certs, 1, NULL); - SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); - SecTrustRef myTrust; + SecPolicyRef policyRef = SecPolicyCreateBasicX509(); + SecTrustRef trustRef; - OSStatus status = SecTrustCreateWithCertificates(array, myPolicy, &myTrust); - if (status == noErr) { - NSLog(@"No Err creating certificate"); - } else { - NSLog(@"Possible Err Creating certificate"); + OSStatus status = SecTrustCreateWithCertificates(certArray, policyRef, &trustRef); + if (status != noErr) { + NSLog(@"Error Creating certificate"); } - return array; + return certArray; } // Returns the identity - (SecIdentityRef)getClientCertificate { SecIdentityRef identityApp = nil; - NSData *PKCS12Data = [CryptoManager readP12FromFile]; - CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; - - CFStringRef password = CFSTR("limelight"); // no password - const void *keys[] = { kSecImportExportPassphrase };//kSecImportExportPassphrase }; + CFDataRef p12Data = (__bridge CFDataRef)[CryptoManager readP12FromFile]; + + CFStringRef password = CFSTR("limelight"); + const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); - OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items); + OSStatus securityError = SecPKCS12Import(p12Data, options, &items); if (securityError == errSecSuccess) { - NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items)); + //NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items)); CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); } else { diff --git a/Limelight/MainFrameViewController.m b/Limelight/MainFrameViewController.m index 9f0d23e..e691254 100644 --- a/Limelight/MainFrameViewController.m +++ b/Limelight/MainFrameViewController.m @@ -11,9 +11,10 @@ #import "Computer.h" #import "CryptoManager.h" #import "HttpManager.h" +#import "PairManager.h" @implementation MainFrameViewController -NSString* hostAddr = @"cement-truck.case.edu"; +NSString* hostAddr; MDNSManager* mDNSManager; + (const char*)getHostAddr @@ -24,7 +25,15 @@ MDNSManager* mDNSManager; - (void)PairButton:(UIButton *)sender { NSLog(@"Pair Button Pressed!"); - [ConnectionHandler pairWithHost:hostAddr]; + [CryptoManager generateKeyPairUsingSSl]; + NSString* uniqueId = [CryptoManager getUniqueID]; + NSData* cert = [CryptoManager readCertFromFile]; + + HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddr uniqueId:uniqueId deviceName:@"roth" cert:cert]; + PairManager* pMan = [[PairManager alloc] initWithManager:hMan andCert:cert]; + + NSOperationQueue* opQueue = [[NSOperationQueue alloc] init]; + [opQueue addOperation:pMan]; } - (void)StreamButton:(UIButton *)sender @@ -50,9 +59,9 @@ MDNSManager* mDNSManager; - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - //self.hostPickerVals = [mDNSManager getFoundHosts]; + self.hostPickerVals = [mDNSManager getFoundHosts]; - //[self.HostPicker reloadAllComponents]; + [self.HostPicker reloadAllComponents]; if (pickerView == self.HostPicker) { hostAddr = ((Computer*)([self.hostPickerVals objectAtIndex:[self.HostPicker selectedRowInComponent:0]])).hostName; } @@ -85,21 +94,9 @@ MDNSManager* mDNSManager; self.streamConfigVals = [[NSArray alloc] initWithObjects:@"1280x720 (30Hz)", @"1280x720 (60Hz)", @"1920x1080 (30Hz)", @"1920x1080 (60Hz)",nil]; self.hostPickerVals = [[NSArray alloc] init]; + mDNSManager = [[MDNSManager alloc] initWithCallback:self]; - //[mDNSManager searchForHosts]; - - [CryptoManager generateKeyPairUsingSSl]; - NSString* uniqueId = [CryptoManager getUniqueID]; - NSData* cert = [CryptoManager readCertFromFile]; - - HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddr uniqueId:uniqueId deviceName:@"roth" cert:cert]; - NSString* PIN = [hMan generatePIN]; - NSData* saltedPIN = [hMan saltPIN:PIN]; - NSLog(@"PIN: %@, saltedPIN: %@", PIN, saltedPIN); - NSURL* pairUrl = [hMan newPairRequest]; - NSURLRequest* pairRequest = [[NSURLRequest alloc] initWithURL:pairUrl]; - // NSLog(@"making pair request: %@", [pairRequest description]); - [NSURLConnection connectionWithRequest:pairRequest delegate:hMan]; + [mDNSManager searchForHosts]; } - (void)updateHosts:(NSArray *)hosts { diff --git a/Limelight/PairManager.h b/Limelight/PairManager.h new file mode 100644 index 0000000..e707768 --- /dev/null +++ b/Limelight/PairManager.h @@ -0,0 +1,17 @@ +// +// PairManager.h +// Limelight +// +// Created by Diego Waxemberg on 10/19/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import +#import "HttpManager.h" + +@interface PairManager : NSOperation +- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert; +- (NSString*) generatePIN; +- (NSData*) saltPIN:(NSString*)PIN; +- (void) initiatePair; +@end diff --git a/Limelight/PairManager.m b/Limelight/PairManager.m new file mode 100644 index 0000000..65c57f1 --- /dev/null +++ b/Limelight/PairManager.m @@ -0,0 +1,158 @@ +// +// PairManager.m +// Limelight +// +// Created by Diego Waxemberg on 10/19/14. +// Copyright (c) 2014 Limelight Stream. All rights reserved. +// + +#import "PairManager.h" +#import "CryptoManager.h" + +#include + +@implementation PairManager { + HttpManager* _httpManager; + NSData* _cert; +} + +- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert { + self = [super init]; + _httpManager = httpManager; + _cert = cert; + return self; +} + +- (void) main { + [self initiatePair]; +} + +- (void) initiatePair { + NSString* PIN = [self generatePIN]; + NSData* salt = [self saltPIN:PIN]; + NSLog(@"PIN: %@, saltedPIN: %@", PIN, salt); + + NSData* pairResp = [_httpManager executeRequestSynchronously:[_httpManager newPairRequest:salt]]; + if ([[HttpManager getStringFromXML:pairResp tag:@"paired"] intValue] != 1) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSString* plainCert = [HttpManager getStringFromXML:pairResp tag:@"plaincert"]; + + CryptoManager* cryptoMan = [[CryptoManager alloc] init]; + NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt]; + + NSData* randomChallenge = [self randomBytes:16]; + NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey]; + + NSData* challengeResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRequest:encryptedChallenge]]; + if ([[HttpManager getStringFromXML:challengeResp tag:@"paired"] intValue] != 1) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSData* encServerChallengeResp = [self hexToBytes:[HttpManager getStringFromXML:challengeResp tag:@"challengeresponse"]]; + NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey]; + + NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)]; + NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)]; + + NSData* clientSecret = [self randomBytes:16]; + NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]]; + NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey]; + + NSData* secretResp = [_httpManager executeRequestSynchronously:[_httpManager newChallengeRespRequest:challengeRespEncrypted]]; + if ([[HttpManager getStringFromXML:secretResp tag:@"paired"] intValue] != 1) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSData* serverSecretResp = [self hexToBytes:[HttpManager getStringFromXML:secretResp tag:@"pairingsecret"]]; + NSData* serverSecret = [serverSecretResp subdataWithRange:NSMakeRange(0, 16)]; + NSData* serverSignature = [serverSecretResp subdataWithRange:NSMakeRange(16, 256)]; + + if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[self hexToBytes:plainCert]]) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[self hexToBytes:plainCert]]] with:serverSecret]]; + if (![serverChallengeRespHash isEqual:serverResponse]) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSData* clientPairingSecret = [self concatData:clientSecret with:[cryptoMan signData:clientSecret withKey:[CryptoManager readKeyFromFile]]]; + NSData* clientSecretResp = [_httpManager executeRequestSynchronously:[_httpManager newClientSecretRespRequest:[self bytesToHex:clientPairingSecret]]]; + if (![[HttpManager getStringFromXML:clientSecretResp tag:@"paired"] isEqual:@"1"]) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } + + NSData* clientPairChallenge = [_httpManager executeRequestSynchronously:[_httpManager newPairChallenge]]; + if (![[HttpManager getStringFromXML:clientPairChallenge tag:@"paired"] isEqual:@"1"]) { + [_httpManager executeRequestSynchronously:[_httpManager newUnpairRequest]]; + return; + } +} + +- (NSData*) concatData:(NSData*)data with:(NSData*)moreData { + NSMutableData* concatData = [[NSMutableData alloc] initWithData:data]; + [concatData appendData:moreData]; + return concatData; +} + +- (NSString*) generatePIN { + NSString* PIN = [NSString stringWithFormat:@"%d%d%d%d", + arc4random() % 10, arc4random() % 10, + arc4random() % 10, arc4random() % 10]; + NSLog(@"PIN: %@", PIN); + return PIN; +} + +- (NSData*) saltPIN:(NSString*)PIN { + NSMutableData* saltedPIN = [[NSMutableData alloc] initWithCapacity:20]; + [saltedPIN appendData:[self randomBytes:16]]; + [saltedPIN appendBytes:[PIN UTF8String] length:4]; + + //NSLog(@"Salted PIN: %@", [saltedPIN description]); + return saltedPIN; +} + +- (NSData*) randomBytes:(NSInteger)length { + char* bytes = malloc(length); + arc4random_buf(bytes, length); + NSData* randomData = [NSData dataWithBytes:bytes length:length]; + free(bytes); + return randomData; +} + +- (NSData*) hexToBytes:(NSString*) hex { + int len = [hex length]; + NSMutableData* data = [NSMutableData dataWithCapacity:len / 2]; + char byteChars[3] = {'\0','\0','\0'}; + unsigned long wholeByte; + + const char *chars = [hex UTF8String]; + int i = 0; + while (i < len) { + byteChars[0] = chars[i++]; + byteChars[1] = chars[i++]; + wholeByte = strtoul(byteChars, NULL, 16); + [data appendBytes:&wholeByte length:1]; + } + + return data; +} + +- (NSString*) bytesToHex:(NSData*)data { + const unsigned char* bytes = [data bytes]; + NSMutableString *hex = [[NSMutableString alloc] init]; + for (int i = 0; i < [data length]; i++) { + [hex appendFormat:@"%02X" , bytes[i]]; + } + return hex; +} + +@end