SecOTRRemote.m
1 /* 2 * Copyright (c) 2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 #include "AssertMacros.h" 25 #include <stdio.h> 26 #include "SecOTRRemote.h" 27 #include <Security/SecOTRSession.h> 28 #include <Security/SecOTRIdentityPriv.h> 29 #include "keychain/securityd/SecItemServer.h" 30 #include "keychain/securityd/SOSCloudCircleServer.h" 31 32 #include "SOSAccountPriv.h" 33 34 #import "keychain/SecureObjectSync/SOSAccountTrustClassic.h" 35 36 CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFDataRef publicPeerId, CFDataRef privateAccountData, CFErrorRef *error) { 37 SOSDataSourceFactoryRef ds = SecItemDataSourceFactoryGetDefault(); 38 39 SOSAccount* privateAccount = NULL; 40 SOSAccount* publicAccount = NULL; 41 CFStringRef publicKeyString = NULL; 42 SecKeyRef privateKeyRef = NULL; 43 SecKeyRef publicKeyRef = NULL; 44 SecOTRFullIdentityRef privateIdentity = NULL; 45 SecOTRPublicIdentityRef publicIdentity = NULL; 46 CFDataRef result = NULL; 47 SecOTRSessionRef ourSession = NULL; 48 49 require_quiet(ds, fail); 50 require_quiet(publicPeerId, fail); 51 52 if (privateAccountData) { 53 NSError* ns_error = nil; 54 privateAccount = [SOSAccount accountFromData:(__bridge NSData*) privateAccountData factory:ds error:&ns_error]; 55 if (error && *error == NULL && !privateAccount) { 56 *error = (CFErrorRef) CFBridgingRetain(ns_error); 57 } 58 } else { 59 privateAccount = (__bridge SOSAccount*)(SOSKeychainAccountGetSharedAccount()); 60 } 61 62 require_quiet(privateAccount, fail); 63 64 privateKeyRef = SOSAccountCopyDeviceKey(privateAccount, error); 65 require_quiet(privateKeyRef, fail); 66 67 privateIdentity = SecOTRFullIdentityCreateFromSecKeyRefSOS(kCFAllocatorDefault, privateKeyRef, error); 68 require_quiet(privateIdentity, fail); 69 CFReleaseNull(privateKeyRef); 70 71 publicKeyString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, publicPeerId, kCFStringEncodingUTF8); 72 require_quiet(publicKeyString, fail); 73 74 if (publicAccountData) { 75 NSError* ns_error = nil; 76 publicAccount = [SOSAccount accountFromData:(__bridge NSData*) publicAccountData factory:ds error:&ns_error]; 77 if (error && *error == NULL && !publicAccount) { 78 *error = (CFErrorRef) CFBridgingRetain(ns_error); 79 } 80 } else { 81 publicAccount = (__bridge SOSAccount*)(SOSKeychainAccountGetSharedAccount()); 82 } 83 84 require_quiet(publicAccount, fail); 85 86 publicKeyRef = [publicAccount.trust copyPublicKeyForPeer:publicKeyString err:error]; 87 88 if(!publicKeyRef){ 89 if(!ds){ 90 CFReleaseNull(ourSession); 91 CFReleaseNull(publicKeyString); 92 privateAccount= nil; 93 publicAccount = nil; 94 CFReleaseNull(privateKeyRef); 95 CFReleaseNull(publicKeyRef); 96 CFReleaseNull(publicIdentity); 97 CFReleaseNull(privateIdentity); 98 return result; 99 } 100 } 101 publicIdentity = SecOTRPublicIdentityCreateFromSecKeyRef(kCFAllocatorDefault, publicKeyRef, error); 102 require_quiet(publicIdentity, fail); 103 104 CFReleaseNull(publicKeyRef); 105 106 ourSession = SecOTRSessionCreateFromID(kCFAllocatorDefault, privateIdentity, publicIdentity); 107 108 CFMutableDataRef exportSession = CFDataCreateMutable(kCFAllocatorDefault, 0); 109 SecOTRSAppendSerialization(ourSession, exportSession); 110 111 result = exportSession; 112 exportSession = NULL; 113 114 fail: 115 CFReleaseNull(ourSession); 116 CFReleaseNull(publicKeyString); 117 privateAccount= nil; 118 publicAccount = nil; 119 CFReleaseNull(privateKeyRef); 120 CFReleaseNull(publicKeyRef); 121 CFReleaseNull(publicIdentity); 122 CFReleaseNull(privateIdentity); 123 return result; 124 } 125 126 CFDataRef _SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error) { 127 return SecOTRSessionCreateRemote_internal(NULL, publicPeerId, NULL, error); 128 } 129 130 bool _SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) { 131 132 bool result = false; 133 SecOTRSessionRef session = SecOTRSessionCreateFromData(kCFAllocatorDefault, sessionData); 134 require_quiet(session, done); 135 136 CFMutableDataRef negotiationResponse = CFDataCreateMutable(kCFAllocatorDefault, 0); 137 138 if (inputPacket) { 139 SecOTRSProcessPacket(session, inputPacket, negotiationResponse); 140 } else { 141 SecOTRSAppendStartPacket(session, negotiationResponse); 142 } 143 144 CFMutableDataRef outputSession = CFDataCreateMutable(kCFAllocatorDefault, 0); 145 146 SecOTRSAppendSerialization(session, outputSession); 147 *outputSessionData = outputSession; 148 149 *outputPacket = negotiationResponse; 150 151 *readyForMessages = SecOTRSGetIsReadyForMessages(session); 152 CFReleaseNull(session); 153 154 result = true; 155 156 done: 157 return result; 158 } 159