blob: e3ba616f16916dc0d1adae94f3365ebdc2b1bcd0 [file] [log] [blame]
Eric Romanbcc4fa82015-01-28 12:23:34 -08001/* Copyright (c) 2015, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <stdio.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080016#include <string.h>
Eric Romanbcc4fa82015-01-28 12:23:34 -080017
18#include <openssl/bio.h>
19#include <openssl/crypto.h>
20#include <openssl/digest.h>
21#include <openssl/err.h>
22#include <openssl/evp.h>
23
24
25/* Prints out the data buffer as a sequence of hex bytes */
26static void print_data_hex(const void *data, size_t len) {
27 size_t i;
28 for (i = 0; i < len; ++i) {
29 fprintf(stderr, "%02x", (int)((const uint8_t *)data)[i]);
30 }
31}
32
33/* Helper for testing that PBKDF2 derives the expected key from the given
34 * inputs. Returns 1 on success, 0 otherwise. */
35static int test_PBKDF2(const void *password, size_t password_len,
36 const void *salt, size_t salt_len, unsigned iterations,
37 const EVP_MD *digest, size_t key_len,
38 const uint8_t *expected_key) {
39 uint8_t key[64];
40
41 if (key_len > sizeof(key)) {
42 fprintf(stderr, "Output buffer is not large enough.\n");
43 return 0;
44 }
45
46 if (!PKCS5_PBKDF2_HMAC(password, password_len, salt, salt_len, iterations,
47 digest, key_len, key)) {
48 fprintf(stderr, "Call to PKCS5_PBKDF2_HMAC failed\n");
49 BIO_print_errors_fp(stderr);
50 return 0;
51 }
52
53 if (memcmp(key, expected_key, key_len) != 0) {
54 fprintf(stderr, "Resulting key material does not match expectation\n");
55 fprintf(stderr, "Expected:\n ");
56 print_data_hex(expected_key, key_len);
57 fprintf(stderr, "\nActual:\n ");
58 print_data_hex(key, key_len);
59 fprintf(stderr, "\n");
60 return 0;
61 }
62
63 return 1;
64}
65
66/* Tests deriving a key using an empty password (specified both as NULL and as
67 * non-NULL). Note that NULL has special meaning to HMAC initialization. */
68static int test_empty_password(void) {
69 const uint8_t kKey[] = {0xa3, 0x3d, 0xdd, 0xc3, 0x04, 0x78, 0x18,
70 0x55, 0x15, 0x31, 0x1f, 0x87, 0x52, 0x89,
71 0x5d, 0x36, 0xea, 0x43, 0x63, 0xa2};
72
73 if (!test_PBKDF2(NULL, 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey) ||
74 !test_PBKDF2("", 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey)) {
75 return 0;
76 }
77
78 return 1;
79}
80
81/* Tests deriving a key using an empty salt. Note that the expectation was
82 * generated using OpenSSL itself, and hence is not verified. */
83static int test_empty_salt(void) {
84 const uint8_t kKey[] = {0x8b, 0xc2, 0xf9, 0x16, 0x7a, 0x81, 0xcd, 0xcf,
85 0xad, 0x12, 0x35, 0xcd, 0x90, 0x47, 0xf1, 0x13,
86 0x62, 0x71, 0xc1, 0xf9, 0x78, 0xfc, 0xfc, 0xb3,
87 0x5e, 0x22, 0xdb, 0xea, 0xfa, 0x46, 0x34, 0xf6};
88
89 if (!test_PBKDF2("password", 8, NULL, 0, 2, EVP_sha256(), sizeof(kKey),
90 kKey) ||
91 !test_PBKDF2("password", 8, "", 0, 2, EVP_sha256(), sizeof(kKey), kKey)) {
92 return 0;
93 }
94
95 return 1;
96}
97
98/* Exercises test vectors taken from https://tools.ietf.org/html/rfc6070.
99 * Note that each of these test vectors uses SHA-1 as the digest. */
100static int test_rfc6070_vectors(void) {
101 const uint8_t kKey1[] = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e,
102 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60,
103 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6};
104 const uint8_t kKey2[] = {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f,
105 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d,
106 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57};
107 const uint8_t kKey3[] = {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
108 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3};
109
110 if (!test_PBKDF2("password", 8, "salt", 4, 1, EVP_sha1(), sizeof(kKey1),
111 kKey1) ||
112 !test_PBKDF2("password", 8, "salt", 4, 2, EVP_sha1(), sizeof(kKey2),
113 kKey2) ||
114 !test_PBKDF2("pass\0word", 9, "sa\0lt", 5, 4096, EVP_sha1(),
115 sizeof(kKey3), kKey3)) {
116 return 0;
117 }
118
119 return 1;
120}
121
122/* Tests key derivation using SHA-2 digests */
123static int test_sha2(void) {
124 /* This test was taken from:
125 * http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors */
126 const uint8_t kKey1[] = {0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
127 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
128 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
129 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43};
130
131 /* This test was taken from:
132 * http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors */
133 const uint8_t kKey2[] = {
134 0x8c, 0x05, 0x11, 0xf4, 0xc6, 0xe5, 0x97, 0xc6, 0xac, 0x63, 0x15,
135 0xd8, 0xf0, 0x36, 0x2e, 0x22, 0x5f, 0x3c, 0x50, 0x14, 0x95, 0xba,
136 0x23, 0xb8, 0x68, 0xc0, 0x05, 0x17, 0x4d, 0xc4, 0xee, 0x71, 0x11,
137 0x5b, 0x59, 0xf9, 0xe6, 0x0c, 0xd9, 0x53, 0x2f, 0xa3, 0x3e, 0x0f,
138 0x75, 0xae, 0xfe, 0x30, 0x22, 0x5c, 0x58, 0x3a, 0x18, 0x6c, 0xd8,
139 0x2b, 0xd4, 0xda, 0xea, 0x97, 0x24, 0xa3, 0xd3, 0xb8};
140
141 if (!test_PBKDF2("password", 8, "salt", 4, 2, EVP_sha256(), sizeof(kKey1),
142 kKey1) ||
143 !test_PBKDF2("passwordPASSWORDpassword", 24,
144 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096,
145 EVP_sha512(), sizeof(kKey2), kKey2)) {
146 return 0;
147 }
148
149 return 1;
150}
151
152int main(void) {
153 CRYPTO_library_init();
154 ERR_load_crypto_strings();
155
156 if (!test_empty_password()) {
157 fprintf(stderr, "test_empty_password failed\n");
158 return 1;
159 }
160
161 if (!test_empty_salt()) {
162 fprintf(stderr, "test_empty_salt failed\n");
163 return 1;
164 }
165
166 if (!test_rfc6070_vectors()) {
167 fprintf(stderr, "test_rfc6070_vectors failed\n");
168 return 1;
169 }
170
171 if (!test_sha2()) {
172 fprintf(stderr, "test_sha2 failed\n");
173 return 1;
174 }
175
176 printf("PASS\n");
177 ERR_free_strings();
178 return 0;
179}