Removed incorrect test on IPAddresses (was relying on IPaddresses encoded as text)
[gnutls.git] / lib / pkcs11_privkey.c
blob7842f06c07d993cd7c892587f9a73f11b9248fd8
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
4 *
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,
20 * MA 02111-1307, USA
23 #include <gnutls_int.h>
24 #include <pakchois/pakchois.h>
25 #include <gnutls/pkcs11.h>
26 #include <stdio.h>
27 #include <stdbool.h>
28 #include <string.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;
37 unsigned int flags;
38 struct pkcs11_url_info info;
41 /**
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.
49 **/
50 int
51 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
53 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
54 if (*key == NULL)
56 gnutls_assert ();
57 return GNUTLS_E_MEMORY_ERROR;
60 return 0;
63 /**
64 * gnutls_pkcs11_privkey_deinit:
65 * @key: The structure to be initialized
67 * This function will deinitialize a private key structure.
68 **/
69 void
70 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
72 gnutls_free (key);
75 /**
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
80 * key.
82 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
83 * success, or a negative value on error.
84 **/
85 int
86 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
87 unsigned int *bits)
89 if (bits)
90 *bits = 0; /* FIXME */
91 return key->pk_algorithm;
94 /**
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) \
118 do { \
119 int retries = 0; \
120 int rret; \
121 ret = pkcs11_find_object (&pks, &obj, &key->info, \
122 SESSION_LOGIN); \
123 if (ret < 0) { \
124 rret = token_func(token_data, key->info.token, retries++); \
125 if (rret == 0) continue; \
126 gnutls_assert(); \
127 return ret; \
129 } while (ret < 0);
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)
149 ck_rv_t rv;
150 int ret;
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);
158 mech.mechanism =
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
164 * earlier. */
165 rv = pakchois_sign_init (pks, &mech, obj);
166 if (rv != CKR_OK)
168 gnutls_assert ();
169 ret = pkcs11_rv_to_err (rv);
170 goto cleanup;
173 /* Work out how long the signature must be: */
174 rv = pakchois_sign (pks, hash->data, hash->size, NULL, &siglen);
175 if (rv != CKR_OK)
177 gnutls_assert ();
178 ret = pkcs11_rv_to_err (rv);
179 goto cleanup;
182 signature->data = gnutls_malloc (siglen);
183 signature->size = siglen;
185 rv = pakchois_sign (pks, hash->data, hash->size, signature->data, &siglen);
186 if (rv != CKR_OK)
188 gnutls_free (signature->data);
189 gnutls_assert ();
190 ret = pkcs11_rv_to_err (rv);
191 goto cleanup;
194 signature->size = siglen;
196 ret = 0;
198 cleanup:
199 pakchois_close_session (pks);
201 return ret;
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)
222 int ret;
224 ret = pkcs11_url_to_info (url, &pkey->info);
225 if (ret < 0)
227 gnutls_assert ();
228 return ret;
231 pkey->flags = flags;
233 if (pkey->info.type[0] != 0 && strcmp (pkey->info.type, "private") != 0)
235 gnutls_assert ();
236 return GNUTLS_E_INVALID_REQUEST;
239 if (pkey->info.id[0] == 0)
241 gnutls_assert ();
242 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
245 return 0;
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,
263 unsigned int flags,
264 const gnutls_datum_t * ciphertext,
265 gnutls_datum_t * plaintext)
267 ck_rv_t rv;
268 int ret;
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);
276 mech.mechanism =
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
282 * earlier. */
283 rv = pakchois_decrypt_init (pks, &mech, obj);
284 if (rv != CKR_OK)
286 gnutls_assert ();
287 ret = pkcs11_rv_to_err (rv);
288 goto cleanup;
291 /* Work out how long the plaintext must be: */
292 rv = pakchois_decrypt (pks, ciphertext->data, ciphertext->size,
293 NULL, &siglen);
294 if (rv != CKR_OK)
296 gnutls_assert ();
297 ret = pkcs11_rv_to_err (rv);
298 goto cleanup;
301 plaintext->data = gnutls_malloc (siglen);
302 plaintext->size = siglen;
304 rv = pakchois_decrypt (pks, ciphertext->data, ciphertext->size,
305 plaintext->data, &siglen);
306 if (rv != CKR_OK)
308 gnutls_free (plaintext->data);
309 gnutls_assert ();
310 ret = pkcs11_rv_to_err (rv);
311 goto cleanup;
314 plaintext->size = siglen;
316 ret = 0;
318 cleanup:
319 pakchois_close_session (pks);
321 return ret;
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,
338 char **url)
340 int ret;
342 ret = pkcs11_info_to_url (&key->info, detailed, url);
343 if (ret < 0)
345 gnutls_assert ();
346 return ret;
349 return 0;