2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "SecOTRSession.h"
27 #include "SecOTRMath.h"
28 #include "SecOTRIdentityPriv.h"
29 #include "SecOTRSessionPriv.h"
30 #include "SecOTRPackets.h"
31 #include "SecOTRPacketData.h"
32 #include "SecOTRDHKey.h"
34 #include <utilities/SecCFWrappers.h>
35 #include <utilities/SecBuffer.h>
37 #include <CoreFoundation/CFRuntime.h>
38 #include <CoreFoundation/CFString.h>
40 #include <Security/SecBase.h>
41 #include <Security/SecRandom.h>
43 #include <AssertMacros.h>
45 #include <corecrypto/cchmac.h>
46 #include <corecrypto/ccsha2.h>
48 #include <os/activity.h>
52 static void SecOTRInitMyDHKeys(SecOTRSessionRef session
)
55 CFReleaseNull(session
->_myKey
);
56 session
->_myKey
= SecOTRFullDHKCreate(kCFAllocatorDefault
);
57 CFReleaseNull(session
->_myNextKey
);
58 session
->_myNextKey
= SecOTRFullDHKCreate(kCFAllocatorDefault
);
60 session
->_missedAck
= true;
61 session
->_receivedAck
= false;
62 bzero(session
->_keyCache
, sizeof(session
->_keyCache
));
64 secnotice("otr", "%@ Reinitializing DH Keys, first: %@", session
, session
->_myKey
);
67 bool SecOTRSessionIsSessionInAwaitingState(SecOTRSessionRef session
)
69 bool isInAwaitingState
= false;
70 SecOTRAuthState currentCoderState
= session
->_state
;
71 switch (currentCoderState
){
74 case kAwaitingSignature
:
75 case kAwaitingRevealSignature
:
76 isInAwaitingState
= true;
81 secnotice("otrtimer", "unknown otr auth state");
83 return isInAwaitingState
;
86 OSStatus
SecOTRSAppendStartPacket(SecOTRSessionRef session
, CFMutableDataRef appendPacket
)
88 __block OSStatus result
= errSecSuccess
;
90 dispatch_sync(session
->_queue
, ^{
91 session
->_state
= kAwaitingDHKey
;
93 // Generate r and x and calculate gx:
94 SecOTRInitMyDHKeys(session
);
96 CFMutableDataRef dhMessage
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
98 result
= SecRandomCopyBytes(kSecRandomDefault
, sizeof(session
->_r
), session
->_r
);
99 if (result
== errSecSuccess
) {
100 SecOTRAppendDHMessage(session
, dhMessage
);
103 CFDataPerformWithHexString(dhMessage
, ^(CFStringRef messageString
) {
104 secnotice("otr", "%@ Start packet: %@", session
, messageString
);
107 if (session
->_textOutput
) {
108 SecOTRPrepareOutgoingBytes(dhMessage
, appendPacket
);
110 CFDataAppend(appendPacket
, dhMessage
);
113 CFReleaseSafe(dhMessage
);
120 OSStatus
SecOTRSAppendRestartPacket(SecOTRSessionRef session
, CFMutableDataRef appendPacket
)
122 __block OSStatus result
= errSecSuccess
;
124 dispatch_sync(session
->_queue
, ^{
125 if (!session
->_myKey
) {
126 secerror("_myKey is NULL, avoiding crash");
127 result
= errSecDecode
;
130 CFMutableDataRef dhMessage
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
132 session
->_state
= kAwaitingDHKey
;
133 CFReleaseNull(session
->_receivedDHMessage
);
134 CFReleaseNull(session
->_receivedDHKeyMessage
);
136 SecOTRAppendDHMessage(session
, dhMessage
);
138 CFDataPerformWithHexString(dhMessage
, ^(CFStringRef messageString
) {
139 secnotice("otr", "%@ Restart packet: %@", session
, messageString
);
142 if (session
->_textOutput
) {
143 SecOTRPrepareOutgoingBytes(dhMessage
, appendPacket
);
145 CFDataAppend(appendPacket
, dhMessage
);
147 CFReleaseSafe(dhMessage
);
153 static const uint8_t* FindGXHash(CFDataRef dhPacket
)
155 const uint8_t* messageBytes
= CFDataGetBytePtr(dhPacket
);
156 size_t remainingBytes
= (size_t)CFDataGetLength(dhPacket
);
158 OTRMessageType messageType
;
160 require_noerr(ReadHeader(&messageBytes
, &remainingBytes
, &messageType
), fail
);
161 require(messageType
== kDHMessage
, fail
);
163 uint32_t egxiLength
= 0;
164 require_noerr(ReadLong(&messageBytes
, &remainingBytes
, & egxiLength
), fail
);
165 require(egxiLength
<= remainingBytes
, fail
);
166 messageBytes
+= egxiLength
;
167 remainingBytes
-= egxiLength
;
169 uint32_t dataLength
= 0;
170 require_noerr(ReadLong(&messageBytes
, &remainingBytes
, &dataLength
), fail
);
171 require(dataLength
<= remainingBytes
, fail
);
172 require(dataLength
== CCSHA256_OUTPUT_SIZE
, fail
);
180 static bool SecOTRMyGXHashIsBigger(SecOTRSessionRef session
, CFDataRef dhCommitMessage
)
182 bool mineIsBigger
= false;
184 CFMutableDataRef myDHCommitMessage
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
186 SecOTRAppendDHMessage(session
, myDHCommitMessage
);
188 const uint8_t* myHash
= FindGXHash(myDHCommitMessage
);
189 const uint8_t* theirHash
= FindGXHash(dhCommitMessage
);
191 require(myHash
, fail
);
192 require(theirHash
, fail
);
194 mineIsBigger
= 0 < memcmp(myHash
, theirHash
, CCSHA256_OUTPUT_SIZE
);
196 BufferPerformWithHexString(myHash
, CCSHA256_OUTPUT_SIZE
, ^(CFStringRef myHashString
) {
197 BufferPerformWithHexString(theirHash
, CCSHA256_OUTPUT_SIZE
, ^(CFStringRef theirHashString
) {
198 secdebug("otr", "%@ %s gx is bigger, M:%@ T:%@", session
, mineIsBigger
? "mine" : "their", myHashString
, theirHashString
);
203 CFReleaseNull(myDHCommitMessage
);
207 static OSStatus
SecOTRSProcessDHMessage(SecOTRSessionRef session
,
208 CFDataRef incomingPacket
,
209 CFMutableDataRef negotiationResponse
)
211 OSStatus result
= errSecParam
;
213 CFStringRef messageMessage
= CFSTR("");
215 switch (session
->_state
) {
217 // Compare hash values.
218 if (SecOTRMyGXHashIsBigger(session
, incomingPacket
)) {
219 // If we're bigger we resend to force them to deal.
220 messageMessage
= CFSTR("Our GX is bigger, resending DH");
221 CFReleaseNull(session
->_receivedDHMessage
);
222 SecOTRAppendDHMessage(session
, negotiationResponse
);
223 result
= errSecSuccess
;
225 } // Else intentionally fall through to idle
226 messageMessage
= CFSTR("Our GX is smaller, sending DHKey");
227 case kAwaitingSignature
:
230 // Generate a new X and GX..
231 SecOTRInitMyDHKeys(session
);
232 // If we were already waiting on reveal, then just send the packet again
233 case kAwaitingRevealSignature
:
234 SecOTRAppendDHKeyMessage(session
, negotiationResponse
);
236 if (messageMessage
== 0)
237 messageMessage
= CFSTR("Sending DHKey");
238 // Keep the packet for use later.
239 CFReleaseNull(session
->_receivedDHMessage
);
240 session
->_receivedDHMessage
= CFDataCreateCopy(kCFAllocatorDefault
, incomingPacket
);
242 session
->_state
= kAwaitingRevealSignature
;
243 result
= errSecSuccess
;
246 result
= errSecInteractionNotAllowed
;
250 if (result
== errSecSuccess
) {
251 CFDataPerformWithHexString(negotiationResponse
, ^(CFStringRef responseString
) {
252 secnotice("otr", "%@ %@: %@", session
, messageMessage
, responseString
);
255 secnotice("otr", "%@ Process DH failed %d", session
, (int)result
);
260 static OSStatus
SecOTRSetupTheirKeyFrom(SecOTRSessionRef session
, const uint8_t**data
, size_t*size
)
262 SecOTRPublicDHKeyRef tempKey
= SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault
, data
, size
);
263 require(tempKey
!= NULL
, fail
);
265 return SecOTRSetupInitialRemoteKey(session
, tempKey
);
271 static OSStatus
SecOTRSExtractTheirPublicDHKey(SecOTRSessionRef session
, CFDataRef dhPacket
)
273 OSStatus result
= errSecParam
;
275 const uint8_t *messageBytes
= CFDataGetBytePtr(dhPacket
);
276 size_t messageSize
= (size_t)CFDataGetLength(dhPacket
);
277 OTRMessageType messageType
= kDHMessage
; // Suppress warning.
279 ReadHeader(&messageBytes
, &messageSize
, &messageType
);
280 require(messageType
== kDHKeyMessage
, exit
);
282 result
= SecOTRSetupTheirKeyFrom(session
, &messageBytes
, &messageSize
);
289 static OSStatus
SecOTRSProcessDHKeyMessage(SecOTRSessionRef session
,
290 CFDataRef incomingPacket
,
291 CFMutableDataRef negotiationResponse
)
293 OSStatus result
= errSecUnimplemented
;
294 CFStringRef messageMessage
= CFSTR("");
296 result
= SecOTRSExtractTheirPublicDHKey(session
, incomingPacket
);
297 require_noerr(result
, exit
);
299 switch (session
->_state
) {
301 CFReleaseNull(session
->_receivedDHKeyMessage
);
302 SecOTRAppendRevealSignatureMessage(session
, negotiationResponse
);
303 session
->_state
= kAwaitingSignature
;
304 session
->_receivedDHKeyMessage
= CFDataCreateCopy(kCFAllocatorDefault
, incomingPacket
);
305 result
= errSecSuccess
;
306 messageMessage
= CFSTR("Sending reveal signature");
308 case kAwaitingSignature
:
309 if (CFEqualSafe(incomingPacket
, session
->_receivedDHKeyMessage
)) {
310 SecOTRAppendRevealSignatureMessage(session
, negotiationResponse
);
311 messageMessage
= CFSTR("Resending reveal signature");
313 messageMessage
= CFSTR("Ignoring new DHKey message");
315 result
= errSecSuccess
;
319 case kAwaitingRevealSignature
:
320 result
= errSecSuccess
;
321 messageMessage
= CFSTR("Ignoring DHKey message");
324 result
= errSecInteractionNotAllowed
;
329 if (result
== errSecSuccess
) {
330 CFDataPerformWithHexString(negotiationResponse
, ^(CFStringRef responseString
) {
331 secnotice("otr", "%@ %@: %@", session
, messageMessage
, responseString
);
334 secnotice("otr", "%@ Process DH failed %d", session
, (int)result
);
341 static OSStatus
SecOTRSExtractR(SecOTRSessionRef session
,
342 const uint8_t **messageBytes
,
345 OSStatus result
= errSecDecode
;
347 OTRMessageType messageType
= kDHMessage
; // Suppress warning
349 ReadHeader(messageBytes
, messageSize
, &messageType
);
350 require(messageType
== kRevealSignatureMessage
, exit
);
354 ReadLong(messageBytes
, messageSize
, &rSize
);
355 require(rSize
== kOTRAuthKeyBytes
, exit
);
358 memcpy(session
->_r
, *messageBytes
, kOTRAuthKeyBytes
);
360 *messageBytes
+= kOTRAuthKeyBytes
;
361 *messageSize
-= kOTRAuthKeyBytes
;
363 result
= errSecSuccess
;
368 static OSStatus
FindEncGYInDHPacket(SecOTRSessionRef session
,
369 const uint8_t **dhMessageBytesPtr
,
370 size_t *messageSizePtr
,
371 size_t* encGYBufferSize
)
373 OSStatus result
= errSecParam
;
374 require_action(*encGYBufferSize
>= kExponentiationBytes
+ 4, exit
, result
= errSecParam
);
376 OTRMessageType messageType
;
377 result
= ReadHeader(dhMessageBytesPtr
, messageSizePtr
, &messageType
);
378 require_noerr(result
, exit
);
379 require_action(messageType
== kDHMessage
, exit
, result
= errSecDecode
);
381 uint32_t readEncSize
;
382 result
= ReadLong(dhMessageBytesPtr
, messageSizePtr
, &readEncSize
);
383 require_noerr(result
, exit
);
385 *encGYBufferSize
= readEncSize
;
387 // Don't bother erasing the public gy decrypted, it's public after all.
392 static OSStatus
SecOTRSExtractRAndTheirDHKey(SecOTRSessionRef session
,
393 const uint8_t **messageBytes
,
396 OSStatus result
= errSecDecode
;
398 require(session
->_receivedDHMessage
!= NULL
, exit
);
399 result
= SecOTRSExtractR(session
, messageBytes
, messageSize
);
400 require_noerr(result
, exit
);
402 uint8_t gxiDecrypted
[kExponentiationBytes
+ 4];
403 const uint8_t *gxiDecryptedBuffer
= gxiDecrypted
;
405 const uint8_t* dhMessageBytes
= CFDataGetBytePtr(session
->_receivedDHMessage
);
406 size_t dhMessageSize
= (size_t)CFDataGetLength(session
->_receivedDHMessage
);
408 size_t encGYSize
= sizeof(gxiDecrypted
);
409 result
= FindEncGYInDHPacket(session
, &dhMessageBytes
, &dhMessageSize
, &encGYSize
);
410 require_noerr(result
, exit
);
411 require_action(encGYSize
<= kExponentiationBytes
+ 4, exit
, result
= errSecDecode
);
413 AES_CTR_IV0_Transform(sizeof(session
->_r
), session
->_r
, encGYSize
, dhMessageBytes
, gxiDecrypted
);
415 result
= SecOTRSetupTheirKeyFrom(session
, &gxiDecryptedBuffer
, &encGYSize
);
418 // Don't bother erasing the public gy decrypted, it's public after all.
422 static OSStatus
SecVerifySignatureAndMac(SecOTRSessionRef session
,
424 const uint8_t **signatureAndMacBytes
,
425 size_t *signatureAndMacSize
)
427 __block OSStatus result
= errSecDecode
;
429 PerformWithBufferAndClear(kOTRAuthMACKeyBytes
, ^(size_t m1_size
, uint8_t *m1
) {
430 PerformWithBufferAndClear(kOTRAuthMACKeyBytes
, ^(size_t m2_size
, uint8_t *m2
) {
431 PerformWithBufferAndClear(kOTRAuthKeyBytes
, ^(size_t c_size
, uint8_t *c
) {
433 cc_unit s
[kExponentiationUnits
];
435 SecPDHKeyGenerateS(session
->_myKey
, session
->_theirKey
, s
);
436 // Derive M1, M2 and C, either prime or normal versions.
437 DeriveOTR256BitsFromS(usePrimes
? kM1Prime
: kM1
,
438 kExponentiationUnits
, s
, m1_size
, m1
);
439 DeriveOTR256BitsFromS(usePrimes
? kM2Prime
: kM2
,
440 kExponentiationUnits
, s
, m2_size
, m2
);
441 DeriveOTR128BitPairFromS(kCs
,
442 kExponentiationUnits
, s
,
443 c_size
,usePrimes
? NULL
: c
,
444 c_size
, usePrimes
? c
: NULL
);
448 const uint8_t* encSigDataBlobStart
= *signatureAndMacBytes
;
451 result
= ReadLong(signatureAndMacBytes
, signatureAndMacSize
, &xbSize
);
452 require_noerr(result
, exit
);
453 require_action(xbSize
> 4, exit
, result
= errSecDecode
);
454 require_action(xbSize
<= *signatureAndMacSize
, exit
, result
= errSecDecode
);
456 uint8_t signatureMac
[CCSHA256_OUTPUT_SIZE
];
457 cchmac(ccsha256_di(), m2_size
, m2
, xbSize
+ 4, encSigDataBlobStart
, signatureMac
);
459 require_action(xbSize
+ kSHA256HMAC160Bytes
<= *signatureAndMacSize
, exit
, result
= errSecDecode
);
460 const uint8_t *macStart
= *signatureAndMacBytes
+ xbSize
;
462 // check the outer hmac
463 require_action(0 == cc_cmp_safe(kSHA256HMAC160Bytes
, macStart
, signatureMac
), exit
, result
= errSecDecode
);
466 PerformWithBufferAndClear(xbSize
, ^(size_t size
, uint8_t *xb
) {
467 cchmac_di_decl(ccsha256_di(), mBContext
);
469 cchmac_init(ccsha256_di(), mBContext
, m1_size
, m1
);
472 CFMutableDataRef toHash
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
474 SecPDHKAppendSerialization(session
->_theirKey
, toHash
);
475 SecFDHKAppendPublicSerialization(session
->_myKey
, toHash
);
477 cchmac_update(ccsha256_di(), mBContext
, (size_t)CFDataGetLength(toHash
), CFDataGetBytePtr(toHash
));
479 CFReleaseNull(toHash
);
482 // Decrypt and copy the signature block
483 AES_CTR_IV0_Transform(c_size
, c
, xbSize
, *signatureAndMacBytes
, xb
);
485 const uint8_t* signaturePacket
= xb
;
486 size_t signaturePacketSize
= xbSize
;
489 result
= ReadShort(&signaturePacket
, &signaturePacketSize
, &pubKeyType
);
490 require_noerr(result
, exit
);
491 require_action(pubKeyType
== 0xF000, exit
, result
= errSecUnimplemented
);
494 result
= ReadLong(&signaturePacket
, &signaturePacketSize
, &pubKeySize
);
495 require_noerr(result
, exit
);
496 require_action(pubKeySize
<= signaturePacketSize
, exit
, result
= errSecDecode
);
497 require(((CFIndex
)pubKeySize
) >= 0, exit
);
499 // Add the signature and keyid to the hash.
500 // PUBKEY of our type is 2 bytes of type, 2 bytes of size and size bytes.
501 // Key ID is 4 bytes.
502 cchmac_update(ccsha256_di(), mBContext
, 2 + 4 + pubKeySize
+ 4, xb
);
504 uint8_t mb
[CCSHA256_OUTPUT_SIZE
];
505 cchmac_final(ccsha256_di(), mBContext
, mb
);
507 // Make reference to the deflated key
508 require_action(SecOTRPIEqualToBytes(session
->_them
, signaturePacket
, (CFIndex
)pubKeySize
), exit
, result
= errSecAuthFailed
);
510 signaturePacket
+= pubKeySize
;
511 signaturePacketSize
-= pubKeySize
;
513 result
= ReadLong(&signaturePacket
, &signaturePacketSize
, &session
->_theirKeyID
);
514 require_noerr(result
, exit
);
517 result
= ReadLong(&signaturePacket
, &signaturePacketSize
, &sigSize
);
518 require_noerr(result
, exit
);
519 require_action(sigSize
<= signaturePacketSize
, exit
, result
= errSecDecode
);
521 bool bresult
= SecOTRPIVerifySignature(session
->_them
, mb
, sizeof(mb
), signaturePacket
, sigSize
, NULL
);
522 result
= bresult
? errSecSuccess
: errSecDecode
;
523 require_noerr(result
, exit
);
537 static OSStatus
SecOTRSProcessRevealSignatureMessage(SecOTRSessionRef session
,
538 CFDataRef incomingPacket
,
539 CFMutableDataRef negotiationResponse
)
541 OSStatus result
= errSecParam
;
543 require_action_quiet(session
->_state
== kAwaitingRevealSignature
, exit
, result
= errSecSuccess
);
545 const uint8_t *messageBytes
= CFDataGetBytePtr(incomingPacket
);
546 size_t messageSize
= (size_t)CFDataGetLength(incomingPacket
);
548 result
= SecOTRSExtractRAndTheirDHKey(session
, &messageBytes
, &messageSize
);
549 require_noerr(result
, exit
);
551 result
= SecVerifySignatureAndMac(session
, false, &messageBytes
, &messageSize
);
552 require_noerr(result
, exit
);
554 SecOTRAppendSignatureMessage(session
, negotiationResponse
);
556 session
->_state
= kDone
;
557 result
= errSecSuccess
;
559 CFDataPerformWithHexString(negotiationResponse
, ^(CFStringRef responseString
) {
560 secnotice("otr", "%@ Sending Signature message: %@", session
, responseString
);
565 if (result
!= errSecSuccess
) {
566 CFDataPerformWithHexString(incomingPacket
, ^(CFStringRef incomingString
) {
567 secnotice("otr", "%@ Failed to process reveal sig message (%d): %@", session
, (int)result
, incomingString
);
573 static OSStatus
SecOTRSProcessSignatureMessage(SecOTRSessionRef session
,
574 CFDataRef incomingPacket
,
575 CFMutableDataRef negotiationResponse
)
577 OSStatus result
= errSecParam
;
579 require_action_quiet(session
->_state
== kAwaitingSignature
, exit
, result
= errSecSuccess
);
581 const uint8_t *messageBytes
= CFDataGetBytePtr(incomingPacket
);
582 size_t messageSize
= (size_t)CFDataGetLength(incomingPacket
);
584 OTRMessageType messageType
;
585 result
= ReadHeader(&messageBytes
, &messageSize
, &messageType
);
586 require_noerr(result
, exit
);
587 require_action(messageType
== kSignatureMessage
, exit
, result
= errSecDecode
);
589 result
= SecVerifySignatureAndMac(session
, true, &messageBytes
, &messageSize
);
590 require_noerr(result
, exit
);
592 CFReleaseNull(session
->_receivedDHKeyMessage
);
593 session
->_state
= kDone
;
595 result
= errSecSuccess
;
600 OSStatus
SecOTRSProcessPacket(SecOTRSessionRef session
,
601 CFDataRef incomingPacket
,
602 CFMutableDataRef negotiationResponse
)
604 __block OSStatus result
= errSecParam
;
606 require(CFDataGetLength(incomingPacket
) > 0, fail
);
607 dispatch_sync(session
->_queue
, ^{
608 os_activity_initiate("OTR Process Packet", OS_ACTIVITY_FLAG_DEFAULT
, ^{
609 CFDataRef decodedBytes
= SecOTRCopyIncomingBytes(incomingPacket
);
611 const uint8_t* bytes
= CFDataGetBytePtr(decodedBytes
);
612 size_t size
= CFDataGetLength(decodedBytes
);
614 OTRMessageType packetType
= kInvalidMessage
;
615 if (ReadHeader(&bytes
, &size
, &packetType
))
616 packetType
= kInvalidMessage
;
618 CFMutableDataRef destinationMessage
;
619 if (session
->_textOutput
) {
620 destinationMessage
= CFDataCreateMutable(kCFAllocatorDefault
, 0);
622 destinationMessage
= CFRetainSafe(negotiationResponse
);
625 switch (packetType
) {
627 result
= SecOTRSProcessDHMessage(session
, decodedBytes
, destinationMessage
);
630 result
= SecOTRSProcessDHKeyMessage(session
, decodedBytes
, destinationMessage
);
632 case kRevealSignatureMessage
:
633 result
= SecOTRSProcessRevealSignatureMessage(session
, decodedBytes
, destinationMessage
);
635 case kSignatureMessage
:
636 result
= SecOTRSProcessSignatureMessage(session
, decodedBytes
, destinationMessage
);
639 result
= errSecDecode
;
643 if (result
!= errSecSuccess
) {
644 CFDataPerformWithHexString(decodedBytes
, ^(CFStringRef bytesString
) {
645 secnotice("session", "%@ Error %d processing packet type %d, session state %d, keyid %d, myKey %p, myNextKey %p, theirKeyId %d, theirKey %p, theirPreviousKey %p, bytes %@", session
, (int)result
, packetType
, session
->_state
, session
->_keyID
, session
->_myKey
, session
->_myNextKey
, session
->_theirKeyID
, session
->_theirKey
, session
->_theirPreviousKey
, bytesString
);
650 if (session
->_textOutput
) {
651 SecOTRPrepareOutgoingBytes(destinationMessage
, negotiationResponse
);
653 CFReleaseSafe(destinationMessage
);
654 CFReleaseSafe(decodedBytes
);