typedef krb5_error_code (*prf_fn)(krb5_key pass, krb5_data *salt,
krb5_data *out);
-/* Not exported, for now. */
-static krb5_error_code
-krb5int_pbkdf2 (prf_fn prf, size_t hlen, krb5_key pass,
- const krb5_data *salt, unsigned long count,
- const krb5_data *output);
-
static int debug_hmac = 0;
static void printd (const char *descr, krb5_data *d) {
printf("\n");
}
+/*
+ * Implements the hmac-sha1 PRF. pass has been pre-hashed (if
+ * necessary) and converted to a key already; salt has had the block
+ * index appended to the original salt.
+ */
+static krb5_error_code
+hmac(const struct krb5_hash_provider *hash, krb5_keyblock *pass,
+ krb5_data *salt, krb5_data *out)
+{
+ krb5_error_code err;
+ krb5_crypto_iov iov;
+
+ if (debug_hmac)
+ printd(" hmac input", salt);
+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
+ iov.data = *salt;
+ err = krb5int_hmac_keyblock(hash, pass, &iov, 1, out);
+ if (err == 0 && debug_hmac)
+ printd(" hmac output", out);
+ return err;
+}
+
static krb5_error_code
-F(char *output, char *u_tmp1, char *u_tmp2, prf_fn prf, size_t hlen,
- krb5_key pass, const krb5_data *salt, unsigned long count, int i)
+F(char *output, char *u_tmp1, char *u_tmp2,
+ const struct krb5_hash_provider *hash, size_t hlen, krb5_keyblock *pass,
+ const krb5_data *salt, unsigned long count, int i)
{
unsigned char ibytes[4];
size_t tlen;
#if 0
printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents);
#endif
- err = (*prf)(pass, &sdata, &out);
+ err = hmac(hash, pass, &sdata, &out);
if (err)
return err;
#if 0
printf("F: computing hmac #%d (U_%d)\n", j, j);
#endif
memcpy(u_tmp2, u_tmp1, hlen);
- err = (*prf)(pass, &sdata, &out);
+ err = hmac(hash, pass, &sdata, &out);
if (err)
return err;
#if 0
}
static krb5_error_code
-krb5int_pbkdf2 (prf_fn prf, size_t hlen, krb5_key pass,
- const krb5_data *salt, unsigned long count,
- const krb5_data *output)
+pbkdf2(const struct krb5_hash_provider *hash, krb5_keyblock *pass,
+ const krb5_data *salt, unsigned long count, const krb5_data *output)
{
+ size_t hlen = hash->hashsize;
int l, i;
char *utmp1, *utmp2;
- char utmp3[20]; /* XXX length shouldn't be hardcoded! */
+ char utmp3[128]; /* XXX length shouldn't be hardcoded! */
if (output->length == 0 || hlen == 0)
abort();
out = utmp3;
else
out = output->data + (i-1) * hlen;
- err = F(out, utmp1, utmp2, prf, hlen, pass, salt, count, i);
+ err = F(out, utmp1, utmp2, hash, hlen, pass, salt, count, i);
if (err) {
free(utmp1);
free(utmp2);
return 0;
}
-/*
- * Implements the hmac-sha1 PRF. pass has been pre-hashed (if
- * necessary) and converted to a key already; salt has had the block
- * index appended to the original salt.
- */
-static krb5_error_code
-hmac_sha1(krb5_key pass, krb5_data *salt, krb5_data *out)
-{
- const struct krb5_hash_provider *h = &krb5int_hash_sha1;
- krb5_error_code err;
- krb5_crypto_iov iov;
-
- if (debug_hmac)
- printd(" hmac input", salt);
- iov.flags = KRB5_CRYPTO_TYPE_DATA;
- iov.data = *salt;
- err = krb5int_hmac(h, pass, &iov, 1, out);
- if (err == 0 && debug_hmac)
- printd(" hmac output", out);
- return err;
-}
-
krb5_error_code
-krb5int_pbkdf2_hmac_sha1(const krb5_data *out, unsigned long count,
- const krb5_data *pass, const krb5_data *salt)
+krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash,
+ const krb5_data *out, unsigned long count,
+ const krb5_data *pass, const krb5_data *salt)
{
- const struct krb5_hash_provider *h = &krb5int_hash_sha1;
krb5_keyblock keyblock;
- krb5_key key;
- char tmp[40];
+ char tmp[128];
krb5_data d;
krb5_crypto_iov iov;
krb5_error_code err;
- assert(h->hashsize <= sizeof(tmp));
- if (pass->length > h->blocksize) {
- d = make_data(tmp, h->hashsize);
+ assert(hash->hashsize <= sizeof(tmp));
+ if (pass->length > hash->blocksize) {
+ d = make_data(tmp, hash->hashsize);
iov.flags = KRB5_CRYPTO_TYPE_DATA;
iov.data = *pass;
- err = h->hash(&iov, 1, &d);
+ err = hash->hash(&iov, 1, &d);
if (err)
return err;
keyblock.length = d.length;
}
keyblock.enctype = ENCTYPE_NULL;
- err = krb5_k_create_key(NULL, &keyblock, &key);
- if (err)
- return err;
-
- err = krb5int_pbkdf2(hmac_sha1, 20, key, salt, count, out);
- krb5_k_free_key(NULL, key);
+ err = pbkdf2(hash, &keyblock, salt, count, out);
return err;
}
#include <openssl/hmac.h>
krb5_error_code
-krb5int_pbkdf2_hmac_sha1 (const krb5_data *out, unsigned long count,
- const krb5_data *pass, const krb5_data *salt)
+krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash,
+ const krb5_data *out, unsigned long count,
+ const krb5_data *pass, const krb5_data *salt)
{
-/*
- * This is an implementation of PKCS#5 v2.0
- * Does not return an error
- */
- PKCS5_PBKDF2_HMAC_SHA1(pass->data, pass->length,
- (unsigned char *)salt->data, salt->length, count,
- out->length, (unsigned char *)out->data);
+ const EVP_MD *md = NULL;
+
+ /* Get the message digest handle corresponding to the hash. */
+ if (hash == &krb5int_hash_sha1)
+ md = EVP_sha1();
+ else if (hash == &krb5int_hash_sha256)
+ md = EVP_sha256();
+ else if (hash == &krb5int_hash_sha384)
+ md = EVP_sha384();
+ if (md == NULL)
+ return KRB5_CRYPTO_INTERNAL;
+
+ PKCS5_PBKDF2_HMAC(pass->data, pass->length, (unsigned char *)salt->data,
+ salt->length, count, md, out->length,
+ (unsigned char *)out->data);
return 0;
}