1/*
2 * Copyright (c) 2010,2012 Apple Inc. All Rights Reserved.
3 */
4
5#include <CoreFoundation/CoreFoundation.h>
6#include <Security/SecItem.h>
7#include <Security/SecBase.h>
8#include <CommonCrypto/CommonHMAC.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <Security/pbkdf2.h>
12
13#include "Security_regressions.h"
14
15static
16void
17hmac_sha1(const uint8_t *key, size_t key_len, const uint8_t *text, size_t text_len,
18    uint8_t digest[CC_SHA1_DIGEST_LENGTH])
19{
20    CCHmacContext hmac_sha1_context;
21
22    CCHmacInit(&hmac_sha1_context, kCCHmacAlgSHA1, key, key_len);
23    CCHmacUpdate(&hmac_sha1_context, text, text_len);
24    CCHmacFinal(&hmac_sha1_context, digest);
25}
26
27static
28void
29pbkdf2_hmac_sha1_deriviation(const uint8_t *passphrase, size_t passphrase_length,
30                             const uint8_t *salt, size_t salt_length,
31                             size_t iterations,
32                             uint8_t *key_out, size_t key_length)
33{
34        // MAX(salt_length + 4, 20 /* SHA1 Digest size */) + 2 * 20;
35    uint8_t temp_data[3*20+salt_length];
36
37    pbkdf2(hmac_sha1, 20, passphrase, passphrase_length,
38                   salt, salt_length, iterations, key_out, key_length, temp_data);
39}
40
41
42
43#if 0
44static void
45printComparison(const uint8_t*left, const uint8_t* right, int length)
46{
47    int i;
48    for(i = 0; i < length; ++i)
49    {
50        fprintf(stderr, "#  Values :: 0x%02x :: 0x%02x\n", left[i], right[i]);
51    }
52}
53#endif
54
55static int kTestTestCount = 4;
56static void tests(void)
57{
58    {
59        const char *password =          "password";
60        const char *salt =              "salt";
61        const int iterations =          1;
62        const uint8_t expected[20] =  { 0x0c, 0x60, 0xc8, 0x0f,
63                                        0x96, 0x1f, 0x0e, 0x71,
64                                        0xf3, 0xa9, 0xb5, 0x24,
65                                        0xaf, 0x60, 0x12, 0x06,
66                                        0x2f, 0xe0, 0x37, 0xa6 };
67
68        const char resultSize = sizeof(expected);
69
70        uint8_t actual[resultSize];
71
72        pbkdf2_hmac_sha1_deriviation((const uint8_t*) password, strlen(password), (const uint8_t*) salt, strlen(salt), iterations, actual, resultSize);
73
74        ok(memcmp(expected, actual, resultSize) == 0, "pbkdf-sha-1: P-'password' S-'Salt' I-1");
75    }
76
77    {
78        const char *password =          "password";
79        const char *salt =              "salt";
80        const int iterations =          2;
81        const uint8_t expected[20] =  { 0xea, 0x6c, 0x01, 0x4d,
82                                        0xc7, 0x2d, 0x6f, 0x8c,
83                                        0xcd, 0x1e, 0xd9, 0x2a,
84                                        0xce, 0x1d, 0x41, 0xf0,
85                                        0xd8, 0xde, 0x89, 0x57 };
86
87        const char resultSize = sizeof(expected);
88
89        uint8_t actual[resultSize];
90
91        pbkdf2_hmac_sha1_deriviation((const uint8_t*) password, strlen(password), (const uint8_t*) salt, strlen(salt), iterations, actual, resultSize);
92
93        ok(memcmp(expected, actual, resultSize) == 0, "pbkdf-sha-1: P-'password' S-'Salt' I-2");
94    }
95
96    {
97        const char *password =          "password";
98        const char *salt =              "salt";
99        const int iterations =          4096;
100        const uint8_t expected[20] =  { 0x4b, 0x00, 0x79, 0x01,
101                                        0xb7, 0x65, 0x48, 0x9a,
102                                        0xbe, 0xad, 0x49, 0xd9,
103                                        0x26, 0xf7, 0x21, 0xd0,
104                                        0x65, 0xa4, 0x29, 0xc1 };
105
106        const char resultSize = sizeof(expected);
107
108        uint8_t actual[resultSize];
109
110        pbkdf2_hmac_sha1_deriviation((const uint8_t*) password, strlen(password), (const uint8_t*) salt, strlen(salt), iterations, actual, resultSize);
111
112        ok(memcmp(expected, actual, resultSize) == 0, "pbkdf-sha-1: P-'password' S-'Salt' I-4096");
113    }
114
115    SKIP: {
116        skip("16777216 iterations is too slow", 1, 0);
117
118        const char *password =          "password";
119        const char *salt =              "salt";
120        const int iterations =          16777216;
121        const uint8_t expected[20] =  { 0xee, 0xfe, 0x3d, 0x61,
122                                        0xcd, 0x4d, 0xa4, 0xe4,
123                                        0xe9, 0x94, 0x5b, 0x3d,
124                                        0x6b, 0xa2, 0x15, 0x8c,
125                                        0x26, 0x34, 0xe9, 0x84 };
126
127        const char resultSize = sizeof(expected);
128
129        uint8_t actual[resultSize];
130
131        pbkdf2_hmac_sha1_deriviation((const uint8_t*) password, strlen(password), (const uint8_t*) salt, strlen(salt), iterations, actual, resultSize);
132
133        ok(memcmp(expected, actual, resultSize) == 0, "pbkdf-sha-1: P-'password' S-'Salt' I-16777216");
134    }
135}
136
137int pbkdf2_00_hmac_sha1(int argc, char *const *argv)
138{
139	plan_tests(kTestTestCount);
140
141	tests();
142
143	return 0;
144}
145