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