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