Line data Source code
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 8702 : EGG_SECURE_DEFINE_GLIB_GLOBALS ();
34 :
35 : static CK_RV
36 15 : mock_secret_C_Initialize (CK_VOID_PTR pInitArgs)
37 : {
38 : GArray *attrs;
39 : CK_RV rv;
40 :
41 15 : rv = gkm_mock_C_Initialize (pInitArgs);
42 15 : if (rv != CKR_OK)
43 0 : return rv;
44 :
45 15 : attrs = gkm_template_new (NULL, 0);
46 15 : gkm_template_set_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
47 15 : gkm_template_set_boolean (attrs, CKA_G_LOGIN_COLLECTION, CK_TRUE);
48 15 : gkm_template_set_string (attrs, CKA_ID, "login");
49 15 : gkm_template_set_string (attrs, CKA_LABEL, "Login Keyring");
50 15 : gkm_template_set_boolean (attrs, CKA_TRUSTED, CK_TRUE);
51 15 : gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_FALSE);
52 15 : gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
53 15 : gkm_mock_module_take_object (attrs);
54 :
55 15 : attrs = gkm_template_new (NULL, 0);
56 15 : gkm_template_set_ulong (attrs, CKA_CLASS, CKO_G_COLLECTION);
57 15 : gkm_template_set_boolean (attrs, CKA_G_LOGIN_COLLECTION, CK_FALSE);
58 15 : gkm_template_set_string (attrs, CKA_ID, "other");
59 15 : gkm_template_set_string (attrs, CKA_LABEL, "Other Keyring");
60 15 : gkm_template_set_boolean (attrs, CKA_TRUSTED, CK_TRUE);
61 15 : gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_TRUE);
62 15 : gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
63 15 : gkm_mock_module_take_object (attrs);
64 :
65 15 : attrs = gkm_template_new (NULL, 0);
66 15 : gkm_template_set_string (attrs, CKA_G_COLLECTION, "login");
67 15 : gkm_template_set_string (attrs, CKA_ID, "23");
68 15 : gkm_template_set_string (attrs, CKA_LABEL, "Unlock password for: Mock");
69 15 : gkm_template_set_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
70 15 : gkm_template_set_value (attrs, CKA_G_FIELDS, "one\0" "1\0" "two\0" "2\0", 12);
71 15 : gkm_template_set_string (attrs, CKA_VALUE, "mock");
72 15 : gkm_template_set_boolean (attrs, CKA_TOKEN, CK_TRUE);
73 15 : gkm_template_set_boolean (attrs, CKA_G_LOCKED, CK_FALSE);
74 15 : gkm_mock_module_take_object (attrs);
75 :
76 15 : return CKR_OK;
77 : }
78 :
79 : typedef struct {
80 : GArray *template;
81 : GArray *objects;
82 : } FieldSearch;
83 :
84 : static gboolean
85 32 : 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 32 : g_assert (all);
93 32 : g_assert (fields);
94 :
95 32 : ptr = fields;
96 32 : last = ptr + n_fields;
97 :
98 32 : g_assert (ptr || last == ptr);
99 54 : while (ptr && ptr != last) {
100 42 : g_assert (ptr < last);
101 :
102 42 : field = ptr;
103 42 : ptr = memchr (ptr, 0, last - ptr);
104 42 : g_assert (ptr);
105 42 : ++ptr;
106 :
107 42 : ptr = memchr (ptr, 0, last - ptr);
108 42 : g_assert (ptr);
109 42 : ++ptr;
110 :
111 42 : n_field = ptr - field;
112 42 : if (!memmem (all, n_all, field, n_field))
113 20 : return FALSE;
114 : }
115 :
116 12 : return TRUE;
117 : }
118 :
119 : static gboolean
120 189 : enumerate_field_search (CK_OBJECT_HANDLE handle, GArray *attrs, gpointer user_data)
121 : {
122 189 : FieldSearch *ctx = user_data;
123 : CK_ATTRIBUTE_PTR tattr;
124 : CK_ATTRIBUTE_PTR oattr;
125 :
126 189 : tattr = gkm_template_find (ctx->template, CKA_G_FIELDS);
127 189 : g_assert (tattr);
128 :
129 189 : oattr = gkm_template_find (attrs, CKA_G_FIELDS);
130 189 : if (!oattr)
131 157 : return TRUE; /* Continue */
132 32 : if (!match_fields (tattr->pValue, tattr->ulValueLen, oattr->pValue, oattr->ulValueLen))
133 20 : return TRUE; /* Continue */
134 :
135 12 : tattr = gkm_template_find (ctx->template, CKA_G_COLLECTION);
136 12 : if (tattr) {
137 5 : oattr = gkm_template_find (attrs, CKA_G_COLLECTION);
138 5 : if (!oattr || oattr->ulValueLen != tattr->ulValueLen)
139 0 : return TRUE; /* Continue */
140 5 : if (memcmp (oattr->pValue, tattr->pValue, oattr->ulValueLen) != 0)
141 0 : return TRUE; /* Continue */
142 : }
143 :
144 : /* Add it to the set */
145 12 : g_array_append_val (ctx->objects, handle);
146 12 : return TRUE; /* Continue */
147 : }
148 :
149 : static CK_RV
150 36 : mock_secret_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
151 : CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
152 : {
153 36 : GArray *template = NULL;
154 : CK_OBJECT_CLASS klass;
155 : CK_ATTRIBUTE_PTR attr;
156 : gchar *text;
157 : CK_RV rv;
158 :
159 36 : g_return_val_if_fail (phObject, CKR_ARGUMENTS_BAD);
160 :
161 36 : if (!gkm_attributes_find_ulong (pTemplate, ulCount, CKA_CLASS, &klass))
162 0 : klass = (CK_ULONG)-1;
163 :
164 : /* Is it a search object? */
165 36 : if (klass == CKO_G_SEARCH) {
166 :
167 : FieldSearch ctx;
168 22 : ctx.template = template = gkm_template_new (pTemplate, ulCount);
169 22 : ctx.objects = g_array_new (FALSE, FALSE, sizeof (CK_OBJECT_HANDLE));
170 :
171 : /* Find all the fields */
172 22 : gkm_mock_module_enumerate_objects (hSession, enumerate_field_search, &ctx);
173 :
174 22 : gkm_template_set_value (template, CKA_G_MATCHED, ctx.objects->data,
175 22 : ctx.objects->len * sizeof (CK_OBJECT_HANDLE));
176 22 : g_array_free (ctx.objects, TRUE);
177 :
178 14 : } else if (klass == CKO_SECRET_KEY) {
179 :
180 : /* If it's a secret key and id set, just overwrite */
181 7 : attr = gkm_attributes_find (pTemplate, ulCount, CKA_ID);
182 7 : if (attr) {
183 : CK_ATTRIBUTE attrs[2];
184 :
185 1 : memcpy (attrs, attr, sizeof (CK_ATTRIBUTE));
186 1 : attrs[1].type = CKA_CLASS;
187 1 : attrs[1].ulValueLen = sizeof (klass);
188 1 : attrs[1].pValue = &klass;
189 :
190 1 : *phObject = gkm_mock_module_find_object (hSession, attrs, 2);
191 1 : g_return_val_if_fail (*phObject, CKR_TEMPLATE_INCONSISTENT);
192 1 : return gkm_mock_C_SetAttributeValue (hSession, *phObject, pTemplate, ulCount);
193 : }
194 :
195 : /* Otherwise add a unique identifier */
196 6 : template = gkm_template_new (pTemplate, ulCount);
197 6 : text = g_strdup_printf ("%d", ++secret_identifier);
198 6 : gkm_template_set_string (template, CKA_ID, text);
199 6 : g_free (text);
200 : }
201 :
202 35 : if (template) {
203 28 : pTemplate = (CK_ATTRIBUTE_PTR)template->data;
204 28 : ulCount = template->len;
205 : }
206 :
207 35 : rv = gkm_mock_C_CreateObject (hSession, pTemplate, ulCount, phObject);
208 :
209 35 : if (template)
210 28 : gkm_template_free (template);
211 :
212 35 : 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 : };
|