1 /* $OpenBSD: pbkdf2.c,v 1.3 2023/11/19 13:11:06 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 #include <openssl/err.h> 60 #include <openssl/conf.h> 61 62 typedef struct { 63 const char *pass; 64 int passlen; 65 const char *salt; 66 int saltlen; 67 int iter; 68 } testdata; 69 70 static const testdata test_cases[] = { 71 {"password", 8, "salt", 4, 1}, 72 {"password", 8, "salt", 4, 2}, 73 {"password", 8, "salt", 4, 4096}, 74 {"passwordPASSWORDpassword", 24, 75 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096}, 76 {"pass\0word", 9, "sa\0lt", 5, 4096}, 77 {NULL}, 78 }; 79 80 static const char *sha1_results[] = { 81 "0c60c80f961f0e71f3a9b524af6012062fe037a6", 82 "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 83 "4b007901b765489abead49d926f721d065a429c1", 84 "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", 85 "56fa6aa75548099dcc37d7f03425e0c3", 86 }; 87 88 static const char *sha256_results[] = { 89 "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b", 90 "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43", 91 "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a", 92 "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c63551" 93 "8c7dac47e9", 94 "89b69d0516f829893c696226650a8687", 95 }; 96 97 static const char *sha512_results[] = { 98 "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d47" 99 "0a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce", 100 "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab" 101 "2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e", 102 "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30" 103 "602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5", 104 "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59" 105 "f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8", 106 "9d9e9c4cd21fe4be24d5b8244c759665", 107 }; 108 109 static void 110 hexdump(FILE *f, const char *title, const unsigned char *s, size_t len) 111 { 112 fprintf(f, "%s", title); 113 for (; len != 0; len--) 114 fprintf(f, " 0x%02x", *(s++)); 115 fprintf(f, "\n"); 116 } 117 118 static int 119 convert(unsigned char *dst, const unsigned char *src, size_t len) 120 { 121 unsigned int n; 122 123 for (; len != 0; src += 2, len--) { 124 if (sscanf((char *)src, "%2x", &n) != 1) 125 return EINVAL; 126 *dst++ = (unsigned char)n; 127 } 128 return 0; 129 } 130 131 static void 132 test_p5_pbkdf2(unsigned int n, const char *digestname, const testdata *test, 133 const char *hex) 134 { 135 const EVP_MD *digest; 136 unsigned char *out; 137 unsigned char *expected; 138 size_t keylen; 139 int r; 140 141 digest = EVP_get_digestbyname(digestname); 142 if (digest == NULL) { 143 fprintf(stderr, "unknown digest %s\n", digestname); 144 exit(5); 145 } 146 147 keylen = strlen(hex); 148 if ((keylen % 2) != 0) { 149 fprintf(stderr, "odd hex string %s, digest %u\n", digestname, n); 150 exit(5); 151 } 152 keylen /= 2; 153 expected = malloc(keylen); 154 out = malloc(keylen); 155 if (expected == NULL || out == NULL) { 156 fprintf(stderr, "malloc() failed\n"); 157 exit(5); 158 } 159 if (convert(expected, (const unsigned char *)hex, keylen) != 0) { 160 fprintf(stderr, "invalid hex string %s, digest %u\n", hex, n); 161 exit(5); 162 } 163 164 r = PKCS5_PBKDF2_HMAC(test->pass, test->passlen, 165 (const unsigned char *)test->salt, test->saltlen, 166 test->iter, digest, keylen, out); 167 168 if (r == 0) { 169 fprintf(stderr, "PKCS5_PBKDF2_HMAC(%s) failure test %u\n", 170 digestname, n); 171 exit(3); 172 } 173 if (memcmp(expected, out, keylen) != 0) { 174 fprintf(stderr, 175 "Wrong result for PKCS5_PBKDF2_HMAC(%s) test %u\n", 176 digestname, n); 177 hexdump(stderr, "expected: ", expected, keylen); 178 hexdump(stderr, "result: ", out, keylen); 179 exit(2); 180 } 181 free(expected); 182 free(out); 183 } 184 185 int 186 main(int argc,char **argv) 187 { 188 unsigned int n; 189 const testdata *test = test_cases; 190 191 OpenSSL_add_all_digests(); 192 193 for (n = 0; test->pass != NULL; n++, test++) { 194 test_p5_pbkdf2(n, "sha1", test, sha1_results[n]); 195 test_p5_pbkdf2(n, "sha256", test, sha256_results[n]); 196 test_p5_pbkdf2(n, "sha512", test, sha512_results[n]); 197 } 198 199 EVP_cleanup(); 200 CRYPTO_cleanup_all_ex_data(); 201 ERR_remove_thread_state(NULL); 202 ERR_free_strings(); 203 return 0; 204 } 205