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 a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <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 : #include "egg-secure-memory.h"
27 :
28 : #include <gcrypt.h>
29 :
30 : #include <string.h>
31 :
32 : gboolean
33 8 : egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
34 : gconstpointer salt, gsize n_salt, gconstpointer info,
35 : gsize n_info, gpointer output, gsize n_output)
36 : {
37 8 : gpointer alloc = NULL;
38 8 : gpointer buffer = NULL;
39 : gcry_md_hd_t md1, md2;
40 : guint hash_len;
41 : gint i;
42 : gint flags, algo;
43 : gsize step, n_buffer;
44 : guchar *at;
45 : gcry_error_t gcry;
46 :
47 8 : algo = gcry_md_map_name (hash_algo);
48 8 : g_return_val_if_fail (algo != 0, FALSE);
49 :
50 8 : hash_len = gcry_md_get_algo_dlen (algo);
51 8 : g_return_val_if_fail (hash_len != 0, FALSE);
52 8 : g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);
53 :
54 : /* Buffer we need to for intermediate stuff */
55 8 : if (gcry_is_secure (input)) {
56 1 : flags = GCRY_MD_FLAG_SECURE;
57 1 : buffer = gcry_malloc_secure (hash_len);
58 : } else {
59 7 : flags = 0;
60 7 : buffer = gcry_malloc (hash_len);
61 : }
62 :
63 8 : g_return_val_if_fail (buffer, FALSE);
64 8 : n_buffer = 0;
65 :
66 : /* Salt defaults to hash_len zeros */
67 8 : if (!salt) {
68 2 : salt = alloc = g_malloc0 (hash_len);
69 2 : n_salt = hash_len;
70 : }
71 :
72 : /* Step 1: Extract */
73 8 : gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags);
74 8 : g_return_val_if_fail (gcry == 0, FALSE);
75 8 : gcry = gcry_md_setkey (md1, salt, n_salt);
76 8 : g_return_val_if_fail (gcry == 0, FALSE);
77 8 : gcry_md_write (md1, input, n_input);
78 :
79 : /* Step 2: Expand */
80 8 : gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags);
81 8 : g_return_val_if_fail (gcry == 0, FALSE);
82 8 : gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
83 8 : g_return_val_if_fail (gcry == 0, FALSE);
84 8 : gcry_md_close (md1);
85 :
86 8 : at = output;
87 22 : for (i = 1; i < 256; ++i) {
88 22 : gcry_md_reset (md2);
89 22 : gcry_md_write (md2, buffer, n_buffer);
90 22 : gcry_md_write (md2, info, n_info);
91 22 : gcry_md_putc (md2, i);
92 :
93 22 : n_buffer = hash_len;
94 22 : memcpy (buffer, gcry_md_read (md2, algo), n_buffer);
95 :
96 22 : step = MIN (n_buffer, n_output);
97 22 : memcpy (at, buffer, step);
98 22 : n_output -= step;
99 22 : at += step;
100 :
101 22 : if (!n_output)
102 8 : break;
103 : }
104 :
105 8 : gcry_md_close (md2);
106 8 : g_free (alloc);
107 8 : gcry_free (buffer);
108 8 : return TRUE;
109 : }
|