Statistics
| Revision:

root / libsylph / md5_hmac.c @ 2326

History | View | Annotate | Download (3.5 kB)

1 559 hiro
/*
2 578 hiro
 * LibSylph -- E-Mail client library
3 1102 hiro
 * Copyright (C) 1999-2006 Hiroyuki Yamamoto
4 559 hiro
 *
5 578 hiro
 * This library is free software; you can redistribute it and/or
6 578 hiro
 * modify it under the terms of the GNU Lesser General Public
7 578 hiro
 * License as published by the Free Software Foundation; either
8 578 hiro
 * version 2.1 of the License, or (at your option) any later version.
9 559 hiro
 *
10 578 hiro
 * This library is distributed in the hope that it will be useful,
11 559 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 578 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 578 hiro
 * Lesser General Public License for more details.
14 559 hiro
 *
15 578 hiro
 * You should have received a copy of the GNU Lesser General Public
16 578 hiro
 * License along with this library; if not, write to the Free Software
17 578 hiro
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 559 hiro
 */
19 559 hiro
20 559 hiro
#ifdef HAVE_CONFIG_H
21 559 hiro
#  include "config.h"
22 559 hiro
#endif
23 559 hiro
24 559 hiro
#include <glib.h>
25 559 hiro
#include <string.h>
26 559 hiro
27 559 hiro
#include "md5.h"
28 559 hiro
#include "md5_hmac.h"
29 559 hiro
30 559 hiro
/*
31 559 hiro
** Function: md5_hmac_get
32 559 hiro
** taken from the file rfc2104.txt
33 559 hiro
** originally written by Martin Schaaf <mascha@ma-scha.de>
34 559 hiro
** rewritten by Hiroyuki Yamamoto <hiro-y@kcn.ne.jp>
35 559 hiro
*/
36 559 hiro
static SMD5*
37 559 hiro
md5_hmac_get(const guchar *text, gint text_len,
38 559 hiro
             const guchar *key, gint key_len)
39 559 hiro
{
40 559 hiro
        SMD5 *md5;
41 559 hiro
        guchar k_ipad[64];    /* inner padding -
42 559 hiro
                               * key XORd with ipad
43 559 hiro
                               */
44 559 hiro
        guchar k_opad[64];    /* outer padding -
45 559 hiro
                               * key XORd with opad
46 559 hiro
                               */
47 559 hiro
        guchar digest[S_GNET_MD5_HASH_LENGTH];
48 559 hiro
        gint i;
49 559 hiro
50 559 hiro
        /* start out by storing key in pads */
51 559 hiro
        memset(k_ipad, 0, sizeof k_ipad);
52 559 hiro
        memset(k_opad, 0, sizeof k_opad);
53 559 hiro
54 559 hiro
        if (key_len > 64) {
55 559 hiro
                /* if key is longer than 64 bytes reset it to key=MD5(key) */
56 559 hiro
                SMD5 *tmd5;
57 559 hiro
58 561 hiro
                tmd5 = s_gnet_md5_new(key, key_len);
59 559 hiro
                memcpy(k_ipad, s_gnet_md5_get_digest(tmd5),
60 559 hiro
                       S_GNET_MD5_HASH_LENGTH);
61 559 hiro
                memcpy(k_opad, s_gnet_md5_get_digest(tmd5),
62 559 hiro
                       S_GNET_MD5_HASH_LENGTH);
63 559 hiro
                s_gnet_md5_delete(tmd5);
64 559 hiro
        } else {
65 559 hiro
                memcpy(k_ipad, key, key_len);
66 559 hiro
                memcpy(k_opad, key, key_len);
67 559 hiro
        }
68 559 hiro
69 559 hiro
        /*
70 559 hiro
         * the HMAC_MD5 transform looks like:
71 559 hiro
         *
72 559 hiro
         * MD5(K XOR opad, MD5(K XOR ipad, text))
73 559 hiro
         *
74 559 hiro
         * where K is an n byte key
75 559 hiro
         * ipad is the byte 0x36 repeated 64 times
76 559 hiro
         * opad is the byte 0x5c repeated 64 times
77 559 hiro
         * and text is the data being protected
78 559 hiro
         */
79 559 hiro
80 559 hiro
81 559 hiro
        /* XOR key with ipad and opad values */
82 559 hiro
        for (i = 0; i < 64; i++) {
83 559 hiro
                k_ipad[i] ^= 0x36;
84 559 hiro
                k_opad[i] ^= 0x5c;
85 559 hiro
        }
86 559 hiro
87 559 hiro
        /*
88 559 hiro
         * perform inner MD5
89 559 hiro
         */
90 559 hiro
        md5 = s_gnet_md5_new_incremental();        /* init context for 1st
91 559 hiro
                                                 * pass */
92 559 hiro
        s_gnet_md5_update(md5, k_ipad, 64);        /* start with inner pad */
93 559 hiro
        s_gnet_md5_update(md5, text, text_len);        /* then text of datagram */
94 559 hiro
        s_gnet_md5_final(md5);                        /* finish up 1st pass */
95 559 hiro
        memcpy(digest, s_gnet_md5_get_digest(md5), S_GNET_MD5_HASH_LENGTH);
96 559 hiro
        s_gnet_md5_delete(md5);
97 559 hiro
98 559 hiro
        /*
99 559 hiro
         * perform outer MD5
100 559 hiro
         */
101 559 hiro
        md5 = s_gnet_md5_new_incremental();        /* init context for 2nd
102 559 hiro
                                                 * pass */
103 559 hiro
        s_gnet_md5_update(md5, k_opad, 64);        /* start with outer pad */
104 559 hiro
        s_gnet_md5_update(md5, digest, 16);        /* then results of 1st
105 559 hiro
                                                 * hash */
106 559 hiro
        s_gnet_md5_final(md5);                        /* finish up 2nd pass */
107 559 hiro
108 559 hiro
        return md5;
109 559 hiro
}
110 559 hiro
111 559 hiro
void
112 559 hiro
md5_hmac(guchar *digest,
113 559 hiro
         const guchar *text, gint text_len,
114 559 hiro
         const guchar *key, gint key_len)
115 559 hiro
{
116 559 hiro
        SMD5 *md5;
117 559 hiro
118 559 hiro
        md5 = md5_hmac_get(text, text_len, key, key_len);
119 559 hiro
        memcpy(digest, s_gnet_md5_get_digest(md5), S_GNET_MD5_HASH_LENGTH);
120 559 hiro
        s_gnet_md5_delete(md5);
121 559 hiro
}
122 559 hiro
123 559 hiro
void
124 559 hiro
md5_hex_hmac(gchar *hexdigest,
125 559 hiro
             const guchar *text, gint text_len,
126 559 hiro
             const guchar *key, gint key_len)
127 559 hiro
{
128 559 hiro
        SMD5 *md5;
129 559 hiro
130 559 hiro
        md5 = md5_hmac_get(text, text_len, key, key_len);
131 559 hiro
        s_gnet_md5_copy_string(md5, hexdigest);
132 559 hiro
        hexdigest[S_GNET_MD5_HASH_LENGTH * 2] = '\0';
133 1102 hiro
        s_gnet_md5_delete(md5);
134 559 hiro
}