Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / 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 static const char rcsid[]="$Id: hmac.c,v 1.4 2006/01/22 03:37:04 mrsam Exp $";
13
14 struct hmac_hashinfo *hmac_list[]= {HMAC_LIST};
15
16 struct 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
26 static void dohashkey(unsigned char *, void *);
27 static void docalcc(void *, void *);
28
29 void hmac_hashkey(const struct hmac_hashinfo *hh, const char *k,
30 size_t kl, unsigned char *kxopad, unsigned char *kxipad)
31 {
32 struct 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
43 static void dokeycalc(struct hhki *);
44
45 static void docalcc(void *c, void *v)
46 {
47 struct 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
57 static void dohashkey(unsigned char *keybuf, void *v)
58 {
59 struct 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
70 static void dokeycalc(struct hhki *i)
71 {
72 char buf[64]; /* Random guess :-) */
73 unsigned n;
74 unsigned 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
107 struct 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
116 static void docalch(void *, void *);
117
118 void 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 {
126 struct 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
138 static void docalch(void *c, void *v)
139 {
140 struct 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 }