otr-30-negotiation.c [plain text]
#include "Security_regressions.h"
#include <CoreFoundation/CFData.h>
#include <Security/SecOTRSession.h>
#include <Security/SecInternal.h>
#include <Security/SecBasePriv.h>
static void SecMPLogError(CFErrorRef error) {
if (error == NULL) {
return;
}
CFDictionaryRef tempDictionary = CFErrorCopyUserInfo(error);
CFIndex errorCode = CFErrorGetCode(error);
CFStringRef errorDomain = CFErrorGetDomain(error);
CFStringRef errorString = CFDictionaryGetValue(tempDictionary, kCFErrorDescriptionKey);
CFErrorRef previousError = (CFErrorRef)CFDictionaryGetValue(tempDictionary, kCFErrorUnderlyingErrorKey);
if (previousError != NULL) {
SecMPLogError(previousError);
}
char errorDomainStr[1024];
char errorStringStr[1024];
CFStringGetCString(errorDomain, errorDomainStr, 1024, kCFStringEncodingUTF8);
CFStringGetCString(errorString, errorStringStr, 1024, kCFStringEncodingUTF8);
printf("MessageProtection: %s (%ld) -- %s\n", errorDomainStr, errorCode, errorStringStr);
CFReleaseSafe(tempDictionary);
}
static void serializeAndDeserialize(SecOTRSessionRef* thisOne)
{
CFMutableDataRef serialized = CFDataCreateMutable(kCFAllocatorDefault, 0);
SecOTRSAppendSerialization(*thisOne, serialized);
CFReleaseNull(*thisOne);
*thisOne = SecOTRSessionCreateFromData(kCFAllocatorDefault, serialized);
CFReleaseSafe(serialized);
}
#define sendMessagesCount(n) ((n) * 8)
static void sendMessages(int howMany, SecOTRSessionRef *bobSession, SecOTRSessionRef *aliceSession, bool serialize)
{
for(int count = howMany; count > 0; --count) {
const char* aliceToBob = "aliceToBob";
CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
ok_status(SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode message");
if (serialize) {
serializeAndDeserialize(bobSession);
serializeAndDeserialize(aliceSession);
}
ok(CFDataGetLength(rawAliceToBob) == CFDataGetLength(bobDecode)
&& 0 == memcmp(CFDataGetBytePtr(rawAliceToBob), CFDataGetBytePtr(bobDecode), (size_t)CFDataGetLength(rawAliceToBob)), "Didn't match!");
CFReleaseNull(rawAliceToBob);
CFReleaseNull(protectedAliceToBob);
CFReleaseNull(bobDecode);
const char* bobToAlice = "i liked your silly message from me to you";
CFDataRef rawBobToAlice = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)bobToAlice, (CFIndex) strlen(bobToAlice));
CFMutableDataRef protectedBobToAlice = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFMutableDataRef aliceDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSSignAndProtectMessage(*bobSession, rawBobToAlice, protectedBobToAlice), "encode reply");
ok_status(SecOTRSVerifyAndExposeMessage(*aliceSession, protectedBobToAlice, aliceDecode), "decode reply");
if (serialize) {
serializeAndDeserialize(bobSession);
serializeAndDeserialize(aliceSession);
}
ok(CFDataGetLength(rawBobToAlice) == CFDataGetLength(aliceDecode)
&& 0 == memcmp(CFDataGetBytePtr(rawBobToAlice), CFDataGetBytePtr(aliceDecode), (size_t)CFDataGetLength(rawBobToAlice)), "reply matched");
CFReleaseNull(rawAliceToBob);
CFReleaseNull(protectedAliceToBob);
CFReleaseNull(aliceDecode);
CFStringRef stateString = CFCopyDescription(*bobSession);
ok(stateString, "getting state from bob");
CFReleaseNull(stateString);
stateString = CFCopyDescription(*aliceSession);
ok(stateString, "getting state from alice");
CFReleaseNull(stateString);
}
}
#define kNegotiateTestCount (14 + sendMessagesCount(5) \
+ 2 + sendMessagesCount(1) \
+ 1 + sendMessagesCount(1))
static void negotiate(SecOTRSessionRef* aliceSession, SecOTRSessionRef* bobSession, bool serialize)
{
CFMutableDataRef bobStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSAppendStartPacket(*bobSession, bobStartPacket), "Bob start packet");
if (serialize)
serializeAndDeserialize(bobSession);
CFMutableDataRef aliceStartPacket = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSAppendStartPacket(*aliceSession, aliceStartPacket), "Alice start packet");
if (serialize)
serializeAndDeserialize(aliceSession);
CFMutableDataRef aliceDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*aliceSession, bobStartPacket, aliceDHKeyResponse),
"Bob DH packet failed");
if (serialize)
serializeAndDeserialize(aliceSession);
CFReleaseNull(bobStartPacket);
CFMutableDataRef bobDHKeyResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*bobSession, aliceStartPacket, bobDHKeyResponse),
"Alice DH packet failed");
if (serialize)
serializeAndDeserialize(bobSession);
CFReleaseNull(aliceStartPacket);
CFMutableDataRef bobRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*bobSession, aliceDHKeyResponse, bobRevealSigResponse),
"Alice DH Key packet failed");
if (serialize)
serializeAndDeserialize(bobSession);
CFReleaseNull(aliceDHKeyResponse);
CFMutableDataRef aliceRevealSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*aliceSession, bobDHKeyResponse, aliceRevealSigResponse),
"Bob DH Key packet failed");
if (serialize)
serializeAndDeserialize(aliceSession);
CFReleaseNull(bobDHKeyResponse);
CFMutableDataRef aliceSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*aliceSession, bobRevealSigResponse, aliceSigResponse),
"Bob Reveal sig failed");
if (serialize)
serializeAndDeserialize(aliceSession);
CFReleaseNull(bobRevealSigResponse);
CFMutableDataRef bobSigResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*bobSession, aliceRevealSigResponse, bobSigResponse),
"Alice Reveal sig failed");
if (serialize)
serializeAndDeserialize(bobSession);
CFReleaseNull(aliceRevealSigResponse);
CFMutableDataRef bobFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*bobSession, aliceSigResponse, bobFinalResponse),
"Alice Final Sig failed");
if (serialize)
serializeAndDeserialize(bobSession);
CFMutableDataRef aliceFinalResponse = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSProcessPacket(*aliceSession, bobSigResponse, aliceFinalResponse),
"Bob Final Sig failed");
if (serialize)
serializeAndDeserialize(aliceSession);
is(6, CFDataGetLength(bobFinalResponse), "Alice had nothing left to say");
is(6, CFDataGetLength(bobFinalResponse), "Bob had nothing left to say");
ok(SecOTRSGetIsReadyForMessages(*bobSession), "Bob is ready");
ok(SecOTRSGetIsReadyForMessages(*aliceSession), "Alice is ready");
CFReleaseNull(aliceSigResponse);
CFReleaseNull(bobFinalResponse);
sendMessages(5, bobSession, aliceSession, serialize);
const char* aliceToBob = "deferredMessage";
CFDataRef rawAliceToBob = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)aliceToBob, (CFIndex) strlen(aliceToBob));
CFMutableDataRef protectedAliceToBob = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFMutableDataRef bobDecode = CFDataCreateMutable(kCFAllocatorDefault, 0);
ok_status(SecOTRSSignAndProtectMessage(*aliceSession, rawAliceToBob, protectedAliceToBob), "encode message");
sendMessages(1, bobSession, aliceSession, serialize);
ok(errSecOTRTooOld ==SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Decode old message");
sendMessages(1, bobSession, aliceSession, serialize);
ok(errSecOTRTooOld == SecOTRSVerifyAndExposeMessage(*bobSession, protectedAliceToBob, bobDecode), "Fail to decode excessively old message");
CFReleaseNull(rawAliceToBob);
CFReleaseNull(protectedAliceToBob);
CFReleaseNull(bobDecode);
}
#define kTestTestCount (7 + kNegotiateTestCount)
static void tests()
{
CFErrorRef testError = NULL;
SecOTRFullIdentityRef aliceID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
SecMPLogError(testError);
CFReleaseNull(testError);
testError = NULL;
SecOTRFullIdentityRef bobID = SecOTRFullIdentityCreate(kCFAllocatorDefault, &testError);
SecMPLogError(testError);
CFReleaseNull(testError);
testError = NULL;
ok(aliceID, "create alice ID");
ok(bobID, "create bob ID");
SecOTRPublicIdentityRef alicePublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, aliceID, &testError);
SecMPLogError(testError);
CFReleaseNull(testError);
SecOTRPublicIdentityRef bobPublicID = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, bobID, &testError);
SecMPLogError(testError);
CFReleaseNull(testError);
ok(alicePublicID, "extract alice public");
ok(bobPublicID, "extract bob public");
SecOTRSessionRef aliceSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, aliceID, bobPublicID, kSecOTRSendTextMessages);
SecOTRSessionRef bobSession = SecOTRSessionCreateFromIDAndFlags(kCFAllocatorDefault, bobID, alicePublicID, kSecOTRSendTextMessages);
ok(aliceSession, "create alice session");
ok(bobSession, "create bob session");
CFReleaseNull(aliceID);
CFReleaseNull(bobID);
CFReleaseNull(alicePublicID);
CFReleaseNull(bobPublicID);
negotiate(&aliceSession, &bobSession, true);
ok(SecOTRFIPurgeAllFromKeychain(&testError),"cleanup keychain");
SecMPLogError(testError);
CFReleaseNull(testError);
CFReleaseNull(aliceSession);
CFReleaseNull(bobSession);
}
int otr_30_negotiation(int argc, char *const *argv)
{
plan_tests(kTestTestCount);
tests();
return 0;
}