]> git.saurik.com Git - apple/security.git/blob - OSX/sec/Security/SecOTRSessionAKE.c
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / sec / Security / SecOTRSessionAKE.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 "SecOTRSession.h"
26
27 #include "SecOTRMath.h"
28 #include "SecOTRIdentityPriv.h"
29 #include "SecOTRSessionPriv.h"
30 #include "SecOTRPackets.h"
31 #include "SecOTRPacketData.h"
32 #include "SecOTRDHKey.h"
33
34 #include <utilities/SecCFWrappers.h>
35
36 #include <CoreFoundation/CFRuntime.h>
37 #include <CoreFoundation/CFString.h>
38
39 #include <Security/SecBase.h>
40 #include <Security/SecRandom.h>
41
42 #include <AssertMacros.h>
43
44 #include <corecrypto/cchmac.h>
45 #include <corecrypto/ccsha2.h>
46
47 #include <os/activity.h>
48
49 #include <string.h>
50
51 static void SecOTRInitMyDHKeys(SecOTRSessionRef session)
52 {
53
54 CFReleaseNull(session->_myKey);
55 session->_myKey = SecOTRFullDHKCreate(kCFAllocatorDefault);
56 CFReleaseNull(session->_myNextKey);
57 session->_myNextKey = SecOTRFullDHKCreate(kCFAllocatorDefault);
58 session->_keyID = 1;
59 session->_missedAck = true;
60 session->_receivedAck = false;
61 bzero(session->_keyCache, sizeof(session->_keyCache));
62
63 secnotice("otr", "%@ Reinitializing DH Keys, first: %@", session, session->_myKey);
64 }
65
66 OSStatus SecOTRSAppendStartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket)
67 {
68 __block OSStatus result = errSecSuccess;
69
70 dispatch_sync(session->_queue, ^{
71 session->_state = kAwaitingDHKey;
72
73 // Generate r and x and calculate gx:
74 SecOTRInitMyDHKeys(session);
75
76 CFMutableDataRef dhMessage = CFDataCreateMutable(kCFAllocatorDefault, 0);
77
78 result = SecRandomCopyBytes(kSecRandomDefault, sizeof(session->_r), session->_r);
79 if (result == errSecSuccess) {
80 SecOTRAppendDHMessage(session, dhMessage);
81 }
82
83 CFDataPerformWithHexString(dhMessage, ^(CFStringRef messageString) {
84 secnotice("otr", "%@ Start packet: %@", session, messageString);
85 });
86
87 if (session->_textOutput) {
88 SecOTRPrepareOutgoingBytes(dhMessage, appendPacket);
89 } else {
90 CFDataAppend(appendPacket, dhMessage);
91 }
92
93 CFReleaseSafe(dhMessage);
94 });
95
96
97 return result;
98 }
99
100 OSStatus SecOTRSAppendRestartPacket(SecOTRSessionRef session, CFMutableDataRef appendPacket)
101 {
102 __block OSStatus result = errSecSuccess;
103
104 dispatch_sync(session->_queue, ^{
105 if (!session->_myKey) {
106 secerror("_myKey is NULL, avoiding crash");
107 result = errSecDecode;
108 return;
109 }
110 CFMutableDataRef dhMessage = CFDataCreateMutable(kCFAllocatorDefault, 0);
111
112 session->_state = kAwaitingDHKey;
113 CFReleaseNull(session->_receivedDHMessage);
114 CFReleaseNull(session->_receivedDHKeyMessage);
115
116 SecOTRAppendDHMessage(session, dhMessage);
117
118 CFDataPerformWithHexString(dhMessage, ^(CFStringRef messageString) {
119 secnotice("otr", "%@ Restart packet: %@", session, messageString);
120 });
121
122 if (session->_textOutput) {
123 SecOTRPrepareOutgoingBytes(dhMessage, appendPacket);
124 } else {
125 CFDataAppend(appendPacket, dhMessage);
126 }
127 CFReleaseSafe(dhMessage);
128 });
129
130 return result;
131 }
132
133 static const uint8_t* FindGXHash(CFDataRef dhPacket)
134 {
135 const uint8_t* messageBytes = CFDataGetBytePtr(dhPacket);
136 size_t remainingBytes = (size_t)CFDataGetLength(dhPacket);
137
138 OTRMessageType messageType;
139
140 require_noerr(ReadHeader(&messageBytes, &remainingBytes, &messageType), fail);
141 require(messageType == kDHMessage, fail);
142
143 uint32_t egxiLength = 0;
144 require_noerr(ReadLong(&messageBytes, &remainingBytes, & egxiLength), fail);
145 require(egxiLength <= remainingBytes, fail);
146 messageBytes += egxiLength;
147 remainingBytes -= egxiLength;
148
149 uint32_t dataLength = 0;
150 require_noerr(ReadLong(&messageBytes, &remainingBytes, &dataLength), fail);
151 require(dataLength <= remainingBytes, fail);
152 require(dataLength == CCSHA256_OUTPUT_SIZE, fail);
153
154 return messageBytes;
155
156 fail:
157 return NULL;
158 }
159
160 static bool SecOTRMyGXHashIsBigger(SecOTRSessionRef session, CFDataRef dhCommitMessage)
161 {
162 bool mineIsBigger = false;
163
164 CFMutableDataRef myDHCommitMessage = CFDataCreateMutable(kCFAllocatorDefault, 0);
165
166 SecOTRAppendDHMessage(session, myDHCommitMessage);
167
168 const uint8_t* myHash = FindGXHash(myDHCommitMessage);
169 const uint8_t* theirHash = FindGXHash(dhCommitMessage);
170
171 require(myHash, fail);
172 require(theirHash, fail);
173
174 mineIsBigger = 0 < memcmp(myHash, theirHash, CCSHA256_OUTPUT_SIZE);
175
176 BufferPerformWithHexString(myHash, CCSHA256_OUTPUT_SIZE, ^(CFStringRef myHashString) {
177 BufferPerformWithHexString(theirHash, CCSHA256_OUTPUT_SIZE, ^(CFStringRef theirHashString) {
178 secdebug("otr", "%@ %s gx is bigger, M:%@ T:%@", session, mineIsBigger ? "mine" : "their", myHashString, theirHashString);
179 });
180 });
181
182 fail:
183 CFReleaseNull(myDHCommitMessage);
184 return mineIsBigger;
185 }
186
187 static OSStatus SecOTRSProcessDHMessage(SecOTRSessionRef session,
188 CFDataRef incomingPacket,
189 CFMutableDataRef negotiationResponse)
190 {
191 OSStatus result = errSecParam;
192
193 CFStringRef messageMessage = CFSTR("");
194
195 switch (session->_state) {
196 case kAwaitingDHKey:
197 // Compare hash values.
198 if (SecOTRMyGXHashIsBigger(session, incomingPacket)) {
199 // If we're bigger we resend to force them to deal.
200 messageMessage = CFSTR("Our GX is bigger, resending DH");
201 CFReleaseNull(session->_receivedDHMessage);
202 SecOTRAppendDHMessage(session, negotiationResponse);
203 result = errSecSuccess;
204 break;
205 } // Else intentionally fall through to idle
206 messageMessage = CFSTR("Our GX is bigger, resending DH");
207 case kAwaitingSignature:
208 case kIdle:
209 case kDone:
210 // Generate a new X and GX..
211 SecOTRInitMyDHKeys(session);
212 // If we were already waiting on reveal, then just send the packet again
213 case kAwaitingRevealSignature:
214 SecOTRAppendDHKeyMessage(session, negotiationResponse);
215
216 if (messageMessage == 0)
217 messageMessage = CFSTR("Sending DHKey");
218 // Keep the packet for use later.
219 CFReleaseNull(session->_receivedDHMessage);
220 session->_receivedDHMessage = CFDataCreateCopy(kCFAllocatorDefault, incomingPacket);
221
222 session->_state = kAwaitingRevealSignature;
223 result = errSecSuccess;
224 break;
225 default:
226 result = errSecInteractionNotAllowed;
227 break;
228 }
229
230 if (result == errSecSuccess) {
231 CFDataPerformWithHexString(negotiationResponse, ^(CFStringRef responseString) {
232 secnotice("otr", "%@ %@: %@", session, messageMessage, responseString);
233 });
234 } else {
235 secnotice("otr", "%@ Process DH failed %d", session, (int)result);
236 }
237 return result;
238 }
239
240 static OSStatus SecOTRSetupTheirKeyFrom(SecOTRSessionRef session, const uint8_t**data, size_t*size)
241 {
242 SecOTRPublicDHKeyRef tempKey = SecOTRPublicDHKCreateFromSerialization(kCFAllocatorDefault, data, size);
243 require(tempKey != NULL, fail);
244
245 return SecOTRSetupInitialRemoteKey(session, tempKey);
246
247 fail:
248 return errSecDecode;
249 }
250
251 static OSStatus SecOTRSExtractTheirPublicDHKey(SecOTRSessionRef session, CFDataRef dhPacket)
252 {
253 OSStatus result = errSecParam;
254
255 const uint8_t *messageBytes = CFDataGetBytePtr(dhPacket);
256 size_t messageSize = (size_t)CFDataGetLength(dhPacket);
257 OTRMessageType messageType = kDHMessage; // Suppress warning.
258
259 ReadHeader(&messageBytes, &messageSize, &messageType);
260 require(messageType == kDHKeyMessage, exit);
261
262 result = SecOTRSetupTheirKeyFrom(session, &messageBytes, &messageSize);
263
264 exit:
265 return result;
266 }
267
268
269 static OSStatus SecOTRSProcessDHKeyMessage(SecOTRSessionRef session,
270 CFDataRef incomingPacket,
271 CFMutableDataRef negotiationResponse)
272 {
273 OSStatus result = errSecUnimplemented;
274 CFStringRef messageMessage = CFSTR("");
275
276 result = SecOTRSExtractTheirPublicDHKey(session, incomingPacket);
277 require_noerr(result, exit);
278
279 switch (session->_state) {
280 case kAwaitingDHKey:
281 CFReleaseNull(session->_receivedDHKeyMessage);
282 SecOTRAppendRevealSignatureMessage(session, negotiationResponse);
283 session->_state = kAwaitingSignature;
284 session->_receivedDHKeyMessage = CFDataCreateCopy(kCFAllocatorDefault, incomingPacket);
285 result = errSecSuccess;
286 messageMessage = CFSTR("Sending reveal signature");
287 break;
288 case kAwaitingSignature:
289 if (CFEqualSafe(incomingPacket, session->_receivedDHKeyMessage)) {
290 SecOTRAppendRevealSignatureMessage(session, negotiationResponse);
291 messageMessage = CFSTR("Resending reveal signature");
292 } else {
293 messageMessage = CFSTR("Ignoring new DHKey message");
294 }
295 result = errSecSuccess;
296 break;
297 case kIdle:
298 case kDone:
299 case kAwaitingRevealSignature:
300 result = errSecSuccess;
301 messageMessage = CFSTR("Ignoring DHKey message");
302 break;
303 default:
304 result = errSecInteractionNotAllowed;
305 break;
306 }
307
308 exit:
309 if (result == errSecSuccess) {
310 CFDataPerformWithHexString(negotiationResponse, ^(CFStringRef responseString) {
311 secnotice("otr", "%@ %@: %@", session, messageMessage, responseString);
312 });
313 } else {
314 secnotice("otr", "%@ Process DH failed %d", session, (int)result);
315 }
316
317 return result;
318 }
319
320
321 static OSStatus SecOTRSExtractR(SecOTRSessionRef session,
322 const uint8_t **messageBytes,
323 size_t *messageSize)
324 {
325 OSStatus result = errSecDecode;
326
327 OTRMessageType messageType = kDHMessage; // Suppress warning
328
329 ReadHeader(messageBytes, messageSize, &messageType);
330 require(messageType == kRevealSignatureMessage, exit);
331
332 {
333 uint32_t rSize = 0;
334 ReadLong(messageBytes, messageSize, &rSize);
335 require(rSize == kOTRAuthKeyBytes, exit);
336 }
337
338 memcpy(session->_r, *messageBytes, kOTRAuthKeyBytes);
339
340 *messageBytes += kOTRAuthKeyBytes;
341 *messageSize -= kOTRAuthKeyBytes;
342
343 result = errSecSuccess;
344 exit:
345 return result;
346 }
347
348 static OSStatus FindEncGYInDHPacket(SecOTRSessionRef session,
349 const uint8_t **dhMessageBytesPtr,
350 size_t *messageSizePtr,
351 size_t* encGYBufferSize)
352 {
353 OSStatus result = errSecParam;
354 require_action(*encGYBufferSize >= kExponentiationBytes + 4, exit, result = errSecParam);
355
356 OTRMessageType messageType;
357 result = ReadHeader(dhMessageBytesPtr, messageSizePtr, &messageType);
358 require_noerr(result, exit);
359 require_action(messageType == kDHMessage, exit, result = errSecDecode);
360
361 uint32_t readEncSize;
362 result = ReadLong(dhMessageBytesPtr, messageSizePtr, &readEncSize);
363 require_noerr(result, exit);
364
365 *encGYBufferSize = readEncSize;
366 exit:
367 // Don't bother erasing the public gy decrypted, it's public after all.
368 return result;
369
370 }
371
372 static OSStatus SecOTRSExtractRAndTheirDHKey(SecOTRSessionRef session,
373 const uint8_t **messageBytes,
374 size_t *messageSize)
375 {
376 OSStatus result = errSecDecode;
377
378 require(session->_receivedDHMessage != NULL, exit);
379 result = SecOTRSExtractR(session, messageBytes, messageSize);
380 require_noerr(result, exit);
381
382 uint8_t gxiDecrypted[kExponentiationBytes + 4];
383 const uint8_t *gxiDecryptedBuffer = gxiDecrypted;
384
385 const uint8_t* dhMessageBytes = CFDataGetBytePtr(session->_receivedDHMessage);
386 size_t dhMessageSize = (size_t)CFDataGetLength(session->_receivedDHMessage);
387
388 size_t encGYSize = sizeof(gxiDecrypted);
389 result = FindEncGYInDHPacket(session, &dhMessageBytes, &dhMessageSize, &encGYSize);
390 require_noerr(result, exit);
391 require_action(encGYSize <= kExponentiationBytes + 4, exit, result = errSecDecode);
392
393 AES_CTR_IV0_Transform(sizeof(session->_r), session->_r, encGYSize, dhMessageBytes, gxiDecrypted);
394
395 result = SecOTRSetupTheirKeyFrom(session, &gxiDecryptedBuffer, &encGYSize);
396
397 exit:
398 // Don't bother erasing the public gy decrypted, it's public after all.
399 return result;
400 }
401
402 static OSStatus SecVerifySignatureAndMac(SecOTRSessionRef session,
403 bool usePrimes,
404 const uint8_t **signatureAndMacBytes,
405 size_t *signatureAndMacSize)
406 {
407 OSStatus result = errSecDecode;
408
409 uint8_t m1[kOTRAuthMACKeyBytes];
410 uint8_t m2[kOTRAuthMACKeyBytes];
411 uint8_t c[kOTRAuthKeyBytes];
412
413 {
414 cc_unit s[kExponentiationUnits];
415
416 SecPDHKeyGenerateS(session->_myKey, session->_theirKey, s);
417 // Derive M1, M2 and C, either prime or normal versions.
418 DeriveOTR256BitsFromS(usePrimes ? kM1Prime : kM1,
419 kExponentiationUnits, s, sizeof(m1), m1);
420 DeriveOTR256BitsFromS(usePrimes ? kM2Prime : kM2,
421 kExponentiationUnits, s, sizeof(m2), m2);
422 DeriveOTR128BitPairFromS(kCs,
423 kExponentiationUnits, s,
424 sizeof(c),usePrimes ? NULL : c,
425 sizeof(c), usePrimes ? c : NULL);
426 bzero(s, sizeof(s));
427 }
428
429 cchmac_di_decl(ccsha256_di(), mBContext);
430
431 cchmac_init(ccsha256_di(), mBContext, sizeof(m1), m1);
432
433 {
434 CFMutableDataRef toHash = CFDataCreateMutable(kCFAllocatorDefault, 0);
435
436 SecPDHKAppendSerialization(session->_theirKey, toHash);
437 SecFDHKAppendPublicSerialization(session->_myKey, toHash);
438
439 cchmac_update(ccsha256_di(), mBContext, (size_t)CFDataGetLength(toHash), CFDataGetBytePtr(toHash));
440
441 CFReleaseNull(toHash);
442 }
443
444 const uint8_t* encSigDataBlobStart = *signatureAndMacBytes;
445
446 uint32_t xbSize = 0;
447 result = ReadLong(signatureAndMacBytes, signatureAndMacSize, &xbSize);
448 require_noerr(result, exit);
449 require_action(xbSize > 4, exit, result = errSecDecode);
450 require_action(xbSize <= *signatureAndMacSize, exit, result = errSecDecode);
451
452 uint8_t signatureMac[CCSHA256_OUTPUT_SIZE];
453 cchmac(ccsha256_di(), sizeof(m2), m2, xbSize + 4, encSigDataBlobStart, signatureMac);
454
455 require(xbSize + kSHA256HMAC160Bytes <= *signatureAndMacSize, exit);
456 const uint8_t *macStart = *signatureAndMacBytes + xbSize;
457
458 // check the outer hmac
459 require_action(0 == cc_cmp_safe(kSHA256HMAC160Bytes, macStart, signatureMac), exit, result = errSecDecode);
460
461
462 {
463 uint8_t xb[xbSize];
464 // Decrypt and copy the signature block
465 AES_CTR_IV0_Transform(sizeof(c), c, xbSize, *signatureAndMacBytes, xb);
466
467 const uint8_t* signaturePacket = xb;
468 size_t signaturePacketSize = xbSize;
469
470 uint16_t pubKeyType;
471 result = ReadShort(&signaturePacket, &signaturePacketSize, &pubKeyType);
472 require_noerr(result, exit);
473 require_action(pubKeyType == 0xF000, exit, result = errSecUnimplemented);
474
475 uint32_t pubKeySize;
476 result = ReadLong(&signaturePacket, &signaturePacketSize, &pubKeySize);
477 require_noerr(result, exit);
478 require_action(pubKeySize <= signaturePacketSize, exit, result = errSecDecode);
479 require(((CFIndex)pubKeySize) >= 0, exit);
480
481 // Add the signature and keyid to the hash.
482 // PUBKEY of our type is 2 bytes of type, 2 bytes of size and size bytes.
483 // Key ID is 4 bytes.
484 cchmac_update(ccsha256_di(), mBContext, 2 + 4 + pubKeySize + 4, xb);
485
486 uint8_t mb[CCSHA256_OUTPUT_SIZE];
487 cchmac_final(ccsha256_di(), mBContext, mb);
488
489 // Make reference to the deflated key
490 require_action(SecOTRPIEqualToBytes(session->_them, signaturePacket, (CFIndex)pubKeySize), exit, result = errSecAuthFailed);
491
492 signaturePacket += pubKeySize;
493 signaturePacketSize -= pubKeySize;
494
495 result = ReadLong(&signaturePacket, &signaturePacketSize, &session->_theirKeyID);
496 require_noerr(result, exit);
497
498 uint32_t sigSize;
499 result = ReadLong(&signaturePacket, &signaturePacketSize, &sigSize);
500 require_noerr(result, exit);
501 require_action(sigSize <= signaturePacketSize, exit, result = errSecDecode);
502
503 bool bresult = SecOTRPIVerifySignature(session->_them, mb, sizeof(mb), signaturePacket, sigSize, NULL);
504 result = bresult ? errSecSuccess : errSecDecode;
505 require_noerr(result, exit);
506
507 }
508
509 exit:
510 bzero(m1, sizeof(m1));
511 bzero(m2, sizeof(m2));
512 bzero(c, sizeof(c));
513
514 return result;
515 }
516
517 static OSStatus SecOTRSProcessRevealSignatureMessage(SecOTRSessionRef session,
518 CFDataRef incomingPacket,
519 CFMutableDataRef negotiationResponse)
520 {
521 OSStatus result = errSecParam;
522
523 require_action_quiet(session->_state == kAwaitingRevealSignature, exit, result = errSecSuccess);
524
525 const uint8_t *messageBytes = CFDataGetBytePtr(incomingPacket);
526 size_t messageSize = (size_t)CFDataGetLength(incomingPacket);
527
528 result = SecOTRSExtractRAndTheirDHKey(session, &messageBytes, &messageSize);
529 require_noerr(result, exit);
530
531 result = SecVerifySignatureAndMac(session, false, &messageBytes, &messageSize);
532 require_noerr(result, exit);
533
534 SecOTRAppendSignatureMessage(session, negotiationResponse);
535
536 session->_state = kDone;
537 result = errSecSuccess;
538
539 CFDataPerformWithHexString(negotiationResponse, ^(CFStringRef responseString) {
540 secnotice("otr", "%@ Sending Signature message: %@", session, responseString);
541 });
542
543 exit:
544
545 if (result != errSecSuccess) {
546 CFDataPerformWithHexString(incomingPacket, ^(CFStringRef incomingString) {
547 secnotice("otr", "%@ Failed to process reveal sig message (%d): %@", session, (int)result, incomingString);
548 });
549 }
550 return result;
551 }
552
553 static OSStatus SecOTRSProcessSignatureMessage(SecOTRSessionRef session,
554 CFDataRef incomingPacket,
555 CFMutableDataRef negotiationResponse)
556 {
557 OSStatus result = errSecParam;
558
559 require_action_quiet(session->_state == kAwaitingSignature, exit, result = errSecSuccess);
560
561 const uint8_t *messageBytes = CFDataGetBytePtr(incomingPacket);
562 size_t messageSize = (size_t)CFDataGetLength(incomingPacket);
563
564 OTRMessageType messageType;
565 result = ReadHeader(&messageBytes, &messageSize, &messageType);
566 require_noerr(result, exit);
567 require_action(messageType == kSignatureMessage, exit, result = errSecDecode);
568
569 result = SecVerifySignatureAndMac(session, true, &messageBytes, &messageSize);
570 require_noerr(result, exit);
571
572 CFReleaseNull(session->_receivedDHKeyMessage);
573 session->_state = kDone;
574
575 result = errSecSuccess;
576 exit:
577 return result;
578 }
579
580 OSStatus SecOTRSProcessPacket(SecOTRSessionRef session,
581 CFDataRef incomingPacket,
582 CFMutableDataRef negotiationResponse)
583 {
584 __block OSStatus result = errSecParam;
585
586 require(CFDataGetLength(incomingPacket) > 0, fail);
587 dispatch_sync(session->_queue, ^{
588 os_activity_initiate("OTR Process Packet", OS_ACTIVITY_FLAG_DEFAULT, ^{
589 CFDataRef decodedBytes = SecOTRCopyIncomingBytes(incomingPacket);
590
591 const uint8_t* bytes = CFDataGetBytePtr(decodedBytes);
592 size_t size = CFDataGetLength(decodedBytes);
593
594 OTRMessageType packetType = kInvalidMessage;
595 if (ReadHeader(&bytes, &size, &packetType))
596 packetType = kInvalidMessage;
597
598 CFMutableDataRef destinationMessage;
599 if (session->_textOutput) {
600 destinationMessage = CFDataCreateMutable(kCFAllocatorDefault, 0);
601 } else {
602 destinationMessage = CFRetainSafe(negotiationResponse);
603 }
604
605 switch (packetType) {
606 case kDHMessage:
607 result = SecOTRSProcessDHMessage(session, decodedBytes, destinationMessage);
608 break;
609 case kDHKeyMessage:
610 result = SecOTRSProcessDHKeyMessage(session, decodedBytes, destinationMessage);
611 break;
612 case kRevealSignatureMessage:
613 result = SecOTRSProcessRevealSignatureMessage(session, decodedBytes, destinationMessage);
614 break;
615 case kSignatureMessage:
616 result = SecOTRSProcessSignatureMessage(session, decodedBytes, destinationMessage);
617 break;
618 default:
619 result = errSecDecode;
620 break;
621 };
622
623 if (result != errSecSuccess) {
624 CFDataPerformWithHexString(decodedBytes, ^(CFStringRef bytesString) {
625 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);
626
627 });
628 }
629
630 if (session->_textOutput) {
631 SecOTRPrepareOutgoingBytes(destinationMessage, negotiationResponse);
632 }
633 CFReleaseSafe(destinationMessage);
634 CFReleaseSafe(decodedBytes);
635 });
636 });
637
638 fail:
639 return result;
640 }