#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "hash_provider.h"
#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))
const char *whoami;
static void keyToData (krb5_keyblock *k, krb5_data *d) {
d->length = k->length;
d->data = (char *) k->contents;
}
#if 0
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__)
#endif
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(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;
printk(" test key", key);
blocksize = h->blocksize;
hashsize = h->hashsize;
if (hashsize > sizeof(tmp))
abort();
if (key->length > blocksize) {
krb5_data d, d2;
d.data = (char *) 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 = (krb5_octet *) 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;
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"
},
};
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");
}
if (lose) {
printf("%d failures; exiting.\n", lose);
exit(1);
}
}
int main (int argc, char **argv)
{
whoami = argv[0];
test_hmac();
return 0;
}