Branch data Line data Source code
1 : : /*
2 : : * gnome-keyring
3 : : *
4 : : * Copyright (C) 2011 Collabora Ltd.
5 : : *
6 : : * This program is free software; you can redistribute it and/or modify
7 : : * it under the terms of the GNU Lesser General Public License as
8 : : * published by the Free Software Foundation; either version 2.1 of
9 : : * the License, or (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful, but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received copies of the GNU General Public License and
17 : : * the GNU Lesser General Public License along with this program. If
18 : : * 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 "egg-hkdf.h"
26 : :
27 : : #include <gcrypt.h>
28 : : #include <string.h>
29 : :
30 : : gboolean
31 : 59 : egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
32 : : gconstpointer salt, gsize n_salt, gconstpointer info,
33 : : gsize n_info, gpointer output, gsize n_output)
34 : : {
35 : 59 : gpointer alloc = NULL;
36 : 59 : gpointer buffer = NULL;
37 : : gcry_md_hd_t md1, md2;
38 : : guint hash_len;
39 : : gint i;
40 : : gint flags, algo;
41 : : gsize step, n_buffer;
42 : : guchar *at;
43 : : gcry_error_t gcry;
44 : :
45 : 59 : algo = gcry_md_map_name (hash_algo);
46 [ - + ]: 59 : g_return_val_if_fail (algo != 0, FALSE);
47 : :
48 : 59 : hash_len = gcry_md_get_algo_dlen (algo);
49 [ - + ]: 59 : g_return_val_if_fail (hash_len != 0, FALSE);
50 [ - + ]: 59 : g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
51 : :
52 : : /* Buffer we need to for intermediate stuff */
53 [ + + ]: 59 : if (gcry_is_secure (input)) {
54 : 52 : flags = GCRY_MD_FLAG_SECURE;
55 : 52 : buffer = gcry_malloc_secure (hash_len);
56 : : } else {
57 : 7 : flags = 0;
58 : 7 : buffer = gcry_malloc (hash_len);
59 : : }
60 : :
61 [ - + ]: 59 : g_return_val_if_fail (buffer, FALSE);
62 : 59 : n_buffer = 0;
63 : :
64 : : /* Salt defaults to hash_len zeros */
65 [ + + ]: 59 : if (!salt) {
66 : 53 : salt = alloc = g_malloc0 (hash_len);
67 : 53 : n_salt = hash_len;
68 : : }
69 : :
70 : : /* Step 1: Extract */
71 : 59 : gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags);
72 [ - + ]: 59 : g_return_val_if_fail (gcry == 0, FALSE);
73 : 59 : gcry = gcry_md_setkey (md1, salt, n_salt);
74 [ - + ]: 59 : g_return_val_if_fail (gcry == 0, FALSE);
75 : 59 : gcry_md_write (md1, input, n_input);
76 : :
77 : : /* Step 2: Expand */
78 : 59 : gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags);
79 [ - + ]: 59 : g_return_val_if_fail (gcry == 0, FALSE);
80 : 59 : gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
81 [ - + ]: 59 : g_return_val_if_fail (gcry == 0, FALSE);
82 : 59 : gcry_md_close (md1);
83 : :
84 : 59 : at = output;
85 [ + - ]: 73 : for (i = 1; i < 256; ++i) {
86 : 73 : gcry_md_reset (md2);
87 : 73 : gcry_md_write (md2, buffer, n_buffer);
88 : 73 : gcry_md_write (md2, info, n_info);
89 [ - + ]: 73 : gcry_md_putc (md2, i);
90 : :
91 : 73 : n_buffer = hash_len;
92 : 73 : memcpy (buffer, gcry_md_read (md2, algo), n_buffer);
93 : :
94 : 73 : step = MIN (n_buffer, n_output);
95 : 73 : memcpy (at, buffer, step);
96 : 73 : n_output -= step;
97 : 73 : at += step;
98 : :
99 [ + + ]: 73 : if (!n_output)
100 : 59 : break;
101 : : }
102 : :
103 : 59 : g_free (alloc);
104 : 59 : gcry_free (buffer);
105 : 59 : gcry_md_close (md2);
106 : 59 : return TRUE;
107 : : }
|