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