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
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include "gkm-crypto.h"
24 #include "gkm-aes-mechanism.h"
25 #include "gkm-dh-mechanism.h"
26 #include "gkm-dsa-mechanism.h"
27 #include "gkm-ecdsa-mechanism.h"
28 #include "gkm-hkdf-mechanism.h"
29 #include "gkm-null-mechanism.h"
30 #include "gkm-rsa-mechanism.h"
31 #include "gkm-session.h"
32 #include "gkm-sexp.h"
33 #include "gkm-sexp-key.h"
34 
35 #include "egg/egg-libgcrypt.h"
36 #include "egg/egg-secure-memory.h"
37 
38 /* ----------------------------------------------------------------------------
39  * PUBLIC
40  */
41 
42 CK_RV
gkm_crypto_data_to_sexp(const gchar * format,guint nbits,EggPadding padding,CK_BYTE_PTR data,CK_ULONG n_data,gcry_sexp_t * sexp)43 gkm_crypto_data_to_sexp (const gchar *format, guint nbits, EggPadding padding,
44                          CK_BYTE_PTR data, CK_ULONG n_data, gcry_sexp_t *sexp)
45 {
46 	gpointer padded = NULL;
47 	gcry_error_t gcry;
48 	gcry_mpi_t mpi;
49 	gsize n_padded;
50 	gsize block;
51 
52 	g_assert (format);
53 	g_assert (sexp);
54 
55 	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
56 
57 	block = (nbits + 7) / 8;
58 	if (n_data > block)
59 		return CKR_DATA_LEN_RANGE;
60 
61 	if (padding) {
62 		if (!(padding) (g_realloc, block, data, n_data, &padded, &n_padded))
63 			return CKR_DATA_LEN_RANGE;
64 	}
65 
66 	/* Prepare the input s expression */
67 	gcry = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG,
68 	                      padded ? padded : data,
69 	                      padded ? n_padded : n_data, NULL);
70 	g_free (padded);
71 
72 	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
73 
74 	gcry = gcry_sexp_build (sexp, NULL, format, mpi);
75 	gcry_mpi_release (mpi);
76 
77 	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
78 
79 	g_assert (*sexp);
80 	return CKR_OK;
81 }
82 
83 CK_RV
gkm_crypto_sexp_to_data(gcry_sexp_t sexp,guint bits,CK_BYTE_PTR data,CK_ULONG * n_data,EggPadding padding,...)84 gkm_crypto_sexp_to_data (gcry_sexp_t sexp, guint bits, CK_BYTE_PTR data,
85                          CK_ULONG *n_data, EggPadding padding, ...)
86 {
87 	gcry_sexp_t at = NULL;
88 	gsize n_block, offset, len;
89 	gcry_mpi_t mpi = NULL;
90 	gpointer padded;
91 	guchar *block;
92 	va_list va;
93 	gboolean ret;
94 	gcry_error_t gcry;
95 
96 	g_assert (sexp);
97 	g_assert (data);
98 	g_assert (n_data);
99 	g_assert (bits);
100 
101 	/* First try and dig out sexp child based on arguments */
102 	va_start (va, padding);
103 	at = gkm_sexp_get_childv (sexp, va);
104 	va_end (va);
105 
106 	/* It's expected we would find it */
107 	g_return_val_if_fail (at != NULL, CKR_GENERAL_ERROR);
108 
109 	/* Parse out the MPI */
110 	mpi = gcry_sexp_nth_mpi (at, 1, GCRYMPI_FMT_USG);
111 	g_return_val_if_fail (mpi != NULL, CKR_GENERAL_ERROR);
112 	gcry_sexp_release (at);
113 
114 	/* Print out the MPI into the end of a temporary buffer */
115 	n_block = (bits + 7) / 8;
116 	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
117 	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
118 	g_return_val_if_fail (len <= n_block, CKR_GENERAL_ERROR);
119 	offset = n_block - len;
120 	block = g_malloc0 (n_block);
121 	memset (block, 0, offset);
122 	gcry = gcry_mpi_print (GCRYMPI_FMT_USG, block + offset, len, &len, mpi);
123 	g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
124 	g_return_val_if_fail (len == n_block - offset, CKR_GENERAL_ERROR);
125 	gcry_mpi_release (mpi);
126 
127 	/* Pad it properly if necessary */
128 	if (padding != NULL) {
129 		ret = (padding) (g_realloc, n_block, block, n_block, &padded, &n_block);
130 		g_free (block);
131 		if (ret == FALSE)
132 			return CKR_DATA_LEN_RANGE;
133 		block = padded;
134 	}
135 
136 	/* Now stuff it into the output buffer */
137 	if (n_block > *n_data)
138 		return CKR_BUFFER_TOO_SMALL;
139 
140 	memcpy (data, block, n_block);
141 	*n_data = n_block;
142 	g_free (block);
143 
144 	return CKR_OK;
145 }
146 
147 
148 CK_RV
gkm_crypto_encrypt(GkmSession * session,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR encrypted,CK_ULONG_PTR n_encrypted)149 gkm_crypto_encrypt (GkmSession *session, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
150                     CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted)
151 {
152 	GkmSexp *sexp;
153 
154 	switch (mech) {
155 	case CKM_RSA_PKCS:
156 	case CKM_RSA_X_509:
157 		sexp = gkm_session_get_crypto_state (session);
158 		g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
159 		return gkm_crypto_encrypt_xsa (gkm_sexp_get (sexp), mech, data, n_data, encrypted, n_encrypted);
160 	default:
161 		g_return_val_if_reached (CKR_GENERAL_ERROR);
162 	}
163 }
164 
165 CK_RV
gkm_crypto_encrypt_xsa(gcry_sexp_t sexp,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR encrypted,CK_ULONG_PTR n_encrypted)166 gkm_crypto_encrypt_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
167                         CK_ULONG n_data, CK_BYTE_PTR encrypted, CK_ULONG_PTR n_encrypted)
168 {
169 	int algorithm;
170 	CK_RV rv;
171 
172 	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
173 	g_return_val_if_fail (n_encrypted, CKR_ARGUMENTS_BAD);
174 	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
175 
176 	if (!gkm_sexp_parse_key (sexp, &algorithm, NULL, NULL))
177 		g_return_val_if_reached (CKR_GENERAL_ERROR);
178 
179 	/*
180 	 * The algorithm checks below are merely sanity checks.
181 	 * Other code should have checed this at an earlier stage
182 	 * and return the right error codes if invalid.
183 	 */
184 
185 	switch (mech) {
186 	case CKM_RSA_PKCS:
187 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
188 		rv = gkm_rsa_mechanism_encrypt (sexp, egg_padding_pkcs1_pad_02, data, n_data, encrypted, n_encrypted);
189 		break;
190 	case CKM_RSA_X_509:
191 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
192 		rv = gkm_rsa_mechanism_encrypt (sexp, egg_padding_zero_pad, data, n_data, encrypted, n_encrypted);
193 		break;
194 	default:
195 		/* Again shouldn't be reached */
196 		g_return_val_if_reached (CKR_GENERAL_ERROR);
197 	};
198 
199 	return rv;
200 }
201 
202 CK_RV
gkm_crypto_decrypt(GkmSession * session,CK_MECHANISM_TYPE mech,CK_BYTE_PTR encrypted,CK_ULONG n_encrypted,CK_BYTE_PTR data,CK_ULONG_PTR n_data)203 gkm_crypto_decrypt (GkmSession *session, CK_MECHANISM_TYPE mech, CK_BYTE_PTR encrypted,
204                     CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data)
205 {
206 	GkmSexp *sexp;
207 
208 	switch (mech) {
209 	case CKM_RSA_PKCS:
210 	case CKM_RSA_X_509:
211 		sexp = gkm_session_get_crypto_state (session);
212 		g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
213 		return gkm_crypto_decrypt_xsa (gkm_sexp_get (sexp), mech, encrypted, n_encrypted, data, n_data);
214 	default:
215 		g_return_val_if_reached (CKR_GENERAL_ERROR);
216 	}
217 }
218 
219 CK_RV
gkm_crypto_decrypt_xsa(gcry_sexp_t sexp,CK_MECHANISM_TYPE mech,CK_BYTE_PTR encrypted,CK_ULONG n_encrypted,CK_BYTE_PTR data,CK_ULONG_PTR n_data)220 gkm_crypto_decrypt_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR encrypted,
221                         CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data)
222 {
223 	int algorithm;
224 	CK_RV rv;
225 
226 	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
227 	g_return_val_if_fail (n_data, CKR_ARGUMENTS_BAD);
228 	g_return_val_if_fail (encrypted, CKR_ARGUMENTS_BAD);
229 
230 	if (!gkm_sexp_parse_key (sexp, &algorithm, NULL, NULL))
231 		g_return_val_if_reached (CKR_GENERAL_ERROR);
232 
233 	/*
234 	 * The algorithm checks below are merely sanity checks.
235 	 * Other code should have checed this at an earlier stage
236 	 * and return the right error codes if invalid.
237 	 */
238 
239 	switch (mech) {
240 	case CKM_RSA_PKCS:
241 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
242 		rv = gkm_rsa_mechanism_decrypt (sexp, egg_padding_pkcs1_unpad_02, encrypted, n_encrypted, data, n_data);
243 		break;
244 	case CKM_RSA_X_509:
245 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
246 		rv = gkm_rsa_mechanism_decrypt (sexp, NULL, encrypted, n_encrypted, data, n_data);
247 		break;
248 	default:
249 		/* Again shouldn't be reached */
250 		g_return_val_if_reached (CKR_GENERAL_ERROR);
251 	};
252 
253 	return rv;
254 }
255 
256 CK_RV
gkm_crypto_sign(GkmSession * session,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR signature,CK_ULONG_PTR n_signature)257 gkm_crypto_sign (GkmSession *session, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
258                  CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
259 {
260 	GkmSexp *sexp;
261 
262 	switch (mech) {
263 	case CKM_RSA_PKCS:
264 	case CKM_RSA_X_509:
265 	case CKM_DSA:
266 	case CKM_ECDSA:
267 		sexp = gkm_session_get_crypto_state (session);
268 		g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
269 		return gkm_crypto_sign_xsa (gkm_sexp_get (sexp), mech, data, n_data, signature, n_signature);
270 	default:
271 		g_return_val_if_reached (CKR_GENERAL_ERROR);
272 	}
273 }
274 
275 CK_RV
gkm_crypto_sign_xsa(gcry_sexp_t sexp,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR signature,CK_ULONG_PTR n_signature)276 gkm_crypto_sign_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
277                      CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG_PTR n_signature)
278 {
279 	int algorithm;
280 	CK_RV rv;
281 
282 	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
283 	g_return_val_if_fail (n_signature, CKR_ARGUMENTS_BAD);
284 	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
285 
286 	if (!gkm_sexp_parse_key (sexp, &algorithm, NULL, NULL))
287 		g_return_val_if_reached (CKR_GENERAL_ERROR);
288 
289 	/*
290 	 * The algorithm checks below are merely sanity checks.
291 	 * Other code should have checed this at an earlier stage
292 	 * and return the right error codes if invalid.
293 	 */
294 
295 	switch (mech) {
296 	case CKM_RSA_PKCS:
297 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
298 		rv = gkm_rsa_mechanism_sign (sexp, egg_padding_pkcs1_pad_01, data, n_data, signature, n_signature);
299 		break;
300 	case CKM_RSA_X_509:
301 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
302 		rv = gkm_rsa_mechanism_sign (sexp, egg_padding_zero_pad, data, n_data, signature, n_signature);
303 		break;
304 	case CKM_DSA:
305 		g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
306 		rv = gkm_dsa_mechanism_sign (sexp, data, n_data, signature, n_signature);
307 		break;
308 	case CKM_ECDSA:
309 		g_return_val_if_fail (algorithm == GCRY_PK_ECC, CKR_GENERAL_ERROR);
310 		rv = gkm_ecdsa_mechanism_sign (sexp, data, n_data, signature, n_signature);
311 		break;
312 	default:
313 		/* Again shouldn't be reached */
314 		g_return_val_if_reached (CKR_GENERAL_ERROR);
315 	};
316 
317 	return rv;
318 }
319 
320 CK_RV
gkm_crypto_verify(GkmSession * session,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR signature,CK_ULONG n_signature)321 gkm_crypto_verify (GkmSession *session, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
322                    CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature)
323 {
324 	GkmSexp *sexp;
325 
326 	switch (mech) {
327 	case CKM_RSA_PKCS:
328 	case CKM_RSA_X_509:
329 	case CKM_DSA:
330 	case CKM_ECDSA:
331 		sexp = gkm_session_get_crypto_state (session);
332 		g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
333 		return gkm_crypto_verify_xsa (gkm_sexp_get (sexp), mech, data, n_data, signature, n_signature);
334 	default:
335 		g_return_val_if_reached (CKR_GENERAL_ERROR);
336 	}
337 }
338 
339 CK_RV
gkm_crypto_verify_xsa(gcry_sexp_t sexp,CK_MECHANISM_TYPE mech,CK_BYTE_PTR data,CK_ULONG n_data,CK_BYTE_PTR signature,CK_ULONG n_signature)340 gkm_crypto_verify_xsa (gcry_sexp_t sexp, CK_MECHANISM_TYPE mech, CK_BYTE_PTR data,
341                        CK_ULONG n_data, CK_BYTE_PTR signature, CK_ULONG n_signature)
342 {
343 	int algorithm;
344 	CK_RV rv;
345 
346 	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);
347 	g_return_val_if_fail (signature, CKR_ARGUMENTS_BAD);
348 	g_return_val_if_fail (data, CKR_ARGUMENTS_BAD);
349 
350 	if (!gkm_sexp_parse_key (sexp, &algorithm, NULL, NULL))
351 		g_return_val_if_reached (CKR_GENERAL_ERROR);
352 
353 	/*
354 	 * The algorithm checks below are merely sanity checks.
355 	 * Other code should have checed this at an earlier stage
356 	 * and return the right error codes if invalid.
357 	 */
358 
359 	switch (mech) {
360 	case CKM_RSA_PKCS:
361 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
362 		rv = gkm_rsa_mechanism_verify (sexp, egg_padding_pkcs1_pad_01, data, n_data, signature, n_signature);
363 		break;
364 	case CKM_RSA_X_509:
365 		g_return_val_if_fail (algorithm == GCRY_PK_RSA, CKR_GENERAL_ERROR);
366 		rv = gkm_rsa_mechanism_verify (sexp, egg_padding_zero_pad, data, n_data, signature, n_signature);
367 		break;
368 	case CKM_DSA:
369 		g_return_val_if_fail (algorithm == GCRY_PK_DSA, CKR_GENERAL_ERROR);
370 		rv = gkm_dsa_mechanism_verify (sexp, data, n_data, signature, n_signature);
371 		break;
372 	case CKM_ECDSA:
373 		g_return_val_if_fail (algorithm == GCRY_PK_ECC, CKR_GENERAL_ERROR);
374 		rv = gkm_ecdsa_mechanism_verify (sexp, data, n_data, signature, n_signature);
375 		break;
376 	default:
377 		/* Again shouldn't be reached */
378 		g_return_val_if_reached (CKR_GENERAL_ERROR);
379 	};
380 
381 	return rv;
382 }
383 
384 CK_RV
gkm_crypto_perform(GkmSession * session,CK_MECHANISM_TYPE mech,CK_ATTRIBUTE_TYPE method,CK_BYTE_PTR bufone,CK_ULONG n_bufone,CK_BYTE_PTR buftwo,CK_ULONG_PTR n_buftwo)385 gkm_crypto_perform (GkmSession *session, CK_MECHANISM_TYPE mech, CK_ATTRIBUTE_TYPE method,
386                     CK_BYTE_PTR bufone, CK_ULONG n_bufone, CK_BYTE_PTR buftwo, CK_ULONG_PTR n_buftwo)
387 {
388 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
389 	g_return_val_if_fail (method, CKR_GENERAL_ERROR);
390 	g_return_val_if_fail (n_buftwo, CKR_GENERAL_ERROR);
391 
392 	switch (method) {
393 	case CKA_ENCRYPT:
394 		return gkm_crypto_encrypt (session, mech, bufone, n_bufone, buftwo, n_buftwo);
395 	case CKA_DECRYPT:
396 		return gkm_crypto_decrypt (session, mech, bufone, n_bufone, buftwo, n_buftwo);
397 	case CKA_SIGN:
398 		return gkm_crypto_sign (session, mech, bufone, n_bufone, buftwo, n_buftwo);
399 	case CKA_VERIFY:
400 		return gkm_crypto_verify (session, mech, bufone, n_bufone, buftwo, *n_buftwo);
401 	default:
402 		g_return_val_if_reached (CKR_GENERAL_ERROR);
403 	}
404 }
405 
406 CK_RV
gkm_crypto_generate_key_pair(GkmSession * session,CK_MECHANISM_TYPE mech,CK_ATTRIBUTE_PTR pub_atts,CK_ULONG n_pub_atts,CK_ATTRIBUTE_PTR priv_atts,CK_ULONG n_priv_atts,GkmObject ** pub_key,GkmObject ** priv_key)407 gkm_crypto_generate_key_pair (GkmSession *session, CK_MECHANISM_TYPE mech,
408                               CK_ATTRIBUTE_PTR pub_atts, CK_ULONG n_pub_atts,
409                               CK_ATTRIBUTE_PTR priv_atts, CK_ULONG n_priv_atts,
410                               GkmObject **pub_key, GkmObject **priv_key)
411 {
412 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
413 	g_return_val_if_fail (pub_key, CKR_GENERAL_ERROR);
414 	g_return_val_if_fail (priv_key, CKR_GENERAL_ERROR);
415 
416 	switch (mech) {
417 	case CKM_DH_PKCS_KEY_PAIR_GEN:
418 		return gkm_dh_mechanism_generate (session, pub_atts, n_pub_atts,
419 		                                  priv_atts, n_priv_atts,
420 		                                  pub_key, priv_key);
421 	default:
422 		return CKR_MECHANISM_INVALID;
423 	}
424 }
425 
426 CK_RV
gkm_crypto_derive_key(GkmSession * session,CK_MECHANISM_PTR mech,GkmObject * base,CK_ATTRIBUTE_PTR attrs,CK_ULONG n_attrs,GkmObject ** derived)427 gkm_crypto_derive_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *base,
428                        CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GkmObject **derived)
429 {
430 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
431 	g_return_val_if_fail (GKM_IS_OBJECT (base), CKR_GENERAL_ERROR);
432 	g_return_val_if_fail (derived, CKR_GENERAL_ERROR);
433 
434 	if (!gkm_object_has_attribute_ulong (base, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
435 		return CKR_KEY_TYPE_INCONSISTENT;
436 
437 	if (!gkm_object_has_attribute_boolean (base, session, CKA_DERIVE, TRUE))
438 		return CKR_KEY_FUNCTION_NOT_PERMITTED;
439 
440 	switch (mech->mechanism) {
441 	case CKM_DH_PKCS_DERIVE:
442 		return gkm_dh_mechanism_derive (session, mech, base, attrs,
443 		                                n_attrs, derived);
444 	case CKM_G_HKDF_SHA256_DERIVE:
445 		return gkm_hkdf_mechanism_derive (session, "sha256", mech, base,
446 		                                  attrs, n_attrs, derived);
447 	default:
448 		return CKR_MECHANISM_INVALID;
449 	}
450 }
451 
452 CK_RV
gkm_crypto_wrap_key(GkmSession * session,CK_MECHANISM_PTR mech,GkmObject * wrapper,GkmObject * wrapped,CK_BYTE_PTR output,CK_ULONG_PTR n_output)453 gkm_crypto_wrap_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *wrapper,
454                      GkmObject *wrapped, CK_BYTE_PTR output, CK_ULONG_PTR n_output)
455 {
456 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
457 	g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR);
458 	g_return_val_if_fail (GKM_IS_OBJECT (wrapped), CKR_GENERAL_ERROR);
459 	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
460 	g_return_val_if_fail (n_output, CKR_GENERAL_ERROR);
461 
462 	if (!gkm_object_has_attribute_ulong (wrapper, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
463 		return CKR_KEY_TYPE_INCONSISTENT;
464 
465 	if (!gkm_object_has_attribute_boolean (wrapper, session, CKA_WRAP, TRUE))
466 		return CKR_KEY_FUNCTION_NOT_PERMITTED;
467 
468 	switch (mech->mechanism) {
469 	case CKM_AES_CBC_PAD:
470 		return gkm_aes_mechanism_wrap (session, mech, wrapper, wrapped,
471 		                               output, n_output);
472 	case CKM_G_NULL:
473 		return gkm_null_mechanism_wrap (session, mech, wrapper, wrapped,
474 		                                output, n_output);
475 	default:
476 		return CKR_MECHANISM_INVALID;
477 	}
478 }
479 
480 CK_RV
gkm_crypto_unwrap_key(GkmSession * session,CK_MECHANISM_PTR mech,GkmObject * wrapper,CK_VOID_PTR input,CK_ULONG n_input,CK_ATTRIBUTE_PTR attrs,CK_ULONG n_attrs,GkmObject ** unwrapped)481 gkm_crypto_unwrap_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *wrapper,
482                        CK_VOID_PTR input, CK_ULONG n_input, CK_ATTRIBUTE_PTR attrs,
483                        CK_ULONG n_attrs, GkmObject **unwrapped)
484 {
485 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
486 	g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR);
487 	g_return_val_if_fail (mech, CKR_GENERAL_ERROR);
488 	g_return_val_if_fail (unwrapped, CKR_GENERAL_ERROR);
489 
490 	if (!gkm_object_has_attribute_ulong (wrapper, session, CKA_ALLOWED_MECHANISMS, mech->mechanism))
491 		return CKR_KEY_TYPE_INCONSISTENT;
492 
493 	if (!gkm_object_has_attribute_boolean (wrapper, session, CKA_UNWRAP, TRUE))
494 		return CKR_KEY_FUNCTION_NOT_PERMITTED;
495 
496 	switch (mech->mechanism) {
497 	case CKM_AES_CBC_PAD:
498 		return gkm_aes_mechanism_unwrap (session, mech, wrapper, input,
499 		                                 n_input, attrs, n_attrs, unwrapped);
500 	case CKM_G_NULL:
501 		return gkm_null_mechanism_unwrap (session, mech, wrapper, input,
502 		                                  n_input, attrs, n_attrs, unwrapped);
503 	default:
504 		return CKR_MECHANISM_INVALID;
505 	}
506 }
507 
508 /* ----------------------------------------------------------------------------
509  * PREPARE FUNCTIONS
510  */
511 
512 CK_RV
gkm_crypto_prepare(GkmSession * session,CK_MECHANISM_TYPE mech,GkmObject * key)513 gkm_crypto_prepare (GkmSession *session, CK_MECHANISM_TYPE mech, GkmObject *key)
514 {
515 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
516 
517 	switch (mech) {
518 	case CKM_RSA_PKCS:
519 	case CKM_RSA_X_509:
520 	case CKM_ECDSA:
521 	case CKM_DSA:
522 		return gkm_crypto_prepare_xsa (session, mech, key);
523 	default:
524 		g_return_val_if_reached (CKR_GENERAL_ERROR);
525 	}
526 }
527 
528 CK_RV
gkm_crypto_prepare_xsa(GkmSession * session,CK_MECHANISM_TYPE mech,GkmObject * key)529 gkm_crypto_prepare_xsa (GkmSession *session, CK_MECHANISM_TYPE mech, GkmObject *key)
530 {
531 	GkmSexp *sexp;
532 
533 	g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR);
534 	g_return_val_if_fail (GKM_IS_SEXP_KEY (key), CKR_GENERAL_ERROR);
535 
536 	/* Load up the actual sexp we're going to use */
537 	sexp = gkm_sexp_key_acquire_crypto_sexp (GKM_SEXP_KEY (key), session);
538 	if (sexp == NULL)
539 		return CKR_USER_NOT_LOGGED_IN;
540 
541 	gkm_session_set_crypto_state (session, sexp, gkm_sexp_unref);
542 	return CKR_OK;
543 }
544 
545 /* --------------------------------------------------------------------------
546  * UTILITY
547  */
548 
549 
550 void
gkm_crypto_initialize(void)551 gkm_crypto_initialize (void)
552 {
553 	egg_libgcrypt_initialize ();
554 }
555 
556 gulong
gkm_crypto_secret_key_length(CK_KEY_TYPE type)557 gkm_crypto_secret_key_length (CK_KEY_TYPE type)
558 {
559 	switch (type) {
560 	case CKK_AES:
561 		return GKM_AES_MECHANISM_MIN_LENGTH;
562 	default:
563 		return 0;
564 	}
565 }
566