1 /* $OpenBSD: pbkdf2.c,v 1.2 2018/07/17 17:06:49 tb Exp $ */ 2 /* Written by Christian Heimes, 2013 */ 3 /* 4 * Copyright (c) 2013 The OpenSSL Project. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. All advertising materials mentioning features or use of this 19 * software must display the following acknowledgment: 20 * "This product includes software developed by the OpenSSL Project 21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 22 * 23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 24 * endorse or promote products derived from this software without 25 * prior written permission. For written permission, please contact 26 * openssl-core@openssl.org. 27 * 28 * 5. Products derived from this software may not be called "OpenSSL" 29 * nor may "OpenSSL" appear in their names without prior written 30 * permission of the OpenSSL Project. 31 * 32 * 6. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by the OpenSSL Project 35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 48 * OF THE POSSIBILITY OF SUCH DAMAGE. 49 */ 50 51 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <errno.h> 56 57 #include <openssl/opensslconf.h> 58 #include <openssl/evp.h> 59 #ifndef OPENSSL_NO_ENGINE 60 #include <openssl/engine.h> 61 #endif 62 #include <openssl/err.h> 63 #include <openssl/conf.h> 64 65 typedef struct { 66 const char *pass; 67 int passlen; 68 const char *salt; 69 int saltlen; 70 int iter; 71 } testdata; 72 73 static const testdata test_cases[] = { 74 {"password", 8, "salt", 4, 1}, 75 {"password", 8, "salt", 4, 2}, 76 {"password", 8, "salt", 4, 4096}, 77 {"passwordPASSWORDpassword", 24, 78 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096}, 79 {"pass\0word", 9, "sa\0lt", 5, 4096}, 80 {NULL}, 81 }; 82 83 static const char *sha1_results[] = { 84 "0c60c80f961f0e71f3a9b524af6012062fe037a6", 85 "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 86 "4b007901b765489abead49d926f721d065a429c1", 87 "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", 88 "56fa6aa75548099dcc37d7f03425e0c3", 89 }; 90 91 static const char *sha256_results[] = { 92 "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b", 93 "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43", 94 "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a", 95 "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c63551" 96 "8c7dac47e9", 97 "89b69d0516f829893c696226650a8687", 98 }; 99 100 static const char *sha512_results[] = { 101 "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d47" 102 "0a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce", 103 "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab" 104 "2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e", 105 "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30" 106 "602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5", 107 "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59" 108 "f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8", 109 "9d9e9c4cd21fe4be24d5b8244c759665", 110 }; 111 112 static void 113 hexdump(FILE *f, const char *title, const unsigned char *s, size_t len) 114 { 115 fprintf(f, "%s", title); 116 for (; len != 0; len--) 117 fprintf(f, " 0x%02x", *(s++)); 118 fprintf(f, "\n"); 119 } 120 121 static int 122 convert(unsigned char *dst, const unsigned char *src, size_t len) 123 { 124 unsigned int n; 125 126 for (; len != 0; src += 2, len--) { 127 if (sscanf((char *)src, "%2x", &n) != 1) 128 return EINVAL; 129 *dst++ = (unsigned char)n; 130 } 131 return 0; 132 } 133 134 static void 135 test_p5_pbkdf2(unsigned int n, const char *digestname, const testdata *test, 136 const char *hex) 137 { 138 const EVP_MD *digest; 139 unsigned char *out; 140 unsigned char *expected; 141 size_t keylen; 142 int r; 143 144 digest = EVP_get_digestbyname(digestname); 145 if (digest == NULL) { 146 fprintf(stderr, "unknown digest %s\n", digestname); 147 exit(5); 148 } 149 150 keylen = strlen(hex); 151 if ((keylen % 2) != 0) { 152 fprintf(stderr, "odd hex string %s, digest %u\n", digestname, n); 153 exit(5); 154 } 155 keylen /= 2; 156 expected = malloc(keylen); 157 out = malloc(keylen); 158 if (expected == NULL || out == NULL) { 159 fprintf(stderr, "malloc() failed\n"); 160 exit(5); 161 } 162 if (convert(expected, (const unsigned char *)hex, keylen) != 0) { 163 fprintf(stderr, "invalid hex string %s, digest %u\n", hex, n); 164 exit(5); 165 } 166 167 r = PKCS5_PBKDF2_HMAC(test->pass, test->passlen, 168 (const unsigned char *)test->salt, test->saltlen, 169 test->iter, digest, keylen, out); 170 171 if (r == 0) { 172 fprintf(stderr, "PKCS5_PBKDF2_HMAC(%s) failure test %u\n", 173 digestname, n); 174 exit(3); 175 } 176 if (memcmp(expected, out, keylen) != 0) { 177 fprintf(stderr, 178 "Wrong result for PKCS5_PBKDF2_HMAC(%s) test %u\n", 179 digestname, n); 180 hexdump(stderr, "expected: ", expected, keylen); 181 hexdump(stderr, "result: ", out, keylen); 182 exit(2); 183 } 184 free(expected); 185 free(out); 186 } 187 188 int 189 main(int argc,char **argv) 190 { 191 unsigned int n; 192 const testdata *test = test_cases; 193 194 OpenSSL_add_all_digests(); 195 #ifndef OPENSSL_NO_ENGINE 196 ENGINE_load_builtin_engines(); 197 ENGINE_register_all_digests(); 198 #endif 199 200 for (n = 0; test->pass != NULL; n++, test++) { 201 test_p5_pbkdf2(n, "sha1", test, sha1_results[n]); 202 test_p5_pbkdf2(n, "sha256", test, sha256_results[n]); 203 test_p5_pbkdf2(n, "sha512", test, sha512_results[n]); 204 } 205 206 #ifndef OPENSSL_NO_ENGINE 207 ENGINE_cleanup(); 208 #endif 209 EVP_cleanup(); 210 CRYPTO_cleanup_all_ex_data(); 211 ERR_remove_thread_state(NULL); 212 ERR_free_strings(); 213 return 0; 214 } 215