1/* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * 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 the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include <config.h> 35 36#ifdef KRB5 37#include <krb5-types.h> 38#endif 39 40#ifdef HAVE_COMMONCRYPTO_COMMONKEYDERIVATION_H 41#include <CommonCrypto/CommonKeyDerivation.h> 42#endif 43 44#include <stdio.h> 45#include <stdlib.h> 46 47#include <evp.h> 48#include <hmac.h> 49 50#include <roken.h> 51 52/** 53 * As descriped in PKCS5, convert a password, salt, and iteration counter into a crypto key. 54 * 55 * @param password Password. 56 * @param password_len Length of password. 57 * @param salt Salt 58 * @param salt_len Length of salt. 59 * @param iter iteration counter. 60 * @param keylen the output key length. 61 * @param key the output key. 62 * 63 * @return 1 on success, non 1 on failure. 64 * 65 * @ingroup hcrypto_misc 66 */ 67 68int 69PKCS5_PBKDF2_HMAC_SHA1(const void * password, size_t password_len, 70 const void * salt, size_t salt_len, 71 unsigned long iter, 72 size_t keylen, void *key) 73{ 74#ifdef HAVE_COMMONCRYPTO_COMMONKEYDERIVATION_H 75 if (CCKeyDerivationPBKDF(kCCPBKDF2, password, password_len, 76 salt, salt_len, 77 kCCPRFHmacAlgSHA1, iter, 78 key, keylen) != 0) 79 return 0; 80 return 1; 81#else 82 size_t datalen, leftofkey, checksumsize; 83 char *data, *tmpcksum; 84 uint32_t keypart; 85 const EVP_MD *md; 86 unsigned long i; 87 int j; 88 char *p; 89 unsigned int hmacsize; 90 91 md = EVP_sha1(); 92 checksumsize = EVP_MD_size(md); 93 datalen = salt_len + 4; 94 95 tmpcksum = malloc(checksumsize + datalen); 96 if (tmpcksum == NULL) 97 return 0; 98 99 data = &tmpcksum[checksumsize]; 100 101 memcpy(data, salt, salt_len); 102 103 keypart = 1; 104 leftofkey = keylen; 105 p = key; 106 107 while (leftofkey) { 108 int len; 109 110 if (leftofkey > checksumsize) 111 len = checksumsize; 112 else 113 len = leftofkey; 114 115 data[datalen - 4] = (keypart >> 24) & 0xff; 116 data[datalen - 3] = (keypart >> 16) & 0xff; 117 data[datalen - 2] = (keypart >> 8) & 0xff; 118 data[datalen - 1] = (keypart) & 0xff; 119 120 HMAC(md, password, password_len, data, datalen, 121 tmpcksum, &hmacsize); 122 123 memcpy(p, tmpcksum, len); 124 for (i = 1; i < iter; i++) { 125 HMAC(md, password, password_len, tmpcksum, checksumsize, 126 tmpcksum, &hmacsize); 127 128 for (j = 0; j < len; j++) 129 p[j] ^= tmpcksum[j]; 130 } 131 132 p += len; 133 leftofkey -= len; 134 keypart++; 135 } 136 137 free(tmpcksum); 138 139 return 1; 140#endif 141} 142