/src/opensc/src/libopensc/pkcs15-gemsafeV1.c
Line | Count | Source |
1 | | /* |
2 | | * This library is free software; you can redistribute it and/or |
3 | | * modify it under the terms of the GNU Lesser General Public |
4 | | * License as published by the Free Software Foundation; either |
5 | | * version 2.1 of the License, or (at your option) any later version. |
6 | | * |
7 | | * This library is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10 | | * Lesser General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU Lesser General Public |
13 | | * License along with this library; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
15 | | */ |
16 | | |
17 | | /* Initially written by David Mattes <david.mattes@boeing.com> */ |
18 | | /* Support for multiple key containers by Lukas Wunner <lukas@wunner.de> */ |
19 | | |
20 | | #ifdef HAVE_CONFIG_H |
21 | | #include "config.h" |
22 | | #endif |
23 | | |
24 | | #include <stdlib.h> |
25 | | #include <string.h> |
26 | | #include <stdio.h> |
27 | | |
28 | | #include "internal.h" |
29 | | #include "pkcs15.h" |
30 | | |
31 | 255 | #define MANU_ID "Gemplus" |
32 | 772 | #define APPLET_NAME "GemSAFE V1" |
33 | 772 | #define DRIVER_SERIAL_NUMBER "v0.9" |
34 | 58 | #define GEMSAFE_APP_PATH "3F001600" |
35 | 255 | #define GEMSAFE_PATH "3F0016000004" |
36 | | |
37 | | /* Apparently, the Applet max read "quanta" is 248 bytes |
38 | | * Gemalto ClassicClient reads files in chunks of 238 bytes |
39 | | */ |
40 | 211 | #define GEMSAFE_READ_QUANTUM 248 |
41 | 182 | #define GEMSAFE_MAX_OBJLEN 28672 |
42 | | |
43 | | static int |
44 | | sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card, |
45 | | int type, int authority, |
46 | | const sc_path_t *path, |
47 | | const sc_pkcs15_id_t *id, |
48 | | const char *label, int obj_flags); |
49 | | |
50 | | static int |
51 | | sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, |
52 | | const sc_pkcs15_id_t *id, const char *label, |
53 | | const sc_path_t *path, int ref, int type, |
54 | | unsigned int min_length, |
55 | | unsigned int max_length, |
56 | | int flags, int tries_left, const char pad_char, int obj_flags); |
57 | | |
58 | | static int |
59 | | sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, |
60 | | const sc_pkcs15_id_t *id, |
61 | | const char *label, |
62 | | int type, unsigned int modulus_length, int usage, |
63 | | const sc_path_t *path, int ref, |
64 | | const sc_pkcs15_id_t *auth_id, int obj_flags); |
65 | | |
66 | | typedef struct cdata_st { |
67 | | char *label; |
68 | | int authority; |
69 | | const char *path; |
70 | | int index; |
71 | | int count; |
72 | | const char *id; |
73 | | int obj_flags; |
74 | | } cdata; |
75 | | |
76 | | const unsigned int gemsafe_cert_max = 12; |
77 | | |
78 | | cdata gemsafe_cert[] = { |
79 | | {"DS certificate #1", 0, GEMSAFE_PATH, 0, 0, "45", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
80 | | {"DS certificate #2", 0, GEMSAFE_PATH, 0, 0, "46", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
81 | | {"DS certificate #3", 0, GEMSAFE_PATH, 0, 0, "47", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
82 | | {"DS certificate #4", 0, GEMSAFE_PATH, 0, 0, "48", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
83 | | {"DS certificate #5", 0, GEMSAFE_PATH, 0, 0, "49", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
84 | | {"DS certificate #6", 0, GEMSAFE_PATH, 0, 0, "50", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
85 | | {"DS certificate #7", 0, GEMSAFE_PATH, 0, 0, "51", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
86 | | {"DS certificate #8", 0, GEMSAFE_PATH, 0, 0, "52", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
87 | | {"DS certificate #9", 0, GEMSAFE_PATH, 0, 0, "53", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
88 | | {"DS certificate #10", 0, GEMSAFE_PATH, 0, 0, "54", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
89 | | {"DS certificate #11", 0, GEMSAFE_PATH, 0, 0, "55", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
90 | | {"DS certificate #12", 0, GEMSAFE_PATH, 0, 0, "56", SC_PKCS15_CO_FLAG_MODIFIABLE}, |
91 | | }; |
92 | | |
93 | | typedef struct pdata_st { |
94 | | const u8 atr[SC_MAX_ATR_SIZE]; |
95 | | const size_t atr_len; |
96 | | const char *id; |
97 | | const char *label; |
98 | | const char *path; |
99 | | const int ref; |
100 | | const int type; |
101 | | const unsigned int maxlen; |
102 | | const unsigned int minlen; |
103 | | const int flags; |
104 | | const int tries_left; |
105 | | const char pad_char; |
106 | | const int obj_flags; |
107 | | } pindata; |
108 | | |
109 | | const unsigned int gemsafe_pin_max = 2; |
110 | | |
111 | | const pindata gemsafe_pin[] = { |
112 | | /* ATR-specific PIN policies, first match found is used: */ |
113 | | { {0x3B, 0x7D, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, |
114 | | 0xB0, 0x83, 0x11, 0x48, 0xC8, 0x83, 0x00, 0x90, 0x00}, 18, |
115 | | "01", "DS pin", GEMSAFE_PATH, 0x01, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, |
116 | | 8, 4, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, |
117 | | 3, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, |
118 | | /* default PIN policy comes last: */ |
119 | | { { 0 }, 0, |
120 | | "01", "DS pin", GEMSAFE_PATH, 0x01, SC_PKCS15_PIN_TYPE_BCD, |
121 | | 16, 6, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, |
122 | | 3, 0xFF, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE } |
123 | | }; |
124 | | |
125 | | typedef struct prdata_st { |
126 | | const char *id; |
127 | | char *label; |
128 | | unsigned int modulus_len; |
129 | | int usage; |
130 | | const char *path; |
131 | | int ref; |
132 | | const char *auth_id; |
133 | | int obj_flags; |
134 | | } prdata; |
135 | | |
136 | | #define USAGE_NONREP SC_PKCS15_PRKEY_USAGE_NONREPUDIATION |
137 | | #define USAGE_KE SC_PKCS15_PRKEY_USAGE_ENCRYPT | \ |
138 | | SC_PKCS15_PRKEY_USAGE_DECRYPT | \ |
139 | | SC_PKCS15_PRKEY_USAGE_WRAP | \ |
140 | | SC_PKCS15_PRKEY_USAGE_UNWRAP |
141 | | #define USAGE_AUT SC_PKCS15_PRKEY_USAGE_ENCRYPT | \ |
142 | | SC_PKCS15_PRKEY_USAGE_DECRYPT | \ |
143 | | SC_PKCS15_PRKEY_USAGE_WRAP | \ |
144 | | SC_PKCS15_PRKEY_USAGE_UNWRAP | \ |
145 | | SC_PKCS15_PRKEY_USAGE_SIGN |
146 | | |
147 | | prdata gemsafe_prkeys[] = { |
148 | | { "45", "DS key #1", 1024, USAGE_AUT, GEMSAFE_PATH, 0x03, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
149 | | { "46", "DS key #2", 1024, USAGE_AUT, GEMSAFE_PATH, 0x04, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
150 | | { "47", "DS key #3", 1024, USAGE_AUT, GEMSAFE_PATH, 0x05, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
151 | | { "48", "DS key #4", 1024, USAGE_AUT, GEMSAFE_PATH, 0x06, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
152 | | { "49", "DS key #5", 1024, USAGE_AUT, GEMSAFE_PATH, 0x07, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
153 | | { "50", "DS key #6", 1024, USAGE_AUT, GEMSAFE_PATH, 0x08, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
154 | | { "51", "DS key #7", 1024, USAGE_AUT, GEMSAFE_PATH, 0x09, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
155 | | { "52", "DS key #8", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0a, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
156 | | { "53", "DS key #9", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0b, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
157 | | { "54", "DS key #10", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0c, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
158 | | { "55", "DS key #11", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0d, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
159 | | { "56", "DS key #12", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0e, "01", SC_PKCS15_CO_FLAG_PRIVATE}, |
160 | | }; |
161 | | |
162 | | static int gemsafe_get_cert_len(sc_card_t *card) |
163 | 255 | { |
164 | 255 | int r; |
165 | 255 | u8 ibuf[GEMSAFE_MAX_OBJLEN]; |
166 | 255 | u8 *iptr; |
167 | 255 | struct sc_path path; |
168 | 255 | struct sc_file *file; |
169 | 255 | size_t objlen; |
170 | 255 | int certlen; |
171 | 255 | unsigned int ind, i=0; |
172 | 255 | int read_len; |
173 | | |
174 | 255 | sc_format_path(GEMSAFE_PATH, &path); |
175 | 255 | r = sc_select_file(card, &path, &file); |
176 | 255 | if (r != SC_SUCCESS || !file) |
177 | 44 | return SC_ERROR_INTERNAL; |
178 | 211 | sc_file_free(file); |
179 | | |
180 | | /* Initial read */ |
181 | 211 | read_len = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); |
182 | 211 | if (read_len <= 2) { |
183 | 25 | sc_log(card->ctx, "Invalid size of object data: %d", read_len); |
184 | 25 | return SC_ERROR_INTERNAL; |
185 | 25 | } |
186 | | |
187 | | /* Actual stored object size is encoded in first 2 bytes |
188 | | * (allocated EF space is much greater!) |
189 | | */ |
190 | 186 | objlen = (((size_t) ibuf[0]) << 8) | ibuf[1]; |
191 | 186 | sc_log(card->ctx, "Stored object is of size: %zu", objlen); |
192 | 186 | if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) { |
193 | 16 | sc_log(card->ctx, "Invalid object size: %zu", objlen); |
194 | 16 | return SC_ERROR_INTERNAL; |
195 | 16 | } |
196 | | |
197 | | /* It looks like the first thing in the block is a table of |
198 | | * which keys are allocated. The table is small and is in the |
199 | | * first 248 bytes. Example for a card with 10 key containers: |
200 | | * 01 f0 00 03 03 b0 00 03 <= 1st key unallocated |
201 | | * 01 f0 00 04 03 b0 00 04 <= 2nd key unallocated |
202 | | * 01 fe 14 00 05 03 b0 00 05 <= 3rd key allocated |
203 | | * 01 fe 14 01 06 03 b0 00 06 <= 4th key allocated |
204 | | * 01 f0 00 07 03 b0 00 07 <= 5th key unallocated |
205 | | * ... |
206 | | * 01 f0 00 0c 03 b0 00 0c <= 10th key unallocated |
207 | | * For allocated keys, the fourth byte seems to indicate the |
208 | | * default key and the fifth byte indicates the key_ref of |
209 | | * the private key. |
210 | | */ |
211 | 170 | ind = 2; /* skip length */ |
212 | 261 | while (ind + 1 < (size_t)read_len && ibuf[ind] == 0x01 && i < gemsafe_cert_max) { |
213 | 91 | if (ibuf[ind+1] == 0xFE) { |
214 | 20 | gemsafe_prkeys[i].ref = ibuf[ind+4]; |
215 | 20 | sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d", |
216 | 20 | i+1, gemsafe_prkeys[i].ref); |
217 | 20 | ind += 9; |
218 | 20 | } |
219 | 71 | else { |
220 | 71 | gemsafe_prkeys[i].label = NULL; |
221 | 71 | gemsafe_cert[i].label = NULL; |
222 | 71 | sc_log(card->ctx, "Key container %d is unallocated", i+1); |
223 | 71 | ind += 8; |
224 | 71 | } |
225 | 91 | i++; |
226 | 91 | } |
227 | | |
228 | | /* Delete additional key containers from the data structures if |
229 | | * this card can't accommodate them. |
230 | | */ |
231 | 2.11k | for (; i < gemsafe_cert_max; i++) { |
232 | 1.94k | gemsafe_prkeys[i].label = NULL; |
233 | 1.94k | gemsafe_cert[i].label = NULL; |
234 | 1.94k | } |
235 | | |
236 | | /* Read entire file, then dissect in memory. |
237 | | * Gemalto ClassicClient seems to do it the same way. |
238 | | */ |
239 | 170 | iptr = ibuf + read_len; |
240 | 2.57k | while ((size_t)(iptr - ibuf) < objlen) { |
241 | 2.51k | r = sc_read_binary(card, (unsigned)(iptr - ibuf), iptr, |
242 | 2.51k | MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0); |
243 | 2.51k | if (r < 0) { |
244 | 93 | sc_log(card->ctx, "Could not read cert object"); |
245 | 93 | return SC_ERROR_INTERNAL; |
246 | 93 | } |
247 | 2.42k | if (r == 0) |
248 | 19 | break; |
249 | 2.40k | read_len += r; |
250 | 2.40k | iptr += r; |
251 | 2.40k | } |
252 | 77 | if ((size_t)read_len < objlen) { |
253 | 19 | sc_log(card->ctx, "Could not read cert object"); |
254 | 19 | return SC_ERROR_INTERNAL; |
255 | 19 | } |
256 | | |
257 | | /* Search buffer for certificates, they start with 0x3082. */ |
258 | 58 | i = 0; |
259 | 114k | while (ind < objlen - 1) { |
260 | 114k | if (ibuf[ind] == 0x30 && ibuf[ind+1] == 0x82) { |
261 | | /* Find next allocated key container */ |
262 | 13 | while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL) |
263 | 12 | i++; |
264 | 1 | if (i == gemsafe_cert_max) { |
265 | 1 | sc_log(card->ctx, "Warning: Found orphaned certificate at offset %d", ind); |
266 | 1 | return SC_SUCCESS; |
267 | 1 | } |
268 | | /* DER cert len is encoded this way */ |
269 | 0 | if (ind+3 >= sizeof ibuf) |
270 | 0 | return SC_ERROR_INVALID_DATA; |
271 | 0 | certlen = ((((int)ibuf[ind + 2]) << 8) | ibuf[ind + 3]) + 4; |
272 | 0 | sc_log(card->ctx, |
273 | 0 | "Found certificate of key container %d at offset %d, len %d", |
274 | 0 | i+1, ind, certlen); |
275 | 0 | gemsafe_cert[i].index = ind; |
276 | 0 | gemsafe_cert[i].count = certlen; |
277 | 0 | ind += certlen; |
278 | 0 | i++; |
279 | 0 | } else |
280 | 114k | ind++; |
281 | 114k | } |
282 | | |
283 | | /* Delete additional key containers from the data structures if |
284 | | * they're missing on the card. |
285 | | */ |
286 | 741 | for (; i < gemsafe_cert_max; i++) { |
287 | 684 | if (gemsafe_cert[i].label) { |
288 | 0 | sc_log(card->ctx, "Warning: Certificate of key container %d is missing", i+1); |
289 | 0 | gemsafe_prkeys[i].label = NULL; |
290 | 0 | gemsafe_cert[i].label = NULL; |
291 | 0 | } |
292 | 684 | } |
293 | | |
294 | 57 | return SC_SUCCESS; |
295 | 58 | } |
296 | | |
297 | | static int gemsafe_detect_card( sc_pkcs15_card_t *p15card) |
298 | 12.2k | { |
299 | 12.2k | if (strcmp(p15card->card->name, "GemSAFE V1")) |
300 | 11.4k | return SC_ERROR_WRONG_CARD; |
301 | | |
302 | 772 | return SC_SUCCESS; |
303 | 12.2k | } |
304 | | |
305 | | static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) |
306 | 772 | { |
307 | 772 | int r; |
308 | 772 | unsigned int i; |
309 | 772 | struct sc_path path; |
310 | 772 | struct sc_file *file = NULL; |
311 | 772 | struct sc_card *card = p15card->card; |
312 | 772 | struct sc_apdu apdu; |
313 | 772 | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
314 | | |
315 | 772 | sc_log(p15card->card->ctx, "Setting pkcs15 parameters"); |
316 | | |
317 | 772 | set_string(&p15card->tokeninfo->label, APPLET_NAME); |
318 | 772 | if (!p15card->tokeninfo->label) |
319 | 0 | return SC_ERROR_INTERNAL; |
320 | | |
321 | 772 | set_string(&p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER); |
322 | 772 | if (!p15card->tokeninfo->serial_number) { |
323 | 0 | free(p15card->tokeninfo->label); |
324 | 0 | p15card->tokeninfo->label = NULL; |
325 | 0 | return SC_ERROR_INTERNAL; |
326 | 0 | } |
327 | | |
328 | | /* the GemSAFE applet version number */ |
329 | 772 | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03); |
330 | 772 | apdu.cla = 0x80; |
331 | 772 | apdu.resp = rbuf; |
332 | 772 | apdu.resplen = sizeof(rbuf); |
333 | | /* Manual says Le=0x05, but should be 0x08 to return full version number */ |
334 | 772 | apdu.le = 0x08; |
335 | 772 | apdu.lc = 0; |
336 | 772 | apdu.datalen = 0; |
337 | 772 | r = sc_transmit_apdu(card, &apdu); |
338 | 772 | if (r < 0) |
339 | 23 | sc_pkcs15_card_clear(p15card); |
340 | 772 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
341 | | |
342 | 749 | if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || r != SC_SUCCESS) { |
343 | 494 | sc_pkcs15_card_clear(p15card); |
344 | 494 | return SC_ERROR_INTERNAL; |
345 | 494 | } |
346 | | |
347 | | /* the manufacturer ID, in this case GemPlus */ |
348 | 255 | set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID); |
349 | 255 | if (!p15card->tokeninfo->manufacturer_id) { |
350 | 0 | sc_pkcs15_card_clear(p15card); |
351 | 0 | return SC_ERROR_INTERNAL; |
352 | 0 | } |
353 | | |
354 | | /* determine allocated key containers and length of certificates */ |
355 | 255 | r = gemsafe_get_cert_len(card); |
356 | 255 | if (r != SC_SUCCESS) { |
357 | 197 | sc_pkcs15_card_clear(p15card); |
358 | 197 | return SC_ERROR_INTERNAL; |
359 | 197 | } |
360 | | |
361 | | /* set certs */ |
362 | 58 | sc_log(p15card->card->ctx, "Setting certificates"); |
363 | 754 | for (i = 0; i < gemsafe_cert_max; i++) { |
364 | 696 | struct sc_pkcs15_id p15Id; |
365 | 696 | struct sc_path path; |
366 | | |
367 | 696 | if (gemsafe_cert[i].label == NULL) |
368 | 696 | continue; |
369 | 0 | sc_format_path(gemsafe_cert[i].path, &path); |
370 | 0 | sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id); |
371 | 0 | path.index = gemsafe_cert[i].index; |
372 | 0 | path.count = gemsafe_cert[i].count; |
373 | 0 | sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, |
374 | 0 | gemsafe_cert[i].authority, &path, &p15Id, |
375 | 0 | gemsafe_cert[i].label, gemsafe_cert[i].obj_flags); |
376 | 0 | } |
377 | | |
378 | | /* set gemsafe_pin */ |
379 | 58 | sc_log(p15card->card->ctx, "Setting PIN"); |
380 | 116 | for (i=0; i < gemsafe_pin_max; i++) { |
381 | 116 | struct sc_pkcs15_id p15Id; |
382 | 116 | struct sc_path path; |
383 | | |
384 | 116 | sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id); |
385 | 116 | sc_format_path(gemsafe_pin[i].path, &path); |
386 | 116 | if (gemsafe_pin[i].atr_len == 0 || |
387 | 58 | (gemsafe_pin[i].atr_len == p15card->card->atr.len && |
388 | 0 | memcmp(p15card->card->atr.value, gemsafe_pin[i].atr, |
389 | 58 | p15card->card->atr.len) == 0)) { |
390 | 58 | sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label, |
391 | 58 | &path, gemsafe_pin[i].ref, gemsafe_pin[i].type, |
392 | 58 | gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen, |
393 | 58 | gemsafe_pin[i].flags, gemsafe_pin[i].tries_left, |
394 | 58 | gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags); |
395 | 58 | break; |
396 | 58 | } |
397 | 116 | }; |
398 | | |
399 | | /* set private keys */ |
400 | 58 | sc_log(p15card->card->ctx, "Setting private keys"); |
401 | 754 | for (i = 0; i < gemsafe_cert_max; i++) { |
402 | 696 | struct sc_pkcs15_id p15Id, authId, *pauthId; |
403 | 696 | struct sc_path path; |
404 | 696 | int key_ref = 0x03; |
405 | | |
406 | 696 | if (gemsafe_prkeys[i].label == NULL) |
407 | 696 | continue; |
408 | 0 | sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id); |
409 | 0 | if (gemsafe_prkeys[i].auth_id) { |
410 | 0 | sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId); |
411 | 0 | pauthId = &authId; |
412 | 0 | } else |
413 | 0 | pauthId = NULL; |
414 | 0 | sc_format_path(gemsafe_prkeys[i].path, &path); |
415 | | /* |
416 | | * The key ref may be different for different sites; |
417 | | * by adding flags=n where the low order 4 bits can be |
418 | | * the key ref we can force it. |
419 | | */ |
420 | 0 | if ( p15card->card->flags & 0x0F) { |
421 | 0 | key_ref = p15card->card->flags & 0x0F; |
422 | 0 | sc_log(p15card->card->ctx, |
423 | 0 | "Overriding key_ref %d with %d\n", |
424 | 0 | gemsafe_prkeys[i].ref, key_ref); |
425 | 0 | } else |
426 | 0 | key_ref = gemsafe_prkeys[i].ref; |
427 | 0 | sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label, |
428 | 0 | SC_PKCS15_TYPE_PRKEY_RSA, |
429 | 0 | gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage, |
430 | 0 | &path, key_ref, pauthId, |
431 | 0 | gemsafe_prkeys[i].obj_flags); |
432 | 0 | } |
433 | | |
434 | | /* select the application DF */ |
435 | 58 | sc_log(p15card->card->ctx, "Selecting application DF"); |
436 | 58 | sc_format_path(GEMSAFE_APP_PATH, &path); |
437 | 58 | r = sc_select_file(card, &path, &file); |
438 | 58 | if (r != SC_SUCCESS || !file) { |
439 | 37 | sc_pkcs15_card_clear(p15card); |
440 | 37 | return SC_ERROR_INTERNAL; |
441 | 37 | } |
442 | | /* set the application DF */ |
443 | 21 | sc_file_free(p15card->file_app); |
444 | 21 | p15card->file_app = file; |
445 | | |
446 | 21 | return SC_SUCCESS; |
447 | 58 | } |
448 | | |
449 | | int sc_pkcs15emu_gemsafeV1_init_ex( sc_pkcs15_card_t *p15card, |
450 | | struct sc_aid *aid) |
451 | 12.2k | { |
452 | 12.2k | if (gemsafe_detect_card(p15card)) |
453 | 11.4k | return SC_ERROR_WRONG_CARD; |
454 | 772 | return sc_pkcs15emu_gemsafeV1_init(p15card); |
455 | 12.2k | } |
456 | | |
457 | | static sc_pkcs15_df_t * |
458 | | sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type) |
459 | 58 | { |
460 | 58 | sc_pkcs15_df_t *df; |
461 | 58 | sc_file_t *file; |
462 | 58 | int created = 0; |
463 | | |
464 | 116 | while (1) { |
465 | 116 | for (df = p15card->df_list; df; df = df->next) { |
466 | 58 | if (df->type == type) { |
467 | 58 | if (created) |
468 | 58 | df->enumerated = 1; |
469 | 58 | return df; |
470 | 58 | } |
471 | 58 | } |
472 | | |
473 | 58 | if (created != 0) |
474 | 0 | return NULL; |
475 | | |
476 | 58 | file = sc_file_new(); |
477 | 58 | if (!file) |
478 | 0 | return NULL; |
479 | 58 | sc_format_path("11001101", &file->path); |
480 | 58 | sc_pkcs15_add_df(p15card, type, &file->path); |
481 | 58 | sc_file_free(file); |
482 | 58 | created++; |
483 | 58 | } |
484 | 58 | } |
485 | | |
486 | | static int |
487 | | sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type, |
488 | | const char *label, void *data, |
489 | | const sc_pkcs15_id_t *auth_id, int obj_flags) |
490 | 58 | { |
491 | 58 | sc_pkcs15_object_t *obj; |
492 | 58 | int df_type; |
493 | | |
494 | 58 | obj = calloc(1, sizeof(*obj)); |
495 | 58 | if (!obj) { |
496 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
497 | 0 | } |
498 | | |
499 | 58 | obj->type = type; |
500 | 58 | obj->data = data; |
501 | | |
502 | 58 | if (label) |
503 | 58 | strncpy(obj->label, label, sizeof(obj->label)-1); |
504 | | |
505 | 58 | obj->flags = obj_flags; |
506 | 58 | if (auth_id) |
507 | 0 | obj->auth_id = *auth_id; |
508 | | |
509 | 58 | switch (type & SC_PKCS15_TYPE_CLASS_MASK) { |
510 | 58 | case SC_PKCS15_TYPE_AUTH: |
511 | 58 | df_type = SC_PKCS15_AODF; |
512 | 58 | break; |
513 | 0 | case SC_PKCS15_TYPE_PRKEY: |
514 | 0 | df_type = SC_PKCS15_PRKDF; |
515 | 0 | break; |
516 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
517 | 0 | df_type = SC_PKCS15_PUKDF; |
518 | 0 | break; |
519 | 0 | case SC_PKCS15_TYPE_CERT: |
520 | 0 | df_type = SC_PKCS15_CDF; |
521 | 0 | break; |
522 | 0 | default: |
523 | 0 | sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type); |
524 | 0 | free(obj); |
525 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
526 | 58 | } |
527 | | |
528 | 58 | obj->df = sc_pkcs15emu_get_df(p15card, df_type); |
529 | 58 | sc_pkcs15_add_object(p15card, obj); |
530 | | |
531 | 58 | return 0; |
532 | 58 | } |
533 | | |
534 | | static int |
535 | | sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, |
536 | | const sc_pkcs15_id_t *id, const char *label, |
537 | | const sc_path_t *path, int ref, int type, |
538 | | unsigned int min_length, |
539 | | unsigned int max_length, |
540 | | int flags, int tries_left, const char pad_char, int obj_flags) |
541 | 58 | { |
542 | 58 | sc_pkcs15_auth_info_t *info; |
543 | | |
544 | 58 | info = calloc(1, sizeof(*info)); |
545 | 58 | if (!info) |
546 | 58 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
547 | | |
548 | 58 | info->auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; |
549 | 58 | info->auth_method = SC_AC_CHV; |
550 | 58 | info->auth_id = *id; |
551 | 58 | info->attrs.pin.min_length = min_length; |
552 | 58 | info->attrs.pin.max_length = max_length; |
553 | 58 | info->attrs.pin.stored_length = max_length; |
554 | 58 | info->attrs.pin.type = type; |
555 | 58 | info->attrs.pin.reference = ref; |
556 | 58 | info->attrs.pin.flags = flags; |
557 | 58 | info->attrs.pin.pad_char = pad_char; |
558 | 58 | info->tries_left = tries_left; |
559 | 58 | info->logged_in = SC_PIN_STATE_UNKNOWN; |
560 | | |
561 | 58 | if (path) |
562 | 58 | info->path = *path; |
563 | | |
564 | 58 | return sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info, NULL, obj_flags); |
565 | 58 | } |
566 | | |
567 | | static int |
568 | | sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card, |
569 | | int type, int authority, |
570 | | const sc_path_t *path, |
571 | | const sc_pkcs15_id_t *id, |
572 | | const char *label, int obj_flags) |
573 | 0 | { |
574 | 0 | sc_pkcs15_cert_info_t *info; |
575 | 0 | info = calloc(1, sizeof(*info)); |
576 | 0 | if (!info) |
577 | 0 | { |
578 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
579 | 0 | } |
580 | 0 | info->id = *id; |
581 | 0 | info->authority = authority; |
582 | 0 | if (path) |
583 | 0 | info->path = *path; |
584 | |
|
585 | 0 | return sc_pkcs15emu_add_object(p15card, type, label, info, NULL, obj_flags); |
586 | 0 | } |
587 | | |
588 | | static int |
589 | | sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, |
590 | | const sc_pkcs15_id_t *id, |
591 | | const char *label, |
592 | | int type, unsigned int modulus_length, int usage, |
593 | | const sc_path_t *path, int ref, |
594 | | const sc_pkcs15_id_t *auth_id, int obj_flags) |
595 | 0 | { |
596 | 0 | sc_pkcs15_prkey_info_t *info; |
597 | |
|
598 | 0 | info = calloc(1, sizeof(*info)); |
599 | 0 | if (!info) |
600 | 0 | { |
601 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
602 | 0 | } |
603 | 0 | info->id = *id; |
604 | 0 | info->modulus_length = modulus_length; |
605 | 0 | info->usage = usage; |
606 | 0 | info->native = 1; |
607 | 0 | info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE |
608 | 0 | | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE |
609 | 0 | | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE |
610 | 0 | | SC_PKCS15_PRKEY_ACCESS_LOCAL; |
611 | 0 | info->key_reference = ref; |
612 | |
|
613 | 0 | if (path) |
614 | 0 | info->path = *path; |
615 | |
|
616 | 0 | return sc_pkcs15emu_add_object(p15card, type, label, |
617 | 0 | info, auth_id, obj_flags); |
618 | 0 | } |
619 | | |
620 | | /* SC_IMPLEMENT_DRIVER_VERSION("0.9.4") */ |