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
13#include <string.h>
14
15/* CC Based HMAC PRF functions */
16void hmac_sha1_PRF(const uint8_t *key,
17                   size_t key_len,
18                   const uint8_t *text,
19                   size_t text_len,
20                   uint8_t digest[CC_SHA1_DIGEST_LENGTH])
21{
22    CCHmacContext hmac_sha1_context;
23
24    CCHmacInit(&hmac_sha1_context, kCCHmacAlgSHA1, key, key_len);
25    CCHmacUpdate(&hmac_sha1_context, text, text_len);
26    CCHmacFinal(&hmac_sha1_context, digest);
27}
28
29
30/* This implements the HMAC SHA-1 version of pbkdf2 and allocates a local buffer for the HMAC */
31void pbkdf2_hmac_sha1(const uint8_t *passwordPtr, size_t passwordLen,
32                      const uint8_t *saltPtr, size_t saltLen,
33                      uint32_t iterationCount,
34                      void *dkPtr, size_t dkLen)
35{
36    // MAX(salt_length + 4, 20 /* SHA1 Digest size */) + 2 * 20;
37    // salt_length + HASH_SIZE is bigger than either salt + 4 and digestSize.
38    const size_t kBigEnoughSize = (saltLen + CC_SHA1_DIGEST_LENGTH) + 2 * CC_SHA1_DIGEST_LENGTH;
39    uint8_t temp_data[kBigEnoughSize];
40
41    pbkdf2(hmac_sha1_PRF, CC_SHA1_DIGEST_LENGTH,
42           passwordPtr, passwordLen,
43           saltPtr, saltLen,
44           iterationCount,
45           dkPtr, dkLen,
46           temp_data);
47
48    bzero(temp_data, kBigEnoughSize);
49}
50
51
52void SecKeyFromPassphraseDataHMACSHA1(CFDataRef password, CFDataRef salt, uint32_t interationCount, CFMutableDataRef derivedKey)
53{
54    pbkdf2_hmac_sha1(CFDataGetBytePtr(password), CFDataGetLength(password),
55                     CFDataGetBytePtr(salt), CFDataGetLength(salt),
56                     interationCount,
57                     CFDataGetMutableBytePtr(derivedKey), CFDataGetLength(derivedKey));
58
59}
60