/ OSX / sec / Security / SecPBKDF.c
SecPBKDF.c
  1  /*
  2   *  SecPBKDF.c
  3   *
  4   *  Copyright (c) 2010,2012 Apple Inc. All Rights Reserved.
  5   *
  6   */
  7  
  8  #include "Security/SecPBKDF.h"
  9  #include "Security/pbkdf2.h"
 10  
 11  #include <CommonCrypto/CommonHMAC.h>
 12  #include "Security/SecBase.h"
 13  
 14  #include <stdlib.h>
 15  #include <string.h>
 16  
 17  /* CC Based HMAC PRF functions */
 18  void hmac_sha1_PRF(const uint8_t *key,
 19                     size_t key_len,
 20                     const uint8_t *text,
 21                     size_t text_len,
 22                     uint8_t digest[CC_SHA1_DIGEST_LENGTH])
 23  {
 24      CCHmacContext hmac_sha1_context;
 25      
 26      CCHmacInit(&hmac_sha1_context, kCCHmacAlgSHA1, key, key_len);
 27      CCHmacUpdate(&hmac_sha1_context, text, text_len);
 28      CCHmacFinal(&hmac_sha1_context, digest);
 29  }
 30  
 31  void hmac_sha256_PRF(const uint8_t *key,
 32                     size_t key_len,
 33                     const uint8_t *text,
 34                     size_t text_len,
 35                     uint8_t digest[CC_SHA256_DIGEST_LENGTH])
 36  {
 37      CCHmacContext hmac_sha256_context;
 38  
 39      CCHmacInit(&hmac_sha256_context, kCCHmacAlgSHA256, key, key_len);
 40      CCHmacUpdate(&hmac_sha256_context, text, text_len);
 41      CCHmacFinal(&hmac_sha256_context, digest);
 42  }
 43  
 44  
 45  /* This implements the HMAC SHA-1 version of pbkdf2 and allocates a local buffer for the HMAC */
 46  OSStatus pbkdf2_hmac_sha1(const uint8_t *passwordPtr, size_t passwordLen,
 47                        const uint8_t *saltPtr, size_t saltLen,
 48                        uint32_t iterationCount,
 49                        void *dkPtr, size_t dkLen)
 50  {
 51      // MAX(salt_length + 4, 20 /* SHA1 Digest size */) + 2 * 20;
 52      // salt_length + HASH_SIZE is bigger than either salt + 4 and digestSize.
 53      size_t kBigEnoughSize = (saltLen + CC_SHA1_DIGEST_LENGTH) + 2 * CC_SHA1_DIGEST_LENGTH;
 54      uint8_t *temp_data = malloc(kBigEnoughSize);
 55      
 56      if (temp_data == NULL) {
 57          return errSecMemoryError;
 58      }
 59  
 60      pbkdf2(hmac_sha1_PRF, CC_SHA1_DIGEST_LENGTH,
 61             passwordPtr, passwordLen,
 62             saltPtr, saltLen,
 63             iterationCount,
 64             dkPtr, dkLen,
 65             temp_data);
 66                     
 67      bzero(temp_data, kBigEnoughSize);
 68      
 69      return errSecSuccess;
 70  }
 71  
 72  /* This implements the HMAC SHA-256 version of pbkdf2 and allocates a local buffer for the HMAC */
 73  OSStatus pbkdf2_hmac_sha256(const uint8_t *passwordPtr, size_t passwordLen,
 74                        const uint8_t *saltPtr, size_t saltLen,
 75                        uint32_t iterationCount,
 76                        void *dkPtr, size_t dkLen)
 77  {
 78      // MAX(salt_length + 4, 32 /* SHA1 Digest size */) + 2 * 32;
 79      // salt_length + HASH_SIZE is bigger than either salt + 4 and digestSize.
 80      size_t kBigEnoughSize = (saltLen + CC_SHA256_DIGEST_LENGTH) + 2 * CC_SHA256_DIGEST_LENGTH;
 81      uint8_t *temp_data = malloc(kBigEnoughSize);
 82      
 83      if (temp_data == NULL) {
 84          return errSecMemoryError;
 85      }
 86  
 87      pbkdf2(hmac_sha256_PRF, CC_SHA256_DIGEST_LENGTH,
 88             passwordPtr, passwordLen,
 89             saltPtr, saltLen,
 90             iterationCount,
 91             dkPtr, dkLen,
 92             temp_data);
 93  
 94      bzero(temp_data, kBigEnoughSize);
 95      
 96      return errSecSuccess;
 97  }
 98  
 99  OSStatus SecKeyFromPassphraseDataHMACSHA1(CFDataRef password, CFDataRef salt, uint32_t interationCount, CFMutableDataRef derivedKey)
100  {
101      return pbkdf2_hmac_sha1(CFDataGetBytePtr(password), CFDataGetLength(password),
102                       CFDataGetBytePtr(salt), CFDataGetLength(salt),
103                       interationCount,
104                       CFDataGetMutableBytePtr(derivedKey), CFDataGetLength(derivedKey));
105  
106  }
107  
108  OSStatus SecKeyFromPassphraseDataHMACSHA256(CFDataRef password, CFDataRef salt, uint32_t interationCount, CFMutableDataRef derivedKey)
109  {
110      return pbkdf2_hmac_sha256(CFDataGetBytePtr(password), CFDataGetLength(password),
111                         CFDataGetBytePtr(salt), CFDataGetLength(salt),
112                         interationCount,
113                         CFDataGetMutableBytePtr(derivedKey), CFDataGetLength(derivedKey));
114  
115  }