X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/c38e3ce98599a410a47dc10253faa4d5830f13b2..427c49bcad63d042b29ada2ac27e3dfc4845c779:/sec/Security/SecOTRPackets.c diff --git a/sec/Security/SecOTRPackets.c b/sec/Security/SecOTRPackets.c new file mode 100644 index 00000000..f13d967d --- /dev/null +++ b/sec/Security/SecOTRPackets.c @@ -0,0 +1,264 @@ +// +// SecOTRPackets.c +// libsecurity_libSecOTR +// +// Created by Mitch Adler on 2/23/11. +// Copyright 2011 Apple Inc. All rights reserved. +// + +#include "SecOTRSessionPriv.h" +#include "SecOTRPackets.h" + +#include "SecOTR.h" +#include "SecOTRIdentityPriv.h" + +//*****************************************#include "SecCFWrappers.h" +#include "SecOTRPacketData.h" +#include "SecOTRDHKey.h" + +#ifdef USECOMMONCRYPTO +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +// +// Crypto functions +// + +static inline void AppendSHA256HMAC(CFMutableDataRef appendTo, + size_t keybytes, + const uint8_t* key, + size_t howMuch, + const uint8_t* from) +{ + uint8_t *to = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE); + +#ifdef USECOMMONCRYPTO + CCHmac(kCCHmacAlgSHA256, key, keybytes, from, howMuch, to); +#else + cchmac(ccsha256_di(), keybytes, key, howMuch, from, to); +#endif +} + +// First 160 bits of the HMAC +static inline void AppendSHA256HMAC_160(CFMutableDataRef appendTo, + size_t keySize, + const uint8_t* key, + size_t howMuch, + const uint8_t* from) +{ + AppendSHA256HMAC(appendTo, keySize, key, howMuch, from); + const CFIndex bytesToRemove = CCSHA256_OUTPUT_SIZE - kSHA256HMAC160Bytes; + const CFRange rangeToDelete = CFRangeMake(CFDataGetLength(appendTo) - bytesToRemove, bytesToRemove); + + CFDataDeleteBytes(appendTo, rangeToDelete); +} + +static inline void DeriveAndAppendSHA256HMAC(CFMutableDataRef appendTo, + cc_size sN, + const cc_unit* s, + KeyType whichKey, + size_t howMuch, + const uint8_t* from) +{ + size_t localKeySize = CCSHA256_OUTPUT_SIZE; + uint8_t localKey[localKeySize]; + + DeriveOTR256BitsFromS(whichKey, sN, s, localKeySize, localKey); + + AppendSHA256HMAC(appendTo, localKeySize, localKey, howMuch, from); + + bzero(localKey, localKeySize); +} + +static inline void DeriveAndAppendSHA256HMAC_160(CFMutableDataRef appendTo, + cc_size sN, + const cc_unit* s, + KeyType whichKey, + size_t howMuch, + const uint8_t* from) +{ + size_t localKeySize = CCSHA256_OUTPUT_SIZE; + uint8_t localKey[localKeySize]; + + DeriveOTR256BitsFromS(whichKey, sN, s, localKeySize, localKey); + + AppendSHA256HMAC_160(appendTo, localKeySize, localKey, howMuch, from); + + bzero(localKey, sizeof(localKey)); +} + +// +// Message creators +// + +void SecOTRAppendDHMessage(SecOTRSessionRef session, + CFMutableDataRef appendTo) +{ + // + // Message Type: kDHMessage (0x02) + // AES_CTR(r, 0) of G^X MPI + // SHA256(gxmpi) + // + + if(!session) return; + CFMutableDataRef gxmpi = CFDataCreateMutable(kCFAllocatorDefault, 0); + if(!gxmpi) return; + + AppendHeader(appendTo, kDHMessage); + + SecFDHKAppendPublicSerialization(session->_myKey, gxmpi); + + size_t gxmpiSize = (size_t)CFDataGetLength(gxmpi); + if(gxmpiSize == 0) { + CFReleaseNull(gxmpi); + return; + } + const uint8_t* gxmpiLocation = CFDataGetBytePtr(gxmpi); + + /* 64 bits cast: gxmpiSize is the size of the EC public key, which is hardcoded and never more than 2^32 bytes. */ + assert(gxmpiSize_r), session->_r, gxmpiSize, gxmpiLocation, encGxmpiLocation); + + AppendLong(appendTo, CCSHA256_OUTPUT_SIZE); + uint8_t* hashLocation = CFDataIncreaseLengthAndGetMutableBytes(appendTo, CCSHA256_OUTPUT_SIZE); + +#ifdef USECOMMONCRYPTO + (void) CC_SHA256(gxmpiLocation, (uint32_t)gxmpiSize, hashLocation); +#else + ccdigest(ccsha256_di(), gxmpiSize, gxmpiLocation, hashLocation); +#endif + CFReleaseNull(gxmpi); +} + +void SecOTRAppendDHKeyMessage(SecOTRSessionRef session, + CFMutableDataRef appendTo) +{ + // + // Message Type: kDHKeyMessage (0x0A) + // G^X Data MPI + // + + AppendHeader(appendTo, kDHKeyMessage); + SecFDHKAppendPublicSerialization(session->_myKey, appendTo); +} + +static uint8_t* AppendEncryptedSignature(SecOTRSessionRef session, + const cc_unit* s, + bool usePrime, + CFMutableDataRef appendTo) +{ + CFMutableDataRef signature = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFMutableDataRef mbData = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFMutableDataRef mb = CFDataCreateMutable(kCFAllocatorDefault, 0); + + SecFDHKAppendPublicSerialization(session->_myKey, mbData); + SecPDHKAppendSerialization(session->_theirKey, mbData); + + CFIndex publicKeyOffset = CFDataGetLength(mbData); + + SecOTRPublicIdentityRef myPublic = SecOTRPublicIdentityCopyFromPrivate(kCFAllocatorDefault, session->_me, NULL); + AppendPublicKey(mbData, myPublic); + CFReleaseNull(myPublic); + + AppendLong(mbData, session->_keyID); + + DeriveAndAppendSHA256HMAC(mb, + kExponentiationUnits, s, + usePrime ? kM1Prime : kM1, + (size_t)CFDataGetLength(mbData), CFDataGetBytePtr(mbData)); + + CFDataDeleteBytes(mbData, CFRangeMake(0, publicKeyOffset)); + + CFMutableDataRef xb = mbData; mbData = NULL; + SecOTRFIAppendSignature(session->_me, mb, signature, NULL); + CFReleaseNull(mb); + + AppendCFDataAsDATA(xb, signature); + CFReleaseNull(signature); + + CFIndex dataLength = CFDataGetLength(xb); + + CFIndex signatureStartIndex = CFDataGetLength(appendTo); + /* 64 bits cast: We are appending the signature we just generated, which is never bigger than 2^32 bytes. */ + assert(((unsigned long)dataLength)<=UINT32_MAX); /* debug check, correct as long as CFIndex is a signed long */ + AppendLong(appendTo, (uint32_t)dataLength); + uint8_t *destination = CFDataIncreaseLengthAndGetMutableBytes(appendTo, dataLength); + + uint8_t c[kOTRAuthKeyBytes]; + DeriveOTR128BitPairFromS(kCs, kExponentiationUnits, s, + sizeof(c), usePrime ? NULL : c, + sizeof(c), usePrime ? c : NULL); + + AES_CTR_IV0_Transform(sizeof(c), c, + (size_t)dataLength, CFDataGetBytePtr(xb), + destination); + bzero(c, sizeof(c)); + CFReleaseNull(xb); + + return CFDataGetMutableBytePtr(appendTo) + signatureStartIndex; +} + + +static void AppendMACedEncryptedSignature(SecOTRSessionRef session, + bool usePrime, + CFMutableDataRef appendTo) +{ + + cc_unit s[kExponentiationUnits]; + + SecPDHKeyGenerateS(session->_myKey, session->_theirKey, s); + + CFIndex signatureStartOffset = CFDataGetLength(appendTo); + const uint8_t *signatureStart = AppendEncryptedSignature(session, s, usePrime, appendTo); + size_t signatureSize = (size_t)CFDataGetLength(appendTo) - (size_t)signatureStartOffset; + + + DeriveAndAppendSHA256HMAC_160(appendTo, + kExponentiationUnits, s, + usePrime ? kM2Prime : kM2, + signatureSize, signatureStart); + bzero(s, sizeof(s)); +} + + +void SecOTRAppendRevealSignatureMessage(SecOTRSessionRef session, + CFMutableDataRef appendTo) +{ + // + // Message Type: kRevealSignatureMessage (0x11) + // G^X Data MPI + // + + AppendHeader(appendTo, kRevealSignatureMessage); + + AppendLong(appendTo, kOTRAuthKeyBytes); + uint8_t* keyPosition = CFDataIncreaseLengthAndGetMutableBytes(appendTo, kOTRAuthKeyBytes); + memcpy(keyPosition, session->_r, kOTRAuthKeyBytes); + + AppendMACedEncryptedSignature(session, false, appendTo); +} + +void SecOTRAppendSignatureMessage(SecOTRSessionRef session, + CFMutableDataRef appendTo) +{ + // + // Message Type: kSignatureMessage (0x12) + // G^X Data MPI + // + + AppendHeader(appendTo, kSignatureMessage); + AppendMACedEncryptedSignature(session, true, appendTo); +} +