/ keychain / securityd / SecOTRRemote.m
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