Line data Source code
1 : /*
2 : * gnome-keyring
3 : *
4 : * Copyright (C) 2011 Collabora Ltd.
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 : * Author: Stef Walter <stefw@collabora.co.uk>
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include "pkcs11/pkcs11.h"
26 : #include "pkcs11/pkcs11i.h"
27 :
28 : #include "gkm-attributes.h"
29 : #include "gkm-generic-key.h"
30 : #include "gkm-session.h"
31 : #include "gkm-transaction.h"
32 : #include "gkm-util.h"
33 :
34 : #include "egg/egg-secure-memory.h"
35 :
36 : struct _GkmGenericKey {
37 : GkmSecretKey parent;
38 : gpointer value;
39 : gsize n_value;
40 : };
41 :
42 13 : G_DEFINE_TYPE (GkmGenericKey, gkm_generic_key, GKM_TYPE_SECRET_KEY);
43 :
44 : static const CK_MECHANISM_TYPE GKM_GENERIC_MECHANISMS[] = {
45 : CKM_G_HKDF_SHA256_DERIVE
46 : };
47 :
48 1 : EGG_SECURE_DECLARE (generic_key);
49 :
50 : /* -----------------------------------------------------------------------------
51 : * INTERNAL
52 : */
53 :
54 : static CK_RV
55 0 : attribute_set_check_value (GkmGenericKey *self, CK_ATTRIBUTE *attr)
56 : {
57 : guchar buffer[20];
58 :
59 0 : g_assert (GKM_IS_GENERIC_KEY (self));
60 0 : g_assert (attr);
61 :
62 : /* Just asking for the length */
63 0 : if (!attr->pValue) {
64 0 : attr->ulValueLen = 3;
65 0 : return CKR_OK;
66 : }
67 :
68 : /* Just the a sha1 of the value */
69 0 : gcry_md_hash_buffer (GCRY_MD_SHA1, buffer, self->value, self->n_value);
70 :
71 : /* Use the first three bytes */
72 0 : return gkm_attribute_set_data (attr, buffer, 3);
73 : }
74 :
75 : static GkmObject*
76 1 : factory_create_generic_key (GkmSession *session, GkmTransaction *transaction,
77 : CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
78 : {
79 : GkmGenericKey *key;
80 : GkmManager *manager;
81 : CK_ATTRIBUTE_PTR value;
82 :
83 1 : value = gkm_attributes_find (attrs, n_attrs, CKA_VALUE);
84 1 : if (value == NULL) {
85 0 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
86 0 : return NULL;
87 : }
88 :
89 1 : if (gkm_attributes_find (attrs, n_attrs, CKA_VALUE_LEN)) {
90 0 : gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
91 0 : return NULL;
92 : }
93 :
94 1 : manager = gkm_manager_for_template (attrs, n_attrs, session);
95 1 : key = g_object_new (GKM_TYPE_GENERIC_KEY,
96 : "module", gkm_session_get_module (session),
97 : "manager", manager,
98 : NULL);
99 :
100 1 : key->value = egg_secure_alloc (value->ulValueLen);
101 1 : key->n_value = value->ulValueLen;
102 1 : memcpy (key->value, value->pValue, key->n_value);
103 :
104 1 : gkm_attribute_consume (value);
105 :
106 1 : gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (key),
107 : TRUE, attrs, n_attrs);
108 1 : return GKM_OBJECT (key);
109 : }
110 :
111 : /* -----------------------------------------------------------------------------
112 : * OBJECT
113 : */
114 :
115 : static CK_RV
116 8 : gkm_generic_key_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE *attr)
117 : {
118 8 : GkmGenericKey *self = GKM_GENERIC_KEY (base);
119 :
120 8 : switch (attr->type)
121 : {
122 1 : case CKA_KEY_TYPE:
123 1 : return gkm_attribute_set_ulong (attr, CKK_GENERIC_SECRET);
124 :
125 1 : case CKA_DERIVE:
126 1 : return gkm_attribute_set_bool (attr, CK_TRUE);
127 :
128 0 : case CKA_UNWRAP:
129 : case CKA_WRAP:
130 0 : return gkm_attribute_set_bool (attr, CK_FALSE);
131 :
132 0 : case CKA_VALUE:
133 0 : return gkm_attribute_set_data (attr, self->value, self->n_value);
134 :
135 0 : case CKA_VALUE_LEN:
136 0 : return gkm_attribute_set_ulong (attr, self->n_value);
137 :
138 0 : case CKA_CHECK_VALUE:
139 0 : return attribute_set_check_value (self, attr);
140 :
141 2 : case CKA_ALLOWED_MECHANISMS:
142 2 : return gkm_attribute_set_data (attr, (CK_VOID_PTR)GKM_GENERIC_MECHANISMS,
143 : sizeof (GKM_GENERIC_MECHANISMS));
144 : };
145 :
146 4 : return GKM_OBJECT_CLASS (gkm_generic_key_parent_class)->get_attribute (base, session, attr);
147 : }
148 :
149 : static gconstpointer
150 1 : gkm_generic_key_get_key_value (GkmSecretKey *key, gsize *n_value)
151 : {
152 1 : GkmGenericKey *self = GKM_GENERIC_KEY (key);
153 1 : *n_value = self->n_value;
154 1 : return self->value;
155 : }
156 :
157 : static void
158 1 : gkm_generic_key_init (GkmGenericKey *self)
159 : {
160 :
161 1 : }
162 :
163 : static void
164 1 : gkm_generic_key_finalize (GObject *obj)
165 : {
166 1 : GkmGenericKey *self = GKM_GENERIC_KEY (obj);
167 :
168 1 : if (self->value) {
169 1 : egg_secure_clear (self->value, self->n_value);
170 1 : egg_secure_free (self->value);
171 1 : self->value = NULL;
172 1 : self->n_value = 0;
173 : }
174 :
175 1 : G_OBJECT_CLASS (gkm_generic_key_parent_class)->finalize (obj);
176 1 : }
177 :
178 : static void
179 1 : gkm_generic_key_class_init (GkmGenericKeyClass *klass)
180 : {
181 1 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
182 1 : GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
183 1 : GkmSecretKeyClass *key_class = GKM_SECRET_KEY_CLASS (klass);
184 :
185 1 : gkm_generic_key_parent_class = g_type_class_peek_parent (klass);
186 :
187 1 : gobject_class->finalize = gkm_generic_key_finalize;
188 :
189 1 : gkm_class->get_attribute = gkm_generic_key_get_attribute;
190 :
191 1 : key_class->get_key_value = gkm_generic_key_get_key_value;
192 1 : }
193 :
194 : /* -----------------------------------------------------------------------------
195 : * PUBLIC
196 : */
197 :
198 : GkmFactory*
199 287 : gkm_generic_key_get_factory (void)
200 : {
201 : static CK_OBJECT_CLASS klass = CKO_SECRET_KEY;
202 : static CK_KEY_TYPE type = CKK_GENERIC_SECRET;
203 :
204 : static CK_ATTRIBUTE attributes[] = {
205 : { CKA_CLASS, &klass, sizeof (klass) },
206 : { CKA_KEY_TYPE, &type, sizeof (type) }
207 : };
208 :
209 : static GkmFactory factory = {
210 : attributes,
211 : G_N_ELEMENTS (attributes),
212 : factory_create_generic_key
213 : };
214 :
215 287 : return &factory;
216 : }
|