From: Ken Raeburn Date: Thu, 10 Oct 2002 02:41:52 +0000 (+0000) Subject: * pbkdf2.c, t_hmac.c, t_pkcs5.c: New files X-Git-Tag: krb5-1.3-alpha1~335 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=3285e55e5b6ca3c76fc03a5b71357ea432422476;p=krb5.git * pbkdf2.c, t_hmac.c, t_pkcs5.c: New files git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14916 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/crypto/ChangeLog b/src/lib/crypto/ChangeLog index 2fc031488..15efc059d 100644 --- a/src/lib/crypto/ChangeLog +++ b/src/lib/crypto/ChangeLog @@ -1,3 +1,7 @@ +2002-10-09 Ken Raeburn + + * pbkdf2.c, t_hmac.c, t_pkcs5.c: New files. + 2002-08-29 Ken Raeburn * Makefile.in: Revert $(S)=>/ change, for Windows support. diff --git a/src/lib/crypto/pbkdf2.c b/src/lib/crypto/pbkdf2.c new file mode 100644 index 000000000..b5d0bfcae --- /dev/null +++ b/src/lib/crypto/pbkdf2.c @@ -0,0 +1,280 @@ +/* + * lib/crypto/pbkdf2.c + * + * Copyright 2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Implementation of PBKDF2 from RFC 2898. + * Not currently used; likely to be used when we get around to AES support. + */ + +#include +#include "k5-int.h" +#include "hash_provider.h" + +/* for k5-int.h */ +extern krb5_error_code +krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, + krb5_data *), + size_t hlen, const char *pass, const char *salt, + unsigned long count, size_t dklen, char *output); +extern krb5_error_code +krb5int_pbkdf2_hmac_sha1 (char *out, size_t len, unsigned long count, + const char *pass, const char *salt); +extern krb5_error_code +krb5int_pbkdf2_hmac_sha1_128 (char *out, unsigned long count, + const char *pass, const char *salt); +extern krb5_error_code +krb5int_pbkdf2_hmac_sha1_256 (char *out, unsigned long count, + const char *pass, const char *salt); + + + + +static int debug_hmac = 0; + +static void printd (const char *descr, krb5_data *d) { + int i, j; + const int r = 16; + + printf("%s:", descr); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + d.data = k->contents; + d.length = k->length; + printd(descr, &d); +} + +static krb5_error_code +F(char *output, char *u_tmp1, char *u_tmp2, + krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, krb5_data *), + size_t hlen, + const char *pass, const char *salt, + unsigned long count, int i) +{ + unsigned char ibytes[4]; + size_t tlen; + int j, k; + krb5_keyblock pdata; + krb5_data sdata; + krb5_data out; + krb5_error_code err; + + pdata.contents = pass; + pdata.length = strlen(pass); + +#if 0 + printf("F(i=%d, count=%lu, pass=%s)\n", i, count, pass); + printk("F password", &pdata); +#endif + + /* Compute U_1. */ + ibytes[3] = i & 0xff; + ibytes[2] = (i >> 8) & 0xff; + ibytes[1] = (i >> 16) & 0xff; + ibytes[0] = (i >> 24) & 0xff; + + tlen = strlen(salt); + memcpy(u_tmp2, salt, tlen); + memcpy(u_tmp2 + tlen, ibytes, 4); + tlen += 4; + sdata.data = u_tmp2; + sdata.length = tlen; + +#if 0 + printd("initial salt", &sdata); +#endif + + out.data = u_tmp1; + out.length = hlen; + +#if 0 + printf("F: computing hmac #1 (U_1) with %s\n", pdata.contents); +#endif + err = (*prf)(&pdata, &sdata, &out); + if (err) + return err; +#if 0 + printd("F: prf return value", &out); +#endif + memcpy(output, u_tmp1, hlen); + + /* Compute U_2, .. U_c. */ + sdata.length = hlen; + for (j = 2; j <= count; j++) { +#if 0 + printf("F: computing hmac #%d (U_%d)\n", j, j); +#endif + memcpy(u_tmp2, u_tmp1, hlen); + err = (*prf)(&pdata, &sdata, &out); + if (err) + return err; +#if 0 + printd("F: prf return value", &out); +#endif + /* And xor them together. */ + for (k = 0; k < hlen; k++) + output[k] ^= u_tmp1[k]; +#if 0 + printf("F: xor result:\n"); + for (k = 0; k < hlen; k++) + printf(" %02x", 0xff & output[k]); + printf("\n"); +#endif + } + return 0; +} + +krb5_error_code +krb5int_pbkdf2 (krb5_error_code (*prf)(krb5_keyblock *, krb5_data *, + krb5_data *), + size_t hlen, + const char *pass, const char *salt, + unsigned long count, size_t dklen, + char *output) +{ + int l, r, i; + char *utmp1, *utmp2; + + if (dklen == 0 || hlen == 0) + abort(); + /* Step 1 & 2. */ + if (dklen / hlen > 0xffffffff) + abort(); + /* Step 2. */ + l = (dklen + hlen - 1) / hlen; + r = dklen - (l - 1) * hlen; + +#if 0 + output = malloc(dklen + hlen + strlen(salt) + 4 + hlen); + if (output == NULL) { + abort(); + } +#endif + utmp1 = /*output + dklen; */ malloc(hlen); + utmp2 = /*utmp1 + hlen; */ malloc(strlen(salt) + 4 + hlen); + + /* Step 3. */ + for (i = 1; i <= l; i++) { +#if 0 + int j; +#endif + krb5_error_code err; + + err = F(output + (i-1) * hlen, utmp1, utmp2, prf, hlen, + pass, salt, count, i); + if (err) + return err; + +#if 0 + printf("after F(%d), @%p:\n", i, output); + for (j = (i-1) * hlen; j < i * hlen; j++) + printf(" %02x", 0xff & output[j]); + printf ("\n"); +#endif + } + return 0; +} + +static krb5_error_code hmac1(const struct krb5_hash_provider *h, + krb5_keyblock *key, krb5_data *in, krb5_data *out) +{ + char tmp[40]; + size_t blocksize, hashsize; + krb5_error_code err; + + if (debug_hmac) + printk(" test key", key); + h->block_size(&blocksize); + h->hash_size(&hashsize); + if (hashsize > sizeof(tmp)) + abort(); + if (key->length > blocksize) { + krb5_data d, d2; + d.data = key->contents; + d.length = key->length; + d2.data = tmp; + d2.length = hashsize; + err = h->hash (1, &d, &d2); + if (err) + return err; + key->length = d2.length; + key->contents = d2.data; + if (debug_hmac) + printk(" pre-hashed key", key); + } + if (debug_hmac) + printd(" hmac input", in); + err = krb5_hmac(h, key, 1, in, out); + if (err == 0 && debug_hmac) + printd(" hmac output", out); + return err; +} + +static krb5_error_code +foo(krb5_keyblock *pass, krb5_data *salt, krb5_data *out) +{ + krb5_error_code err; + + memset(out->data, 0, out->length); + err = hmac1 (&krb5int_hash_sha1, pass, salt, out); + if (err) + com_err("foo", err, "computing hmac"); + return err; +} + +krb5_error_code +krb5int_pbkdf2_hmac_sha1 (char *out, size_t len, unsigned long count, + const char *pass, const char *salt) +{ + return krb5int_pbkdf2 (foo, 20, pass, salt, count, len, out); +} + +krb5_error_code +krb5int_pbkdf2_hmac_sha1_128 (char *out, unsigned long count, + const char *pass, const char *salt) +{ + return krb5int_pbkdf2 (foo, 20, pass, salt, count, 16, out); +} + +krb5_error_code +krb5int_pbkdf2_hmac_sha1_256 (char *out, unsigned long count, + const char *pass, const char *salt) +{ + return krb5int_pbkdf2 (foo, 20, pass, salt, count, 32, out); +} diff --git a/src/lib/crypto/t_hmac.c b/src/lib/crypto/t_hmac.c new file mode 100644 index 000000000..69ca42ad2 --- /dev/null +++ b/src/lib/crypto/t_hmac.c @@ -0,0 +1,351 @@ +/* + * lib/crypto/t_hmac.c + * + * Copyright 2001,2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Test vectors for HMAC-MD5 and HMAC-SHA1 (placeholder only). + * Tests taken from RFC 2202. + */ + +#include +#include +#include +#include + +#include +#include "hash_provider.h" + +#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +const char *whoami; + +static void printhex (size_t len, const char *p) { + while (len--) + printf ("%02x", 0xff & *p++); +} + +static void printstringhex (const char *p) { printhex (strlen (p), p); } + +static void printdata (krb5_data *d) { printhex (d->length, d->data); } + +static void printkey (krb5_keyblock *k) { printhex (k->length, k->contents); } + +static void keyToData (krb5_keyblock *k, krb5_data *d) { + d->length = k->length; + d->data = k->contents; +} + +static void check_error (int r, int line) { + if (r != 0) { + fprintf (stderr, "%s:%d: %s\n", __FILE__, line, + error_message (r)); + exit (1); + } +} +#define CHECK check_error(r, __LINE__) + +static void printd (const char *descr, krb5_data *d) { + int i, j; + const int r = 16; + + printf("%s (%d bytes):", descr, d->length); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + keyToData(k,&d); + printd(descr, &d); +} + + + +struct hmac_test { + int key_len; + unsigned char key[180]; + int data_len; + unsigned char data[80]; + const char *hexdigest; +}; + +static krb5_error_code hmac1(struct krb5_hash_provider *h, krb5_keyblock *key, + krb5_data *in, krb5_data *out) +{ + char tmp[40]; + size_t blocksize, hashsize; + krb5_error_code err; + + printk(" test key", key); + h->block_size(&blocksize); + h->hash_size(&hashsize); + if (hashsize > sizeof(tmp)) + abort(); + if (key->length > blocksize) { + krb5_data d, d2; + d.data = key->contents; + d.length = key->length; + d2.data = tmp; + d2.length = hashsize; + err = h->hash (1, &d, &d2); + if (err) { + com_err(whoami, err, "hashing key before calling hmac"); + exit(1); + } + key->length = d2.length; + key->contents = d2.data; + printk(" pre-hashed key", key); + } + printd(" hmac input", in); + err = krb5_hmac(h, key, 1, in, out); + if (err == 0) + printd(" hmac output", out); + return err; +} + +static void test_hmac() +{ + krb5_keyblock key; + krb5_data in, out; + char outbuf[20]; + char stroutbuf[80]; + krb5_error_code err; + int i, j; + int lose = 0; + + /* RFC 2202 test vector. */ + static const struct hmac_test md5tests[] = { + { + 16, { + 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, + 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, + }, + 8, "Hi There", + "0x9294727a3638bb1c13f48ef8158bfc9d" + }, + + { + 4, "Jefe", + 28, "what do ya want for nothing?", + "0x750c783e6ab0b503eaa86e310a5db738" + }, + + { + 16, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + }, + 50, { + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + }, + "0x56be34521d144c88dbb8c733f0e8b3f6" + }, + + { + 25, { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19 + }, + 50, { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + }, + "0x697eaf0aca3a3aea3a75164746ffaa79" + }, + + { + 16, { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c + }, + 20, "Test With Truncation", + "0x56461ef2342edc00f9bab995690efd4c" + }, + + { + 80, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + 54, "Test Using Larger Than Block-Size Key - Hash Key First", + "0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" + }, + + { + 80, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + 73, ("Test Using Larger Than Block-Size Key and Larger " + "Than One Block-Size Data"), + "0x6f630fad67cda0ee1fb1f562db3aa53e" + }, + }, sha1tests[] = { + { +/* +test_case = 1 +key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +key_len = 20 +data = "Hi There" +data_len = 8 +digest = 0xb617318655057264e28bc0b6fb378c8ef146be00 + +test_case = 2 +key = "Jefe" +key_len = 4 +data = "what do ya want for nothing?" +data_len = 28 +digest = 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 + +test_case = 3 +key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +key_len = 20 +data = 0xdd repeated 50 times +data_len = 50 +digest = 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3 + +test_case = 4 +key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819 +key_len = 25 +data = 0xcd repeated 50 times +data_len = 50 +digest = 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da + +test_case = 5 +key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +key_len = 20 +data = "Test With Truncation" +data_len = 20 +digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 + +test_case = 6 +key = 0xaa repeated 80 times +key_len = 80 +data = "Test Using Larger Than Block-Size Key - Hash Key First" +data_len = 54 +digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 + +test_case = 7 +key = 0xaa repeated 80 times +key_len = 80 +data = "Test Using Larger Than Block-Size Key and Larger + Than One Block-Size Data" +data_len = 73 +digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 +data_len = 20 +digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 + +test_case = 6 +key = 0xaa repeated 80 times +key_len = 80 +data = "Test Using Larger Than Block-Size Key - Hash Key First" +data_len = 54 +digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 + +test_case = 7 +key = 0xaa repeated 80 times +key_len = 80 +data = "Test Using Larger Than Block-Size Key and Larger " + "Than One Block-Size Data" +data_len = 73 +digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 +*/ + 0 }, + }; + + for (i = 0; i < sizeof(md5tests)/sizeof(md5tests[0]); i++) { + key.contents = md5tests[i].key; + key.length = md5tests[i].key_len; + in.data = md5tests[i].data; + in.length = md5tests[i].data_len; + + out.data = outbuf; + out.length = 20; + printf("\nTest #%d:\n", i+1); + err = hmac1(&krb5int_hash_md5, &key, &in, &out); + if (err) { + com_err(whoami, err, "computing hmac"); + exit(1); + } + + if (sizeof(stroutbuf) - 3 < 2 * out.length) + abort(); + strcpy(stroutbuf, "0x"); + for (j = 0; j < out.length; j++) + sprintf(stroutbuf + strlen(stroutbuf), "%02x", 0xff & outbuf[j]); + if (strcmp(stroutbuf, md5tests[i].hexdigest)) { + printf("*** CHECK FAILED!\n" + "\tReturned: %s.\n" + "\tExpected: %s.\n", stroutbuf, md5tests[i].hexdigest); + lose++; + } else + printf("Matches expected result.\n"); + } + + /* Do again with SHA-1 tests.... */ + + if (lose) { + printf("%d failures; exiting.\n", lose); + exit(1); + } +} + + +int main (int argc, char **argv) +{ + whoami = argv[0]; + test_hmac(); + return 0; +} diff --git a/src/lib/crypto/t_pkcs5.c b/src/lib/crypto/t_pkcs5.c new file mode 100644 index 000000000..30e857441 --- /dev/null +++ b/src/lib/crypto/t_pkcs5.c @@ -0,0 +1,103 @@ +/* + * lib/crypto/t_pkcs5.c + * + * Copyright 2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Test vectors for PBKDF2 (from PKCS #5v2), based on RFC 3211. + */ + +#include +#include +#include +#include +#include + +#include "k5-int.h" + +static void printhex (size_t len, const char *p) +{ + while (len--) + printf (" %02X", 0xff & *p++); +} + +static void printdata (krb5_data *d) { + printhex (d->length, d->data); +} + +static void test_pbkdf2_rfc3211() +{ + char x[100]; + krb5_error_code err; + krb5_data d; + int i; + + /* RFC 3211 test cases. */ + static const struct { + const char *pass; + const char *salt; + unsigned int count; + size_t len; + const unsigned char expected[24]; + } t[] = { + { "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 5, 8, + { 0xD1, 0xDA, 0xA7, 0x86, 0x15, 0xF2, 0x87, 0xE6 } }, + { "All n-entities must communicate with other " + "n-entities via n-1 entiteeheehees", + "\x12\x34\x56\x78\x78\x56\x34\x12", 500, 24, + { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE, + 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86, + 0x07, 0x12, 0x63, 0x80, 0xCC, 0x47, 0xAB, 0x2D } }, + }; + + d.data = x; + printf("RFC 3211 test of PBKDF#2\n"); + + for (i = 0; i < sizeof(t)/sizeof(t[0]); i++) { + + printf("pkbdf2(iter_count=%d, dklen=%d (%d bytes), salt=12 34 56 78 78 56 34 12,\n" + " pass=%s):\n ->", + t[i].count, t[i].len * 8, t[i].len, t[i].pass); + + d.length = t[i].len; + err = krb5int_pbkdf2_hmac_sha1 (x, d.length, t[i].count, + t[i].pass, t[i].salt); + if (err) { + printf("error in computing pbkdf2: %s\n", error_message(err)); + exit(1); + } + printdata(&d); + if (!memcmp(x, t[i].expected, t[i].len)) + printf("\nTest passed.\n\n"); + else { + printf("\n*** CHECK FAILED!\n"); + exit(1); + } + } +} + +int main () +{ + test_pbkdf2_rfc3211(); + return 0; +}