]> mj.ucw.cz Git - libucw.git/blob - ucw/sha1-hmac.c
Compatibility with GCC < 4.0 is not needed any longer
[libucw.git] / ucw / sha1-hmac.c
1 /*
2  *      HMAC-SHA1 Message Authentication Code (RFC 2202)
3  *
4  *      (c) 2008--2009 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/sha1.h>
12
13 #include <string.h>
14
15 void
16 sha1_hmac_init(sha1_hmac_context *hd, const byte *key, uint keylen)
17 {
18   byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
19
20   // Hash the key if necessary
21   if (keylen <= SHA1_BLOCK_SIZE)
22     {
23       memcpy(keybuf, key, keylen);
24       bzero(keybuf + keylen, SHA1_BLOCK_SIZE - keylen);
25     }
26   else
27     {
28       sha1_hash_buffer(keybuf, key, keylen);
29       bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
30     }
31
32   // Initialize the inner digest
33   sha1_init(&hd->ictx);
34   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
35     buf[i] = keybuf[i] ^ 0x36;
36   sha1_update(&hd->ictx, buf, SHA1_BLOCK_SIZE);
37
38   // Initialize the outer digest
39   sha1_init(&hd->octx);
40   for (int i=0; i < SHA1_BLOCK_SIZE; i++)
41     buf[i] = keybuf[i] ^ 0x5c;
42   sha1_update(&hd->octx, buf, SHA1_BLOCK_SIZE);
43 }
44
45 void
46 sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uint datalen)
47 {
48   // Just update the inner digest
49   sha1_update(&hd->ictx, data, datalen);
50 }
51
52 byte *sha1_hmac_final(sha1_hmac_context *hd)
53 {
54   // Finish the inner digest
55   byte *isha = sha1_final(&hd->ictx);
56
57   // Finish the outer digest
58   sha1_update(&hd->octx, isha, SHA1_SIZE);
59   return sha1_final(&hd->octx);
60 }
61
62 void
63 sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen)
64 {
65   sha1_hmac_context hd;
66   sha1_hmac_init(&hd, key, keylen);
67   sha1_hmac_update(&hd, data, datalen);
68   byte *osha = sha1_hmac_final(&hd);
69   memcpy(outbuf, osha, SHA1_SIZE);
70 }
71
72 #ifdef TEST
73
74 #include <stdio.h>
75 #include <ucw/string.h>
76
77 static uint rd(char *dest)
78 {
79   char buf[1024];
80   if (!fgets(buf, sizeof(buf), stdin))
81     die("fgets()");
82   *strchr(buf, '\n') = 0;
83   if (buf[0] == '0' && buf[1] == 'x')
84     {
85       const char *e = hex_to_mem(dest, buf+2, 1024, 0);
86       ASSERT(!*e);
87       return (e-buf-2)/2;
88     }
89   else
90     {
91       strcpy(dest, buf);
92       return strlen(dest);
93     }
94 }
95
96 int main(void)
97 {
98   char key[1024], data[1024];
99   byte hmac[SHA1_SIZE];
100   uint kl = rd(key);
101   uint dl = rd(data);
102   sha1_hmac(hmac, key, kl, data, dl);
103   mem_to_hex(data, hmac, SHA1_SIZE, 0);
104   puts(data);
105   return 0;
106 }
107
108 #endif