1 /*
2  * gnome-keyring
3  *
4  * Copyright (C) 2008 Stefan Walter
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 <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "config.h"
21 
22 #include "egg-asn1-defs.h"
23 #include "egg-asn1x.h"
24 #include "egg-secure-memory.h"
25 #include "egg-symkey.h"
26 
27 EGG_SECURE_DECLARE (symkey);
28 
29 /* -----------------------------------------------------------------------------
30  * QUARKS
31  */
32 
33 static GQuark OID_PBE_MD2_DES_CBC;
34 static GQuark OID_PBE_MD5_DES_CBC;
35 static GQuark OID_PBE_MD2_RC2_CBC;
36 static GQuark OID_PBE_MD5_RC2_CBC;
37 static GQuark OID_PBE_SHA1_DES_CBC;
38 static GQuark OID_PBE_SHA1_RC2_CBC;
39 static GQuark OID_PBES2;
40 static GQuark OID_PBKDF2;
41 
42 static GQuark OID_DES_CBC;
43 static GQuark OID_DES_RC2_CBC;
44 static GQuark OID_DES_EDE3_CBC;
45 static GQuark OID_DES_RC5_CBC;
46 
47 static GQuark OID_PKCS12_PBE_ARCFOUR_SHA1;
48 static GQuark OID_PKCS12_PBE_RC4_40_SHA1;
49 static GQuark OID_PKCS12_PBE_3DES_SHA1;
50 static GQuark OID_PKCS12_PBE_2DES_SHA1;
51 static GQuark OID_PKCS12_PBE_RC2_128_SHA1;
52 static GQuark OID_PKCS12_PBE_RC2_40_SHA1;
53 
54 static GQuark OID_SHA1;
55 
56 static void
init_quarks(void)57 init_quarks (void)
58 {
59 	static volatile gsize quarks_inited = 0;
60 
61 	if (g_once_init_enter (&quarks_inited)) {
62 
63 		#define QUARK(name, value) \
64 			name = g_quark_from_static_string(value)
65 
66 		QUARK (OID_PBE_MD2_DES_CBC, "1.2.840.113549.1.5.1");
67 		QUARK (OID_PBE_MD5_DES_CBC, "1.2.840.113549.1.5.3");
68 		QUARK (OID_PBE_MD2_RC2_CBC, "1.2.840.113549.1.5.4");
69 		QUARK (OID_PBE_MD5_RC2_CBC, "1.2.840.113549.1.5.6");
70 		QUARK (OID_PBE_SHA1_DES_CBC, "1.2.840.113549.1.5.10");
71 		QUARK (OID_PBE_SHA1_RC2_CBC, "1.2.840.113549.1.5.11");
72 
73 		QUARK (OID_PBES2, "1.2.840.113549.1.5.13");
74 
75 		QUARK (OID_PBKDF2, "1.2.840.113549.1.5.12");
76 
77 		QUARK (OID_DES_CBC, "1.3.14.3.2.7");
78 		QUARK (OID_DES_RC2_CBC, "1.2.840.113549.3.2");
79 		QUARK (OID_DES_EDE3_CBC, "1.2.840.113549.3.7");
80 		QUARK (OID_DES_RC5_CBC, "1.2.840.113549.3.9");
81 
82 		QUARK (OID_PKCS12_PBE_ARCFOUR_SHA1, "1.2.840.113549.1.12.1.1");
83 		QUARK (OID_PKCS12_PBE_RC4_40_SHA1, "1.2.840.113549.1.12.1.2");
84 		QUARK (OID_PKCS12_PBE_3DES_SHA1, "1.2.840.113549.1.12.1.3");
85 		QUARK (OID_PKCS12_PBE_2DES_SHA1, "1.2.840.113549.1.12.1.4");
86 		QUARK (OID_PKCS12_PBE_RC2_128_SHA1, "1.2.840.113549.1.12.1.5");
87 		QUARK (OID_PKCS12_PBE_RC2_40_SHA1, "1.2.840.113549.1.12.1.6");
88 
89 		QUARK (OID_SHA1, "1.3.14.3.2.26");
90 
91 		#undef QUARK
92 
93 		g_once_init_leave (&quarks_inited, 1);
94 	}
95 }
96 
97 /* -----------------------------------------------------------------------------
98  * PASSWORD TO KEY/IV
99  */
100 
101 gboolean
egg_symkey_generate_simple(int cipher_algo,int hash_algo,const gchar * password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar ** key,guchar ** iv)102 egg_symkey_generate_simple (int cipher_algo, int hash_algo,
103                             const gchar *password, gssize n_password,
104                             const guchar *salt, gsize n_salt, int iterations,
105                             guchar **key, guchar **iv)
106 {
107 	gcry_md_hd_t mdh;
108 	gcry_error_t gcry;
109 	guchar *digest;
110 	guchar *digested;
111 	guint n_digest;
112 	gint pass, i;
113 	gint needed_iv, needed_key;
114 	guchar *at_iv, *at_key;
115 
116 	g_assert (cipher_algo);
117 	g_assert (hash_algo);
118 
119 	g_return_val_if_fail (iterations >= 1, FALSE);
120 
121 	if (!password)
122 		n_password = 0;
123 	if (n_password == -1)
124 		n_password = strlen (password);
125 
126 	/*
127 	 * If cipher algo needs more bytes than hash algo has available
128 	 * then the entire hashing process is done again (with the previous
129 	 * hash bytes as extra input), and so on until satisfied.
130 	 */
131 
132 	needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
133 	needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
134 
135 	gcry = gcry_md_open (&mdh, hash_algo, 0);
136 	if (gcry) {
137 		g_warning ("couldn't create '%s' hash context: %s",
138 			   gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
139 		return FALSE;
140 	}
141 
142 	n_digest = gcry_md_get_algo_dlen (hash_algo);
143 	g_return_val_if_fail (n_digest > 0, FALSE);
144 
145 	digest = egg_secure_alloc (n_digest);
146 	g_return_val_if_fail (digest, FALSE);
147 	if (key) {
148 		*key = egg_secure_alloc (needed_key);
149 		g_return_val_if_fail (*key, FALSE);
150 	}
151 	if (iv)
152 		*iv = g_new0 (guchar, needed_iv);
153 
154 	at_key = key ? *key : NULL;
155 	at_iv = iv ? *iv : NULL;
156 
157 	for (pass = 0; TRUE; ++pass) {
158 		gcry_md_reset (mdh);
159 
160 		/* Hash in the previous buffer on later passes */
161 		if (pass > 0)
162 			gcry_md_write (mdh, digest, n_digest);
163 
164 		if (password)
165 			gcry_md_write (mdh, password, n_password);
166 		if (salt && n_salt)
167 			gcry_md_write (mdh, salt, n_salt);
168 		gcry_md_final (mdh);
169 		digested = gcry_md_read (mdh, 0);
170 		g_return_val_if_fail (digested, FALSE);
171 		memcpy (digest, digested, n_digest);
172 
173 		for (i = 1; i < iterations; ++i) {
174 			gcry_md_reset (mdh);
175 			gcry_md_write (mdh, digest, n_digest);
176 			gcry_md_final (mdh);
177 			digested = gcry_md_read (mdh, 0);
178 			g_return_val_if_fail (digested, FALSE);
179 			memcpy (digest, digested, n_digest);
180 		}
181 
182 		/* Copy as much as possible into the destinations */
183 		i = 0;
184 		while (needed_key && i < n_digest) {
185 			if (at_key)
186 				*(at_key++) = digest[i];
187 			needed_key--;
188 			i++;
189 		}
190 		while (needed_iv && i < n_digest) {
191 			if (at_iv)
192 				*(at_iv++) = digest[i];
193 			needed_iv--;
194 			i++;
195 		}
196 
197 		if (needed_key == 0 && needed_iv == 0)
198 			break;
199 	}
200 
201 	egg_secure_free (digest);
202 	gcry_md_close (mdh);
203 
204 	return TRUE;
205 }
206 
207 gboolean
egg_symkey_generate_pbe(int cipher_algo,int hash_algo,const gchar * password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar ** key,guchar ** iv)208 egg_symkey_generate_pbe (int cipher_algo, int hash_algo, const gchar *password,
209                          gssize n_password, const guchar *salt, gsize n_salt, int iterations,
210                          guchar **key, guchar **iv)
211 {
212 	gcry_md_hd_t mdh;
213 	gcry_error_t gcry;
214 	guchar *digest;
215 	guchar *digested;
216 	guint i, n_digest;
217 	gint needed_iv, needed_key;
218 
219 	g_assert (cipher_algo);
220 	g_assert (hash_algo);
221 
222 	g_return_val_if_fail (iterations >= 1, FALSE);
223 
224 	if (!password)
225 		n_password = 0;
226 	if (n_password == -1)
227 		n_password = strlen (password);
228 
229 	/*
230 	 * We only do one pass here.
231 	 *
232 	 * The key ends up as the first needed_key bytes of the hash buffer.
233 	 * The iv ends up as the last needed_iv bytes of the hash buffer.
234 	 *
235 	 * The IV may overlap the key (which is stupid) if the wrong pair of
236 	 * hash/cipher algorithms are chosen.
237 	 */
238 
239 	n_digest = gcry_md_get_algo_dlen (hash_algo);
240 	g_return_val_if_fail (n_digest > 0, FALSE);
241 
242 	needed_key = gcry_cipher_get_algo_keylen (cipher_algo);
243 	needed_iv = gcry_cipher_get_algo_blklen (cipher_algo);
244 	if (needed_iv + needed_key > 16 || needed_iv + needed_key > n_digest) {
245 		g_warning ("using PBE symkey generation with %s using an algorithm that needs "
246 		           "too many bytes of key and/or IV: %s",
247 		           gcry_cipher_algo_name (hash_algo),
248 		           gcry_cipher_algo_name (cipher_algo));
249 		return FALSE;
250 	}
251 
252 	gcry = gcry_md_open (&mdh, hash_algo, 0);
253 	if (gcry) {
254 		g_warning ("couldn't create '%s' hash context: %s",
255 			   gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
256 		return FALSE;
257 	}
258 
259 	digest = egg_secure_alloc (n_digest);
260 	g_return_val_if_fail (digest, FALSE);
261 	if (key) {
262 		*key = egg_secure_alloc (needed_key);
263 		g_return_val_if_fail (*key, FALSE);
264 	}
265 	if (iv)
266 		*iv = g_new0 (guchar, needed_iv);
267 
268 	if (password)
269 		gcry_md_write (mdh, password, n_password);
270 	if (salt && n_salt)
271 		gcry_md_write (mdh, salt, n_salt);
272 	gcry_md_final (mdh);
273 	digested = gcry_md_read (mdh, 0);
274 	g_return_val_if_fail (digested, FALSE);
275 	memcpy (digest, digested, n_digest);
276 
277 	for (i = 1; i < iterations; ++i)
278 		gcry_md_hash_buffer (hash_algo, digest, digest, n_digest);
279 
280 	/* The first x bytes are the key */
281 	if (key) {
282 		g_assert (needed_key <= n_digest);
283 		memcpy (*key, digest, needed_key);
284 	}
285 
286 	/* The last 16 - x bytes are the iv */
287 	if (iv) {
288 		g_assert (needed_iv <= n_digest && n_digest >= 16);
289 		memcpy (*iv, digest + (16 - needed_iv), needed_iv);
290 	}
291 
292 	egg_secure_free (digest);
293 	gcry_md_close (mdh);
294 
295 	return TRUE;
296 }
297 
298 static gboolean
generate_pkcs12(int hash_algo,int type,const gchar * utf8_password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar * output,gsize n_output)299 generate_pkcs12 (int hash_algo, int type, const gchar *utf8_password,
300                  gssize n_password, const guchar *salt, gsize n_salt,
301                  int iterations, guchar *output, gsize n_output)
302 {
303 	gcry_mpi_t num_b1, num_ij;
304 	guchar *hash, *buf_i, *buf_b;
305 	const gchar *end_password;
306 	gcry_md_hd_t mdh;
307 	const gchar *p2;
308 	guchar *p;
309 	gsize n_hash, i;
310 	gunichar unich;
311 	gcry_error_t gcry;
312 	gsize length;
313 
314 	num_b1 = num_ij = NULL;
315 
316 	n_hash = gcry_md_get_algo_dlen (hash_algo);
317 	g_return_val_if_fail (n_hash > 0, FALSE);
318 
319 	if (!utf8_password)
320 		n_password = 0;
321 	if (n_password == -1)
322 		end_password = utf8_password + strlen (utf8_password);
323 	else
324 		end_password = utf8_password + n_password;
325 
326 	gcry = gcry_md_open (&mdh, hash_algo, 0);
327 	if (gcry) {
328 		g_warning ("couldn't create '%s' hash context: %s",
329 		           gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
330 		return FALSE;
331 	}
332 
333 	/* Reqisition me a buffer */
334 	hash = egg_secure_alloc (n_hash);
335 	buf_i = egg_secure_alloc (128);
336 	buf_b = egg_secure_alloc (64);
337 	g_return_val_if_fail (hash && buf_i && buf_b, FALSE);
338 
339 	/* Bring in the salt */
340 	p = buf_i;
341 	if (salt) {
342 		for (i = 0; i < 64; ++i)
343 			*(p++) = salt[i % n_salt];
344 	} else {
345 		memset (p, 0, 64);
346 		p += 64;
347 	}
348 
349 	/* Bring in the password, as 16bits per character BMP string, ie: UCS2 */
350 	if (utf8_password) {
351 		p2 = utf8_password;
352 		for (i = 0; i < 64; i += 2) {
353 
354 			/* Get a character from the string */
355 			if (p2 < end_password) {
356 				unich = g_utf8_get_char (p2);
357 				p2 = g_utf8_next_char (p2);
358 
359 			/* Get zero null terminator, and loop back to beginning */
360 			} else {
361 				unich = 0;
362 				p2 = utf8_password;
363 			}
364 
365 			/* Encode the bytes received */
366 			*(p++) = (unich & 0xFF00) >> 8;
367 			*(p++) = (unich & 0xFF);
368 		}
369 	} else {
370 		memset (p, 0, 64);
371 	}
372 
373 	/* Hash and bash */
374 	for (;;) {
375 		gcry_md_reset (mdh);
376 
377 		/* Put in the PKCS#12 type of key */
378 		for (i = 0; i < 64; ++i)
379 			gcry_md_putc (mdh, type);
380 
381 		/* Bring in the password */
382 		gcry_md_write (mdh, buf_i, utf8_password ? 128 : 64);
383 
384 		/* First iteration done */
385 		memcpy (hash, gcry_md_read (mdh, hash_algo), n_hash);
386 
387 		/* All the other iterations */
388 		for (i = 1; i < iterations; i++)
389 			gcry_md_hash_buffer (hash_algo, hash, hash, n_hash);
390 
391 		/* Take out as much as we need */
392 		for (i = 0; i < n_hash && n_output; ++i) {
393 			*(output++) = hash[i];
394 			--n_output;
395 		}
396 
397 		/* Is that enough generated keying material? */
398 		if (!n_output)
399 			break;
400 
401 		/* Need more bytes, do some voodoo */
402 		for (i = 0; i < 64; ++i)
403 			buf_b[i] = hash[i % n_hash];
404 		gcry = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, NULL);
405 		g_return_val_if_fail (gcry == 0, FALSE);
406 		gcry_mpi_add_ui (num_b1, num_b1, 1);
407 		for (i = 0; i < 128; i += 64) {
408 			gcry = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, NULL);
409 			g_return_val_if_fail (gcry == 0, FALSE);
410 			gcry_mpi_add (num_ij, num_ij, num_b1);
411 			gcry_mpi_clear_highbit (num_ij, 64 * 8);
412 			/* We take special care to right align the number in the buffer */
413 			gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &length, num_ij);
414 			g_return_val_if_fail (gcry == 0 && length <= 64, FALSE);
415 			memset (buf_i + i, 0, 64 - length);
416 			gcry = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i + (64 - length), 64, NULL, num_ij);
417 			g_return_val_if_fail (gcry == 0, FALSE);
418 			gcry_mpi_release (num_ij);
419 		}
420 	}
421 
422 	egg_secure_free (buf_i);
423 	egg_secure_free (buf_b);
424 	egg_secure_free (hash);
425 	gcry_mpi_release (num_b1);
426 	gcry_md_close (mdh);
427 
428 	return TRUE;
429 }
430 
431 gboolean
egg_symkey_generate_pkcs12(int cipher_algo,int hash_algo,const gchar * password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar ** key,guchar ** iv)432 egg_symkey_generate_pkcs12 (int cipher_algo, int hash_algo, const gchar *password,
433                             gssize n_password, const guchar *salt, gsize n_salt,
434                             int iterations, guchar **key, guchar **iv)
435 {
436 	gsize n_block, n_key;
437 	gboolean ret = TRUE;
438 
439 	g_return_val_if_fail (cipher_algo, FALSE);
440 	g_return_val_if_fail (hash_algo, FALSE);
441 	g_return_val_if_fail (iterations > 0, FALSE);
442 
443 	n_key = gcry_cipher_get_algo_keylen (cipher_algo);
444 	n_block = gcry_cipher_get_algo_blklen (cipher_algo);
445 
446 	if (password && !g_utf8_validate (password, n_password, NULL)) {
447 		g_warning ("invalid non-UTF8 password");
448 		g_return_val_if_reached (FALSE);
449 	}
450 
451 	if (key)
452 		*key = NULL;
453 	if (iv)
454 		*iv = NULL;
455 
456 	/* Generate us an key */
457 	if (key) {
458 		*key = egg_secure_alloc (n_key);
459 		g_return_val_if_fail (*key != NULL, FALSE);
460 		ret = generate_pkcs12 (hash_algo, 1, password, n_password, salt, n_salt,
461 		                       iterations, *key, n_key);
462 	}
463 
464 	/* Generate us an iv */
465 	if (ret && iv) {
466 		if (n_block > 1) {
467 			*iv = g_malloc (n_block);
468 			ret = generate_pkcs12 (hash_algo, 2, password, n_password, salt, n_salt,
469 			                       iterations, *iv, n_block);
470 		} else {
471 			*iv = NULL;
472 		}
473 	}
474 
475 	/* Cleanup in case of failure */
476 	if (!ret) {
477 		g_free (iv ? *iv : NULL);
478 		egg_secure_free (key ? *key : NULL);
479 	}
480 
481 	return ret;
482 }
483 
484 gboolean
egg_symkey_generate_pkcs12_mac(int hash_algo,const gchar * password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar ** key)485 egg_symkey_generate_pkcs12_mac (int hash_algo,
486                                 const gchar *password,
487                                 gssize n_password,
488                                 const guchar *salt,
489                                 gsize n_salt,
490                                 int iterations,
491                                 guchar **key)
492 {
493 	gsize n_key;
494 	gboolean ret = TRUE;
495 
496 	g_return_val_if_fail (hash_algo, FALSE);
497 	g_return_val_if_fail (iterations > 0, FALSE);
498 
499 	n_key = gcry_md_get_algo_dlen (hash_algo);
500 
501 	if (password && !g_utf8_validate (password, n_password, NULL)) {
502 		g_warning ("invalid non-UTF8 password");
503 		g_return_val_if_reached (FALSE);
504 	}
505 
506 	/* Generate us an key */
507 	if (key) {
508 		*key = egg_secure_alloc (n_key);
509 		g_return_val_if_fail (*key != NULL, FALSE);
510 		ret = generate_pkcs12 (hash_algo, 3, password, n_password, salt, n_salt,
511 		                       iterations, *key, n_key);
512 	}
513 
514 	/* Cleanup in case of failure */
515 	if (!key)
516 		egg_secure_free (key ? *key : NULL);
517 
518 	return ret;
519 }
520 
521 static gboolean
generate_pbkdf2(int hash_algo,const gchar * password,gsize n_password,const guchar * salt,gsize n_salt,guint iterations,guchar * output,gsize n_output)522 generate_pbkdf2 (int hash_algo, const gchar *password, gsize n_password,
523 		 const guchar *salt, gsize n_salt, guint iterations,
524 		 guchar *output, gsize n_output)
525 {
526 	gcry_md_hd_t mdh;
527 	guint u, l, r, i, k;
528 	gcry_error_t gcry;
529 	guchar *U, *T, *buf;
530 	gsize n_buf, n_hash;
531 
532 	g_return_val_if_fail (hash_algo > 0, FALSE);
533 	g_return_val_if_fail (iterations > 0, FALSE);
534 	g_return_val_if_fail (n_output > 0, FALSE);
535 	g_return_val_if_fail (n_output < G_MAXUINT32, FALSE);
536 
537 	n_hash = gcry_md_get_algo_dlen (hash_algo);
538 	g_return_val_if_fail (n_hash > 0, FALSE);
539 
540 	gcry = gcry_md_open (&mdh, hash_algo, GCRY_MD_FLAG_HMAC);
541 	if (gcry != 0) {
542 		g_warning ("couldn't create '%s' hash context: %s",
543 		           gcry_md_algo_name (hash_algo), gcry_strerror (gcry));
544 		return FALSE;
545 	}
546 
547 	/* Get us a temporary buffers */
548 	T = egg_secure_alloc (n_hash);
549 	U = egg_secure_alloc (n_hash);
550 	n_buf = n_salt + 4;
551 	buf = egg_secure_alloc (n_buf);
552 	g_return_val_if_fail (buf && T && U, FALSE);
553 
554 	/* n_hash blocks in output, rounding up */
555 	l = ((n_output - 1) / n_hash) + 1;
556 
557 	/* number of bytes in last, rounded up, n_hash block */
558 	r = n_output - (l - 1) * n_hash;
559 
560 	memcpy (buf, salt, n_salt);
561 	for (i = 1; i <= l; i++) {
562 		memset (T, 0, n_hash);
563 		for (u = 1; u <= iterations; u++) {
564 			gcry_md_reset (mdh);
565 
566 			gcry = gcry_md_setkey (mdh, password, n_password);
567 			g_return_val_if_fail (gcry == 0, FALSE);
568 
569 			/* For first iteration on each block add 4 extra bytes */
570 			if (u == 1) {
571 				buf[n_salt + 0] = (i & 0xff000000) >> 24;
572 				buf[n_salt + 1] = (i & 0x00ff0000) >> 16;
573 				buf[n_salt + 2] = (i & 0x0000ff00) >> 8;
574 				buf[n_salt + 3] = (i & 0x000000ff) >> 0;
575 
576 				gcry_md_write (mdh, buf, n_buf);
577 
578 			/* Other iterations, any block */
579 			} else {
580 				gcry_md_write (mdh, U, n_hash);
581 			}
582 
583 			memcpy (U, gcry_md_read (mdh, hash_algo), n_hash);
584 
585 			for (k = 0; k < n_hash; k++)
586 				T[k] ^= U[k];
587 		}
588 
589 		memcpy (output + (i - 1) * n_hash, T, i == l ? r : n_hash);
590 	}
591 
592 	egg_secure_free (T);
593 	egg_secure_free (U);
594 	egg_secure_free (buf);
595 	gcry_md_close (mdh);
596 	return TRUE;
597 }
598 
599 gboolean
egg_symkey_generate_pbkdf2(int cipher_algo,int hash_algo,const gchar * password,gssize n_password,const guchar * salt,gsize n_salt,int iterations,guchar ** key,guchar ** iv)600 egg_symkey_generate_pbkdf2 (int cipher_algo, int hash_algo,
601                             const gchar *password, gssize n_password,
602                             const guchar *salt, gsize n_salt, int iterations,
603                             guchar **key, guchar **iv)
604 {
605 	gsize n_key, n_block;
606 	gboolean ret = TRUE;
607 
608 	g_return_val_if_fail (hash_algo, FALSE);
609 	g_return_val_if_fail (cipher_algo, FALSE);
610 	g_return_val_if_fail (iterations > 0, FALSE);
611 
612 	n_key = gcry_cipher_get_algo_keylen (cipher_algo);
613 	n_block = gcry_cipher_get_algo_blklen (cipher_algo);
614 
615 	if (key)
616 		*key = NULL;
617 	if (iv)
618 		*iv = NULL;
619 
620 	if (!password)
621 		n_password = 0;
622 	if (n_password == -1)
623 		n_password = strlen (password);
624 
625 	/* Generate us an key */
626 	if (key) {
627 		*key = egg_secure_alloc (n_key);
628 		g_return_val_if_fail (*key != NULL, FALSE);
629 		ret = generate_pbkdf2 (hash_algo, password, n_password, salt, n_salt,
630 		                       iterations, *key, n_key);
631 	}
632 
633 	/* Generate us an iv */
634 	if (ret && iv) {
635 		if (n_block > 1) {
636 			*iv = g_malloc (n_block);
637 			gcry_create_nonce (*iv, n_block);
638 		} else {
639 			*iv = NULL;
640 		}
641 	}
642 
643 	/* Cleanup in case of failure */
644 	if (!ret) {
645 		g_free (iv ? *iv : NULL);
646 		egg_secure_free (key ? *key : NULL);
647 	}
648 
649 	return ret;
650 }
651 
652 /* ----------------------------------------------------------------------------
653  * DER encoded cipher params
654  */
655 
656 
657 static gboolean
read_cipher_pkcs5_pbe(int cipher_algo,int cipher_mode,int hash_algo,const gchar * password,gsize n_password,GNode * data,gcry_cipher_hd_t * cih)658 read_cipher_pkcs5_pbe (int cipher_algo,
659                        int cipher_mode,
660                        int hash_algo,
661                        const gchar *password,
662                        gsize n_password,
663                        GNode *data,
664                        gcry_cipher_hd_t *cih)
665 {
666 	GNode *asn = NULL;
667 	gcry_error_t gcry;
668 	GBytes *salt = NULL;
669 	gsize n_block, n_key;
670 	gulong iterations;
671 	guchar *key = NULL;
672 	guchar *iv = NULL;
673 	gboolean ret;
674 
675 	g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, FALSE);
676 	g_return_val_if_fail (cih != NULL, FALSE);
677 	g_return_val_if_fail (data != NULL, FALSE);
678 
679 	*cih = NULL;
680 	ret = FALSE;
681 
682 	/* Check if we can use this algorithm */
683 	if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0 ||
684 	    gcry_md_test_algo (hash_algo) != 0)
685 		goto done;
686 
687 	asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-5-PBE-params");
688 	g_return_val_if_fail (asn, FALSE);
689 
690 	if (!egg_asn1x_get_any_into (data, asn))
691 		goto done;
692 
693 	salt = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "salt", NULL));
694 	g_return_val_if_fail (salt != NULL, FALSE);
695 	if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
696 		g_return_val_if_reached (FALSE);
697 
698 	n_key = gcry_cipher_get_algo_keylen (cipher_algo);
699 	g_return_val_if_fail (n_key > 0, FALSE);
700 	n_block = gcry_cipher_get_algo_blklen (cipher_algo);
701 
702 	if (!egg_symkey_generate_pbe (cipher_algo, hash_algo, password, n_password,
703 	                              g_bytes_get_data (salt, NULL), g_bytes_get_size (salt),
704 	                              iterations, &key, n_block > 1 ? &iv : NULL))
705 		goto done;
706 
707 	gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
708 	if (gcry != 0) {
709 		g_warning ("couldn't create cipher: %s", gcry_strerror (gcry));
710 		goto done;
711 	}
712 
713 	if (iv)
714 		gcry_cipher_setiv (*cih, iv, n_block);
715 	gcry_cipher_setkey (*cih, key, n_key);
716 
717 	ret = TRUE;
718 
719 done:
720 	g_free (iv);
721 	if (salt != NULL)
722 		g_bytes_unref (salt);
723 	egg_secure_free (key);
724 	egg_asn1x_destroy (asn);
725 
726 	return ret;
727 }
728 
729 #if NOT_SUPPORTED
730 static gboolean
setup_pkcs5_rc2_params(GNode * any,gcry_cipher_hd_t cih)731 setup_pkcs5_rc2_params (GNode *any,
732                         gcry_cipher_hd_t cih)
733 {
734 	GNode *asn = NULL;
735 	gcry_error_t gcry;
736 	GBytes *iv = NULL;
737 	gulong version;
738 	gboolean ret = FALSE;
739 
740 	g_assert (any != NULL);
741 
742 	asn = egg_asn1x_get_any_as (any, pkix_asn1_tab, "pkcs-5-rc2-CBC-params");
743 	if (asn == NULL)
744 		goto done;
745 
746 	if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "rc2ParameterVersion", NULL), &version))
747 		goto done;
748 
749 	iv = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "iv", NULL));
750 	if (!iv)
751 		goto done;
752 
753 	gcry = gcry_cipher_setiv (cih, g_bytes_get_data (iv, NULL), g_bytes_get_size (iv));
754 	if (gcry != 0) {
755 		g_message ("couldn't set %lu byte iv on cipher", (gulong)g_bytes_get_size (iv));
756 		goto done;
757 	}
758 
759 	ret = TRUE;
760 
761 done:
762 	if (iv != NULL)
763 		g_bytes_unref (iv);
764 	egg_asn1x_destroy (asn);
765 	return ret;
766 }
767 #endif
768 
769 static gboolean
setup_pkcs5_des_params(GNode * any,gcry_cipher_hd_t cih)770 setup_pkcs5_des_params (GNode *any,
771                         gcry_cipher_hd_t cih)
772 {
773 	GNode *asn = NULL;
774 	gcry_error_t gcry;
775 	GBytes *iv;
776 	gboolean ret;
777 
778 	g_assert (any != NULL);
779 
780 	asn = egg_asn1x_get_any_as (any, pkix_asn1_tab, "pkcs-5-des-EDE3-CBC-params");
781 	if (!asn)
782 		asn = egg_asn1x_get_any_as (any, pkix_asn1_tab, "pkcs-5-des-CBC-params");
783 	if (!asn)
784 		return FALSE;
785 
786 	iv = egg_asn1x_get_string_as_bytes (asn);
787 	egg_asn1x_destroy (asn);
788 
789 	if (!iv)
790 		return FALSE;
791 
792 	gcry = gcry_cipher_setiv (cih, g_bytes_get_data (iv, NULL), g_bytes_get_size (iv));
793 	if (gcry != 0) {
794 		g_message ("couldn't set %lu byte iv on cipher", (gulong)g_bytes_get_size (iv));
795 		ret = FALSE;
796 	} else {
797 		ret = TRUE;
798 	}
799 
800 	g_bytes_unref (iv);
801 	return ret;
802 }
803 
804 static gboolean
setup_pkcs5_pbkdf2_params(const gchar * password,gsize n_password,GNode * any,int cipher_algo,gcry_cipher_hd_t cih)805 setup_pkcs5_pbkdf2_params (const gchar *password,
806                            gsize n_password,
807                            GNode *any,
808                            int cipher_algo,
809                            gcry_cipher_hd_t cih)
810 {
811 	GNode *asn = NULL;
812 	gboolean ret;
813 	gcry_error_t gcry;
814 	guchar *key = NULL;
815 	GBytes *salt = NULL;
816 	gsize n_key;
817 	gulong iterations;
818 
819 	g_assert (cipher_algo);
820 	g_assert (any != NULL);
821 
822 	ret = FALSE;
823 
824 	asn = egg_asn1x_get_any_as (any, pkix_asn1_tab, "pkcs-5-PBKDF2-params");
825 	if (!asn)
826 		goto done;
827 
828 	if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterationCount", NULL), &iterations))
829 		g_return_val_if_reached (FALSE);
830 	salt = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "salt", "specified", NULL));
831 	if (!salt)
832 		goto done;
833 
834 	if (!egg_symkey_generate_pbkdf2 (cipher_algo, GCRY_MD_SHA1, password, n_password,
835 	                                 g_bytes_get_data (salt, NULL), g_bytes_get_size (salt),
836 	                                 iterations, &key, NULL))
837 		goto done;
838 
839 	n_key = gcry_cipher_get_algo_keylen (cipher_algo);
840 	g_return_val_if_fail (n_key > 0, FALSE);
841 
842 	gcry = gcry_cipher_setkey (cih, key, n_key);
843 	if (gcry != 0) {
844 		g_message ("couldn't set %lu byte key on cipher", (gulong)n_key);
845 		goto done;
846 	}
847 
848 	ret = TRUE;
849 
850 done:
851 	if (salt != NULL)
852 		g_bytes_unref (salt);
853 	egg_secure_free (key);
854 	egg_asn1x_destroy (asn);
855 	return ret;
856 }
857 
858 static gboolean
read_cipher_pkcs5_pbes2(const gchar * password,gsize n_password,GNode * data,gcry_cipher_hd_t * cih)859 read_cipher_pkcs5_pbes2 (const gchar *password,
860                          gsize n_password,
861                          GNode *data,
862                          gcry_cipher_hd_t *cih)
863 {
864 	GNode *asn = NULL;
865 	gboolean r, ret;
866 	GQuark key_deriv_algo, enc_oid;
867 	GNode *params = NULL;
868 	gcry_error_t gcry;
869 	int algo, mode;
870 
871 	g_return_val_if_fail (cih != NULL, FALSE);
872 	g_return_val_if_fail (data != NULL, FALSE);
873 
874 	init_quarks ();
875 
876 	*cih = NULL;
877 	ret = FALSE;
878 
879 	asn = egg_asn1x_get_any_as (data, pkix_asn1_tab, "pkcs-5-PBES2-params");
880 	if (!asn)
881 		goto done;
882 
883 	algo = mode = 0;
884 
885 	/* Read in all the encryption type */
886 	enc_oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "encryptionScheme", "algorithm", NULL));
887 	if (!enc_oid)
888 		goto done;
889 	if (enc_oid == OID_DES_EDE3_CBC)
890 		algo = GCRY_CIPHER_3DES;
891 	else if (enc_oid == OID_DES_CBC)
892 		algo = GCRY_CIPHER_DES;
893 	else if (enc_oid == OID_DES_RC2_CBC)
894 		/* GCRY_CIPHER_RFC2268_128 isn't actually implemented in libgcrypt (yet?) */;
895 	else if (enc_oid == OID_DES_RC5_CBC)
896 		/* RC5 doesn't exist in libgcrypt */;
897 
898 	/* Unsupported? */
899 	if (algo == 0 || gcry_cipher_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
900 		goto done;
901 
902 	/* Instantiate our cipher */
903 	gcry = gcry_cipher_open (cih, algo, GCRY_CIPHER_MODE_CBC, 0);
904 	if (gcry != 0) {
905 		g_warning ("couldn't create cipher: %s", gcry_cipher_algo_name (algo)); /* UNREACHABLE: */
906 		goto done; /* UNREACHABLE: with normal libgcrypt behavior */
907 	}
908 
909 	/* Read out the parameters. OPTIONAL, but will always find node */
910 	params = egg_asn1x_node (asn, "encryptionScheme", "parameters", NULL);
911 	g_return_val_if_fail (params != NULL, FALSE);
912 
913 	switch (algo) {
914 	case GCRY_CIPHER_3DES:
915 	case GCRY_CIPHER_DES:
916 		r = setup_pkcs5_des_params (params, *cih);
917 		break;
918 #if 0
919 	case GCRY_CIPHER_RFC2268_128:
920 		r = setup_pkcs5_rc2_params (params, *cih);
921 		break;
922 #endif
923 	default:
924 		/* Should have been caught on the oid check above */
925 		g_assert_not_reached ();
926 		r = FALSE;
927 		break;
928 	};
929 
930 	if (r != TRUE)
931 		goto done;
932 
933 	/* Read out the key creation paramaters */
934 	key_deriv_algo = egg_asn1x_get_oid_as_quark (egg_asn1x_node (asn, "keyDerivationFunc", "algorithm", NULL));
935 	if (!key_deriv_algo)
936 		goto done;
937 	if (key_deriv_algo != OID_PBKDF2) {
938 		g_message ("unsupported key derivation algorithm: %s", g_quark_to_string (key_deriv_algo));
939 		goto done;
940 	}
941 
942 	/* parameters is OPTIONAL, but will always find node */
943 	params = egg_asn1x_node (asn, "keyDerivationFunc", "parameters", NULL);
944 	g_return_val_if_fail (params != NULL, FALSE);
945 
946 	ret = setup_pkcs5_pbkdf2_params (password, n_password, params, algo, *cih);
947 
948 done:
949 	if (ret != TRUE && *cih) {
950 		gcry_cipher_close (*cih);
951 		*cih = NULL;
952 	}
953 
954 	egg_asn1x_destroy (asn);
955 	return ret;
956 }
957 
958 static gboolean
read_cipher_pkcs12_pbe(int cipher_algo,int cipher_mode,const gchar * password,gsize n_password,GNode * data,gcry_cipher_hd_t * cih)959 read_cipher_pkcs12_pbe (int cipher_algo,
960                         int cipher_mode,
961                         const gchar *password,
962                         gsize n_password,
963                         GNode *data,
964                         gcry_cipher_hd_t *cih)
965 {
966 	GNode *asn = NULL;
967 	gcry_error_t gcry;
968 	gboolean ret;
969 	GBytes *salt = NULL;
970 	gsize n_block, n_key;
971 	gulong iterations;
972 	guchar *key = NULL;
973 	guchar *iv = NULL;
974 
975 	g_return_val_if_fail (cipher_algo != 0 && cipher_mode != 0, FALSE);
976 	g_return_val_if_fail (cih != NULL, FALSE);
977 	g_return_val_if_fail (data != NULL, FALSE);
978 
979 	*cih = NULL;
980 	ret = FALSE;
981 
982 	/* Check if we can use this algorithm */
983 	if (gcry_cipher_algo_info (cipher_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
984 		goto done;
985 
986 	asn = egg_asn1x_get_any_as (data, pkix_asn1_tab, "pkcs-12-PbeParams");
987 	if (!asn)
988 		goto done;
989 
990 	salt = egg_asn1x_get_string_as_bytes (egg_asn1x_node (asn, "salt", NULL));
991 	g_return_val_if_fail (salt != NULL, FALSE);
992 	if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "iterations", NULL), &iterations))
993 		g_return_val_if_reached (FALSE);
994 
995 	n_block = gcry_cipher_get_algo_blklen (cipher_algo);
996 	n_key = gcry_cipher_get_algo_keylen (cipher_algo);
997 
998 	/* Generate IV and key using salt read above */
999 	if (!egg_symkey_generate_pkcs12 (cipher_algo, GCRY_MD_SHA1, password, n_password,
1000 	                                 g_bytes_get_data (salt, NULL), g_bytes_get_size (salt),
1001 	                                 iterations, &key, n_block > 1 ? &iv : NULL))
1002 		goto done;
1003 
1004 	gcry = gcry_cipher_open (cih, cipher_algo, cipher_mode, 0);
1005 	if (gcry != 0) {
1006 		g_warning ("couldn't create encryption cipher: %s", gcry_strerror (gcry));
1007 		goto done;
1008 	}
1009 
1010 	if (iv)
1011 		gcry_cipher_setiv (*cih, iv, n_block);
1012 	gcry_cipher_setkey (*cih, key, n_key);
1013 
1014 	ret = TRUE;
1015 
1016 done:
1017 	if (ret != TRUE && *cih) {
1018 		gcry_cipher_close (*cih);
1019 		*cih = NULL;
1020 	}
1021 
1022 	if (salt != NULL)
1023 		g_bytes_unref (salt);
1024 	g_free (iv);
1025 	egg_secure_free (key);
1026 	egg_asn1x_destroy (asn);
1027 	return ret;
1028 }
1029 
1030 static gboolean
read_mac_pkcs12_pbe(int hash_algo,const gchar * password,gsize n_password,GNode * data,gcry_md_hd_t * mdh,gsize * digest_len)1031 read_mac_pkcs12_pbe (int hash_algo,
1032                      const gchar *password,
1033                      gsize n_password,
1034                      GNode *data,
1035                      gcry_md_hd_t *mdh,
1036                      gsize *digest_len)
1037 {
1038 	GNode *asn = NULL;
1039 	gcry_error_t gcry;
1040 	gboolean ret;
1041 	gsize n_key;
1042 	GBytes *salt = NULL;
1043 	gulong iterations;
1044 	guchar *key = NULL;
1045 
1046 	g_return_val_if_fail (hash_algo != 0, FALSE);
1047 	g_return_val_if_fail (mdh != NULL, FALSE);
1048 	g_return_val_if_fail (data != NULL, FALSE);
1049 
1050 	*mdh = NULL;
1051 	ret = FALSE;
1052 
1053 	/* Check if we can use this algorithm */
1054 	if (gcry_md_algo_info (hash_algo, GCRYCTL_TEST_ALGO, NULL, 0) != 0)
1055 		goto done; /* UNREACHABLE: unless libgcrypt changes behavior */
1056 
1057 	if (egg_asn1x_type (data) == EGG_ASN1X_ANY) {
1058 		asn = egg_asn1x_get_any_as (data, pkix_asn1_tab, "pkcs-12-MacData");
1059 		if (!asn)
1060 			goto done;
1061 		data = asn;
1062 	}
1063 
1064 	salt = egg_asn1x_get_string_as_bytes (egg_asn1x_node (data, "macSalt", NULL));
1065 	if (!salt)
1066 		g_return_val_if_reached (FALSE);
1067 	if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (data, "iterations", NULL), &iterations))
1068 		g_return_val_if_reached (FALSE);
1069 
1070 	n_key = gcry_md_get_algo_dlen (hash_algo);
1071 
1072 	/* Generate IV and key using salt read above */
1073 	if (!egg_symkey_generate_pkcs12_mac (hash_algo, password, n_password,
1074 	                                     g_bytes_get_data (salt, NULL), g_bytes_get_size (salt),
1075 	                                     iterations, &key))
1076 		goto done;
1077 
1078 	gcry = gcry_md_open (mdh, hash_algo, GCRY_MD_FLAG_HMAC);
1079 	if (gcry != 0) {
1080 		g_warning ("couldn't create mac digest: %s", gcry_strerror (gcry));
1081 		goto done;
1082 	}
1083 
1084 	if (digest_len)
1085 		*digest_len = n_key;
1086 	gcry_md_setkey (*mdh, key, n_key);
1087 
1088 	ret = TRUE;
1089 
1090 done:
1091 	if (ret != TRUE && *mdh) {
1092 		gcry_md_close (*mdh);
1093 		*mdh = NULL;
1094 	}
1095 
1096 	if (salt != NULL)
1097 		g_bytes_unref (salt);
1098 	egg_secure_free (key);
1099 	egg_asn1x_destroy (asn);
1100 	return ret;
1101 }
1102 
1103 gboolean
egg_symkey_read_cipher(GQuark oid_scheme,const gchar * password,gsize n_password,GNode * data,gcry_cipher_hd_t * cih)1104 egg_symkey_read_cipher (GQuark oid_scheme,
1105                         const gchar *password,
1106                         gsize n_password,
1107                         GNode *data,
1108                         gcry_cipher_hd_t *cih)
1109 {
1110 	gboolean ret = FALSE;
1111 
1112 	g_return_val_if_fail (oid_scheme != 0, FALSE);
1113 	g_return_val_if_fail (cih != NULL, FALSE);
1114 	g_return_val_if_fail (data != NULL, FALSE);
1115 
1116 	init_quarks ();
1117 
1118 	/* PKCS#5 PBE */
1119 	if (oid_scheme == OID_PBE_MD2_DES_CBC)
1120 		ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
1121 		                             GCRY_MD_MD2, password, n_password, data, cih);
1122 
1123 	else if (oid_scheme == OID_PBE_MD2_RC2_CBC)
1124 		/* RC2-64 has no implementation in libgcrypt */;
1125 
1126 	else if (oid_scheme == OID_PBE_MD5_DES_CBC)
1127 		ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
1128 		                             GCRY_MD_MD5, password, n_password, data, cih);
1129 	else if (oid_scheme == OID_PBE_MD5_RC2_CBC)
1130 		/* RC2-64 has no implementation in libgcrypt */;
1131 
1132 	else if (oid_scheme == OID_PBE_SHA1_DES_CBC)
1133 		ret = read_cipher_pkcs5_pbe (GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC,
1134 		                             GCRY_MD_SHA1, password, n_password, data, cih);
1135 	else if (oid_scheme == OID_PBE_SHA1_RC2_CBC)
1136 		/* RC2-64 has no implementation in libgcrypt */;
1137 
1138 
1139 	/* PKCS#5 PBES2 */
1140 	else if (oid_scheme == OID_PBES2)
1141 		ret = read_cipher_pkcs5_pbes2 (password, n_password, data, cih);
1142 
1143 
1144 	/* PKCS#12 PBE */
1145 	else if (oid_scheme == OID_PKCS12_PBE_ARCFOUR_SHA1)
1146 		ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM,
1147 		                              password, n_password, data, cih);
1148 	else if (oid_scheme == OID_PKCS12_PBE_RC4_40_SHA1)
1149 		/* RC4-40 has no implementation in libgcrypt */;
1150 
1151 	else if (oid_scheme == OID_PKCS12_PBE_3DES_SHA1)
1152 		ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC,
1153 		                              password, n_password, data, cih);
1154 	else if (oid_scheme == OID_PKCS12_PBE_2DES_SHA1)
1155 		/* 2DES has no implementation in libgcrypt */;
1156 
1157 	else if (oid_scheme == OID_PKCS12_PBE_RC2_128_SHA1)
1158 		ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_128, GCRY_CIPHER_MODE_CBC,
1159 		                              password, n_password, data, cih);
1160 
1161 	else if (oid_scheme == OID_PKCS12_PBE_RC2_40_SHA1)
1162 		ret = read_cipher_pkcs12_pbe (GCRY_CIPHER_RFC2268_40, GCRY_CIPHER_MODE_CBC,
1163 		                              password, n_password, data, cih);
1164 
1165 	if (ret == FALSE)
1166 		g_message ("unsupported or invalid cipher: %s", g_quark_to_string (oid_scheme));
1167 
1168 	return ret;
1169 }
1170 
1171 gboolean
egg_symkey_read_mac(GQuark oid_scheme,const gchar * password,gsize n_password,GNode * data,gcry_md_hd_t * mdh,gsize * digest_len)1172 egg_symkey_read_mac (GQuark oid_scheme,
1173                      const gchar *password,
1174                      gsize n_password,
1175                      GNode *data,
1176                      gcry_md_hd_t *mdh,
1177                      gsize *digest_len)
1178 {
1179 	gboolean ret = FALSE;
1180 
1181 	g_return_val_if_fail (oid_scheme != 0, FALSE);
1182 	g_return_val_if_fail (mdh != NULL, FALSE);
1183 	g_return_val_if_fail (data != NULL, FALSE);
1184 
1185 	init_quarks ();
1186 
1187 	/* PKCS#12 MAC with SHA-1 */
1188 	if (oid_scheme == OID_SHA1)
1189 		ret = read_mac_pkcs12_pbe (GCRY_MD_SHA1, password, n_password,
1190 		                           data, mdh, digest_len);
1191 
1192 	if (ret == FALSE)
1193 		g_message ("unsupported or invalid mac: %s", g_quark_to_string (oid_scheme));
1194 
1195 	return ret;
1196 }
1197