Imported Debian patch 0.66.1-1
[hcoop/debian/courier-authlib.git] / libs / 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
d9898ee8 12
13struct hmac_hashinfo *hmac_list[]= {HMAC_LIST};
14
15struct 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
25static void dohashkey(unsigned char *, void *);
26static void docalcc(void *, void *);
27
28void hmac_hashkey(const struct hmac_hashinfo *hh, const char *k,
29 size_t kl, unsigned char *kxopad, unsigned char *kxipad)
30{
31struct 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
42static void dokeycalc(struct hhki *);
43
44static void docalcc(void *c, void *v)
45{
46struct 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
56static void dohashkey(unsigned char *keybuf, void *v)
57{
58struct 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
69static void dokeycalc(struct hhki *i)
70{
71char buf[64]; /* Random guess :-) */
72unsigned n;
73unsigned 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
106struct 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
115static void docalch(void *, void *);
116
117void 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{
125struct 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
137static void docalch(void *c, void *v)
138{
139struct 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}