#include "SecOTRMath.h"
#include "SecOTRPacketData.h"
#include <utilities/SecCFWrappers.h>
#include <AssertMacros.h>
#include <pthread.h>
#include <Security/SecRandom.h>
#include <corecrypto/ccsha2.h>
#include <corecrypto/cczp.h>
#include <corecrypto/ccdh_gp.h>
#include <limits.h>
static const uint8_t kIVZero[16] = { };
static void AES_CTR_Transform(size_t keySize, const uint8_t* key,
const uint8_t iv[16],
size_t howMuch, const uint8_t* from, uint8_t* to)
{
const struct ccmode_ctr* ctr_encrypt = ccaes_ctr_crypt_mode();
ccctr_ctx_decl(ctr_encrypt->size, ctr_ctx);
ctr_encrypt->init(ctr_encrypt, ctr_ctx, keySize, key, iv);
ctr_encrypt->ctr(ctr_ctx, howMuch, from, to);
}
void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key,
uint64_t highHalf,
size_t howMuch, const uint8_t* from, uint8_t* to)
{
uint8_t iv[16] = { highHalf >> 56, highHalf >> 48, highHalf >> 40, highHalf >> 32,
highHalf >> 24, highHalf >> 16, highHalf >> 8 , highHalf >> 0,
0, 0, 0, 0,
0, 0, 0, 0 };
AES_CTR_Transform(keySize, key, iv, howMuch, from, to);
}
void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key,
size_t howMuch, const uint8_t* from, uint8_t* to)
{
AES_CTR_Transform(keySize, key, kIVZero, howMuch, from, to);
}
static void HashMPIWithPrefix(uint8_t byte, cc_size sN, const cc_unit* s, uint8_t* buffer)
{
CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFDataAppendBytes(dataToHash, &byte, 1);
AppendMPI(dataToHash, sN, s);
uint8_t *bytesToHash = CFDataGetMutableBytePtr(dataToHash);
CFIndex amountToHash = CFDataGetLength(dataToHash);
assert((unsigned long)amountToHash<UINT32_MAX);
(void) CC_SHA256(bytesToHash, (CC_LONG)amountToHash, buffer);
bzero(bytesToHash, (size_t)amountToHash);
CFReleaseNull(dataToHash);
}
void DeriveOTR256BitsFromS(OTRKeyType whichKey, cc_size sN, const cc_unit* s, size_t keySize, uint8_t* key)
{
HashMPIWithPrefix(whichKey, sN, s, key);
}
void DeriveOTR128BitPairFromS(OTRKeyType whichKey, size_t sSize, const cc_unit* s,
size_t firstKeySize, uint8_t* firstKey,
size_t secondKeySize, uint8_t* secondKey)
{
uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
HashMPIWithPrefix(whichKey, sSize, s, hashBuffer);
if (firstKey) {
firstKeySize = firstKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : firstKeySize;
memcpy(firstKey, hashBuffer, firstKeySize);
}
if (secondKey) {
secondKeySize = secondKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : secondKeySize;
memcpy(secondKey, hashBuffer, secondKeySize);
}
bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
}
void DeriveOTR64BitsFromS(OTRKeyType whichKey, size_t sn, const cc_unit* s,
size_t topKeySize, uint8_t* topKey)
{
uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE];
HashMPIWithPrefix(whichKey, sn, s, hashBuffer);
topKeySize = topKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : topKeySize;
memcpy(topKey, hashBuffer, topKeySize);
bzero(hashBuffer, CCSHA256_OUTPUT_SIZE);
}