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