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