2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
5 * Author: Nikos Mavrogiannopoulos
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 #include <gnutls_int.h>
24 #include <pakchois/pakchois.h>
25 #include <gnutls/pkcs11.h>
29 #include <gnutls_errors.h>
30 #include <gnutls_datum.h>
31 #include <pkcs11_int.h>
32 #include <gnutls_sig.h>
34 struct gnutls_pkcs11_privkey_st
36 gnutls_pk_algorithm_t pk_algorithm
;
38 struct pkcs11_url_info info
;
42 * gnutls_pkcs11_privkey_init:
43 * @key: The structure to be initialized
45 * This function will initialize an private key structure.
47 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
48 * negative error value.
51 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t
* key
)
53 *key
= gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st
));
57 return GNUTLS_E_MEMORY_ERROR
;
64 * gnutls_pkcs11_privkey_deinit:
65 * @key: The structure to be initialized
67 * This function will deinitialize a private key structure.
70 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key
)
76 * gnutls_pkcs11_privkey_get_pk_algorithm:
77 * @key: should contain a #gnutls_pkcs11_privkey_t structure
79 * This function will return the public key algorithm of a private
82 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
83 * success, or a negative value on error.
86 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key
,
90 *bits
= 0; /* FIXME */
91 return key
->pk_algorithm
;
95 * gnutls_pkcs11_privkey_get_info:
96 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
97 * @itype: Denotes the type of information requested
98 * @output: where output will be stored
99 * @output_size: contains the maximum size of the output and will be overwritten with actual
101 * This function will return information about the PKCS 11 private key such
102 * as the label, id as well as token information where the key is stored. When
103 * output is text it returns null terminated string although #output_size contains
104 * the size of the actual data only.
106 * Returns: zero on success or a negative value on error.
109 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey
,
110 gnutls_pkcs11_obj_info_t itype
,
111 void *output
, size_t * output_size
)
113 return pkcs11_get_info (&pkey
->info
, itype
, output
, output_size
);
117 #define FIND_OBJECT(pks, obj, key) \
121 ret = pkcs11_find_object (&pks, &obj, &key->info, \
124 rret = token_func(token_data, key->info.token, retries++); \
125 if (rret == 0) continue; \
132 * _gnutls_pkcs11_privkey_sign_hash:
133 * @key: Holds the key
134 * @hash: holds the data to be signed (should be output of a hash)
135 * @signature: will contain the signature allocated with gnutls_malloc()
137 * This function will sign the given data using a signature algorithm
138 * supported by the private key. It is assumed that the given data
139 * are the output of a hash function.
141 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
142 * negative error value.
145 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key
,
146 const gnutls_datum_t
* hash
,
147 gnutls_datum_t
* signature
)
151 struct ck_mechanism mech
;
152 unsigned long siglen
;
153 pakchois_session_t
*pks
;
154 ck_object_handle_t obj
;
156 FIND_OBJECT (pks
, obj
, key
);
159 key
->pk_algorithm
== GNUTLS_PK_DSA
? CKM_DSA
: CKM_RSA_PKCS
;
160 mech
.parameter
= NULL
;
161 mech
.parameter_len
= 0;
163 /* Initialize signing operation; using the private key discovered
165 rv
= pakchois_sign_init (pks
, &mech
, obj
);
169 ret
= pkcs11_rv_to_err (rv
);
173 /* Work out how long the signature must be: */
174 rv
= pakchois_sign (pks
, hash
->data
, hash
->size
, NULL
, &siglen
);
178 ret
= pkcs11_rv_to_err (rv
);
182 signature
->data
= gnutls_malloc (siglen
);
183 signature
->size
= siglen
;
185 rv
= pakchois_sign (pks
, hash
->data
, hash
->size
, signature
->data
, &siglen
);
188 gnutls_free (signature
->data
);
190 ret
= pkcs11_rv_to_err (rv
);
194 signature
->size
= siglen
;
199 pakchois_close_session (pks
);
205 * gnutls_pkcs11_privkey_import_url:
206 * @pkey: The structure to store the parsed key
207 * @url: a PKCS 11 url identifying the key
208 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
210 * This function will "import" a PKCS 11 URL identifying a private
211 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
212 * in most cases keys cannot be exported, the private key structure
213 * is being associated with the available operations on the token.
215 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
216 * negative error value.
219 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey
,
220 const char *url
, unsigned int flags
)
224 ret
= pkcs11_url_to_info (url
, &pkey
->info
);
233 if (pkey
->info
.type
[0] != 0 && strcmp (pkey
->info
.type
, "private") != 0)
236 return GNUTLS_E_INVALID_REQUEST
;
239 if (pkey
->info
.id
[0] == 0)
242 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
249 * _gnutls_pkcs11_privkey_decrypt_data:
250 * @key: Holds the key
251 * @flags: should be 0 for now
252 * @ciphertext: holds the data to be signed
253 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
255 * This function will decrypt the given data using the public key algorithm
256 * supported by the private key.
258 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
259 * negative error value.
262 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key
,
264 const gnutls_datum_t
* ciphertext
,
265 gnutls_datum_t
* plaintext
)
269 struct ck_mechanism mech
;
270 unsigned long siglen
;
271 pakchois_session_t
*pks
;
272 ck_object_handle_t obj
;
274 FIND_OBJECT (pks
, obj
, key
);
277 key
->pk_algorithm
== GNUTLS_PK_DSA
? CKM_DSA
: CKM_RSA_PKCS
;
278 mech
.parameter
= NULL
;
279 mech
.parameter_len
= 0;
281 /* Initialize signing operation; using the private key discovered
283 rv
= pakchois_decrypt_init (pks
, &mech
, obj
);
287 ret
= pkcs11_rv_to_err (rv
);
291 /* Work out how long the plaintext must be: */
292 rv
= pakchois_decrypt (pks
, ciphertext
->data
, ciphertext
->size
,
297 ret
= pkcs11_rv_to_err (rv
);
301 plaintext
->data
= gnutls_malloc (siglen
);
302 plaintext
->size
= siglen
;
304 rv
= pakchois_decrypt (pks
, ciphertext
->data
, ciphertext
->size
,
305 plaintext
->data
, &siglen
);
308 gnutls_free (plaintext
->data
);
310 ret
= pkcs11_rv_to_err (rv
);
314 plaintext
->size
= siglen
;
319 pakchois_close_session (pks
);
325 * gnutls_pkcs11_privkey_export_url:
326 * @key: Holds the PKCS 11 key
327 * @detailed: non zero if a detailed URL is required
328 * @url: will contain an allocated url
330 * This function will export a URL identifying the given key.
332 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
333 * negative error value.
336 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key
,
337 gnutls_pkcs11_url_type_t detailed
,
342 ret
= pkcs11_info_to_url (&key
->info
, detailed
, url
);