~liuxingcs/+junk/pidgin

« back to all changes in this revision

Viewing changes to libpurple/ciphers/hmac.c

  • Committer: liuxing
  • Date: 2013-04-25 11:10:17 UTC
  • Revision ID: liuxingcs@yeah.net-20130425111017-fm4mtfsuvhq0dbqd
pidgin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * purple
 
3
 *
 
4
 * Purple is the legal property of its developers, whose names are too numerous
 
5
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 
6
 * source distribution.
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
21
 */
 
22
#include <cipher.h>
 
23
 
 
24
#include <util.h>
 
25
 
 
26
struct HMAC_Context {
 
27
        PurpleCipherContext *hash;
 
28
        char *name;
 
29
        int blocksize;
 
30
        guchar *opad;
 
31
};
 
32
 
 
33
        static void
 
34
hmac_init(PurpleCipherContext *context, gpointer extra)
 
35
{
 
36
        struct HMAC_Context *hctx;
 
37
        hctx = g_new0(struct HMAC_Context, 1);
 
38
        purple_cipher_context_set_data(context, hctx);
 
39
        purple_cipher_context_reset(context, extra);
 
40
}
 
41
 
 
42
        static void
 
43
hmac_reset(PurpleCipherContext *context, gpointer extra)
 
44
{
 
45
        struct HMAC_Context *hctx;
 
46
 
 
47
        hctx = purple_cipher_context_get_data(context);
 
48
 
 
49
        g_free(hctx->name);
 
50
        hctx->name = NULL;
 
51
        if (hctx->hash)
 
52
                purple_cipher_context_destroy(hctx->hash);
 
53
        hctx->hash = NULL;
 
54
        hctx->blocksize = 0;
 
55
        g_free(hctx->opad);
 
56
        hctx->opad = NULL;
 
57
}
 
58
 
 
59
        static void
 
60
hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value)
 
61
{
 
62
        struct HMAC_Context *hctx;
 
63
 
 
64
        hctx = purple_cipher_context_get_data(context);
 
65
 
 
66
        if (purple_strequal(name, "hash")) {
 
67
                g_free(hctx->name);
 
68
                if (hctx->hash)
 
69
                        purple_cipher_context_destroy(hctx->hash);
 
70
                hctx->name = g_strdup((char*)value);
 
71
                hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL);
 
72
                hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash);
 
73
        }
 
74
}
 
75
 
 
76
        static void *
 
77
hmac_get_opt(PurpleCipherContext *context, const gchar *name)
 
78
{
 
79
        struct HMAC_Context *hctx;
 
80
 
 
81
        hctx = purple_cipher_context_get_data(context);
 
82
 
 
83
        if (purple_strequal(name, "hash")) {
 
84
                return hctx->name;
 
85
        }
 
86
 
 
87
        return NULL;
 
88
}
 
89
 
 
90
        static void
 
91
hmac_append(PurpleCipherContext *context, const guchar *data, size_t len)
 
92
{
 
93
        struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
 
94
 
 
95
        g_return_if_fail(hctx->hash != NULL);
 
96
 
 
97
        purple_cipher_context_append(hctx->hash, data, len);
 
98
}
 
99
 
 
100
        static gboolean
 
101
hmac_digest(PurpleCipherContext *context, size_t in_len, guchar *out, size_t *out_len)
 
102
{
 
103
        struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
 
104
        PurpleCipherContext *hash = hctx->hash;
 
105
        guchar *inner_hash;
 
106
        size_t hash_len;
 
107
        gboolean result;
 
108
 
 
109
        g_return_val_if_fail(hash != NULL, FALSE);
 
110
 
 
111
        inner_hash = g_malloc(100); /* TODO: Should be enough for now... */
 
112
        result = purple_cipher_context_digest(hash, 100, inner_hash, &hash_len);
 
113
 
 
114
        purple_cipher_context_reset(hash, NULL);
 
115
 
 
116
        purple_cipher_context_append(hash, hctx->opad, hctx->blocksize);
 
117
        purple_cipher_context_append(hash, inner_hash, hash_len);
 
118
 
 
119
        g_free(inner_hash);
 
120
 
 
121
        result = result && purple_cipher_context_digest(hash, in_len, out, out_len);
 
122
 
 
123
        return result;
 
124
}
 
