/ OSX / sec / Security / SecOTRSession.c
SecOTRSession.c
   1  /*
   2   * Copyright (c) 2011-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  
  25  #include <stdint.h>
  26  #include <sys/types.h>
  27  #include <CoreFoundation/CFDate.h>
  28  
  29  #include "SecOTRSession.h"
  30  
  31  #include "SecOTRMath.h"
  32  #include "SecOTRDHKey.h"
  33  #include "SecOTRSessionPriv.h"
  34  #include "SecOTRPackets.h"
  35  #include "SecOTRPacketData.h"
  36  #include "SecOTRIdentityPriv.h"
  37  
  38  #include <utilities/SecCFWrappers.h>
  39  
  40  #include <CoreFoundation/CFRuntime.h>
  41  #include <CoreFoundation/CFString.h>
  42  
  43  #include <Security/SecBasePriv.h>
  44  #include <Security/SecRandom.h>
  45  #include <Security/SecBase64.h>
  46  #include <Security/SecKeyPriv.h>
  47  
  48  #include <Security/SecureObjectSync/SOSPeerInfo.h>
  49  #include "keychain/SecureObjectSync/SOSCircle.h"
  50  #include <Security/SecureObjectSync/SOSCloudCircle.h>
  51  #include "keychain/SecureObjectSync/SOSInternal.h"
  52  #include "keychain/SecureObjectSync/SOSUserKeygen.h"
  53  
  54  #include <AssertMacros.h>
  55  
  56  #include <corecrypto/cchmac.h>
  57  #include <corecrypto/ccsha2.h>
  58  #include <corecrypto/ccsha1.h>
  59  
  60  #include <string.h>
  61  #include <stdlib.h>
  62  
  63  #include <syslog.h>
  64  #include <os/activity.h>
  65  
  66  #include <utilities/array_size.h>
  67  
  68  #include <ipc/securityd_client.h>
  69  #include <Security/SecuritydXPC.h>
  70  
  71  CFGiblisFor(SecOTRSession);
  72  
  73  static uint64_t setup_defaults_settings(){
  74      
  75      Boolean keyExistsAndHasValue = false;
  76      uint64_t seconds;
  77      seconds = CFPreferencesGetAppIntegerValue(CFSTR("OTR"), CFSTR("com.apple.security"), &keyExistsAndHasValue);
  78      secdebug("OTR", "Retrieving OTR default settings was success? %d value retrieved: %llu", keyExistsAndHasValue, seconds);
  79      return keyExistsAndHasValue ? seconds : (kSecondsPerMinute * 15); //15 minutes by default
  80  }
  81  
  82  static uint64_t SecOTRGetDefaultsWriteSeconds(void) {
  83      static dispatch_once_t sdOnceToken;
  84      static uint64_t seconds;
  85      
  86      dispatch_once(&sdOnceToken, ^{
  87          seconds = setup_defaults_settings();
  88      });
  89      
  90      return seconds;
  91  }
  92  
  93  static void SecOTRSEnableTimeToRoll(SecOTRSessionRef session){
  94      CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
  95      CFAbsoluteTime nextTimeToRoll = now + session->_stallSeconds;
  96      
  97      if(session->_timeToRoll == 0 || session->_timeToRoll > nextTimeToRoll){
  98          session->_timeToRoll = nextTimeToRoll;
  99      }
 100  }
 101  
 102  static void SecOTRSExpireCachedKeysForFullKey(SecOTRSessionRef session, SecOTRFullDHKeyRef myKey)
 103  {
 104      for(int i = 0; i < kOTRKeyCacheSize; ++i)
 105      {
 106          if (0 == timingsafe_bcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE)) {
 107              CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey));
 108              bzero(&session->_keyCache[i], sizeof(session->_keyCache[i]));
 109          }
 110      }
 111  }
 112  
 113  static void SecOTRSExpireCachedKeysForPublicKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef theirKey)
 114  {
 115      for(int i = 0; i < kOTRKeyCacheSize; ++i)
 116      {
 117          if (0 == timingsafe_bcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE)) {
 118              CFDataAppendBytes(session->_macKeysToExpose, session->_keyCache[i]._receiveMacKey, sizeof(session->_keyCache[i]._receiveMacKey));
 119              
 120              bzero(&session->_keyCache[i], sizeof(session->_keyCache[i]));
 121          }
 122      }
 123  }
 124  
 125  static OSStatus SecOTRGenerateNewProposedKey(SecOTRSessionRef session)
 126  {
 127      SecOTRSExpireCachedKeysForFullKey(session, session->_myKey);
 128      
 129      // Swap the keys so we know the current key.
 130      {
 131          SecOTRFullDHKeyRef oldKey = session->_myKey;
 132          session->_myKey = session->_myNextKey;
 133          session->_myNextKey = oldKey;
 134      }
 135      
 136      // Derive a new next key by regenerating over the old key.
 137      OSStatus ret = SecFDHKNewKey(session->_myNextKey);
 138      
 139      session->_keyID += 1;
 140  
 141      return ret;
 142  }
 143  
 144  
 145  static void SecOTRSHandleProposalAcknowledge(SecOTRSessionRef session){
 146      if(session->_missedAck){
 147          SecOTRGenerateNewProposedKey(session);
 148          session->_missedAck = false;
 149      }
 150      else{
 151          session->_receivedAck = true;
 152          SecOTRSEnableTimeToRoll(session);
 153      }
 154  }
 155  
 156  static void SecOTRSRollIfTime(SecOTRSessionRef session){
 157      
 158      CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
 159      CFAbsoluteTime longestTimeToRoll = now + session->_stallSeconds;
 160      
 161      //in case time to roll becomes too large we're going to roll now!
 162      if(session->_timeToRoll < now || session->_timeToRoll > longestTimeToRoll){
 163          SOSOTRSRoll(session);
 164          session->_timeToRoll = 0;
 165      }
 166  }
 167  
 168  
 169  static OTRMessageType SecOTRSGetMessageType(CFDataRef message)
 170  {
 171      OTRMessageType type = kInvalidMessage;
 172  
 173      CFDataRef decodedBytes = SecOTRCopyIncomingBytes(message);
 174  
 175      const uint8_t *bytes = CFDataGetBytePtr(decodedBytes);
 176      size_t size = CFDataGetLength(decodedBytes);
 177  
 178      if (noErr != ReadHeader(&bytes, &size, &type)) {
 179          uint8_t firstByte = *CFDataGetBytePtr(decodedBytes);
 180          switch (firstByte) {
 181              case kOddCompactDataMessage:
 182              case kEvenCompactDataMessage:
 183              case kOddCompactDataMessageWithHashes:
 184              case kEvenCompactDataMessageWithHashes:
 185                  type = firstByte;
 186                  break;
 187                  
 188              default:
 189                  break;
 190          }
 191      }
 192  
 193      CFReleaseNull(decodedBytes);
 194  
 195      return type;
 196  }
 197  
 198  #if DEBUG
 199  
 200  static CFStringRef SecOTRCacheElementCopyDescription(SecOTRCacheElement *keyCache){
 201      __block CFStringRef description = NULL;
 202      BufferPerformWithHexString(keyCache->_fullKeyHash, sizeof(keyCache->_fullKeyHash), ^(CFStringRef fullKeyHashString) {
 203          BufferPerformWithHexString(keyCache->_publicKeyHash,sizeof(keyCache->_publicKeyHash), ^(CFStringRef publicKeyHashString) {
 204              description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("fkh: [%@], pkh: [%@], c: %llu tc: %llu"), fullKeyHashString, publicKeyHashString, keyCache->_counter, keyCache->_theirCounter);
 205          });
 206      });
 207      return description;
 208  }
 209  
 210  #endif
 211  const char *SecOTRPacketTypeString(CFDataRef message)
 212  {
 213      if (!message) return "NoMessage";
 214      switch (SecOTRSGetMessageType(message)) {
 215          case kDHMessage:                        return "DHMessage (0x02)";
 216          case kDataMessage:                      return "DataMessage (0x03)";
 217          case kDHKeyMessage:                     return "DHKeyMessage (0x0A)";
 218          case kRevealSignatureMessage:           return "RevealSignatureMessage (0x11)";
 219          case kSignatureMessage:                 return "SignatureMessage (0x12)";
 220          case kEvenCompactDataMessage:           return "kEvenCompactDatamessage (0x20)";
 221          case kOddCompactDataMessage:            return "kOddCompactDataMessage (0x21)";
 222          case kEvenCompactDataMessageWithHashes: return "kEvenCompactDatamessage (0x30)";
 223          case kOddCompactDataMessageWithHashes:  return "kOddCompactDataMessage (0x31)";
 224          case kInvalidMessage:                   return "InvalidMessage (0xFF)";
 225          default:                                return "UnknownMessage";
 226      }
 227  }
 228  
 229  static const char *SecOTRAuthStateString(SecOTRAuthState authState)
 230  {
 231      switch (authState) {
 232          case kIdle:                     return "Idle";
 233          case kAwaitingDHKey:            return "AwaitingDHKey";
 234          case kAwaitingRevealSignature:  return "AwaitingRevealSignature";
 235          case kAwaitingSignature:        return "AwaitingSignature";
 236          case kDone:                     return "Done";
 237          default:                        return "InvalidState";
 238      }
 239  }
 240  
 241  static CF_RETURNS_RETAINED CFStringRef SecOTRSessionCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) {
 242      SecOTRSessionRef session = (SecOTRSessionRef)cf;
 243      
 244      CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
 245      
 246      return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<%s %s %s %s%s%s%s %d:%d %s%s %llu %s%s%s%s>"),
 247                                      SecOTRAuthStateString(session->_state),
 248                                      session->_compactAppleMessages ? "C" :"c",
 249                                      session->_includeHashes ? "I" : "i",
 250                                      session->_me ? "F" : "f",
 251                                      session->_them ? "P" : "p",
 252                                      session->_receivedDHMessage ? "D" : "d",
 253                                      session->_receivedDHKeyMessage ? "K" : "k",
 254                                      session->_keyID,
 255                                      session->_theirKeyID,
 256                                      session->_theirPreviousKey ? "P" : "p",
 257                                      session->_theirKey ? "T" : "t",
 258                                      session->_stallSeconds,
 259                                      session->_missedAck ? "M" : "m",
 260                                      session->_receivedAck ? "R" : "r",
 261                                      session->_stallingTheirRoll ? "S" : "s",
 262                                      (session->_timeToRoll > now && session->_timeToRoll != 0) ? "E" : "e");
 263  }
 264  
 265  static void SecOTRSessionDestroy(CFTypeRef cf) {
 266      SecOTRSessionRef session = (SecOTRSessionRef)cf;
 267  
 268      CFReleaseNull(session->_receivedDHMessage);
 269      CFReleaseNull(session->_receivedDHKeyMessage);
 270  
 271      CFReleaseNull(session->_me);
 272      CFReleaseNull(session->_myKey);
 273      CFReleaseNull(session->_myNextKey);
 274  
 275      CFReleaseNull(session->_them);
 276      CFReleaseNull(session->_theirKey);
 277      CFReleaseNull(session->_theirPreviousKey);
 278  
 279      CFReleaseNull(session->_macKeysToExpose);
 280  
 281      dispatch_release(session->_queue);
 282  }
 283  
 284  static void SecOTRSessionResetInternal(SecOTRSessionRef session)
 285  {
 286      session->_state = kIdle;
 287      
 288      CFReleaseNull(session->_receivedDHMessage);
 289      CFReleaseNull(session->_receivedDHKeyMessage);
 290  
 291      session->_keyID = 0;
 292      CFReleaseNull(session->_myKey);
 293      CFReleaseNull(session->_myNextKey);
 294      //session->_myNextKey = SecOTRFullDHKCreate(kCFAllocatorDefault);
 295      session->_theirKeyID = 0;
 296      CFReleaseNull(session->_theirKey);
 297      CFReleaseNull(session->_theirPreviousKey);
 298      CFReleaseNull(session->_macKeysToExpose);
 299      session->_macKeysToExpose = CFDataCreateMutable(kCFAllocatorDefault, 0);
 300  
 301      bzero(session->_keyCache, sizeof(session->_keyCache));
 302  }
 303  
 304  int SecOTRSGetKeyID(SecOTRSessionRef session){
 305      return session->_keyID;
 306  }
 307  
 308  int SecOTRSGetTheirKeyID(SecOTRSessionRef session){
 309      return session->_theirKeyID;
 310  }
 311  
 312  void SecOTRSessionReset(SecOTRSessionRef session)
 313  {
 314      dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSessionResetInternal);
 315  }
 316  
 317  
 318  static void SecOTRPIPerformWithSerializationString(SecOTRPublicIdentityRef id, void (^action)(CFStringRef string)) {
 319      CFMutableDataRef idData = CFDataCreateMutable(kCFAllocatorDefault, 0);
 320      SecOTRPIAppendSerialization(id, idData, NULL);
 321      CFDataPerformWithHexString(idData, action);
 322      CFReleaseNull(idData);
 323  }
 324  
 325  SecOTRSessionRef SecOTRSessionCreateFromID(CFAllocatorRef allocator,
 326                                             SecOTRFullIdentityRef myID,
 327                                             SecOTRPublicIdentityRef theirID)
 328  {
 329      SecOTRSessionRef newID = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator);
 330  
 331      (void)SecOTRGetDefaultsWriteSeconds();
 332      newID->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL);
 333  
 334      newID->_me = CFRetainSafe(myID);
 335      newID->_them = CFRetainSafe(theirID);
 336      newID->_receivedDHMessage = NULL;
 337      newID->_receivedDHKeyMessage = NULL;
 338      newID->_myKey = NULL;
 339      newID->_myNextKey = NULL;
 340      newID->_theirKey = NULL;
 341      newID->_theirPreviousKey = NULL;
 342      newID->_macKeysToExpose = NULL;
 343      newID->_textOutput = false;
 344      newID->_compactAppleMessages = false;
 345      newID->_includeHashes = false;
 346      
 347      newID->_timeToRoll =  0;
 348      newID->_stallingTheirRoll = false;
 349      newID->_stallSeconds = 0;
 350      newID->_missedAck = true;
 351      newID->_receivedAck = false;
 352      
 353      SecOTRSessionResetInternal(newID);
 354  
 355      {
 356          SecOTRPublicIdentityRef myPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, newID->_me, NULL);
 357          SecOTRPIPerformWithSerializationString(myPublicID, ^(CFStringRef myIDString) {
 358              SecOTRPIPerformWithSerializationString(newID->_them, ^(CFStringRef theirIDString) {
 359                  secnotice("otr", "%@ Creating with M: %@, T: %@", newID, myIDString, theirIDString);
 360              });
 361          });
 362          CFReleaseNull(myPublicID);
 363      }
 364  
 365      return newID;
 366  }
 367  
 368  SecOTRSessionRef SecOTRSessionCreateFromIDAndFlags(CFAllocatorRef allocator,
 369                                             SecOTRFullIdentityRef myID,
 370                                             SecOTRPublicIdentityRef theirID,
 371                                             uint32_t flags)
 372  {
 373      
 374      uint64_t seconds = SecOTRGetDefaultsWriteSeconds();
 375      
 376      SecOTRSessionRef newID = SecOTRSessionCreateFromID(allocator, myID, theirID);
 377      if (flags & kSecOTRSendTextMessages) {
 378          newID->_textOutput = true;
 379      }
 380      if (flags & kSecOTRUseAppleCustomMessageFormat) {
 381          newID->_compactAppleMessages = true;
 382      }
 383      if(flags & kSecOTRIncludeHashesInMessages)
 384      {
 385          newID->_includeHashes = true;
 386      }
 387      if(flags & kSecOTRSlowRoll)
 388      {
 389          newID->_stallSeconds = seconds;
 390      }
 391      
 392      return newID;
 393  }
 394  
 395  static uint64_t constant_zero = 0;
 396  
 397  static bool hashIsZero(uint8_t hash[CCSHA1_OUTPUT_SIZE])
 398  {
 399      bool isZero = true;
 400      for(size_t byte = 0; isZero && byte < CCSHA1_OUTPUT_SIZE; ++byte)
 401          isZero = (0 == hash[byte]);
 402      
 403      return isZero;
 404  }
 405  
 406  static bool SOSOTRSCacheEntryIsEmpty(SecOTRCacheElement *element)
 407  {
 408      return hashIsZero(element->_fullKeyHash) && hashIsZero(element->_publicKeyHash);
 409  }
 410  
 411  #if DEBUG
 412  
 413  static void WithCacheDescription(SecOTRSessionRef session, void (^operation)(CFStringRef cacheDescription)) {
 414      CFStringRef description = NULL;
 415      
 416      CFStringRef keyCache0Description = SecOTRCacheElementCopyDescription(&session->_keyCache[0]);
 417      CFStringRef keyCache1Description = SecOTRCacheElementCopyDescription(&session->_keyCache[1]);
 418      CFStringRef keyCache2Description = SecOTRCacheElementCopyDescription(&session->_keyCache[2]);
 419      CFStringRef keyCache3Description = SecOTRCacheElementCopyDescription(&session->_keyCache[3]);
 420      
 421      description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("{%@, %@, %@, %@}"), keyCache0Description, keyCache1Description, keyCache2Description, keyCache3Description);
 422      
 423      operation(description);
 424      
 425      CFReleaseNull(keyCache0Description);
 426      CFReleaseNull(keyCache1Description);
 427      CFReleaseNull(keyCache2Description);
 428      CFReleaseNull(keyCache3Description);
 429      CFReleaseNull(description);
 430  }
 431  
 432  #endif
 433  
 434  static void SecOTRSFindKeysForMessage(SecOTRSessionRef session,
 435                                        SecOTRFullDHKeyRef myKey,
 436                                        SecOTRPublicDHKeyRef theirKey,
 437                                        bool sending,
 438                                        uint8_t** messageKey, uint8_t** macKey, uint64_t **counter)
 439  {
 440      SecOTRCacheElement* emptyKeys = NULL;
 441      SecOTRCacheElement* cachedKeys = NULL;
 442  #if DEBUG
 443      int emptyPosition = kOTRKeyCacheSize;
 444  #endif
 445  
 446      if ((NULL == myKey) || (NULL == theirKey)) {
 447          if (messageKey)
 448              *messageKey = NULL;
 449          if (macKey)
 450              *macKey = NULL;
 451          if (counter)
 452              *counter = &constant_zero;
 453              
 454          return;
 455      }
 456      
 457      for(int i = 0; i < kOTRKeyCacheSize; ++i)
 458      {
 459          if (0 == timingsafe_bcmp(session->_keyCache[i]._fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE)
 460           && (0 == timingsafe_bcmp(session->_keyCache[i]._publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE))) {
 461              cachedKeys = &session->_keyCache[i];
 462  #if DEBUG
 463              secdebug("OTR","session@[%p] found key match: mk: %@, tk: %@", session, myKey, theirKey);
 464  #endif
 465              break;
 466          }
 467  
 468          if (emptyKeys == NULL && SOSOTRSCacheEntryIsEmpty(&(session->_keyCache[i]))) {
 469  #if DEBUG
 470              emptyPosition = i;
 471  #endif
 472  
 473              emptyKeys = &session->_keyCache[i];
 474          }
 475      }
 476  
 477      if (cachedKeys == NULL) {
 478          if (emptyKeys == NULL) {
 479  #if DEBUG
 480              WithCacheDescription(session, ^(CFStringRef cacheDescription) {
 481                  secdebug("OTR","session@[%p] Cache miss, spooky for mk: %@, tk: %@ cache: %@", session, myKey, theirKey, cacheDescription);
 482              });
 483              emptyPosition = 0;
 484  #endif
 485  
 486              emptyKeys = &session->_keyCache[0];
 487  
 488          }
 489          assert(emptyKeys);
 490  
 491          // Fill in the entry.
 492          memcpy(emptyKeys->_fullKeyHash, SecFDHKGetHash(myKey), CCSHA1_OUTPUT_SIZE);
 493          memcpy(emptyKeys->_publicKeyHash, SecPDHKGetHash(theirKey), CCSHA1_OUTPUT_SIZE);
 494          
 495          emptyKeys->_counter = 0;
 496          emptyKeys->_theirCounter = 0;
 497  
 498          SecOTRDHKGenerateOTRKeys(myKey, theirKey,
 499                                emptyKeys->_sendEncryptionKey, emptyKeys->_sendMacKey,
 500                                emptyKeys->_receiveEncryptionKey, emptyKeys->_receiveMacKey);
 501  
 502          cachedKeys = emptyKeys;
 503  #if DEBUG
 504          WithCacheDescription(session, ^(CFStringRef cacheDescription) {
 505              secdebug("OTR","mk %@, th: %@ session@[%p] new key cache state added key@[%d]: %@", myKey, theirKey, session, emptyPosition, cacheDescription);
 506          });
 507  #endif
 508  
 509      }
 510      
 511      if (messageKey)
 512          *messageKey = sending ? cachedKeys->_sendEncryptionKey : cachedKeys->_receiveEncryptionKey;
 513      if (macKey)
 514          *macKey = sending ? cachedKeys->_sendMacKey : cachedKeys->_receiveMacKey;
 515      if (counter)
 516          *counter = sending ? &cachedKeys->_counter : &cachedKeys->_theirCounter;
 517  }
 518  
 519  SecOTRSessionRef SecOTRSessionCreateFromData(CFAllocatorRef allocator, CFDataRef data)
 520  {
 521      if (data == NULL)
 522          return NULL;
 523  
 524      SecOTRSessionRef result = NULL;
 525      SecOTRSessionRef session = CFTypeAllocate(SecOTRSession, struct _SecOTRSession, allocator);
 526  
 527      uint8_t numberOfKeys;
 528      uint64_t timeToRoll;
 529      
 530      const uint8_t *bytes = CFDataGetBytePtr(data);
 531      size_t size = (size_t)CFDataGetLength(data);
 532      
 533      (void)SecOTRGetDefaultsWriteSeconds();
 534      
 535      session->_queue = dispatch_queue_create("OTRSession", DISPATCH_QUEUE_SERIAL);
 536  
 537      session->_me = NULL;
 538      session->_them = NULL;
 539      session->_myKey = NULL;
 540      session->_myNextKey = NULL;
 541      session->_theirKey = NULL;
 542      session->_theirPreviousKey = NULL;
 543      session->_receivedDHMessage = NULL;
 544      session->_receivedDHKeyMessage = NULL;
 545      session->_textOutput = false;
 546      session->_compactAppleMessages = false;
 547      session->_timeToRoll =  0;
 548      session->_stallingTheirRoll = false;
 549      session->_stallSeconds = 0;
 550      session->_missedAck = true;
 551      session->_receivedAck = false;
 552      
 553      bzero(session->_keyCache, sizeof(session->_keyCache));
 554  
 555      uint8_t version;
 556      require_noerr(ReadByte(&bytes, &size, &version), fail);
 557      require(version <= 6, fail);
 558  
 559      require_noerr(ReadLong(&bytes, &size, &session->_state), fail);
 560      session->_me = SecOTRFullIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL);
 561      require(session->_me != NULL, fail);
 562      session->_them = SecOTRPublicIdentityCreateFromBytes(kCFAllocatorDefault, &bytes, &size, NULL);
 563      require(session->_them != NULL, fail);
 564      
 565      require(size > sizeof(session->_r), fail);
 566      memcpy(session->_r, bytes, sizeof(session->_r));
 567      bytes += sizeof(session->_r);
 568      size -= sizeof(session->_r);
 569  
 570      {
 571          uint8_t hasMessage = false;
 572          ReadByte(&bytes, &size, &hasMessage);
 573          if (hasMessage) {
 574              session->_receivedDHMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size);
 575          }
 576      }
 577  
 578      if (version >= 2) {
 579          uint8_t hasMessage = false;
 580          ReadByte(&bytes, &size, &hasMessage);
 581          if (hasMessage) {
 582              session->_receivedDHKeyMessage = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size);
 583          }
 584      }
 585      
 586      if (version < 3) {
 587          uint8_t ready;
 588          require_noerr(ReadByte(&bytes, &size, &ready), fail);
 589          if (ready && session->_state == kIdle)
 590              session->_state = kDone;
 591      }
 592      
 593      
 594      require_noerr(ReadLong(&bytes, &size, &session->_keyID), fail);
 595      if (session->_keyID > 0) {
 596          session->_myKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size);
 597          require(session->_myKey != NULL, fail);
 598          session->_myNextKey = SecOTRFullDHKCreateFromBytes(kCFAllocatorDefault, &bytes, &size);
 599          require(session->_myNextKey != NULL, fail);
 600      }
 601      
 602      
 603      require_noerr(ReadByte(&bytes, &size, &numberOfKeys), fail);
 604      
 605      require_noerr(ReadLong(&bytes, &size, &session->_theirKeyID), fail);
 606      if (version < 5) {
 607          if (session->_theirKeyID > 0) {
 608              if (session->_theirKeyID > 1) {
 609                  session->_theirPreviousKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size);
 610                  require(session->_theirPreviousKey != NULL, fail);
 611              }
 612              session->_theirKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size);
 613              require(session->_theirKey != NULL, fail);
 614          }
 615      }
 616      else {
 617          if(numberOfKeys >= 1){
 618              if (numberOfKeys >= 2) {
 619                  session->_theirPreviousKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size);
 620                  require(session->_theirPreviousKey != NULL, fail);
 621              }
 622              session->_theirKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, &bytes, &size);
 623              require(session->_theirKey != NULL, fail);
 624          }
 625      }
 626      
 627      
 628      uint64_t *counter;
 629      SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter);
 630      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 631      SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter);
 632      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 633      SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter);
 634      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 635      SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter);
 636      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 637      SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter);
 638      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 639      SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter);
 640      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 641      SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter);
 642      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 643      SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter);
 644      require_noerr(ReadLongLong(&bytes, &size, counter), fail);
 645      
 646      session->_macKeysToExpose = CFDataCreateMutableFromOTRDATA(kCFAllocatorDefault, &bytes, &size);
 647      require(session->_macKeysToExpose != NULL, fail);
 648      
 649      require_noerr(ReadByteAsBool(&bytes, &size, &session->_textOutput), fail);
 650  
 651      if (version >= 4) {
 652          require_noerr(ReadByteAsBool(&bytes, &size, &session->_compactAppleMessages), fail);
 653      }
 654      if (version >= 5) {
 655          require_noerr(ReadByteAsBool(&bytes, &size, &session->_includeHashes), fail);
 656      }
 657      if (version >= 6) {
 658          require_noerr(ReadLongLong(&bytes, &size, &session->_stallSeconds), fail);
 659          require_noerr(ReadByteAsBool(&bytes, &size, &session->_stallingTheirRoll), fail);
 660          require_noerr(ReadLongLong(&bytes, &size, &timeToRoll), fail);
 661          require_noerr(ReadByteAsBool(&bytes, &size, &session->_missedAck), fail);
 662          require_noerr(ReadByteAsBool(&bytes, &size, &session->_receivedAck), fail);
 663          session->_timeToRoll = timeToRoll;
 664      }
 665      result = session;
 666      session = NULL;
 667  
 668  fail:
 669      CFReleaseNull(session);
 670      return result;
 671  }
 672  
 673  
 674  OSStatus SecOTRSAppendSerialization(SecOTRSessionRef session, CFMutableDataRef serializeInto)
 675  {
 676      __block OSStatus result  = errSecParam;
 677  
 678      require(session, abort);
 679      require(serializeInto, abort);
 680  
 681      CFIndex start = CFDataGetLength(serializeInto);
 682      
 683      dispatch_sync(session->_queue, ^{
 684          const uint8_t version = 6;
 685          uint8_t numberOfKeys = 0;
 686          CFDataAppendBytes(serializeInto, &version, sizeof(version));
 687  
 688          AppendLong(serializeInto, session->_state);
 689  
 690          result = (SecOTRFIAppendSerialization(session->_me, serializeInto, NULL)) ? errSecSuccess : errSecParam;
 691      
 692          if (result == errSecSuccess) {
 693              result = (SecOTRPIAppendSerialization(session->_them, serializeInto, NULL)) ? errSecSuccess : errSecParam;
 694          }
 695      
 696          if (result == errSecSuccess) {
 697              CFDataAppendBytes(serializeInto, session->_r, sizeof(session->_r));
 698  
 699              if (session->_receivedDHMessage == NULL) {
 700                  AppendByte(serializeInto, 0);
 701              } else {
 702                  AppendByte(serializeInto, 1);
 703                  AppendCFDataAsDATA(serializeInto, session->_receivedDHMessage);
 704              }
 705              
 706              if (session->_receivedDHKeyMessage == NULL) {
 707                  AppendByte(serializeInto, 0);
 708              } else {
 709                  AppendByte(serializeInto, 1);
 710                  AppendCFDataAsDATA(serializeInto, session->_receivedDHKeyMessage);
 711              }
 712              
 713              AppendLong(serializeInto, session->_keyID);
 714              if (session->_keyID > 0) {
 715                  SecFDHKAppendSerialization(session->_myKey, serializeInto);
 716                  SecFDHKAppendSerialization(session->_myNextKey, serializeInto);
 717              }
 718              
 719              if(session->_theirPreviousKey != NULL)
 720                  numberOfKeys++;
 721              if(session->_theirKey != NULL)
 722                  numberOfKeys++;
 723              
 724              AppendByte(serializeInto, numberOfKeys);
 725              
 726              AppendLong(serializeInto, session->_theirKeyID);
 727              
 728              if (session->_theirPreviousKey != NULL)
 729                  SecPDHKAppendSerialization(session->_theirPreviousKey, serializeInto);
 730              
 731              if (session->_theirKey != NULL )
 732                  SecPDHKAppendSerialization(session->_theirKey, serializeInto);
 733              
 734              
 735              uint64_t *counter;
 736              SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, false, NULL, NULL, &counter);
 737              AppendLongLong(serializeInto, *counter);
 738              SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirKey, true, NULL, NULL, &counter);
 739              AppendLongLong(serializeInto, *counter);
 740              SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, false, NULL, NULL, &counter);
 741              AppendLongLong(serializeInto, *counter);
 742              SecOTRSFindKeysForMessage(session, session->_myKey, session->_theirPreviousKey, true, NULL, NULL, &counter);
 743              AppendLongLong(serializeInto, *counter);
 744              SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, false, NULL, NULL, &counter);
 745              AppendLongLong(serializeInto, *counter);
 746              SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirKey, true, NULL, NULL, &counter);
 747              AppendLongLong(serializeInto, *counter);
 748              SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, false, NULL, NULL, &counter);
 749              AppendLongLong(serializeInto, *counter);
 750              SecOTRSFindKeysForMessage(session, session->_myNextKey, session->_theirPreviousKey, true, NULL, NULL, &counter);
 751              AppendLongLong(serializeInto, *counter);
 752  
 753              AppendCFDataAsDATA(serializeInto, session->_macKeysToExpose);
 754              
 755              AppendByte(serializeInto, session->_textOutput ? 1 : 0);
 756              AppendByte(serializeInto, session->_compactAppleMessages ? 1 : 0);
 757              AppendByte(serializeInto, session->_includeHashes ? 1 : 0);
 758      
 759              AppendLongLong(serializeInto, session->_stallSeconds ? session->_stallSeconds : constant_zero);
 760              
 761              AppendByte(serializeInto, session->_stallingTheirRoll ? 1 : 0);
 762              AppendLongLong(serializeInto, (uint64_t)session->_timeToRoll);
 763              AppendByte(serializeInto, session->_missedAck ? 1 : 0);
 764              AppendByte(serializeInto, session->_receivedAck ? 1 : 0);
 765  
 766          }
 767      });
 768  
 769      if (result != errSecSuccess)
 770          CFDataSetLength(serializeInto, start);
 771  
 772  abort:
 773      return result;
 774  }
 775  
 776  
 777  bool SecOTRSIsForKeys(SecOTRSessionRef session, SecKeyRef myPublic, SecKeyRef theirPublic)
 778  {
 779      __block bool isForKeys = false;
 780  
 781      dispatch_sync(session->_queue, ^{
 782          isForKeys = SecOTRFICompareToPublicKey(session->_me, myPublic) &&
 783                      SecOTRPICompareToPublicKey(session->_them, theirPublic);
 784      });
 785  
 786      return isForKeys;
 787  }
 788  
 789  bool SecOTRSGetIsReadyForMessages(SecOTRSessionRef session)
 790  {
 791      __block bool result;
 792  
 793      dispatch_sync(session->_queue, ^{ result = session->_state == kDone; });
 794  
 795      return result;
 796  }
 797  
 798  bool SecOTRSGetIsIdle(SecOTRSessionRef session)
 799  {
 800      __block bool result;
 801      
 802      dispatch_sync(session->_queue, ^{ result = session->_state == kIdle; });
 803      
 804      return result;
 805  }
 806  
 807  static void SecOTRSPrecalculateForPair(SecOTRSessionRef session,
 808                                         SecOTRFullDHKeyRef myKey,
 809                                         SecOTRPublicDHKeyRef theirKey)
 810  {
 811      if (myKey == NULL || theirKey == NULL)
 812          return;
 813  
 814      SecOTRSFindKeysForMessage(session, myKey, theirKey, true, NULL, NULL, NULL);
 815      SecOTRSFindKeysForMessage(session, myKey, theirKey, false, NULL, NULL, NULL);
 816  }
 817  
 818  static void SecOTRSPrecalculateKeysInternal(SecOTRSessionRef session)
 819  {
 820      SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirKey);
 821      SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirKey);
 822      SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirPreviousKey);
 823      SecOTRSPrecalculateForPair(session, session->_myNextKey, session->_theirPreviousKey);
 824  }
 825  
 826  static void SecOTRSPrecalculateNextKeysInternal(SecOTRSessionRef session)
 827  {
 828      SecOTRSPrecalculateForPair(session, session->_myKey, session->_theirKey);
 829  }
 830  
 831  void SecOTRSPrecalculateKeys(SecOTRSessionRef session)
 832  {
 833      dispatch_sync_f(session->_queue, session, (dispatch_function_t) SecOTRSPrecalculateKeysInternal);
 834  }
 835  
 836  enum SecOTRSMessageKind SecOTRSGetMessageKind(SecOTRSessionRef session, CFDataRef message)
 837  {
 838      OTRMessageType type = SecOTRSGetMessageType(message);
 839  
 840      enum SecOTRSMessageKind kind;
 841  
 842      switch (type) {
 843          case kDataMessage:
 844          case kEvenCompactDataMessage:
 845          case kOddCompactDataMessage:
 846          case kEvenCompactDataMessageWithHashes:
 847          case kOddCompactDataMessageWithHashes:
 848              kind = kOTRDataPacket;
 849              break;
 850          case kDHMessage:
 851          case kDHKeyMessage:
 852          case kRevealSignatureMessage:
 853          case kSignatureMessage:
 854              kind = kOTRNegotiationPacket;
 855              break;
 856          case kInvalidMessage:
 857          default:
 858              kind = kOTRUnknownPacket;
 859              break;
 860      }
 861  
 862      return kind;
 863  }
 864  
 865  static OSStatus SecOTRSSignAndProtectRaw_locked(SecOTRSessionRef session,
 866                                                  CFDataRef sourceMessage, CFMutableDataRef destinationMessage,
 867                                                  uint8_t* messageKey, uint8_t* macKey, uint64_t* counter, uint32_t theirKeyID,  SecOTRPublicDHKeyRef theirKey)
 868  {
 869      CFIndex start = CFDataGetLength(destinationMessage);
 870  
 871      AppendHeader(destinationMessage, kDataMessage);
 872      AppendByte(destinationMessage, 0); // Flags, all zero
 873  
 874      AppendLong(destinationMessage, session->_keyID);
 875      AppendLong(destinationMessage, theirKeyID);
 876      SecFDHKAppendPublicSerialization(session->_myNextKey, destinationMessage);
 877      AppendLongLong(destinationMessage, ++*counter);
 878  
 879      CFIndex sourceSize = CFDataGetLength(sourceMessage);
 880      assert(((unsigned long)sourceSize)<=UINT32_MAX); /* this is correct as long as CFIndex is a signed long */
 881      AppendLong(destinationMessage, (uint32_t)sourceSize);
 882      uint8_t* encryptedDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, sourceSize);
 883      AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey,
 884                                 *counter,
 885                                 (size_t)sourceSize, CFDataGetBytePtr(sourceMessage),
 886                                 encryptedDataPointer);
 887  
 888      CFIndex macedContentsSize = CFDataGetLength(destinationMessage) - start;
 889      CFIndex macSize = CCSHA1_OUTPUT_SIZE;
 890      uint8_t* macDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, macSize);
 891  
 892      cchmac(ccsha1_di(),
 893             kOTRMessageMacKeyBytes, macKey,
 894             macedContentsSize, CFDataGetBytePtr(destinationMessage) + start,
 895             macDataPointer);
 896  
 897      CFDataAppend(destinationMessage, session->_macKeysToExpose);
 898  
 899      return errSecSuccess;
 900  }
 901  
 902  const size_t kCompactMessageMACSize = 16;
 903  
 904  static OSStatus SecOTRSSignAndProtectCompact_locked(SecOTRSessionRef session,
 905                                                      CFDataRef sourceMessage, CFMutableDataRef destinationMessage,
 906                                                      uint8_t* messageKey, uint8_t* macKey, uint64_t* counter, uint32_t theirKeyID, SecOTRPublicDHKeyRef theirKey)
 907  {
 908      CFIndex start = CFDataGetLength(destinationMessage);
 909      bool sendHashes = session->_includeHashes;
 910      
 911      const uint8_t messageType = sendHashes ? ((theirKeyID & 0x1) ? kOddCompactDataMessageWithHashes : kEvenCompactDataMessageWithHashes)
 912                                             : ((theirKeyID & 0x1) ? kOddCompactDataMessage           : kEvenCompactDataMessage);
 913  
 914      AppendByte(destinationMessage, messageType);
 915  
 916      SecFDHKAppendCompactPublicSerialization(session->_myNextKey, destinationMessage);
 917      AppendLongLongCompact(destinationMessage, ++*counter);
 918  
 919      CFIndex sourceSize = CFDataGetLength(sourceMessage);
 920      assert(((unsigned long)sourceSize)<=UINT32_MAX); /* this is correct as long as CFIndex is a signed long */
 921      uint8_t* encryptedDataPointer = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, sourceSize);
 922      AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey,
 923                                 *counter,
 924                                 (size_t)sourceSize, CFDataGetBytePtr(sourceMessage),
 925                                 encryptedDataPointer);
 926  
 927      if (sendHashes) {
 928          uint8_t *senderHashPtr = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, kSecDHKHashSize);
 929          
 930          memcpy(senderHashPtr, SecFDHKGetHash(session->_myKey), kSecDHKHashSize);
 931          
 932          uint8_t *receiverHashPtr = CFDataIncreaseLengthAndGetMutableBytes(destinationMessage, kSecDHKHashSize);
 933          
 934          memcpy(receiverHashPtr, SecPDHKGetHash(theirKey), kSecDHKHashSize);
 935      }
 936      
 937      
 938      CFIndex macedContentsSize = CFDataGetLength(destinationMessage) - start;
 939      CFIndex macSize = CCSHA1_OUTPUT_SIZE;
 940      uint8_t mac[macSize];
 941      cchmac(ccsha1_di(),
 942             kOTRMessageMacKeyBytes, macKey,
 943             macedContentsSize, CFDataGetBytePtr(destinationMessage) + start,
 944             mac);
 945  
 946      CFDataAppendBytes(destinationMessage, mac, kCompactMessageMACSize);
 947  
 948      return errSecSuccess;
 949  }
 950  
 951  OSStatus SecOTRSSignAndProtectMessage(SecOTRSessionRef session,
 952                                        CFDataRef sourceMessage,
 953                                        CFMutableDataRef protectedMessage)
 954  {
 955      __block OSStatus result = errSecParam;
 956  
 957      require(session, abort);
 958      require(sourceMessage, abort);
 959      require(protectedMessage, abort);
 960      
 961      if(session->_state != kDone){
 962          secdebug("OTR", "Cannot sign and protect messages, we are not done negotiating sesion[%p]", session);
 963          require_quiet( session->_state == kDone, abort);
 964      }
 965      
 966      dispatch_sync(session->_queue, ^{
 967          if (session->_myKey == NULL ||
 968              session->_theirKey == NULL) {
 969              return;
 970          }
 971          
 972          uint8_t *messageKey;
 973          uint8_t *macKey;
 974          uint64_t *counter;
 975          uint32_t theirKeyID = session->_theirKeyID;
 976          
 977          SecOTRPublicDHKeyRef theirKeyToUse = session->_theirKey;
 978          
 979          SecOTRSRollIfTime(session);
 980          
 981          if(session->_stallingTheirRoll && session->_theirPreviousKey){
 982              theirKeyToUse = session->_theirPreviousKey;
 983              theirKeyID = session->_theirKeyID - 1;
 984          }
 985          
 986          SecOTRSFindKeysForMessage(session, session->_myKey, theirKeyToUse,
 987                                    true,
 988                                    &messageKey, &macKey, &counter);
 989          // The || !protectedMessage below is only here to shut the static analyzer up, the require(protectedMessage, abort) outside the block already ensures this new term is never true.
 990          CFMutableDataRef destinationMessage = session->_textOutput || !protectedMessage ? CFDataCreateMutable(kCFAllocatorDefault, 0) : CFRetainSafe(protectedMessage);
 991          
 992          result = session->_compactAppleMessages ? SecOTRSSignAndProtectCompact_locked(session, sourceMessage, destinationMessage, messageKey, macKey, counter, theirKeyID, theirKeyToUse)
 993          : SecOTRSSignAndProtectRaw_locked(session, sourceMessage, destinationMessage, messageKey, macKey, counter, theirKeyID, theirKeyToUse);
 994          
 995          if (result == errSecSuccess) {
 996              if (session->_textOutput) {
 997                  SecOTRPrepareOutgoingBytes(destinationMessage, protectedMessage);
 998              }
 999  
1000              CFDataSetLength(session->_macKeysToExpose, 0);
1001          }
1002  
1003          CFReleaseSafe(destinationMessage);
1004  
1005          result = errSecSuccess;
1006      });
1007  
1008  abort:
1009      return result;
1010  }
1011  
1012  void SecOTRSKickTimeToRoll(SecOTRSessionRef session){
1013  	session->_timeToRoll = CFAbsoluteTimeGetCurrent();
1014  }
1015  
1016  static void SecOTRAcceptNewRemoteKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef newKey)
1017  {
1018      if (session->_theirPreviousKey) {
1019          SecOTRSExpireCachedKeysForPublicKey(session, session->_theirPreviousKey);
1020      }
1021  
1022      CFReleaseNull(session->_theirPreviousKey);
1023      session->_theirPreviousKey = session->_theirKey;
1024      session->_theirKey = CFRetainSafe(newKey);
1025      session->_stallingTheirRoll = true;
1026  
1027      session->_theirKeyID += 1;
1028  
1029      SecOTRSEnableTimeToRoll(session);
1030  }
1031  
1032  OSStatus SecOTRSetupInitialRemoteKey(SecOTRSessionRef session, SecOTRPublicDHKeyRef CF_CONSUMED initialKey) {
1033     
1034      bzero(session->_keyCache, sizeof(session->_keyCache));
1035      
1036      CFReleaseNull(session->_theirPreviousKey);
1037      CFAssignRetained(session->_theirKey, initialKey);
1038      session->_theirKeyID = 1;
1039      
1040      return errSecSuccess;
1041  }
1042  
1043  ///
1044  /// MARK: SLOW ROLLING
1045  ///
1046  
1047  void SOSOTRSRoll(SecOTRSessionRef session){
1048      
1049      session->_stallingTheirRoll = false;
1050      
1051      //receiving side roll
1052      if(session->_receivedAck){
1053          SecOTRGenerateNewProposedKey(session);
1054          session->_missedAck = false;
1055          session->_receivedAck = false;
1056      }
1057      else{
1058          session->_missedAck = true;
1059      }
1060  }
1061  
1062  static OSStatus SecOTRVerifyAndExposeRaw_locked(SecOTRSessionRef session,
1063                                                  CFDataRef decodedBytes,
1064                                                  CFMutableDataRef exposedMessageContents)
1065  {
1066      OSStatus result = errSecDecode;
1067      
1068      SecOTRPublicDHKeyRef newKey = NULL;
1069      const uint8_t* bytes;
1070      size_t  size;
1071      SecOTRFullDHKeyRef myKeyForMessage = NULL;
1072      SecOTRPublicDHKeyRef theirKeyForMessage = NULL;
1073      bytes = CFDataGetBytePtr(decodedBytes);
1074      size = CFDataGetLength(decodedBytes);
1075  
1076      const uint8_t* macDataStart = bytes;
1077  
1078      uint32_t theirID;
1079      uint32_t myID;
1080  
1081      require_noerr_quiet(result = ReadAndVerifyHeader(&bytes, &size, kDataMessage), fail);
1082      require_action_quiet(size > 0, fail, result = errSecDecode);
1083  
1084      require_noerr_quiet(result = ReadAndVerifyByte(&bytes, &size, 0), fail); // Flags, always zero
1085  
1086      require_noerr_quiet(result = ReadLong(&bytes, &size, &theirID), fail);
1087  
1088      require_action_quiet(theirID == session->_theirKeyID || (theirID == (session->_theirKeyID - 1) && session->_theirPreviousKey != NULL),
1089                           fail,
1090                           result = ((theirID + 1) < session->_theirKeyID) ? errSecOTRTooOld : errSecOTRIDTooNew);
1091  
1092      require_noerr_quiet(result = ReadLong(&bytes, &size, &myID), fail);
1093  
1094      require_action_quiet(myID == session->_keyID || (myID == session->_keyID + 1 && session->_myNextKey != NULL),
1095                           fail,
1096                           result = (myID < session->_keyID) ? errSecOTRTooOld : errSecOTRIDTooNew);
1097  
1098  
1099      // Choose appripriate keys for message:
1100      {
1101          uint8_t *messageKey;
1102          uint8_t *macKey;
1103          uint64_t *theirCounter;
1104  
1105          myKeyForMessage = (myID == session->_keyID) ? session->_myKey : session->_myNextKey;
1106          theirKeyForMessage = (theirID == session->_theirKeyID) ? session->_theirKey : session->_theirPreviousKey;
1107  
1108          SecOTRSFindKeysForMessage(session, myKeyForMessage, theirKeyForMessage, false,
1109                                    &messageKey, &macKey, &theirCounter);
1110  
1111          size_t nextKeyMPISize;
1112          const uint8_t* nextKeyMPIBytes;
1113          require_noerr_quiet(result = SizeAndSkipMPI(&bytes, &size, &nextKeyMPIBytes, &nextKeyMPISize), fail);
1114  
1115          uint64_t counter;
1116          require_noerr_quiet(result = ReadLongLong(&bytes, &size, &counter), fail);
1117          require_action_quiet(counter > *theirCounter, fail, result = errSecOTRTooOld);
1118  
1119          size_t messageSize;
1120          const uint8_t* messageStart;
1121          require_noerr_quiet(result = SizeAndSkipDATA(&bytes, &size, &messageStart, &messageSize), fail);
1122  
1123          size_t macDataSize = (bytes - macDataStart) ? (size_t)(bytes - macDataStart) : 0;
1124          uint8_t mac[CCSHA1_OUTPUT_SIZE];
1125          require_action_quiet(sizeof(mac) <= size, fail, result = errSecDecode);
1126  
1127          cchmac(ccsha1_di(),
1128                 kOTRMessageMacKeyBytes, macKey,
1129                 macDataSize, macDataStart,
1130                 mac);
1131  
1132          require_noerr_action_quiet(timingsafe_bcmp(mac, bytes, sizeof(mac)), fail, result = errSecAuthFailed);
1133  
1134          uint8_t* dataSpace = CFDataIncreaseLengthAndGetMutableBytes(exposedMessageContents, (CFIndex)messageSize);
1135  
1136          AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey,
1137                                     counter,
1138                                     messageSize, messageStart,
1139                                     dataSpace);
1140  
1141          // Everything is good, accept the meta data.
1142          *theirCounter = counter;
1143  
1144          newKey = SecOTRPublicDHKCreateFromBytes(kCFAllocatorDefault, &nextKeyMPIBytes, &nextKeyMPISize);
1145      }
1146  
1147      bool acceptTheirNewKey = newKey != NULL && theirID == session->_theirKeyID;
1148  
1149      if (acceptTheirNewKey) {
1150          SecOTRAcceptNewRemoteKey(session, newKey);
1151      }
1152  
1153      if (myID == (session->_keyID + 1)) {
1154          SecOTRSHandleProposalAcknowledge(session);
1155      }
1156  
1157      SecOTRSRollIfTime(session);
1158      
1159      SecOTRSPrecalculateNextKeysInternal(session);
1160  
1161  fail:
1162      if(result != errSecSuccess){
1163          CFDataPerformWithHexString(decodedBytes, ^(CFStringRef decodedBytesString) {
1164              SecOTRPublicIdentityRef myPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, session->_me, NULL);
1165              SecOTRPIPerformWithSerializationString(myPublicID, ^(CFStringRef myIDString) {
1166                  SecOTRPIPerformWithSerializationString(session->_them, ^(CFStringRef theirIDString) {
1167              secnotice("OTR","session[%p] failed to decrypt, session: %@, mk: %@, mpk: %@, tpk: %@, tk: %@, chose tktu: %@", session, session,
1168                       session->_myKey, session->_myNextKey, session->_theirPreviousKey, session->_theirKey, theirKeyForMessage);
1169              secnotice("OTR","session[%p] failed to decrypt, mktu: %@, mpi: %@, tpi: %@, m: %@", session, myKeyForMessage, myIDString, theirIDString, decodedBytesString);
1170                  });
1171              });
1172              CFReleaseNull(myPublicID);
1173          });
1174      }
1175      CFReleaseNull(newKey);
1176      return result;
1177  }
1178  
1179  static OSStatus SecOTRVerifyAndExposeRawCompact_locked(SecOTRSessionRef session,
1180                                                  CFDataRef decodedBytes,
1181                                                  CFMutableDataRef exposedMessageContents)
1182  {
1183      SecOTRPublicDHKeyRef theirProposal = NULL;
1184      OSStatus result = errSecDecode;
1185      const uint8_t* bytes;
1186      size_t  size;
1187      SecOTRPublicDHKeyRef theirKeyForMessage = NULL;
1188      bytes = CFDataGetBytePtr(decodedBytes);
1189      size = CFDataGetLength(decodedBytes);
1190      SecOTRFullDHKeyRef myKeyForMessage = NULL;
1191      const uint8_t* macDataStart = bytes;
1192      bool useEvenKey = false;
1193      bool useCurrentKey = false;
1194      bool sentHashes = false;
1195      uint64_t counter = 0;
1196  
1197      uint8_t type_byte = 0;
1198      require_noerr_quiet(result = ReadByte(&bytes, &size, &type_byte), fail);
1199      require_action_quiet(type_byte == kOddCompactDataMessage || type_byte == kEvenCompactDataMessage
1200                           || type_byte == kOddCompactDataMessageWithHashes || type_byte == kEvenCompactDataMessageWithHashes, fail, result = errSecDecode);
1201  
1202      useEvenKey = (type_byte == kEvenCompactDataMessage || type_byte == kEvenCompactDataMessageWithHashes);
1203      sentHashes = (type_byte == kOddCompactDataMessageWithHashes || type_byte == kEvenCompactDataMessageWithHashes);
1204  
1205      useCurrentKey = useEvenKey ^ (session->_keyID & 1);
1206      myKeyForMessage = useCurrentKey ? session->_myKey : session->_myNextKey;
1207      
1208      require_action_quiet(myKeyForMessage, fail, result = errSecDecode);
1209  
1210      theirProposal = SecOTRPublicDHKCreateFromCompactSerialization(kCFAllocatorDefault, &bytes, &size);
1211      
1212      require_action_quiet(theirProposal, fail, result = errSecDecode);
1213      
1214      bool proposalIsNew = !CFEqualSafe(theirProposal, session->_theirKey);
1215      theirKeyForMessage = proposalIsNew ? session->_theirKey : session->_theirPreviousKey;
1216      
1217      require_action_quiet(theirKeyForMessage, fail, result = errSecDecode);
1218      
1219      uint8_t *messageKey;
1220      uint8_t *macKey;
1221      uint64_t *theirCounter;
1222  
1223  
1224      SecOTRSFindKeysForMessage(session, myKeyForMessage, theirKeyForMessage, false, &messageKey, &macKey, &theirCounter);
1225  
1226      require_noerr_quiet(result = ReadLongLongCompact(&bytes, &size, &counter), fail);
1227      require_action_quiet(counter > *theirCounter, fail, result = errSecOTRTooOld);
1228  
1229      size_t messageSize = size - kCompactMessageMACSize - (sentHashes ? 2 * kSecDHKHashSize : 0); // It's all message except for the MAC and maybe hashes
1230      const uint8_t* messageStart = bytes;
1231  
1232      bytes += messageSize;
1233      size -= messageSize;
1234      
1235      if (sentHashes) {
1236          // Sender then receiver keys
1237  
1238          if (memcmp(SecPDHKGetHash(theirKeyForMessage), bytes, kSecDHKHashSize) != 0) {
1239              // Wrong sender key WTF.
1240  #if DEBUG
1241              BufferPerformWithHexString(bytes, kSecDHKHashSize, ^(CFStringRef dataString) {
1242                  secdebug("OTR","session[%p] Sender key hash doesn't match: %@ != %@", session, theirKeyForMessage, dataString);
1243              });
1244  #endif
1245          }
1246          
1247          bytes += kSecDHKHashSize;
1248          size -= kSecDHKHashSize;
1249          
1250          if (memcmp(SecFDHKGetHash(myKeyForMessage), bytes, kSecDHKHashSize) != 0) {
1251              // Wrong sender key WTF.
1252  #if DEBUG
1253              BufferPerformWithHexString(bytes, kSecDHKHashSize, ^(CFStringRef dataString) {
1254                  secdebug("OTR","session[%p] Receiver key hash doesn't match: %@ != %@", session, myKeyForMessage, dataString);
1255              });
1256  #endif
1257          }
1258          
1259          bytes += kSecDHKHashSize;
1260          size -= kSecDHKHashSize;
1261          
1262      }
1263      
1264      uint8_t mac[CCSHA1_OUTPUT_SIZE];
1265      require_action_quiet(kCompactMessageMACSize == size, fail, result = errSecDecode); // require space for the mac and some bytes
1266  
1267      size_t macDataSize = (size_t)(bytes - macDataStart);
1268  
1269      cchmac(ccsha1_di(),
1270             kOTRMessageMacKeyBytes, macKey,
1271             macDataSize, macDataStart,
1272             mac);
1273  
1274      require_noerr_action_quiet(timingsafe_bcmp(mac, bytes, kCompactMessageMACSize), fail, result = errSecAuthFailed);
1275  
1276      uint8_t* dataSpace = CFDataIncreaseLengthAndGetMutableBytes(exposedMessageContents, (CFIndex)messageSize);
1277  
1278      AES_CTR_HighHalf_Transform(kOTRMessageKeyBytes, messageKey,
1279                                 counter,
1280                                 messageSize, messageStart,
1281                                 dataSpace);
1282  
1283      // Everything is good, accept the meta data.
1284      *theirCounter = counter;
1285  
1286      if (proposalIsNew) {
1287          SecOTRAcceptNewRemoteKey(session, theirProposal);
1288      }
1289      
1290      if (!useCurrentKey) {
1291          SecOTRSHandleProposalAcknowledge(session);
1292      }
1293      SecOTRSRollIfTime(session);
1294      
1295      SecOTRSPrecalculateNextKeysInternal(session);
1296  
1297  fail:
1298      if(result != errSecSuccess){
1299          CFDataPerformWithHexString(decodedBytes, ^(CFStringRef decodedBytesString) {
1300              SecOTRPublicIdentityRef myPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, session->_me, NULL);
1301              SecOTRPIPerformWithSerializationString(myPublicID, ^(CFStringRef myIDString) {
1302                  SecOTRPIPerformWithSerializationString(session->_them, ^(CFStringRef theirIDString) {
1303              secnotice("OTR","session[%p] failed to decrypt, session: %@, mk: %@, mpk: %@, tpk: %@, tk: %@, chose tktu: %@", session, session,
1304                       session->_myKey, session->_myNextKey, session->_theirPreviousKey, session->_theirKey, theirKeyForMessage);
1305              secnotice("OTR","session[%p] failed to decrypt, mktu: %@, mpi: %@, tpi: %@, m: %@, tP: %@, tb: %hhx", session, myKeyForMessage, myIDString, theirIDString, decodedBytesString, theirProposal, type_byte);
1306                  });
1307              });
1308              CFReleaseNull(myPublicID);
1309          });
1310      }
1311      CFReleaseNull(theirProposal);
1312      return result;
1313  }
1314  
1315  
1316  OSStatus SecOTRSVerifyAndExposeMessage(SecOTRSessionRef session,
1317                                         CFDataRef incomingMessage,
1318                                         CFMutableDataRef exposedMessageContents)
1319  {
1320      __block OSStatus result = errSecParam;
1321  
1322      
1323      require(session, abort);
1324      require(incomingMessage, abort);
1325      require(exposedMessageContents, abort);
1326      
1327      if(session->_state == kDone){
1328          dispatch_sync(session->_queue, ^{
1329              CFDataRef decodedBytes = SecOTRCopyIncomingBytes(incomingMessage);
1330              
1331              OTRMessageType messageType = SecOTRSGetMessageType(decodedBytes);
1332              
1333              switch (messageType) {
1334                  case kDataMessage:
1335                      result = SecOTRVerifyAndExposeRaw_locked(session, decodedBytes, exposedMessageContents);
1336                      break;
1337                      
1338                  case kOddCompactDataMessage:
1339                  case kEvenCompactDataMessage:
1340                  case kOddCompactDataMessageWithHashes:
1341                  case kEvenCompactDataMessageWithHashes:
1342                      result = SecOTRVerifyAndExposeRawCompact_locked(session, decodedBytes, exposedMessageContents);
1343                      break;
1344                      
1345                  default:
1346                      result = errSecUnsupportedFormat;
1347                      break;
1348              }
1349              
1350              CFReleaseSafe(decodedBytes);
1351          });
1352      }
1353      else{
1354          secnotice("OTR", "session[%p]Cannot process message:%@, session is not done negotiating, session state: %@", session, incomingMessage, session);
1355          result = errSecOTRNotReady;
1356      }
1357  abort:
1358      return result;
1359  }
1360  
1361  
1362  static CFDataRef data_to_data_error_request(enum SecXPCOperation op, CFDataRef publicPeerId, CFErrorRef *error) {
1363      __block CFDataRef result = NULL;
1364      securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1365          return SecXPCDictionarySetDataOptional(message, kSecXPCPublicPeerId, publicPeerId, error);
1366      }, ^bool(xpc_object_t response, CFErrorRef *error) {
1367          return (result = SecXPCDictionaryCopyData(response, kSecXPCKeyResult, error));
1368      });
1369      return result;
1370  }
1371  
1372  static bool data_data_to_data_data_bool_error_request(enum SecXPCOperation op, CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) {
1373      __block CFDataRef tempOutputSessionData = NULL;
1374      __block CFDataRef tempOutputPacket = NULL;
1375      __block bool tempReadyForMessages = false;
1376      
1377      bool result = securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) {
1378          return SecXPCDictionarySetDataOptional(message, kSecXPCOTRSession, sessionData, error)
1379          && SecXPCDictionarySetDataOptional(message, kSecXPCData, inputPacket, error);
1380      }, ^bool(xpc_object_t response, CFErrorRef *error) {
1381          if (xpc_dictionary_get_bool(response, kSecXPCKeyResult)) {
1382              tempOutputSessionData = SecXPCDictionaryCopyData(response, kSecXPCOTRSession, error);
1383              tempOutputPacket = SecXPCDictionaryCopyData(response, kSecXPCData, error);
1384              tempReadyForMessages = xpc_dictionary_get_bool(response, kSecXPCOTRReady);
1385              return true;
1386          } else {
1387              return false;
1388          }
1389          
1390      });
1391      
1392      *outputSessionData = tempOutputSessionData;
1393      *outputPacket = tempOutputPacket;
1394      *readyForMessages = tempReadyForMessages;
1395      
1396      return result;
1397  }
1398  
1399  
1400  CFDataRef SecOTRSessionCreateRemote(CFDataRef publicPeerId, CFErrorRef *error) {
1401      __block CFDataRef result;
1402      os_activity_initiate("SecOTRSessionCreateRemote", OS_ACTIVITY_FLAG_DEFAULT, ^{
1403          (void)SecOTRGetDefaultsWriteSeconds();
1404          result = SECURITYD_XPC(sec_otr_session_create_remote, data_to_data_error_request, publicPeerId, error);
1405      });
1406      return result;
1407  }
1408  
1409  bool SecOTRSessionProcessPacketRemote(CFDataRef sessionData, CFDataRef inputPacket, CFDataRef* outputSessionData, CFDataRef* outputPacket, bool *readyForMessages, CFErrorRef *error) {
1410      __block bool result;
1411      os_activity_initiate("SecOTRSessionProcessPacketRemote", OS_ACTIVITY_FLAG_DEFAULT, ^{
1412          result = SECURITYD_XPC(sec_otr_session_process_packet_remote, data_data_to_data_data_bool_error_request, sessionData, inputPacket, outputSessionData, outputPacket, readyForMessages, error);
1413      });
1414      return result;
1415  }
1416