1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
/*
** Copyright 1998 - 1999 Double Precision, Inc.
** See COPYING for distribution information.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "hmac.h"
static const char rcsid[]="$Id: hmac.c,v 1.4 2006/01/22 03:37:04 mrsam Exp $";
struct hmac_hashinfo *hmac_list[]= {HMAC_LIST};
struct hhki {
const struct hmac_hashinfo *hh;
const char *k;
size_t kl;
unsigned char *kxopad;
unsigned char *kxipad;
void *context;
} ;
static void dohashkey(unsigned char *, void *);
static void docalcc(void *, void *);
void hmac_hashkey(const struct hmac_hashinfo *hh, const char *k,
size_t kl, unsigned char *kxopad, unsigned char *kxipad)
{
struct hhki i;
i.hh=hh;
i.k=k;
i.kl=kl;
i.kxopad=kxopad;
i.kxipad=kxipad;
(*hh->hh_allocacontext)( docalcc, (void *)&i );
}
static void dokeycalc(struct hhki *);
static void docalcc(void *c, void *v)
{
struct hhki *i=(struct hhki *)v;
i->context=c;
if (i->kl > i->hh->hh_B)
(*i->hh->hh_allocaval)(dohashkey, (void *)i);
else
dokeycalc( i );
}
static void dohashkey(unsigned char *keybuf, void *v)
{
struct hhki *i=(struct hhki *)v;
(*i->hh->hh_init)(i->context);
(*i->hh->hh_hash)(i->context, i->k, i->kl);
(*i->hh->hh_endhash)(i->context, i->kl);
(*i->hh->hh_getdigest)(i->context, keybuf);
i->k=(char *)keybuf;
i->kl=i->hh->hh_L;
dokeycalc(i);
}
static void dokeycalc(struct hhki *i)
{
char buf[64]; /* Random guess :-) */
unsigned n;
unsigned l;
(*i->hh->hh_init)(i->context);
n=0;
for (l=0; l<i->hh->hh_B; l++)
{
buf[n] = ( l < i->kl ? i->k[l]:0) ^ 0x5C;
if ( ++n >= sizeof(buf))
{
(*i->hh->hh_hash)(i->context, buf, sizeof(buf));
n=0;
}
}
if (n)
(*i->hh->hh_hash)(i->context, buf, n);
(*i->hh->hh_getdigest)(i->context, i->kxopad);
(*i->hh->hh_init)(i->context);
n=0;
for (l=0; l<i->hh->hh_B; l++)
{
buf[n] = ( l < i->kl ? i->k[l]:0) ^ 0x36;
if ( ++n >= sizeof(buf))
{
(*i->hh->hh_hash)(i->context, buf, sizeof(buf));
n=0;
}
}
if (n)
(*i->hh->hh_hash)(i->context, buf, n);
(*i->hh->hh_getdigest)(i->context, i->kxipad);
}
struct hhko {
const struct hmac_hashinfo *hh;
const char *t;
size_t tl;
const unsigned char *kxopad;
const unsigned char *kxipad;
unsigned char *hash;
} ;
static void docalch(void *, void *);
void hmac_hashtext (
const struct hmac_hashinfo *hh,
const char *t,
size_t tl,
const unsigned char *kxopad,
const unsigned char *kxipad,
unsigned char *hash)
{
struct hhko o;
o.hh=hh;
o.t=t;
o.tl=tl;
o.kxopad=kxopad;
o.kxipad=kxipad;
o.hash=hash;
(*hh->hh_allocacontext)( docalch, (void *)&o );
}
static void docalch(void *c, void *v)
{
struct hhko *o=(struct hhko *)v;
(o->hh->hh_setdigest)(c, o->kxipad);
(o->hh->hh_hash)(c, o->t, o->tl);
(o->hh->hh_endhash)(c, o->tl+o->hh->hh_B);
(o->hh->hh_getdigest)(c, o->hash);
(o->hh->hh_setdigest)(c, o->kxopad);
(o->hh->hh_hash)(c, o->hash, o->hh->hh_L);
(o->hh->hh_endhash)(c, o->hh->hh_L + o->hh->hh_B);
(o->hh->hh_getdigest)(c, o->hash);
}
|