125
 
 
126
        static void
 
127
hmac_uninit(PurpleCipherContext *context)
 
128
{
 
129
        struct HMAC_Context *hctx;
 
130
 
 
131
        purple_cipher_context_reset(context, NULL);
 
132
 
 
133
        hctx = purple_cipher_context_get_data(context);
 
134
 
 
135
        g_free(hctx);
 
136
}
 
137
 
 
138
        static void
 
139
hmac_set_key_with_len(PurpleCipherContext *context, const guchar * key, size_t key_len)
 
140
{
 
141
        struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
 
142
        int blocksize, i;
 
143
        guchar *ipad;
 
144
        guchar *full_key;
 
145
 
 
146
        g_return_if_fail(hctx->hash != NULL);
 
147
 
 
148
        g_free(hctx->opad);
 
149
 
 
150
        blocksize = hctx->blocksize;
 
151
        ipad = g_malloc(blocksize);
 
152
        hctx->opad = g_malloc(blocksize);
 
153
 
 
154
        if (key_len > blocksize) {
 
155
                purple_cipher_context_reset(hctx->hash, NULL);
 
156
                purple_cipher_context_append(hctx->hash, key, key_len);
 
157
                full_key = g_malloc(100); /* TODO: Should be enough for now... */
 
158
                purple_cipher_context_digest(hctx->hash, 100, full_key, &key_len);
 
159
        } else
 
160
                full_key = g_memdup(key, key_len);
 
161
 
 
162
        if (key_len < blocksize) {
 
163
                full_key = g_realloc(full_key, blocksize);
 
164
                memset(full_key + key_len, 0, blocksize - key_len);
 
165
        }
 
166
 
 
167
        for(i = 0; i < blocksize; i++) {
 
168
                ipad[i] = 0x36 ^ full_key[i];
 
169
                hctx->opad[i] = 0x5c ^ full_key[i];
 
170
        }
 
171
 
 
172
        g_free(full_key);
 
173
 
 
174
        purple_cipher_context_reset(hctx->hash, NULL);
 
175
        purple_cipher_context_append(hctx->hash, ipad, blocksize);
 
176
        g_free(ipad);
 
177
}
 
178
 
 
179
        static void
 
180
hmac_set_key(PurpleCipherContext *context, const guchar * key)
 
181
{
 
182
        hmac_set_key_with_len(context, key, strlen((char *)key));
 
183
}
 
184
 
 
185
        static size_t
 
186
hmac_get_block_size(PurpleCipherContext *context)
 
187
{
 
188
        struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
 
189
 
 
190
        return hctx->blocksize;
 
191
}
 
192
 
 
193
static PurpleCipherOps HMACOps = {
 
194
        hmac_set_opt,           /* Set option */
 
195
        hmac_get_opt,           /* Get option */
 
196
        hmac_init,               /* init */
 
197
        hmac_reset,              /* reset */
 
198
        hmac_uninit,             /* uninit */
 
199
        NULL,                   /* set iv */
 
200
        hmac_append,             /* append */
 
201
        hmac_digest,             /* digest */
 
202
        NULL,                   /* encrypt */
 
203
        NULL,                   /* decrypt */
 
204
        NULL,                   /* set salt */
 
205
        NULL,                   /* get salt size */
 
206
        hmac_set_key,           /* set key */
 
207
        NULL,                   /* get key size */
 
208
        NULL,                   /* set batch mode */
 
209
        NULL,                   /* get batch mode */
 
210
        hmac_get_block_size,    /* get block size */
 
211
        hmac_set_key_with_len   /* set key with len */
 
212
};
 
213
 
 
214
PurpleCipherOps *
 
215
purple_hmac_cipher_get_ops(void) {
 
216
        return &HMACOps;
 
217
}
 
218