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