SecOTRMath.c
1 /* 2 * Copyright (c) 2011-2012,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 "SecOTRMath.h" 26 27 #include "SecOTRPacketData.h" 28 29 #include <utilities/SecCFWrappers.h> 30 #include <AssertMacros.h> 31 32 #include <pthread.h> 33 34 #include <Security/SecRandom.h> 35 36 #include <corecrypto/ccsha2.h> 37 #include <corecrypto/cczp.h> 38 #include <corecrypto/ccdh_gp.h> 39 40 #include <limits.h> 41 42 // 43 // Random Number Generation 44 // 45 46 47 static const uint8_t kIVZero[16] = { }; 48 49 static void AES_CTR_Transform(size_t keySize, const uint8_t* key, 50 const uint8_t iv[16], 51 size_t howMuch, const uint8_t* from, uint8_t* to) 52 { 53 const struct ccmode_ctr* ctr_encrypt = ccaes_ctr_crypt_mode(); 54 ccctr_ctx_decl(ctr_encrypt->size, ctr_ctx); 55 ctr_encrypt->init(ctr_encrypt, ctr_ctx, keySize, key, iv); 56 57 ctr_encrypt->ctr(ctr_ctx, howMuch, from, to); 58 } 59 60 void AES_CTR_HighHalf_Transform(size_t keySize, const uint8_t* key, 61 uint64_t highHalf, 62 size_t howMuch, const uint8_t* from, uint8_t* to) 63 { 64 uint8_t iv[16] = { highHalf >> 56, highHalf >> 48, highHalf >> 40, highHalf >> 32, 65 highHalf >> 24, highHalf >> 16, highHalf >> 8 , highHalf >> 0, 66 0, 0, 0, 0, 67 0, 0, 0, 0 }; 68 AES_CTR_Transform(keySize, key, iv, howMuch, from, to); 69 } 70 71 void AES_CTR_IV0_Transform(size_t keySize, const uint8_t* key, 72 size_t howMuch, const uint8_t* from, uint8_t* to) 73 { 74 AES_CTR_Transform(keySize, key, kIVZero, howMuch, from, to); 75 } 76 77 78 // 79 // Key Derivation 80 // 81 82 static void HashMPIWithPrefix(uint8_t byte, cc_size sN, const cc_unit* s, uint8_t* buffer) 83 { 84 CFMutableDataRef dataToHash = CFDataCreateMutable(kCFAllocatorDefault, 0); 85 CFDataAppendBytes(dataToHash, &byte, 1); 86 87 AppendMPI(dataToHash, sN, s); 88 89 uint8_t *bytesToHash = CFDataGetMutableBytePtr(dataToHash); 90 CFIndex amountToHash = CFDataGetLength(dataToHash); 91 92 /* 64 bits cast: amountToHash is the size of an identity +1 , which is currently hardcoded and never more than 2^32 bytes */ 93 assert((unsigned long)amountToHash<UINT32_MAX); /* Debug check, Correct as long as CFIndex is a signed long and CC_LONG is a uint32_t */ 94 95 (void) CC_SHA256(bytesToHash, (CC_LONG)amountToHash, buffer); 96 97 bzero(bytesToHash, (size_t)amountToHash); 98 CFReleaseNull(dataToHash); 99 } 100 101 void DeriveOTR256BitsFromS(OTRKeyType whichKey, cc_size sN, const cc_unit* s, size_t keySize, uint8_t* key) 102 { 103 HashMPIWithPrefix(whichKey, sN, s, key); 104 } 105 106 void DeriveOTR128BitPairFromS(OTRKeyType whichKey, size_t sSize, const cc_unit* s, 107 size_t firstKeySize, uint8_t* firstKey, 108 size_t secondKeySize, uint8_t* secondKey) 109 { 110 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE]; 111 112 HashMPIWithPrefix(whichKey, sSize, s, hashBuffer); 113 114 if (firstKey) { 115 firstKeySize = firstKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : firstKeySize; 116 memcpy(firstKey, hashBuffer, firstKeySize); 117 } 118 if (secondKey) { 119 secondKeySize = secondKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : secondKeySize; 120 memcpy(secondKey, hashBuffer, secondKeySize); 121 } 122 123 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE); 124 125 } 126 127 void DeriveOTR64BitsFromS(OTRKeyType whichKey, size_t sn, const cc_unit* s, 128 size_t topKeySize, uint8_t* topKey) 129 { 130 uint8_t hashBuffer[CCSHA256_OUTPUT_SIZE]; 131 132 HashMPIWithPrefix(whichKey, sn, s, hashBuffer); 133 134 topKeySize = topKeySize > CCSHA256_OUTPUT_SIZE/2 ? CCSHA256_OUTPUT_SIZE/2 : topKeySize; 135 memcpy(topKey, hashBuffer, topKeySize); 136 137 bzero(hashBuffer, CCSHA256_OUTPUT_SIZE); 138 } 139