Line data Source code
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 "pkcs11/pkcs11.h"
24 :
25 : #include "gkm-attributes.h"
26 : #define DEBUG_FLAG GKM_DEBUG_OBJECT
27 : #include "gkm-debug.h"
28 : #include "gkm-dsa-mechanism.h"
29 : #include "gkm-ecdsa-mechanism.h"
30 : #include "gkm-rsa-mechanism.h"
31 : #include "gkm-sexp-key.h"
32 : #include "gkm-data-der.h"
33 : #include "gkm-util.h"
34 :
35 : enum {
36 : PROP_0,
37 : PROP_BASE_SEXP,
38 : PROP_ALGORITHM
39 : };
40 :
41 : struct _GkmSexpKeyPrivate {
42 : GkmSexp *base_sexp;
43 : };
44 :
45 364 : G_DEFINE_TYPE_WITH_PRIVATE (GkmSexpKey, gkm_sexp_key, GKM_TYPE_OBJECT);
46 :
47 : /* -----------------------------------------------------------------------------
48 : * INTERNAL
49 : */
50 :
51 : /* -----------------------------------------------------------------------------
52 : * KEY
53 : */
54 :
55 : static CK_RV
56 64 : gkm_sexp_key_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr)
57 : {
58 64 : GkmSexpKey *self = GKM_SEXP_KEY (base);
59 :
60 64 : switch (attr->type) {
61 3 : case CKA_KEY_TYPE:
62 : {
63 3 : switch (gkm_sexp_key_get_algorithm (self)) {
64 1 : case GCRY_PK_RSA:
65 1 : return gkm_attribute_set_ulong (attr, CKK_RSA);
66 1 : case GCRY_PK_DSA:
67 1 : return gkm_attribute_set_ulong (attr, CKK_DSA);
68 1 : case GCRY_PK_ECC:
69 1 : return gkm_attribute_set_ulong (attr, CKK_ECDSA);
70 0 : default:
71 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
72 : };
73 : }
74 : break;
75 :
76 58 : case CKA_ID:
77 : {
78 : guchar hash[20];
79 58 : g_return_val_if_fail (self->pv->base_sexp, CKR_GENERAL_ERROR);
80 58 : if (!gcry_pk_get_keygrip (gkm_sexp_get (self->pv->base_sexp), hash))
81 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
82 58 : return gkm_attribute_set_data (attr, hash, sizeof (hash));
83 : }
84 : break;
85 :
86 0 : case CKA_START_DATE:
87 : case CKA_END_DATE:
88 0 : return gkm_attribute_set_data (attr, "", 0);
89 :
90 0 : case CKA_DERIVE:
91 0 : return gkm_attribute_set_bool (attr, FALSE);
92 :
93 0 : case CKA_LOCAL:
94 0 : return gkm_attribute_set_bool (attr, FALSE);
95 :
96 0 : case CKA_KEY_GEN_MECHANISM:
97 0 : return gkm_attribute_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
98 :
99 0 : case CKA_ALLOWED_MECHANISMS:
100 0 : switch (gkm_sexp_key_get_algorithm (self)) {
101 0 : case GCRY_PK_RSA:
102 0 : return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_RSA_MECHANISMS,
103 : sizeof (GKM_RSA_MECHANISMS));
104 0 : case GCRY_PK_DSA:
105 0 : return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_DSA_MECHANISMS,
106 : sizeof (GKM_DSA_MECHANISMS));
107 0 : case GCRY_PK_ECC:
108 0 : return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_ECDSA_MECHANISMS,
109 : sizeof (GKM_ECDSA_MECHANISMS));
110 0 : default:
111 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
112 : };
113 :
114 : /* Lookup the certificate subject */
115 2 : case CKA_SUBJECT:
116 : /* TODO: When we have certificates, implement this */
117 2 : return gkm_attribute_set_data (attr, "", 0);
118 : };
119 :
120 1 : return GKM_OBJECT_CLASS (gkm_sexp_key_parent_class)->get_attribute (base, session, attr);
121 : }
122 :
123 : static void
124 60 : gkm_sexp_key_init (GkmSexpKey *self)
125 : {
126 60 : self->pv = gkm_sexp_key_get_instance_private (self);
127 60 : }
128 :
129 : static void
130 60 : gkm_sexp_key_finalize (GObject *obj)
131 : {
132 60 : GkmSexpKey *self = GKM_SEXP_KEY (obj);
133 :
134 60 : if (self->pv->base_sexp)
135 60 : gkm_sexp_unref (self->pv->base_sexp);
136 60 : self->pv->base_sexp = NULL;
137 :
138 60 : G_OBJECT_CLASS (gkm_sexp_key_parent_class)->finalize (obj);
139 60 : }
140 :
141 : static void
142 4 : gkm_sexp_key_set_property (GObject *obj, guint prop_id, const GValue *value,
143 : GParamSpec *pspec)
144 : {
145 4 : GkmSexpKey *self = GKM_SEXP_KEY (obj);
146 :
147 4 : switch (prop_id) {
148 4 : case PROP_BASE_SEXP:
149 4 : gkm_sexp_key_set_base (self, g_value_get_boxed (value));
150 4 : break;
151 0 : default:
152 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
153 0 : break;
154 : }
155 4 : }
156 :
157 : static void
158 0 : gkm_sexp_key_get_property (GObject *obj, guint prop_id, GValue *value,
159 : GParamSpec *pspec)
160 : {
161 0 : GkmSexpKey *self = GKM_SEXP_KEY (obj);
162 :
163 0 : switch (prop_id) {
164 0 : case PROP_BASE_SEXP:
165 0 : g_value_set_boxed (value, gkm_sexp_key_get_base (self));
166 0 : break;
167 0 : case PROP_ALGORITHM:
168 0 : g_value_set_int (value, gkm_sexp_key_get_algorithm (self));
169 0 : break;
170 0 : default:
171 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
172 0 : break;
173 : }
174 0 : }
175 :
176 : static void
177 9 : gkm_sexp_key_class_init (GkmSexpKeyClass *klass)
178 : {
179 9 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
180 9 : GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
181 :
182 9 : gobject_class->finalize = gkm_sexp_key_finalize;
183 9 : gobject_class->set_property = gkm_sexp_key_set_property;
184 9 : gobject_class->get_property = gkm_sexp_key_get_property;
185 :
186 9 : gkm_class->get_attribute = gkm_sexp_key_real_get_attribute;
187 :
188 9 : g_object_class_install_property (gobject_class, PROP_BASE_SEXP,
189 : g_param_spec_boxed ("base-sexp", "Base S-Exp", "Base Key S-Expression",
190 : GKM_BOXED_SEXP, G_PARAM_READWRITE));
191 :
192 9 : g_object_class_install_property (gobject_class, PROP_ALGORITHM,
193 : g_param_spec_int ("algorithm", "Algorithm", "GCrypt Algorithm",
194 : 0, G_MAXINT, 0, G_PARAM_READABLE));
195 9 : }
196 :
197 : /* -----------------------------------------------------------------------------
198 : * PUBLIC
199 : */
200 :
201 : GkmSexp*
202 0 : gkm_sexp_key_get_base (GkmSexpKey *self)
203 : {
204 0 : g_return_val_if_fail (GKM_IS_SEXP_KEY (self), NULL);
205 0 : return self->pv->base_sexp;
206 : }
207 :
208 : void
209 60 : gkm_sexp_key_set_base (GkmSexpKey *self, GkmSexp *sexp)
210 : {
211 60 : g_return_if_fail (GKM_IS_SEXP_KEY (self));
212 60 : if (sexp)
213 60 : gkm_sexp_ref (sexp);
214 60 : if (self->pv->base_sexp)
215 0 : gkm_sexp_unref (self->pv->base_sexp);
216 60 : self->pv->base_sexp = sexp;
217 60 : g_object_notify (G_OBJECT (self), "base-sexp");
218 60 : g_object_notify (G_OBJECT (self), "algorithm");
219 : }
220 :
221 : int
222 4 : gkm_sexp_key_get_algorithm (GkmSexpKey *self)
223 : {
224 : int algorithm;
225 4 : g_return_val_if_fail (self->pv->base_sexp, 0);
226 4 : if (!gkm_sexp_parse_key (gkm_sexp_get (self->pv->base_sexp), &algorithm, NULL, NULL))
227 0 : g_return_val_if_reached (0);
228 4 : return algorithm;
229 : }
230 :
231 : static CK_RV
232 6 : gkm_sexp_key_set_part_encode (GkmSexpKey *self, int algo, const char *part,
233 : CK_ATTRIBUTE_PTR attr, int der_encode)
234 : {
235 : gcry_sexp_t numbers;
236 : gcry_mpi_t mpi;
237 : int algorithm;
238 : CK_RV rv;
239 :
240 6 : g_return_val_if_fail (GKM_IS_SEXP_KEY (self), CKR_GENERAL_ERROR);
241 6 : g_return_val_if_fail (self->pv->base_sexp, CKR_GENERAL_ERROR);
242 :
243 6 : if (!gkm_sexp_parse_key (gkm_sexp_get (self->pv->base_sexp),
244 : &algorithm, NULL, &numbers))
245 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
246 :
247 6 : if (algorithm != algo) {
248 0 : gcry_sexp_release (numbers);
249 0 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: attribute %s not valid for key algorithm: %s",
250 : gkm_log_attr_type (attr->type), gcry_pk_algo_name (algo));
251 0 : return CKR_ATTRIBUTE_TYPE_INVALID;
252 : }
253 :
254 6 : if (!gkm_sexp_extract_mpi (numbers, &mpi, part, NULL))
255 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
256 :
257 6 : if (der_encode) {
258 : /* convert mpi to DER encoded OCTET string */
259 : GBytes *data;
260 :
261 1 : rv = gkm_data_der_encode_ecdsa_q (mpi, &data);
262 1 : g_return_val_if_fail (rv, CKR_GENERAL_ERROR);
263 :
264 1 : rv = gkm_attribute_set_bytes (attr, data);
265 1 : g_bytes_unref (data);
266 : } else {
267 5 : rv = gkm_attribute_set_mpi (attr, mpi);
268 : }
269 :
270 6 : gcry_sexp_release (numbers);
271 6 : gcry_mpi_release (mpi);
272 :
273 6 : return rv;
274 : }
275 :
276 : CK_RV
277 5 : gkm_sexp_key_set_part (GkmSexpKey *self, int algo, const char *part, CK_ATTRIBUTE_PTR attr)
278 : {
279 5 : return gkm_sexp_key_set_part_encode (self, algo, part, attr, 0);
280 : }
281 :
282 : CK_RV
283 1 : gkm_sexp_key_set_ec_q (GkmSexpKey *self, int algo, CK_ATTRIBUTE_PTR attr)
284 : {
285 1 : return gkm_sexp_key_set_part_encode (self, algo, "q", attr, 1);
286 : }
287 :
288 : CK_RV
289 1 : gkm_sexp_key_set_ec_params (GkmSexpKey *self, int algo, CK_ATTRIBUTE_PTR attr)
290 : {
291 : CK_RV rv;
292 : gchar *curve_name;
293 : GBytes *data;
294 : int algorithm;
295 : gcry_sexp_t numbers;
296 :
297 1 : g_return_val_if_fail (GKM_IS_SEXP_KEY (self), CKR_GENERAL_ERROR);
298 1 : g_return_val_if_fail (self->pv->base_sexp, CKR_GENERAL_ERROR);
299 :
300 1 : if (!gkm_sexp_parse_key (gkm_sexp_get (self->pv->base_sexp),
301 : &algorithm, NULL, &numbers))
302 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
303 :
304 1 : if (algorithm != algo) {
305 0 : gcry_sexp_release (numbers);
306 0 : gkm_debug ("CKR_ATTRIBUTE_TYPE_INVALID: attribute %s not valid for key algorithm: %s",
307 : gkm_log_attr_type (attr->type), gcry_pk_algo_name (algo));
308 0 : return CKR_ATTRIBUTE_TYPE_INVALID;
309 : }
310 :
311 1 : rv = gkm_sexp_extract_string (numbers, &curve_name, "curve", NULL);
312 1 : g_return_val_if_fail (rv, CKR_GENERAL_ERROR);
313 :
314 1 : data = gkm_data_der_curve_to_ec_params (curve_name);
315 1 : g_return_val_if_fail (data != NULL, CKR_GENERAL_ERROR);
316 :
317 1 : rv = gkm_attribute_set_bytes (attr, data);
318 1 : g_bytes_unref (data);
319 1 : gcry_sexp_release (numbers);
320 1 : g_free (curve_name);
321 :
322 1 : return rv;
323 : }
324 :
325 : GkmSexp*
326 0 : gkm_sexp_key_acquire_crypto_sexp (GkmSexpKey *self, GkmSession *session)
327 : {
328 0 : g_return_val_if_fail (GKM_IS_SEXP_KEY (self), NULL);
329 0 : g_return_val_if_fail (GKM_SEXP_KEY_GET_CLASS (self)->acquire_crypto_sexp, NULL);
330 0 : return GKM_SEXP_KEY_GET_CLASS (self)->acquire_crypto_sexp (self, session);
331 : }
|