Branch data Line data Source code
1 : : /* libsecret - GLib wrapper for Secret Service
2 : : *
3 : : * Copyright 2019 Red Hat, Inc.
4 : : *
5 : : * This program is free software: you can redistribute it and/or modify
6 : : * it under the terms of the GNU Lesser General Public License as published
7 : : * by the Free Software Foundation; either version 2.1 of the licence or (at
8 : : * your option) any later version.
9 : : *
10 : : * See the included COPYING file for more information.
11 : : *
12 : : * Author: Daiki Ueno
13 : : */
14 : :
15 : : #include "config.h"
16 : :
17 : : #include "egg-keyring1.h"
18 : :
19 : : #include "egg/egg-secure-memory.h"
20 : :
21 : 19 : EGG_SECURE_DECLARE (egg_keyring1);
22 : :
23 : : #include <gcrypt.h>
24 : :
25 : : #define PBKDF2_HASH_ALGO GCRY_MD_SHA256
26 : : #define MAC_ALGO GCRY_MAC_HMAC_SHA256
27 : : #define CIPHER_ALGO GCRY_CIPHER_AES128
28 : :
29 : : void
30 : 20 : egg_keyring1_create_nonce (guint8 *nonce,
31 : : gsize nonce_size)
32 : : {
33 : 20 : gcry_create_nonce (nonce, nonce_size);
34 : 20 : }
35 : :
36 : : GBytes *
37 : 19 : egg_keyring1_derive_key (const gchar *password,
38 : : gsize n_password,
39 : : GBytes *salt,
40 : : guint32 iteration_count)
41 : : {
42 : : guint8 *buffer;
43 : : gcry_error_t gcry;
44 : :
45 : 19 : buffer = egg_secure_alloc (KEY_SIZE);
46 [ - + ]: 19 : g_return_val_if_fail (buffer, NULL);
47 : :
48 : 19 : gcry = gcry_kdf_derive (password,
49 : : n_password,
50 : : GCRY_KDF_PBKDF2, PBKDF2_HASH_ALGO,
51 : : g_bytes_get_data (salt, NULL),
52 : : g_bytes_get_size (salt),
53 : : iteration_count,
54 : : KEY_SIZE, buffer);
55 [ - + ]: 19 : if (gcry != 0) {
56 : 0 : egg_secure_free (buffer);
57 : 0 : return NULL;
58 : : }
59 : :
60 : 19 : return g_bytes_new_with_free_func (buffer,
61 : : KEY_SIZE,
62 : : egg_secure_free,
63 : : buffer);
64 : : }
65 : :
66 : : gboolean
67 : 75 : egg_keyring1_calculate_mac (GBytes *key,
68 : : const guint8 *value,
69 : : gsize n_value,
70 : : guint8 *buffer)
71 : : {
72 : : gcry_mac_hd_t hd;
73 : : gcry_error_t gcry;
74 : : gconstpointer secret;
75 : : gsize n_secret;
76 : 75 : gboolean ret = FALSE;
77 : :
78 : 75 : gcry = gcry_mac_open (&hd, MAC_ALGO, 0, NULL);
79 [ - + ]: 75 : g_return_val_if_fail (gcry == 0, FALSE);
80 : :
81 : 75 : secret = g_bytes_get_data (key, &n_secret);
82 : 75 : gcry = gcry_mac_setkey (hd, secret, n_secret);
83 [ - + ]: 75 : if (gcry != 0)
84 : 0 : goto out;
85 : :
86 : 75 : gcry = gcry_mac_write (hd, value, n_value);
87 [ - + ]: 75 : if (gcry != 0)
88 : 0 : goto out;
89 : :
90 : 75 : n_value = MAC_SIZE;
91 : 75 : gcry = gcry_mac_read (hd, buffer, &n_value);
92 [ - + ]: 75 : if (gcry != 0)
93 : 0 : goto out;
94 : :
95 [ - + ]: 75 : if (n_value != MAC_SIZE)
96 : 0 : goto out;
97 : :
98 : 75 : ret = TRUE;
99 : 75 : out:
100 : 75 : gcry_mac_close (hd);
101 : 75 : return ret;
102 : : }
103 : :
104 : : gboolean
105 : 34 : egg_keyring1_verify_mac (GBytes *key,
106 : : const guint8 *value,
107 : : gsize n_value,
108 : : const guint8 *data)
109 : : {
110 : : guint8 buffer[MAC_SIZE];
111 : 34 : guint8 status = 0;
112 : : gsize i;
113 : :
114 [ - + ]: 34 : if (!egg_keyring1_calculate_mac (key, value, n_value, buffer)) {
115 : 0 : return FALSE;
116 : : }
117 : :
118 [ + + ]: 1122 : for (i = 0; i < MAC_SIZE; i++) {
119 : 1088 : status |= data[i] ^ buffer[i];
120 : : }
121 : :
122 : 34 : return status == 0;
123 : : }
124 : :
125 : : gboolean
126 : 11 : egg_keyring1_decrypt (GBytes *key,
127 : : guint8 *data,
128 : : gsize n_data)
129 : : {
130 : : gcry_cipher_hd_t hd;
131 : : gcry_error_t gcry;
132 : : gconstpointer secret;
133 : : gsize n_secret;
134 : 11 : gboolean ret = FALSE;
135 : :
136 : 11 : gcry = gcry_cipher_open (&hd, CIPHER_ALGO, GCRY_CIPHER_MODE_CBC, 0);
137 [ - + ]: 11 : if (gcry != 0)
138 : 0 : goto out;
139 : :
140 : 11 : secret = g_bytes_get_data (key, &n_secret);
141 : 11 : gcry = gcry_cipher_setkey (hd, secret, n_secret);
142 [ - + ]: 11 : if (gcry != 0)
143 : 0 : goto out;
144 : :
145 : 11 : gcry = gcry_cipher_setiv (hd, data + n_data, IV_SIZE);
146 [ - + ]: 11 : if (gcry != 0)
147 : 0 : goto out;
148 : :
149 : 11 : gcry = gcry_cipher_decrypt (hd, data, n_data, NULL, 0);
150 [ - + ]: 11 : if (gcry != 0)
151 : 0 : goto out;
152 : :
153 : 11 : ret = TRUE;
154 : 11 : out:
155 : 11 : gcry_cipher_close (hd);
156 : 11 : return ret;
157 : : }
158 : :
159 : : gboolean
160 : 12 : egg_keyring1_encrypt (GBytes *key,
161 : : guint8 *data,
162 : : gsize n_data)
163 : : {
164 : : gcry_cipher_hd_t hd;
165 : : gcry_error_t gcry;
166 : : gconstpointer secret;
167 : : gsize n_secret;
168 : 12 : gboolean ret = FALSE;
169 : :
170 : 12 : gcry = gcry_cipher_open (&hd, CIPHER_ALGO, GCRY_CIPHER_MODE_CBC, 0);
171 [ - + ]: 12 : if (gcry != 0)
172 : 0 : goto out;
173 : :
174 : 12 : secret = g_bytes_get_data (key, &n_secret);
175 : 12 : gcry = gcry_cipher_setkey (hd, secret, n_secret);
176 [ - + ]: 12 : if (gcry != 0)
177 : 0 : goto out;
178 : :
179 : 12 : egg_keyring1_create_nonce (data + n_data, IV_SIZE);
180 : :
181 : 12 : gcry = gcry_cipher_setiv (hd, data + n_data, IV_SIZE);
182 [ - + ]: 12 : if (gcry != 0)
183 : 0 : goto out;
184 : :
185 : 12 : gcry = gcry_cipher_encrypt (hd, data, n_data, NULL, 0);
186 [ - + ]: 12 : if (gcry != 0)
187 : 0 : goto out;
188 : :
189 : 12 : ret = TRUE;
190 : 12 : out:
191 : 12 : gcry_cipher_close (hd);
192 : 12 : return ret;
193 : : }
|