/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 | 896 | #define MANU_ID "Gemplus" |
32 | 3.48k | #define APPLET_NAME "GemSAFE V1" |
33 | 3.48k | #define DRIVER_SERIAL_NUMBER "v0.9" |
34 | 228 | #define GEMSAFE_APP_PATH "3F001600" |
35 | 896 | #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 | 775 | #define GEMSAFE_READ_QUANTUM 248 |
41 | 707 | #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 | 896 | { |
164 | 896 | int r; |
165 | 896 | u8 ibuf[GEMSAFE_MAX_OBJLEN]; |
166 | 896 | u8 *iptr; |
167 | 896 | struct sc_path path; |
168 | 896 | struct sc_file *file; |
169 | 896 | size_t objlen; |
170 | 896 | int certlen; |
171 | 896 | unsigned int ind, i=0; |
172 | 896 | int read_len; |
173 | | |
174 | 896 | sc_format_path(GEMSAFE_PATH, &path); |
175 | 896 | r = sc_select_file(card, &path, &file); |
176 | 896 | if (r != SC_SUCCESS || !file) |
177 | 121 | return SC_ERROR_INTERNAL; |
178 | 775 | sc_file_free(file); |
179 | | |
180 | | /* Initial read */ |
181 | 775 | read_len = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); |
182 | 775 | if (read_len <= 2) { |
183 | 61 | sc_log(card->ctx, "Invalid size of object data: %d", read_len); |
184 | 61 | return SC_ERROR_INTERNAL; |
185 | 61 | } |
186 | | |
187 | | /* Actual stored object size is encoded in first 2 bytes |
188 | | * (allocated EF space is much greater!) |
189 | | */ |
190 | 714 | objlen = (((size_t) ibuf[0]) << 8) | ibuf[1]; |
191 | 714 | sc_log(card->ctx, "Stored object is of size: %"SC_FORMAT_LEN_SIZE_T"u", |
192 | 714 | objlen); |
193 | 714 | if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) { |
194 | 58 | sc_log(card->ctx, "Invalid object size: %"SC_FORMAT_LEN_SIZE_T"u", |
195 | 58 | objlen); |
196 | 58 | return SC_ERROR_INTERNAL; |
197 | 58 | } |
198 | | |
199 | | /* It looks like the first thing in the block is a table of |
200 | | * which keys are allocated. The table is small and is in the |
201 | | * first 248 bytes. Example for a card with 10 key containers: |
202 | | * 01 f0 00 03 03 b0 00 03 <= 1st key unallocated |
203 | | * 01 f0 00 04 03 b0 00 04 <= 2nd key unallocated |
204 | | * 01 fe 14 00 05 03 b0 00 05 <= 3rd key allocated |
205 | | * 01 fe 14 01 06 03 b0 00 06 <= 4th key allocated |
206 | | * 01 f0 00 07 03 b0 00 07 <= 5th key unallocated |
207 | | * ... |
208 | | * 01 f0 00 0c 03 b0 00 0c <= 10th key unallocated |
209 | | * For allocated keys, the fourth byte seems to indicate the |
210 | | * default key and the fifth byte indicates the key_ref of |
211 | | * the private key. |
212 | | */ |
213 | 656 | ind = 2; /* skip length */ |
214 | 1.14k | while (ind + 1 < (size_t)read_len && ibuf[ind] == 0x01 && i < gemsafe_cert_max) { |
215 | 492 | if (ibuf[ind+1] == 0xFE) { |
216 | 103 | gemsafe_prkeys[i].ref = ibuf[ind+4]; |
217 | 103 | sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d", |
218 | 103 | i+1, gemsafe_prkeys[i].ref); |
219 | 103 | ind += 9; |
220 | 103 | } |
221 | 389 | else { |
222 | 389 | gemsafe_prkeys[i].label = NULL; |
223 | 389 | gemsafe_cert[i].label = NULL; |
224 | 389 | sc_log(card->ctx, "Key container %d is unallocated", i+1); |
225 | 389 | ind += 8; |
226 | 389 | } |
227 | 492 | i++; |
228 | 492 | } |
229 | | |
230 | | /* Delete additional key containers from the data structures if |
231 | | * this card can't accommodate them. |
232 | | */ |
233 | 8.03k | for (; i < gemsafe_cert_max; i++) { |
234 | 7.38k | gemsafe_prkeys[i].label = NULL; |
235 | 7.38k | gemsafe_cert[i].label = NULL; |
236 | 7.38k | } |
237 | | |
238 | | /* Read entire file, then dissect in memory. |
239 | | * Gemalto ClassicClient seems to do it the same way. |
240 | | */ |
241 | 656 | iptr = ibuf + read_len; |
242 | 10.5k | while ((size_t)(iptr - ibuf) < objlen) { |
243 | 10.2k | r = sc_read_binary(card, (unsigned)(iptr - ibuf), iptr, |
244 | 10.2k | MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0); |
245 | 10.2k | if (r < 0) { |
246 | 374 | sc_log(card->ctx, "Could not read cert object"); |
247 | 374 | return SC_ERROR_INTERNAL; |
248 | 374 | } |
249 | 9.91k | if (r == 0) |
250 | 54 | break; |
251 | 9.86k | read_len += r; |
252 | 9.86k | iptr += r; |
253 | 9.86k | } |
254 | 282 | if ((size_t)read_len < objlen) { |
255 | 54 | sc_log(card->ctx, "Could not read cert object"); |
256 | 54 | return SC_ERROR_INTERNAL; |
257 | 54 | } |
258 | | |
259 | | /* Search buffer for certificates, they start with 0x3082. */ |
260 | 228 | i = 0; |
261 | 169k | while (ind < objlen - 1) { |
262 | 169k | if (ibuf[ind] == 0x30 && ibuf[ind+1] == 0x82) { |
263 | | /* Find next allocated key container */ |
264 | 65 | while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL) |
265 | 60 | i++; |
266 | 5 | if (i == gemsafe_cert_max) { |
267 | 5 | sc_log(card->ctx, "Warning: Found orphaned certificate at offset %d", ind); |
268 | 5 | return SC_SUCCESS; |
269 | 5 | } |
270 | | /* DER cert len is encoded this way */ |
271 | 0 | if (ind+3 >= sizeof ibuf) |
272 | 0 | return SC_ERROR_INVALID_DATA; |
273 | 0 | certlen = ((((int)ibuf[ind + 2]) << 8) | ibuf[ind + 3]) + 4; |
274 | 0 | sc_log(card->ctx, |
275 | 0 | "Found certificate of key container %d at offset %d, len %d", |
276 | 0 | i+1, ind, certlen); |
277 | 0 | gemsafe_cert[i].index = ind; |
278 | 0 | gemsafe_cert[i].count = certlen; |
279 | 0 | ind += certlen; |
280 | 0 | i++; |
281 | 0 | } else |
282 | 169k | ind++; |
283 | 169k | } |
284 | | |
285 | | /* Delete additional key containers from the data structures if |
286 | | * they're missing on the card. |
287 | | */ |
288 | 2.89k | for (; i < gemsafe_cert_max; i++) { |
289 | 2.67k | if (gemsafe_cert[i].label) { |
290 | 0 | sc_log(card->ctx, "Warning: Certificate of key container %d is missing", i+1); |
291 | 0 | gemsafe_prkeys[i].label = NULL; |
292 | 0 | gemsafe_cert[i].label = NULL; |
293 | 0 | } |
294 | 2.67k | } |
295 | | |
296 | 223 | return SC_SUCCESS; |
297 | 228 | } |
298 | | |
299 | | static int gemsafe_detect_card( sc_pkcs15_card_t *p15card) |
300 | 58.5k | { |
301 | 58.5k | if (strcmp(p15card->card->name, "GemSAFE V1")) |
302 | 55.1k | return SC_ERROR_WRONG_CARD; |
303 | | |
304 | 3.48k | return SC_SUCCESS; |
305 | 58.5k | } |
306 | | |
307 | | static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) |
308 | 3.48k | { |
309 | 3.48k | int r; |
310 | 3.48k | unsigned int i; |
311 | 3.48k | struct sc_path path; |
312 | 3.48k | struct sc_file *file = NULL; |
313 | 3.48k | struct sc_card *card = p15card->card; |
314 | 3.48k | struct sc_apdu apdu; |
315 | 3.48k | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
316 | | |
317 | 3.48k | sc_log(p15card->card->ctx, "Setting pkcs15 parameters"); |
318 | | |
319 | 3.48k | set_string(&p15card->tokeninfo->label, APPLET_NAME); |
320 | 3.48k | if (!p15card->tokeninfo->label) |
321 | 0 | return SC_ERROR_INTERNAL; |
322 | | |
323 | 3.48k | set_string(&p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER); |
324 | 3.48k | if (!p15card->tokeninfo->serial_number) { |
325 | 0 | free(p15card->tokeninfo->label); |
326 | 0 | p15card->tokeninfo->label = NULL; |
327 | 0 | return SC_ERROR_INTERNAL; |
328 | 0 | } |
329 | | |
330 | | /* the GemSAFE applet version number */ |
331 | 3.48k | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03); |
332 | 3.48k | apdu.cla = 0x80; |
333 | 3.48k | apdu.resp = rbuf; |
334 | 3.48k | apdu.resplen = sizeof(rbuf); |
335 | | /* Manual says Le=0x05, but should be 0x08 to return full version number */ |
336 | 3.48k | apdu.le = 0x08; |
337 | 3.48k | apdu.lc = 0; |
338 | 3.48k | apdu.datalen = 0; |
339 | 3.48k | r = sc_transmit_apdu(card, &apdu); |
340 | 3.48k | if (r < 0) |
341 | 44 | sc_pkcs15_card_clear(p15card); |
342 | 3.48k | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
343 | | |
344 | 3.44k | if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || r != SC_SUCCESS) { |
345 | 2.54k | sc_pkcs15_card_clear(p15card); |
346 | 2.54k | return SC_ERROR_INTERNAL; |
347 | 2.54k | } |
348 | | |
349 | | /* the manufacturer ID, in this case GemPlus */ |
350 | 896 | set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID); |
351 | 896 | if (!p15card->tokeninfo->manufacturer_id) { |
352 | 0 | sc_pkcs15_card_clear(p15card); |
353 | 0 | return SC_ERROR_INTERNAL; |
354 | 0 | } |
355 | | |
356 | | /* determine allocated key containers and length of certificates */ |
357 | 896 | r = gemsafe_get_cert_len(card); |
358 | 896 | if (r != SC_SUCCESS) { |
359 | 668 | sc_pkcs15_card_clear(p15card); |
360 | 668 | return SC_ERROR_INTERNAL; |
361 | 668 | } |
362 | | |
363 | | /* set certs */ |
364 | 228 | sc_log(p15card->card->ctx, "Setting certificates"); |
365 | 2.96k | for (i = 0; i < gemsafe_cert_max; i++) { |
366 | 2.73k | struct sc_pkcs15_id p15Id; |
367 | 2.73k | struct sc_path path; |
368 | | |
369 | 2.73k | if (gemsafe_cert[i].label == NULL) |
370 | 2.73k | continue; |
371 | 0 | sc_format_path(gemsafe_cert[i].path, &path); |
372 | 0 | sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id); |
373 | 0 | path.index = gemsafe_cert[i].index; |
374 | 0 | path.count = gemsafe_cert[i].count; |
375 | 0 | sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, |
376 | 0 | gemsafe_cert[i].authority, &path, &p15Id, |
377 | 0 | gemsafe_cert[i].label, gemsafe_cert[i].obj_flags); |
378 | 0 | } |
379 | | |
380 | | /* set gemsafe_pin */ |
381 | 228 | sc_log(p15card->card->ctx, "Setting PIN"); |
382 | 454 | for (i=0; i < gemsafe_pin_max; i++) { |
383 | 454 | struct sc_pkcs15_id p15Id; |
384 | 454 | struct sc_path path; |
385 | | |
386 | 454 | sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id); |
387 | 454 | sc_format_path(gemsafe_pin[i].path, &path); |
388 | 454 | if (gemsafe_pin[i].atr_len == 0 || |
389 | 228 | (gemsafe_pin[i].atr_len == p15card->card->atr.len && |
390 | 14 | memcmp(p15card->card->atr.value, gemsafe_pin[i].atr, |
391 | 228 | p15card->card->atr.len) == 0)) { |
392 | 228 | sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label, |
393 | 228 | &path, gemsafe_pin[i].ref, gemsafe_pin[i].type, |
394 | 228 | gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen, |
395 | 228 | gemsafe_pin[i].flags, gemsafe_pin[i].tries_left, |
396 | 228 | gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags); |
397 | 228 | break; |
398 | 228 | } |
399 | 454 | }; |
400 | | |
401 | | /* set private keys */ |
402 | 228 | sc_log(p15card->card->ctx, "Setting private keys"); |
403 | 2.96k | for (i = 0; i < gemsafe_cert_max; i++) { |
404 | 2.73k | struct sc_pkcs15_id p15Id, authId, *pauthId; |
405 | 2.73k | struct sc_path path; |
406 | 2.73k | int key_ref = 0x03; |
407 | | |
408 | 2.73k | if (gemsafe_prkeys[i].label == NULL) |
409 | 2.73k | continue; |
410 | 0 | sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id); |
411 | 0 | if (gemsafe_prkeys[i].auth_id) { |
412 | 0 | sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId); |
413 | 0 | pauthId = &authId; |
414 | 0 | } else |
415 | 0 | pauthId = NULL; |
416 | 0 | sc_format_path(gemsafe_prkeys[i].path, &path); |
417 | | /* |
418 | | * The key ref may be different for different sites; |
419 | | * by adding flags=n where the low order 4 bits can be |
420 | | * the key ref we can force it. |
421 | | */ |
422 | 0 | if ( p15card->card->flags & 0x0F) { |
423 | 0 | key_ref = p15card->card->flags & 0x0F; |
424 | 0 | sc_log(p15card->card->ctx, |
425 | 0 | "Overriding key_ref %d with %d\n", |
426 | 0 | gemsafe_prkeys[i].ref, key_ref); |
427 | 0 | } else |
428 | 0 | key_ref = gemsafe_prkeys[i].ref; |
429 | 0 | sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label, |
430 | 0 | SC_PKCS15_TYPE_PRKEY_RSA, |
431 | 0 | gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage, |
432 | 0 | &path, key_ref, pauthId, |
433 | 0 | gemsafe_prkeys[i].obj_flags); |
434 | 0 | } |
435 | | |
436 | | /* select the application DF */ |
437 | 228 | sc_log(p15card->card->ctx, "Selecting application DF"); |
438 | 228 | sc_format_path(GEMSAFE_APP_PATH, &path); |
439 | 228 | r = sc_select_file(card, &path, &file); |
440 | 228 | if (r != SC_SUCCESS || !file) { |
441 | 194 | sc_pkcs15_card_clear(p15card); |
442 | 194 | return SC_ERROR_INTERNAL; |
443 | 194 | } |
444 | | /* set the application DF */ |
445 | 34 | sc_file_free(p15card->file_app); |
446 | 34 | p15card->file_app = file; |
447 | | |
448 | 34 | return SC_SUCCESS; |
449 | 228 | } |
450 | | |
451 | | int sc_pkcs15emu_gemsafeV1_init_ex( sc_pkcs15_card_t *p15card, |
452 | | struct sc_aid *aid) |
453 | 58.5k | { |
454 | 58.5k | if (gemsafe_detect_card(p15card)) |
455 | 55.1k | return SC_ERROR_WRONG_CARD; |
456 | 3.48k | return sc_pkcs15emu_gemsafeV1_init(p15card); |
457 | 58.5k | } |
458 | | |
459 | | static sc_pkcs15_df_t * |
460 | | sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type) |
461 | 228 | { |
462 | 228 | sc_pkcs15_df_t *df; |
463 | 228 | sc_file_t *file; |
464 | 228 | int created = 0; |
465 | | |
466 | 456 | while (1) { |
467 | 456 | for (df = p15card->df_list; df; df = df->next) { |
468 | 228 | if (df->type == type) { |
469 | 228 | if (created) |
470 | 228 | df->enumerated = 1; |
471 | 228 | return df; |
472 | 228 | } |
473 | 228 | } |
474 | | |
475 | 228 | if (created != 0) |
476 | 0 | return NULL; |
477 | | |
478 | 228 | file = sc_file_new(); |
479 | 228 | if (!file) |
480 | 0 | return NULL; |
481 | 228 | sc_format_path("11001101", &file->path); |
482 | 228 | sc_pkcs15_add_df(p15card, type, &file->path); |
483 | 228 | sc_file_free(file); |
484 | 228 | created++; |
485 | 228 | } |
486 | 228 | } |
487 | | |
488 | | static int |
489 | | sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type, |
490 | | const char *label, void *data, |
491 | | const sc_pkcs15_id_t *auth_id, int obj_flags) |
492 | 228 | { |
493 | 228 | sc_pkcs15_object_t *obj; |
494 | 228 | int df_type; |
495 | | |
496 | 228 | obj = calloc(1, sizeof(*obj)); |
497 | 228 | if (!obj) { |
498 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
499 | 0 | } |
500 | | |
501 | 228 | obj->type = type; |
502 | 228 | obj->data = data; |
503 | | |
504 | 228 | if (label) |
505 | 228 | strncpy(obj->label, label, sizeof(obj->label)-1); |
506 | | |
507 | 228 | obj->flags = obj_flags; |
508 | 228 | if (auth_id) |
509 | 0 | obj->auth_id = *auth_id; |
510 | | |
511 | 228 | switch (type & SC_PKCS15_TYPE_CLASS_MASK) { |
512 | 228 | case SC_PKCS15_TYPE_AUTH: |
513 | 228 | df_type = SC_PKCS15_AODF; |
514 | 228 | break; |
515 | 0 | case SC_PKCS15_TYPE_PRKEY: |
516 | 0 | df_type = SC_PKCS15_PRKDF; |
517 | 0 | break; |
518 | 0 | case SC_PKCS15_TYPE_PUBKEY: |
519 | 0 | df_type = SC_PKCS15_PUKDF; |
520 | 0 | break; |
521 | 0 | case SC_PKCS15_TYPE_CERT: |
522 | 0 | df_type = SC_PKCS15_CDF; |
523 | 0 | break; |
524 | 0 | default: |
525 | 0 | sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type); |
526 | 0 | free(obj); |
527 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
528 | 228 | } |
529 | | |
530 | 228 | obj->df = sc_pkcs15emu_get_df(p15card, df_type); |
531 | 228 | sc_pkcs15_add_object(p15card, obj); |
532 | | |
533 | 228 | return 0; |
534 | 228 | } |
535 | | |
536 | | static int |
537 | | sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, |
538 | | const sc_pkcs15_id_t *id, const char *label, |
539 | | const sc_path_t *path, int ref, int type, |
540 | | unsigned int min_length, |
541 | | unsigned int max_length, |
542 | | int flags, int tries_left, const char pad_char, int obj_flags) |
543 | 228 | { |
544 | 228 | sc_pkcs15_auth_info_t *info; |
545 | | |
546 | 228 | info = calloc(1, sizeof(*info)); |
547 | 228 | if (!info) |
548 | 228 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
549 | | |
550 | 228 | info->auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; |
551 | 228 | info->auth_method = SC_AC_CHV; |
552 | 228 | info->auth_id = *id; |
553 | 228 | info->attrs.pin.min_length = min_length; |
554 | 228 | info->attrs.pin.max_length = max_length; |
555 | 228 | info->attrs.pin.stored_length = max_length; |
556 | 228 | info->attrs.pin.type = type; |
557 | 228 | info->attrs.pin.reference = ref; |
558 | 228 | info->attrs.pin.flags = flags; |
559 | 228 | info->attrs.pin.pad_char = pad_char; |
560 | 228 | info->tries_left = tries_left; |
561 | 228 | info->logged_in = SC_PIN_STATE_UNKNOWN; |
562 | | |
563 | 228 | if (path) |
564 | 228 | info->path = *path; |
565 | | |
566 | 228 | return sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info, NULL, obj_flags); |
567 | 228 | } |
568 | | |
569 | | static int |
570 | | sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card, |
571 | | int type, int authority, |
572 | | const sc_path_t *path, |
573 | | const sc_pkcs15_id_t *id, |
574 | | const char *label, int obj_flags) |
575 | 0 | { |
576 | 0 | sc_pkcs15_cert_info_t *info; |
577 | 0 | info = calloc(1, sizeof(*info)); |
578 | 0 | if (!info) |
579 | 0 | { |
580 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
581 | 0 | } |
582 | 0 | info->id = *id; |
583 | 0 | info->authority = authority; |
584 | 0 | if (path) |
585 | 0 | info->path = *path; |
586 | |
|
587 | 0 | return sc_pkcs15emu_add_object(p15card, type, label, info, NULL, obj_flags); |
588 | 0 | } |
589 | | |
590 | | static int |
591 | | sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, |
592 | | const sc_pkcs15_id_t *id, |
593 | | const char *label, |
594 | | int type, unsigned int modulus_length, int usage, |
595 | | const sc_path_t *path, int ref, |
596 | | const sc_pkcs15_id_t *auth_id, int obj_flags) |
597 | 0 | { |
598 | 0 | sc_pkcs15_prkey_info_t *info; |
599 | |
|
600 | 0 | info = calloc(1, sizeof(*info)); |
601 | 0 | if (!info) |
602 | 0 | { |
603 | 0 | LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); |
604 | 0 | } |
605 | 0 | info->id = *id; |
606 | 0 | info->modulus_length = modulus_length; |
607 | 0 | info->usage = usage; |
608 | 0 | info->native = 1; |
609 | 0 | info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE |
610 | 0 | | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE |
611 | 0 | | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE |
612 | 0 | | SC_PKCS15_PRKEY_ACCESS_LOCAL; |
613 | 0 | info->key_reference = ref; |
614 | |
|
615 | 0 | if (path) |
616 | 0 | info->path = *path; |
617 | |
|
618 | 0 | return sc_pkcs15emu_add_object(p15card, type, label, |
619 | 0 | info, auth_id, obj_flags); |
620 | 0 | } |
621 | | |
622 | | /* SC_IMPLEMENT_DRIVER_VERSION("0.9.4") */ |