Mercurial > pidgin
comparison libpurple/ciphers/hmac.c @ 31214: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
31213:a1a0936d10c3 | 31214: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 |