/ OSX / sec / Security / SecOTRMath.c
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