comparison libpurple/ciphers/hmac.c @ 31663:04ead332691f

Broke out the hmac cipher to it's own file. Removed already transitioned info in the fileheader of cipher.c
author Gary Kramlich <grim@reaperworld.com>
date Mon, 14 Feb 2011 05:57:04 +0000
parents
children 2d3c1197f930
comparison
equal deleted inserted replaced
31662:a1a0936d10c3 31663:04ead332691f
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 #include <string.h>
24
25 struct HMAC_Context {
26 PurpleCipherContext *hash;
27 char *name;
28 int blocksize;
29 guchar *opad;
30 };
31
32 static void
33 hmac_init(PurpleCipherContext *context, gpointer extra)
34 {
35 struct HMAC_Context *hctx;
36 hctx = g_new0(struct HMAC_Context, 1);
37 purple_cipher_context_set_data(context, hctx);
38 purple_cipher_context_reset(context, extra);
39 }
40
41 static void
42 hmac_reset(PurpleCipherContext *context, gpointer extra)
43 {
44 struct HMAC_Context *hctx;
45
46 hctx = purple_cipher_context_get_data(context);
47
48 g_free(hctx->name);
49 hctx->name = NULL;
50 if (hctx->hash)
51 purple_cipher_context_destroy(hctx->hash);
52 hctx->hash = NULL;
53 hctx->blocksize = 0;
54 g_free(hctx->opad);
55 hctx->opad = NULL;
56 }
57
58 static void
59 hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value)
60 {
61 struct HMAC_Context *hctx;
62
63 hctx = purple_cipher_context_get_data(context);
64
65 if (purple_strequal(name, "hash")) {
66 g_free(hctx->name);
67 if (hctx->hash)
68 purple_cipher_context_destroy(hctx->hash);
69 hctx->name = g_strdup((char*)value);
70 hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL);
71 hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash);
72 }
73 }
74
75 static void *
76 hmac_get_opt(PurpleCipherContext *context, const gchar *name)
77 {
78 struct HMAC_Context *hctx;
79
80 hctx = purple_cipher_context_get_data(context);
81
82 if (purple_strequal(name, "hash")) {
83 return hctx->name;
84 }
85
86 return NULL;
87 }
88
89 static void
90 hmac_append(PurpleCipherContext *context, const guchar *data, size_t len)
91 {
92 struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
93
94 g_return_if_fail(hctx->hash != NULL);
95
96 purple_cipher_context_append(hctx->hash, data, len);
97 }
98
99 static gboolean
100 hmac_digest(PurpleCipherContext *context, size_t in_len, guchar *out, size_t *out_len)
101 {
102 struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
103 PurpleCipherContext *hash = hctx->hash;
104 guchar *inner_hash;
105 size_t hash_len;
106 gboolean result;
107
108 g_return_val_if_fail(hash != NULL, FALSE);
109
110 inner_hash = g_malloc(100); /* TODO: Should be enough for now... */
111 result = purple_cipher_context_digest(hash, 100, inner_hash, &hash_len);
112
113 purple_cipher_context_reset(hash, NULL);
114
115 purple_cipher_context_append(hash, hctx->opad, hctx->blocksize);
116 purple_cipher_context_append(hash, inner_hash, hash_len);
117
118 g_free(inner_hash);
119
120 result = result && purple_cipher_context_digest(hash, in_len, out, out_len);
121
122 return result;
123 }
124
125 static void
126 hmac_uninit(PurpleCipherContext *context)
127 {
128 struct HMAC_Context *hctx;
129
130 purple_cipher_context_reset(context, NULL);
131
132 hctx = purple_cipher_context_get_data(context);
133
134 g_free(hctx);
135 }
136
137 static void
138 hmac_set_key_with_len(PurpleCipherContext *context, const guchar * key, size_t key_len)
139 {
140 struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
141 int blocksize, i;
142 guchar *ipad;
143 guchar *full_key;
144
145 g_return_if_fail(hctx->hash != NULL);
146
147 g_free(hctx->opad);
148
149 blocksize = hctx->blocksize;
150 ipad = g_malloc(blocksize);
151 hctx->opad = g_malloc(blocksize);
152
153 if (key_len > blocksize) {
154 purple_cipher_context_reset(hctx->hash, NULL);
155 purple_cipher_context_append(hctx->hash, key, key_len);
156 full_key = g_malloc(100); /* TODO: Should be enough for now... */
157 purple_cipher_context_digest(hctx->hash, 100, full_key, &key_len);
158 } else
159 full_key = g_memdup(key, key_len);
160
161 if (key_len < blocksize) {
162 full_key = g_realloc(full_key, blocksize);
163 memset(full_key + key_len, 0, blocksize - key_len);
164 }
165
166 for(i = 0; i < blocksize; i++) {
167 ipad[i] = 0x36 ^ full_key[i];
168 hctx->opad[i] = 0x5c ^ full_key[i];
169 }
170
171 g_free(full_key);
172
173 purple_cipher_context_reset(hctx->hash, NULL);
174 purple_cipher_context_append(hctx->hash, ipad, blocksize);
175 g_free(ipad);
176 }
177
178 static void
179 hmac_set_key(PurpleCipherContext *context, const guchar * key)
180 {
181 hmac_set_key_with_len(context, key, strlen((char *)key));
182 }
183
184 static size_t
185 hmac_get_block_size(PurpleCipherContext *context)
186 {
187 struct HMAC_Context *hctx = purple_cipher_context_get_data(context);
188
189 return hctx->blocksize;
190 }
191
192 static PurpleCipherOps HMACOps = {
193 .set_option = hmac_set_opt,
194 .get_option = hmac_get_opt,
195 .init = hmac_init,
196 .reset = hmac_reset,
197 .uninit = hmac_uninit,
198 .append = hmac_append,
199 .digest = hmac_digest,
200 .set_key = hmac_set_key,
201 .get_block_size = hmac_get_block_size,
202 .set_key_with_len = hmac_set_key_with_len,
203 };
204
205 PurpleCipherOps *
206 purple_hmac_cipher_get_ops(void) {
207 return &HMACOps;
208 }
209