--- /dev/null
+/*
+ * Copyright (c) 2011-2012,2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#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>
+
+void OTRExponentiate(cc_unit* res, const cc_unit* base, const cc_unit* exponent)
+{
+ ccdh_const_gp_t gp = ccdh_gp_rfc3526group05();
+ cczp_power(gp.zp, res, base, exponent);
+}
+
+void OTRGroupExponentiate(cc_unit* res, const cc_unit* exponent)
+{
+ OTRExponentiate(res, ccdh_gp_g(ccdh_gp_rfc3526group05()) , exponent);
+}
+
+//
+// Random Number Generation
+//
+
+OSStatus GetRandomBytesInLSBs(size_t bytesOfRandomness, size_t n, cc_unit* place)
+{
+ OSStatus result = errSecParam;
+ require(bytesOfRandomness * 8 <= ccn_bitsof_n(n), fail);
+ {
+ uint8_t randomBytes[bytesOfRandomness];
+
+ result = SecRandomCopyBytes(kSecRandomDefault, sizeof(randomBytes), randomBytes);
+
+ require_noerr(result, fail);
+
+ ccn_read_uint(n, place, sizeof(randomBytes), randomBytes);
+
+ bzero(randomBytes, bytesOfRandomness);
+ }
+fail:
+ return result;
+}
+
+OSStatus FillWithRandomBytes(size_t n, cc_unit* place)
+{
+ return GetRandomBytesInLSBs(ccn_sizeof(n), n, place);
+}
+
+
+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);
+}
+
+
+//
+// Key Derivation
+//
+
+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);
+
+ /* 64 bits cast: amountToHash is the size of an identity +1 , which is currently hardcoded and never more than 2^32 bytes */
+ assert((unsigned long)amountToHash<UINT32_MAX); /* Debug check, Correct as long as CFIndex is a signed long and CC_LONG is a uint32_t */
+
+ (void) CC_SHA256(bytesToHash, (CC_LONG)amountToHash, buffer);
+
+ bzero(bytesToHash, (size_t)amountToHash);
+ CFReleaseNull(dataToHash);
+}
+
+void DeriveOTR256BitsFromS(KeyType whichKey, cc_size sN, const cc_unit* s, size_t keySize, uint8_t* key)
+{
+ HashMPIWithPrefix(whichKey, sN, s, key);
+}
+
+void DeriveOTR128BitPairFromS(KeyType 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(KeyType 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);
+}
+