• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ghmac.h - data hashing functions
2  *
3  * Copyright (C) 2011  Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Stef Walter <stefw@collabora.co.uk>
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include "ghmac.h"
26 
27 #include "glib/galloca.h"
28 #include "gatomic.h"
29 #include "gslice.h"
30 #include "gmem.h"
31 #include "gstrfuncs.h"
32 #include "gtestutils.h"
33 #include "gtypes.h"
34 #include "glibintl.h"
35 
36 
37 /**
38  * SECTION:hmac
39  * @title: Secure HMAC Digests
40  * @short_description: computes the HMAC for data
41  *
42  * HMACs should be used when producing a cookie or hash based on data
43  * and a key. Simple mechanisms for using SHA1 and other algorithms to
44  * digest a key and data together are vulnerable to various security
45  * issues.
46  * [HMAC](http://en.wikipedia.org/wiki/HMAC)
47  * uses algorithms like SHA1 in a secure way to produce a digest of a
48  * key and data.
49  *
50  * Both the key and data are arbitrary byte arrays of bytes or characters.
51  *
52  * Support for HMAC Digests has been added in GLib 2.30, and support for SHA-512
53  * in GLib 2.42. Support for SHA-384 was added in GLib 2.52.
54  */
55 
56 struct _GHmac
57 {
58   int ref_count;
59   GChecksumType digest_type;
60   GChecksum *digesti;
61   GChecksum *digesto;
62 };
63 
64 /**
65  * g_hmac_new:
66  * @digest_type: the desired type of digest
67  * @key: (array length=key_len): the key for the HMAC
68  * @key_len: the length of the keys
69  *
70  * Creates a new #GHmac, using the digest algorithm @digest_type.
71  * If the @digest_type is not known, %NULL is returned.
72  * A #GHmac can be used to compute the HMAC of a key and an
73  * arbitrary binary blob, using different hashing algorithms.
74  *
75  * A #GHmac works by feeding a binary blob through g_hmac_update()
76  * until the data is complete; the digest can then be extracted
77  * using g_hmac_get_string(), which will return the checksum as a
78  * hexadecimal string; or g_hmac_get_digest(), which will return a
79  * array of raw bytes. Once either g_hmac_get_string() or
80  * g_hmac_get_digest() have been called on a #GHmac, the HMAC
81  * will be closed and it won't be possible to call g_hmac_update()
82  * on it anymore.
83  *
84  * Support for digests of type %G_CHECKSUM_SHA512 has been added in GLib 2.42.
85  * Support for %G_CHECKSUM_SHA384 was added in GLib 2.52.
86  *
87  * Returns: the newly created #GHmac, or %NULL.
88  *   Use g_hmac_unref() to free the memory allocated by it.
89  *
90  * Since: 2.30
91  */
92 GHmac *
g_hmac_new(GChecksumType digest_type,const guchar * key,gsize key_len)93 g_hmac_new (GChecksumType  digest_type,
94             const guchar  *key,
95             gsize          key_len)
96 {
97   GChecksum *checksum;
98   GHmac *hmac;
99   guchar *buffer;
100   guchar *pad;
101   gsize i, len;
102   gsize block_size;
103 
104   checksum = g_checksum_new (digest_type);
105   g_return_val_if_fail (checksum != NULL, NULL);
106 
107   switch (digest_type)
108     {
109     case G_CHECKSUM_MD5:
110     case G_CHECKSUM_SHA1:
111       block_size = 64; /* RFC 2104 */
112       break;
113     case G_CHECKSUM_SHA256:
114       block_size = 64; /* RFC 4868 */
115       break;
116     case G_CHECKSUM_SHA384:
117     case G_CHECKSUM_SHA512:
118       block_size = 128; /* RFC 4868 */
119       break;
120     default:
121       g_return_val_if_reached (NULL);
122     }
123 
124   hmac = g_slice_new0 (GHmac);
125   hmac->ref_count = 1;
126   hmac->digest_type = digest_type;
127   hmac->digesti = checksum;
128   hmac->digesto = g_checksum_new (digest_type);
129 
130   buffer = g_alloca (block_size);
131   pad = g_alloca (block_size);
132 
133   memset (buffer, 0, block_size);
134 
135   /* If the key is too long, hash it */
136   if (key_len > block_size)
137     {
138       len = block_size;
139       g_checksum_update (hmac->digesti, key, key_len);
140       g_checksum_get_digest (hmac->digesti, buffer, &len);
141       g_checksum_reset (hmac->digesti);
142     }
143 
144   /* Otherwise pad it with zeros */
145   else
146     {
147       memcpy (buffer, key, key_len);
148     }
149 
150   /* First pad */
151   for (i = 0; i < block_size; i++)
152     pad[i] = 0x36 ^ buffer[i]; /* ipad value */
153   g_checksum_update (hmac->digesti, pad, block_size);
154 
155   /* Second pad */
156   for (i = 0; i < block_size; i++)
157     pad[i] = 0x5c ^ buffer[i]; /* opad value */
158   g_checksum_update (hmac->digesto, pad, block_size);
159 
160   return hmac;
161 }
162 
163 /**
164  * g_hmac_copy:
165  * @hmac: the #GHmac to copy
166  *
167  * Copies a #GHmac. If @hmac has been closed, by calling
168  * g_hmac_get_string() or g_hmac_get_digest(), the copied
169  * HMAC will be closed as well.
170  *
171  * Returns: the copy of the passed #GHmac. Use g_hmac_unref()
172  *   when finished using it.
173  *
174  * Since: 2.30
175  */
176 GHmac *
g_hmac_copy(const GHmac * hmac)177 g_hmac_copy (const GHmac *hmac)
178 {
179   GHmac *copy;
180 
181   g_return_val_if_fail (hmac != NULL, NULL);
182 
183   copy = g_slice_new (GHmac);
184   copy->ref_count = 1;
185   copy->digest_type = hmac->digest_type;
186   copy->digesti = g_checksum_copy (hmac->digesti);
187   copy->digesto = g_checksum_copy (hmac->digesto);
188 
189   return copy;
190 }
191 
192 /**
193  * g_hmac_ref:
194  * @hmac: a valid #GHmac
195  *
196  * Atomically increments the reference count of @hmac by one.
197  *
198  * This function is MT-safe and may be called from any thread.
199  *
200  * Returns: the passed in #GHmac.
201  *
202  * Since: 2.30
203  **/
204 GHmac *
g_hmac_ref(GHmac * hmac)205 g_hmac_ref (GHmac *hmac)
206 {
207   g_return_val_if_fail (hmac != NULL, NULL);
208 
209   g_atomic_int_inc (&hmac->ref_count);
210 
211   return hmac;
212 }
213 
214 /**
215  * g_hmac_unref:
216  * @hmac: a #GHmac
217  *
218  * Atomically decrements the reference count of @hmac by one.
219  *
220  * If the reference count drops to 0, all keys and values will be
221  * destroyed, and all memory allocated by the hash table is released.
222  * This function is MT-safe and may be called from any thread.
223  * Frees the memory allocated for @hmac.
224  *
225  * Since: 2.30
226  */
227 void
g_hmac_unref(GHmac * hmac)228 g_hmac_unref (GHmac *hmac)
229 {
230   g_return_if_fail (hmac != NULL);
231 
232   if (g_atomic_int_dec_and_test (&hmac->ref_count))
233     {
234       g_checksum_free (hmac->digesti);
235       g_checksum_free (hmac->digesto);
236       g_slice_free (GHmac, hmac);
237     }
238 }
239 
240 /**
241  * g_hmac_update:
242  * @hmac: a #GHmac
243  * @data: (array length=length): buffer used to compute the checksum
244  * @length: size of the buffer, or -1 if it is a nul-terminated string
245  *
246  * Feeds @data into an existing #GHmac.
247  *
248  * The HMAC must still be open, that is g_hmac_get_string() or
249  * g_hmac_get_digest() must not have been called on @hmac.
250  *
251  * Since: 2.30
252  */
253 void
g_hmac_update(GHmac * hmac,const guchar * data,gssize length)254 g_hmac_update (GHmac        *hmac,
255                const guchar *data,
256                gssize        length)
257 {
258   g_return_if_fail (hmac != NULL);
259   g_return_if_fail (length == 0 || data != NULL);
260 
261   g_checksum_update (hmac->digesti, data, length);
262 }
263 
264 /**
265  * g_hmac_get_string:
266  * @hmac: a #GHmac
267  *
268  * Gets the HMAC as a hexadecimal string.
269  *
270  * Once this function has been called the #GHmac can no longer be
271  * updated with g_hmac_update().
272  *
273  * The hexadecimal characters will be lower case.
274  *
275  * Returns: the hexadecimal representation of the HMAC. The
276  *   returned string is owned by the HMAC and should not be modified
277  *   or freed.
278  *
279  * Since: 2.30
280  */
281 const gchar *
g_hmac_get_string(GHmac * hmac)282 g_hmac_get_string (GHmac *hmac)
283 {
284   guint8 *buffer;
285   gsize digest_len;
286 
287   g_return_val_if_fail (hmac != NULL, NULL);
288 
289   digest_len = g_checksum_type_get_length (hmac->digest_type);
290   buffer = g_alloca (digest_len);
291 
292   /* This is only called for its side-effect of updating hmac->digesto... */
293   g_hmac_get_digest (hmac, buffer, &digest_len);
294   /* ... because we get the string from the checksum rather than
295    * stringifying buffer ourselves
296    */
297   return g_checksum_get_string (hmac->digesto);
298 }
299 
300 /**
301  * g_hmac_get_digest:
302  * @hmac: a #GHmac
303  * @buffer: (array length=digest_len): output buffer
304  * @digest_len: (inout): an inout parameter. The caller initializes it to the
305  *   size of @buffer. After the call it contains the length of the digest
306  *
307  * Gets the digest from @checksum as a raw binary array and places it
308  * into @buffer. The size of the digest depends on the type of checksum.
309  *
310  * Once this function has been called, the #GHmac is closed and can
311  * no longer be updated with g_checksum_update().
312  *
313  * Since: 2.30
314  */
315 void
g_hmac_get_digest(GHmac * hmac,guint8 * buffer,gsize * digest_len)316 g_hmac_get_digest (GHmac  *hmac,
317                    guint8 *buffer,
318                    gsize  *digest_len)
319 {
320   gsize len;
321 
322   g_return_if_fail (hmac != NULL);
323 
324   len = g_checksum_type_get_length (hmac->digest_type);
325   g_return_if_fail (*digest_len >= len);
326 
327   /* Use the same buffer, because we can :) */
328   g_checksum_get_digest (hmac->digesti, buffer, &len);
329   g_checksum_update (hmac->digesto, buffer, len);
330   g_checksum_get_digest (hmac->digesto, buffer, digest_len);
331 }
332 
333 /**
334  * g_compute_hmac_for_data:
335  * @digest_type: a #GChecksumType to use for the HMAC
336  * @key: (array length=key_len): the key to use in the HMAC
337  * @key_len: the length of the key
338  * @data: (array length=length): binary blob to compute the HMAC of
339  * @length: length of @data
340  *
341  * Computes the HMAC for a binary @data of @length. This is a
342  * convenience wrapper for g_hmac_new(), g_hmac_get_string()
343  * and g_hmac_unref().
344  *
345  * The hexadecimal string returned will be in lower case.
346  *
347  * Returns: the HMAC of the binary data as a string in hexadecimal.
348  *   The returned string should be freed with g_free() when done using it.
349  *
350  * Since: 2.30
351  */
352 gchar *
g_compute_hmac_for_data(GChecksumType digest_type,const guchar * key,gsize key_len,const guchar * data,gsize length)353 g_compute_hmac_for_data (GChecksumType  digest_type,
354                          const guchar  *key,
355                          gsize          key_len,
356                          const guchar  *data,
357                          gsize          length)
358 {
359   GHmac *hmac;
360   gchar *retval;
361 
362   g_return_val_if_fail (length == 0 || data != NULL, NULL);
363 
364   hmac = g_hmac_new (digest_type, key, key_len);
365   if (!hmac)
366     return NULL;
367 
368   g_hmac_update (hmac, data, length);
369   retval = g_strdup (g_hmac_get_string (hmac));
370   g_hmac_unref (hmac);
371 
372   return retval;
373 }
374 
375 /**
376  * g_compute_hmac_for_bytes:
377  * @digest_type: a #GChecksumType to use for the HMAC
378  * @key: the key to use in the HMAC
379  * @data: binary blob to compute the HMAC of
380  *
381  * Computes the HMAC for a binary @data. This is a
382  * convenience wrapper for g_hmac_new(), g_hmac_get_string()
383  * and g_hmac_unref().
384  *
385  * The hexadecimal string returned will be in lower case.
386  *
387  * Returns: the HMAC of the binary data as a string in hexadecimal.
388  *   The returned string should be freed with g_free() when done using it.
389  *
390  * Since: 2.50
391  */
392 gchar *
g_compute_hmac_for_bytes(GChecksumType digest_type,GBytes * key,GBytes * data)393 g_compute_hmac_for_bytes (GChecksumType  digest_type,
394                           GBytes        *key,
395                           GBytes        *data)
396 {
397   gconstpointer byte_data;
398   gsize length;
399   gconstpointer key_data;
400   gsize key_len;
401 
402   g_return_val_if_fail (data != NULL, NULL);
403   g_return_val_if_fail (key != NULL, NULL);
404 
405   byte_data = g_bytes_get_data (data, &length);
406   key_data = g_bytes_get_data (key, &key_len);
407   return g_compute_hmac_for_data (digest_type, key_data, key_len, byte_data, length);
408 }
409 
410 
411 /**
412  * g_compute_hmac_for_string:
413  * @digest_type: a #GChecksumType to use for the HMAC
414  * @key: (array length=key_len): the key to use in the HMAC
415  * @key_len: the length of the key
416  * @str: the string to compute the HMAC for
417  * @length: the length of the string, or -1 if the string is nul-terminated
418  *
419  * Computes the HMAC for a string.
420  *
421  * The hexadecimal string returned will be in lower case.
422  *
423  * Returns: the HMAC as a hexadecimal string.
424  *     The returned string should be freed with g_free()
425  *     when done using it.
426  *
427  * Since: 2.30
428  */
429 gchar *
g_compute_hmac_for_string(GChecksumType digest_type,const guchar * key,gsize key_len,const gchar * str,gssize length)430 g_compute_hmac_for_string (GChecksumType  digest_type,
431                            const guchar  *key,
432                            gsize          key_len,
433                            const gchar   *str,
434                            gssize         length)
435 {
436   g_return_val_if_fail (length == 0 || str != NULL, NULL);
437 
438   if (length < 0)
439     length = strlen (str);
440 
441   return g_compute_hmac_for_data (digest_type, key, key_len,
442                                   (const guchar *) str, length);
443 }
444