1 /*
2 * gnome-keyring
3 *
4 * Copyright (C) 2010 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 "egg/egg-secure-memory.h"
24
25 #include "gkm/gkm-attributes.h"
26 #include "gkm/gkm-mock.h"
27 #include "gkm/gkm-test.h"
28
29 #include "wrap-layer/gkm-wrap-layer.h"
30
31 static guint secret_identifier = 8800;
32
33 EGG_SECURE_DEFINE_GLIB_GLOBALS ();
34
35 static CK_RV
mock_secret_C_Initialize(CK_VOID_PTR pInitArgs)36 mock_secret_C_Initialize (CK_VOID_PTR pInitArgs)
37 {
38 GArray *attrs;
39 CK_RV rv;
40
41 rv = gkm_mock_C_Initialize (pInitArgs);
42 if (rv != CKR_OK)
43 return rv;
44
45 attrs = gkm_template_new (NULL, 0);
46 gkm_template_set_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
47 gkm_template_set_boolean (attrs, CKA_G_LOGIN_COLLECTION, CK_TRUE);
48 gkm_template_set_string (attrs, CKA_ID, "login");
49 gkm_template_set_string (attrs, CKA_LABEL, "Login Keyring");
50 gkm_template_set_boolean (attrs, CKA_TRUSTED, CK_TRUE);
51 gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_FALSE);
52 gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
53 gkm_mock_module_take_object (attrs);
54
55 attrs = gkm_template_new (NULL, 0);
56 gkm_template_set_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
57 gkm_template_set_boolean (attrs, CKA_G_LOGIN_COLLECTION, CK_FALSE);
58 gkm_template_set_string (attrs, CKA_ID, "other");
59 gkm_template_set_string (attrs, CKA_LABEL, "Other Keyring");
60 gkm_template_set_boolean (attrs, CKA_TRUSTED, CK_TRUE);
61 gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_TRUE);
62 gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
63 gkm_mock_module_take_object (attrs);
64
65 attrs = gkm_template_new (NULL, 0);
66 gkm_template_set_string (attrs, CKA_G_COLLECTION, "login");
67 gkm_template_set_string (attrs, CKA_ID, "23");
68 gkm_template_set_string (attrs, CKA_LABEL, "Unlock password for: Mock");
69 gkm_template_set_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
70 gkm_template_set_value (attrs, CKA_G_FIELDS, "one\0" "1\0" "two\0" "2\0", 12);
71 gkm_template_set_string (attrs, CKA_VALUE, "mock");
72 gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
73 gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_FALSE);
74 gkm_mock_module_take_object (attrs);
75
76 return CKR_OK;
77 }
78
79 typedef struct {
80 GArray *template;
81 GArray *objects;
82 } FieldSearch;
83
84 static gboolean
match_fields(gconstpointer fields,gsize n_fields,gconstpointer all,gsize n_all)85 match_fields (gconstpointer fields, gsize n_fields, gconstpointer all, gsize n_all)
86 {
87 const guchar *field;
88 gsize n_field;
89 const guchar *ptr;
90 const guchar *last;
91
92 g_assert (all);
93 g_assert (fields);
94
95 ptr = fields;
96 last = ptr + n_fields;
97
98 g_assert (ptr || last == ptr);
99 while (ptr && ptr != last) {
100 g_assert (ptr < last);
101
102 field = ptr;
103 ptr = memchr (ptr, 0, last - ptr);
104 g_assert (ptr);
105 ++ptr;
106
107 ptr = memchr (ptr, 0, last - ptr);
108 g_assert (ptr);
109 ++ptr;
110
111 n_field = ptr - field;
112 if (!memmem (all, n_all, field, n_field))
113 return FALSE;
114 }
115
116 return TRUE;
117 }
118
119 static gboolean
enumerate_field_search(CK_OBJECT_HANDLE handle,GArray * attrs,gpointer user_data)120 enumerate_field_search (CK_OBJECT_HANDLE handle, GArray *attrs, gpointer user_data)
121 {
122 FieldSearch *ctx = user_data;
123 CK_ATTRIBUTE_PTR tattr;
124 CK_ATTRIBUTE_PTR oattr;
125
126 tattr = gkm_template_find (ctx->template, CKA_G_FIELDS);
127 g_assert (tattr);
128
129 oattr = gkm_template_find (attrs, CKA_G_FIELDS);
130 if (!oattr)
131 return TRUE; /* Continue */
132 if (!match_fields (tattr->pValue, tattr->ulValueLen, oattr->pValue, oattr->ulValueLen))
133 return TRUE; /* Continue */
134
135 tattr = gkm_template_find (ctx->template, CKA_G_COLLECTION);
136 if (tattr) {
137 oattr = gkm_template_find (attrs, CKA_G_COLLECTION);
138 if (!oattr || oattr->ulValueLen != tattr->ulValueLen)
139 return TRUE; /* Continue */
140 if (memcmp (oattr->pValue, tattr->pValue, oattr->ulValueLen) != 0)
141 return TRUE; /* Continue */
142 }
143
144 /* Add it to the set */
145 g_array_append_val (ctx->objects, handle);
146 return TRUE; /* Continue */
147 }
148
149 static CK_RV
mock_secret_C_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)150 mock_secret_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
151 CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
152 {
153 GArray *template = NULL;
154 CK_OBJECT_CLASS klass;
155 CK_ATTRIBUTE_PTR attr;
156 gchar *text;
157 CK_RV rv;
158
159 g_return_val_if_fail (phObject, CKR_ARGUMENTS_BAD);
160
161 if (!gkm_attributes_find_ulong (pTemplate, ulCount, CKA_CLASS, &klass))
162 klass = (CK_ULONG)-1;
163
164 /* Is it a search object? */
165 if (klass == CKO_G_SEARCH) {
166
167 FieldSearch ctx;
168 ctx.template = template = gkm_template_new (pTemplate, ulCount);
169 ctx.objects = g_array_new (FALSE, FALSE, sizeof (CK_OBJECT_HANDLE));
170
171 /* Find all the fields */
172 gkm_mock_module_enumerate_objects (hSession, enumerate_field_search, &ctx);
173
174 gkm_template_set_value (template, CKA_G_MATCHED, ctx.objects->data,
175 ctx.objects->len * sizeof (CK_OBJECT_HANDLE));
176 g_array_free (ctx.objects, TRUE);
177
178 } else if (klass == CKO_SECRET_KEY) {
179
180 /* If it's a secret key and id set, just overwrite */
181 attr = gkm_attributes_find (pTemplate, ulCount, CKA_ID);
182 if (attr) {
183 CK_ATTRIBUTE attrs[2];
184
185 memcpy (attrs, attr, sizeof (CK_ATTRIBUTE));
186 attrs[1].type = CKA_CLASS;
187 attrs[1].ulValueLen = sizeof (klass);
188 attrs[1].pValue = &klass;
189
190 *phObject = gkm_mock_module_find_object (hSession, attrs, 2);
191 g_return_val_if_fail (*phObject, CKR_TEMPLATE_INCONSISTENT);
192 return gkm_mock_C_SetAttributeValue (hSession, *phObject, pTemplate, ulCount);
193 }
194
195 /* Otherwise add a unique identifier */
196 template = gkm_template_new (pTemplate, ulCount);
197 text = g_strdup_printf ("%d", ++secret_identifier);
198 gkm_template_set_string (template, CKA_ID, text);
199 g_free (text);
200 }
201
202 if (template) {
203 pTemplate = (CK_ATTRIBUTE_PTR)template->data;
204 ulCount = template->len;
205 }
206
207 rv = gkm_mock_C_CreateObject (hSession, pTemplate, ulCount, phObject);
208
209 if (template)
210 gkm_template_free (template);
211
212 return rv;
213 }
214
215 CK_FUNCTION_LIST mock_secret_store = {
216 { 2, 11 }, /* version */
217 mock_secret_C_Initialize,
218 gkm_mock_C_Finalize,
219 gkm_mock_C_GetInfo,
220 gkm_mock_C_GetFunctionList,
221 gkm_mock_C_GetSlotList,
222 gkm_mock_C_GetSlotInfo,
223 gkm_mock_C_GetTokenInfo,
224 gkm_mock_C_GetMechanismList,
225 gkm_mock_C_GetMechanismInfo,
226 gkm_mock_C_InitToken,
227 gkm_mock_C_InitPIN,
228 gkm_mock_C_SetPIN,
229 gkm_mock_C_OpenSession,
230 gkm_mock_C_CloseSession,
231 gkm_mock_C_CloseAllSessions,
232 gkm_mock_C_GetSessionInfo,
233 gkm_mock_unsupported_C_GetOperationState,
234 gkm_mock_unsupported_C_SetOperationState,
235 gkm_mock_C_Login,
236 gkm_mock_C_Logout,
237 mock_secret_C_CreateObject,
238 gkm_mock_unsupported_C_CopyObject,
239 gkm_mock_C_DestroyObject,
240 gkm_mock_unsupported_C_GetObjectSize,
241 gkm_mock_C_GetAttributeValue,
242 gkm_mock_C_SetAttributeValue,
243 gkm_mock_C_FindObjectsInit,
244 gkm_mock_C_FindObjects,
245 gkm_mock_C_FindObjectsFinal,
246 gkm_mock_C_EncryptInit,
247 gkm_mock_C_Encrypt,
248 gkm_mock_unsupported_C_EncryptUpdate,
249 gkm_mock_unsupported_C_EncryptFinal,
250 gkm_mock_C_DecryptInit,
251 gkm_mock_C_Decrypt,
252 gkm_mock_unsupported_C_DecryptUpdate,
253 gkm_mock_unsupported_C_DecryptFinal,
254 gkm_mock_unsupported_C_DigestInit,
255 gkm_mock_unsupported_C_Digest,
256 gkm_mock_unsupported_C_DigestUpdate,
257 gkm_mock_unsupported_C_DigestKey,
258 gkm_mock_unsupported_C_DigestFinal,
259 gkm_mock_C_SignInit,
260 gkm_mock_C_Sign,
261 gkm_mock_unsupported_C_SignUpdate,
262 gkm_mock_unsupported_C_SignFinal,
263 gkm_mock_unsupported_C_SignRecoverInit,
264 gkm_mock_unsupported_C_SignRecover,
265 gkm_mock_C_VerifyInit,
266 gkm_mock_C_Verify,
267 gkm_mock_unsupported_C_VerifyUpdate,
268 gkm_mock_unsupported_C_VerifyFinal,
269 gkm_mock_unsupported_C_VerifyRecoverInit,
270 gkm_mock_unsupported_C_VerifyRecover,
271 gkm_mock_unsupported_C_DigestEncryptUpdate,
272 gkm_mock_unsupported_C_DecryptDigestUpdate,
273 gkm_mock_unsupported_C_SignEncryptUpdate,
274 gkm_mock_unsupported_C_DecryptVerifyUpdate,
275 gkm_mock_unsupported_C_GenerateKey,
276 gkm_mock_unsupported_C_GenerateKeyPair,
277 gkm_mock_unsupported_C_WrapKey,
278 gkm_mock_unsupported_C_UnwrapKey,
279 gkm_mock_unsupported_C_DeriveKey,
280 gkm_mock_unsupported_C_SeedRandom,
281 gkm_mock_unsupported_C_GenerateRandom,
282 gkm_mock_C_GetFunctionStatus,
283 gkm_mock_C_CancelFunction,
284 gkm_mock_unsupported_C_WaitForSlotEvent
285 };
286