/src/opensc/src/pkcs15init/pkcs15-entersafe.c
Line | Count | Source (jump to first uncovered line) |
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 | | /* Initially written by Weitao Sun (weitao@ftsafe.com) 2008*/ |
17 | | /* Disable RSA:512bits by Shengchao Niu (shengchao@ftsafe.com) 2012 */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <sys/types.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | #include <assert.h> |
25 | | #include <stdarg.h> |
26 | | |
27 | | #include "libopensc/log.h" |
28 | | #include "libopensc/opensc.h" |
29 | | #include "libopensc/cardctl.h" |
30 | | #include "pkcs15-init.h" |
31 | | #include "profile.h" |
32 | | |
33 | | static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def) |
34 | 0 | { |
35 | 0 | u8 def = (u8)in_def; |
36 | 0 | const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method); |
37 | 0 | if (!entry) |
38 | 0 | { |
39 | 0 | return def; |
40 | 0 | } |
41 | 0 | else if (entry->method == SC_AC_CHV) |
42 | 0 | { |
43 | 0 | unsigned int key_ref = entry->key_ref; |
44 | 0 | if (key_ref == SC_AC_KEY_REF_NONE) |
45 | 0 | return def; |
46 | 0 | else |
47 | 0 | return ENTERSAFE_AC_ALWAYS&0x04; |
48 | 0 | } |
49 | 0 | else if (entry->method == SC_AC_SYMBOLIC) |
50 | 0 | { |
51 | 0 | return ENTERSAFE_AC_ALWAYS&0x04; |
52 | 0 | } |
53 | 0 | else if (entry->method == SC_AC_NEVER) |
54 | 0 | { |
55 | 0 | return ENTERSAFE_AC_NEVER; |
56 | 0 | } |
57 | 0 | else |
58 | 0 | { |
59 | 0 | return def; |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | | static int entersafe_erase_card(struct sc_profile *profile, sc_pkcs15_card_t *p15card) |
64 | 0 | { |
65 | 0 | SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); |
66 | |
|
67 | 0 | if (sc_select_file(p15card->card, sc_get_mf_path(), NULL) < 0) |
68 | 0 | return SC_SUCCESS; |
69 | | |
70 | 0 | return sc_card_ctl(p15card->card,SC_CARDCTL_ERASE_CARD,0); |
71 | 0 | } |
72 | | |
73 | | static int entersafe_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) |
74 | 0 | { |
75 | 0 | struct sc_card *card = p15card->card; |
76 | 0 | int ret; |
77 | |
|
78 | 0 | {/* MF */ |
79 | 0 | sc_file_t *mf_file; |
80 | 0 | sc_entersafe_create_data mf_data; |
81 | |
|
82 | 0 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
83 | |
|
84 | 0 | ret = sc_profile_get_file(profile, "MF", &mf_file); |
85 | 0 | LOG_TEST_RET(card->ctx,ret,"Get MF info failed"); |
86 | | |
87 | 0 | mf_data.type = SC_ENTERSAFE_MF_DATA; |
88 | 0 | mf_data.data.df.file_id[0]=0x3F; |
89 | 0 | mf_data.data.df.file_id[1]=0x00; |
90 | 0 | mf_data.data.df.file_count=0x04; |
91 | 0 | mf_data.data.df.flag=0x11; |
92 | 0 | mf_data.data.df.ikf_size[0]=(mf_file->size>>8)&0xFF; |
93 | 0 | mf_data.data.df.ikf_size[1]=mf_file->size&0xFF; |
94 | 0 | mf_data.data.df.create_ac=0x10; |
95 | 0 | mf_data.data.df.append_ac=0xC0; |
96 | 0 | mf_data.data.df.lock_ac=0x10; |
97 | 0 | memcpy(mf_data.data.df.aid,mf_file->name,mf_file->namelen); |
98 | 0 | sc_file_free(mf_file); |
99 | |
|
100 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &mf_data); |
101 | 0 | LOG_TEST_RET(card->ctx,ret,"Create MF failed"); |
102 | 0 | } |
103 | | |
104 | 0 | {/* EF(DIR) */ |
105 | 0 | sc_file_t *dir_file; |
106 | 0 | size_t fid,size; |
107 | 0 | sc_entersafe_create_data ef_data; |
108 | 0 | u8 *buff=0; |
109 | | |
110 | | /* get dir profile */ |
111 | 0 | ret = sc_profile_get_file(profile, "dir", &dir_file); |
112 | 0 | LOG_TEST_RET(card->ctx,ret,"Get EF(DIR) info failed"); |
113 | 0 | fid=dir_file->id; |
114 | 0 | size=dir_file->size; |
115 | 0 | sc_file_free(dir_file); |
116 | |
|
117 | 0 | ef_data.type=SC_ENTERSAFE_EF_DATA; |
118 | 0 | ef_data.data.ef.file_id[0]=(fid>>8)&0xFF; |
119 | 0 | ef_data.data.ef.file_id[1]=fid&0xFF; |
120 | 0 | ef_data.data.ef.size[0]=(size>>8)&0xFF; |
121 | 0 | ef_data.data.ef.size[1]=size&0xFF; |
122 | 0 | ef_data.data.ef.attr[0]=0x00; |
123 | 0 | ef_data.data.ef.attr[1]=0x00; |
124 | 0 | ef_data.data.ef.name=0x00; |
125 | 0 | memset(ef_data.data.ef.ac,0x10,sizeof(ef_data.data.ef.ac)); |
126 | 0 | memset(ef_data.data.ef.sm,0x00,sizeof(ef_data.data.ef.sm)); |
127 | |
|
128 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &ef_data); |
129 | 0 | LOG_TEST_RET(card->ctx,ret,"Create EF(DIR) failed"); |
130 | | |
131 | | |
132 | | /* fill file by 0 */ |
133 | 0 | if (size > MAX_FILE_SIZE) |
134 | 0 | LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Initialize EF(DIR) failed with file size too large"); |
135 | 0 | buff = calloc(1,size); |
136 | 0 | if(!buff) |
137 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
138 | 0 | memset(buff,0,size); |
139 | |
|
140 | 0 | ret = sc_update_binary(card,0,buff,size,0); |
141 | 0 | free(buff); |
142 | 0 | LOG_TEST_RET(card->ctx,ret,"Initialize EF(DIR) failed"); |
143 | 0 | } |
144 | | |
145 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
146 | |
|
147 | 0 | } |
148 | | |
149 | | static int entersafe_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
150 | | sc_file_t *df) |
151 | 0 | { |
152 | 0 | struct sc_card *card = p15card->card; |
153 | 0 | int ret; |
154 | |
|
155 | 0 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
156 | |
|
157 | 0 | {/* df */ |
158 | 0 | sc_entersafe_create_data df_data; |
159 | |
|
160 | 0 | df_data.type = SC_ENTERSAFE_DF_DATA; |
161 | 0 | df_data.data.df.file_id[0]=(df->id >> 8) & 0xFF; |
162 | 0 | df_data.data.df.file_id[1]=df->id & 0xFF; |
163 | 0 | df_data.data.df.file_count=0x30; |
164 | 0 | df_data.data.df.flag=0x01; |
165 | 0 | df_data.data.df.ikf_size[0]=(df->size>>8)&0xFF; |
166 | 0 | df_data.data.df.ikf_size[1]=df->size&0xFF; |
167 | 0 | df_data.data.df.create_ac=0x10; |
168 | 0 | df_data.data.df.append_ac=0xC0; |
169 | 0 | df_data.data.df.lock_ac=0x10; |
170 | 0 | memcpy(df_data.data.df.aid,df->name,df->namelen); |
171 | |
|
172 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &df_data); |
173 | 0 | LOG_TEST_RET(card->ctx,ret,"Create DF failed"); |
174 | 0 | } |
175 | | |
176 | 0 | {/* GPKF */ |
177 | 0 | sc_file_t *gpkf_file; |
178 | 0 | sc_entersafe_create_data ef_data; |
179 | | |
180 | | /* get p15_gpkf profile */ |
181 | 0 | ret = sc_profile_get_file(profile, "p15_gpkf", &gpkf_file); |
182 | 0 | LOG_TEST_RET(card->ctx,ret,"Get GPKF info failed"); |
183 | | |
184 | 0 | ef_data.type=SC_ENTERSAFE_EF_DATA; |
185 | 0 | ef_data.data.ef.file_id[0]=(gpkf_file->id>>8)&0xFF; |
186 | 0 | ef_data.data.ef.file_id[1]=gpkf_file->id&0xFF; |
187 | 0 | ef_data.data.ef.size[0]=(gpkf_file->size>>8)&0xFF; |
188 | 0 | ef_data.data.ef.size[1]=gpkf_file->size&0xFF; |
189 | 0 | ef_data.data.ef.attr[0]=0x15; |
190 | 0 | ef_data.data.ef.attr[1]=0x80; |
191 | 0 | ef_data.data.ef.name=0x00; |
192 | 0 | memset(ef_data.data.ef.ac,0x10,sizeof(ef_data.data.ef.ac)); |
193 | 0 | memset(ef_data.data.ef.sm,0x00,sizeof(ef_data.data.ef.sm)); |
194 | |
|
195 | 0 | sc_file_free(gpkf_file); |
196 | |
|
197 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &ef_data); |
198 | 0 | LOG_TEST_RET(card->ctx,ret,"Create GPKF failed"); |
199 | 0 | } |
200 | | |
201 | 0 | {/* p15 efs */ |
202 | 0 | const char * create_efs[]={ |
203 | 0 | "PKCS15-ODF", |
204 | 0 | "PKCS15-TokenInfo", |
205 | 0 | "PKCS15-UnusedSpace", |
206 | 0 | "PKCS15-AODF", |
207 | 0 | "PKCS15-PrKDF", |
208 | 0 | "PKCS15-PuKDF", |
209 | 0 | "PKCS15-CDF", |
210 | 0 | "PKCS15-DODF", |
211 | 0 | NULL, |
212 | 0 | }; |
213 | 0 | int i; |
214 | 0 | sc_file_t *file=0; |
215 | 0 | sc_entersafe_create_data tmp; |
216 | |
|
217 | 0 | for(i = 0; create_efs[i]; ++i) { |
218 | 0 | if (sc_profile_get_file(profile, create_efs[i], &file)) { |
219 | 0 | sc_log(card->ctx, "Inconsistent profile: cannot find %s", create_efs[i]); |
220 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INCONSISTENT_PROFILE); |
221 | 0 | } |
222 | | |
223 | 0 | tmp.type=SC_ENTERSAFE_EF_DATA; |
224 | 0 | tmp.data.ef.file_id[0]=(file->id>>8)&0xFF; |
225 | 0 | tmp.data.ef.file_id[1]=file->id&0xFF; |
226 | 0 | tmp.data.ef.size[0]=(file->size>>8)&0xFF; |
227 | 0 | tmp.data.ef.size[1]=file->size&0xFF; |
228 | 0 | tmp.data.ef.attr[0]=0x00; |
229 | 0 | tmp.data.ef.attr[1]=0x00; |
230 | 0 | tmp.data.ef.name=0x00; |
231 | 0 | memset(tmp.data.ef.ac,ENTERSAFE_AC_ALWAYS,sizeof(tmp.data.ef.ac)); |
232 | 0 | tmp.data.ef.ac[0]=process_acl_entry(file,SC_AC_OP_READ,ENTERSAFE_AC_ALWAYS); /* read */ |
233 | 0 | tmp.data.ef.ac[1]=process_acl_entry(file,SC_AC_OP_UPDATE,ENTERSAFE_AC_ALWAYS); /* update */ |
234 | 0 | memset(tmp.data.ef.sm,0x00,sizeof(tmp.data.ef.sm)); |
235 | |
|
236 | 0 | sc_file_free(file); |
237 | |
|
238 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_CREATE_FILE, &tmp); |
239 | 0 | LOG_TEST_RET(card->ctx,ret,"Create pkcs15 file failed"); |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | 0 | {/* Preinstall keys */ |
244 | 0 | ret = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_PREINSTALL_KEYS, 0); |
245 | 0 | LOG_TEST_RET(card->ctx,ret,"Preinstall keys failed"); |
246 | 0 | } |
247 | | |
248 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,ret); |
249 | 0 | } |
250 | | |
251 | | static int entersafe_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
252 | | sc_pkcs15_auth_info_t *auth_info) |
253 | 0 | { |
254 | 0 | SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); |
255 | |
|
256 | 0 | if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
257 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
258 | | |
259 | 0 | if (auth_info->attrs.pin.reference < ENTERSAFE_USER_PIN_ID) |
260 | 0 | auth_info->attrs.pin.reference = ENTERSAFE_USER_PIN_ID; |
261 | 0 | if (auth_info->attrs.pin.reference > ENTERSAFE_USER_PIN_ID) |
262 | 0 | return SC_ERROR_TOO_MANY_OBJECTS; |
263 | | |
264 | 0 | SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
265 | 0 | } |
266 | | |
267 | | static int entersafe_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
268 | | sc_file_t *df, sc_pkcs15_object_t *pin_obj, |
269 | | const unsigned char *pin, size_t pin_len, |
270 | | const unsigned char *puk, size_t puk_len) |
271 | 0 | { |
272 | 0 | struct sc_card *card = p15card->card; |
273 | 0 | int r; |
274 | 0 | sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data; |
275 | |
|
276 | 0 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
277 | |
|
278 | 0 | if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
279 | 0 | return SC_ERROR_OBJECT_NOT_VALID; |
280 | | |
281 | 0 | {/*pin*/ |
282 | 0 | sc_entersafe_wkey_data data; |
283 | |
|
284 | 0 | if (!pin || !pin_len || pin_len > 16) |
285 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
286 | | |
287 | 0 | data.key_id = auth_info->attrs.pin.reference; |
288 | 0 | data.usage=0x0B; |
289 | 0 | data.key_data.symmetric.EC=0x33; |
290 | 0 | data.key_data.symmetric.ver=0x00; |
291 | | /* pad pin with 0 */ |
292 | 0 | memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val)); |
293 | 0 | memcpy(data.key_data.symmetric.key_val, pin, pin_len); |
294 | 0 | data.key_data.symmetric.key_len=16; |
295 | |
|
296 | 0 | r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); |
297 | 0 | if (r < 0) |
298 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); |
299 | | |
300 | | /* Cache new PIN value. */ |
301 | 0 | sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len); |
302 | 0 | } |
303 | | |
304 | 0 | {/*puk*/ |
305 | 0 | sc_entersafe_wkey_data data; |
306 | |
|
307 | 0 | if (!puk || !puk_len || puk_len > 16) |
308 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
309 | | |
310 | 0 | data.key_id = auth_info->attrs.pin.reference+1; |
311 | 0 | data.usage=0x0B; |
312 | 0 | data.key_data.symmetric.EC=0x33; |
313 | 0 | data.key_data.symmetric.ver=0x00; |
314 | | /* pad pin with 0 */ |
315 | 0 | memset(data.key_data.symmetric.key_val, 0, sizeof(data.key_data.symmetric.key_val)); |
316 | 0 | memcpy(data.key_data.symmetric.key_val, puk, puk_len); |
317 | 0 | data.key_data.symmetric.key_len=16; |
318 | |
|
319 | 0 | r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); |
320 | 0 | } |
321 | | |
322 | | |
323 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); |
324 | 0 | } |
325 | | |
326 | | static int entersafe_key_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
327 | | sc_pkcs15_prkey_info_t *prkey) |
328 | 0 | { |
329 | 0 | SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); |
330 | 0 | if (prkey->key_reference < ENTERSAFE_MIN_KEY_ID) |
331 | 0 | prkey->key_reference = ENTERSAFE_MIN_KEY_ID; |
332 | 0 | if (prkey->key_reference > ENTERSAFE_MAX_KEY_ID) |
333 | 0 | return SC_ERROR_TOO_MANY_OBJECTS; |
334 | 0 | SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
335 | 0 | } |
336 | | |
337 | | static int entersafe_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
338 | | sc_pkcs15_object_t *obj) |
339 | 0 | { |
340 | 0 | SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE); |
341 | 0 | SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
342 | 0 | } |
343 | | |
344 | | static int entersafe_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
345 | | sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) |
346 | 0 | { |
347 | 0 | sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; |
348 | 0 | sc_card_t *card = p15card->card; |
349 | 0 | sc_entersafe_wkey_data data; |
350 | 0 | sc_file_t *tfile; |
351 | 0 | const sc_acl_entry_t *acl_entry; |
352 | 0 | int r; |
353 | |
|
354 | 0 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)obj->data; |
355 | 0 | size_t keybits = key_info->modulus_length; |
356 | |
|
357 | 0 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
358 | |
|
359 | 0 | if ( key->algorithm != SC_ALGORITHM_RSA ) |
360 | 0 | { |
361 | | /* ignore non-RSA keys */ |
362 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS); |
363 | 0 | } |
364 | | |
365 | | /* Disable RSA:512bits */ |
366 | 0 | if ( ( keybits < 1024 ) || |
367 | 0 | ( keybits > 2048 ) || |
368 | 0 | ( keybits % 0x20 ) ) |
369 | 0 | { |
370 | 0 | sc_debug(card->ctx, |
371 | 0 | SC_LOG_DEBUG_NORMAL, |
372 | 0 | "Unsupported key size %"SC_FORMAT_LEN_SIZE_T"u\n", |
373 | 0 | keybits); |
374 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
375 | 0 | } |
376 | | |
377 | 0 | r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile); |
378 | 0 | if (r < 0) |
379 | 0 | return r; |
380 | 0 | acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE); |
381 | 0 | if (acl_entry->method != SC_AC_NONE) { |
382 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, tfile, SC_AC_OP_UPDATE); |
383 | 0 | if(r<0) |
384 | 0 | r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; |
385 | 0 | } |
386 | 0 | sc_file_free(tfile); |
387 | 0 | LOG_TEST_RET(card->ctx, r, "can't verify pin"); |
388 | | |
389 | 0 | data.key_id = (u8) kinfo->key_reference; |
390 | 0 | data.usage=0x22; |
391 | 0 | data.key_data.rsa=&key->u.rsa; |
392 | 0 | return sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); |
393 | 0 | } |
394 | | |
395 | | static int entersafe_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, |
396 | | sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) |
397 | 0 | { |
398 | 0 | int r; |
399 | 0 | sc_entersafe_gen_key_data gendat; |
400 | 0 | sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; |
401 | 0 | sc_card_t *card = p15card->card; |
402 | 0 | sc_file_t *tfile; |
403 | 0 | const sc_acl_entry_t *acl_entry; |
404 | |
|
405 | 0 | struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)obj->data; |
406 | 0 | size_t keybits = key_info->modulus_length; |
407 | |
|
408 | 0 | SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); |
409 | |
|
410 | 0 | if ( obj->type != SC_PKCS15_TYPE_PRKEY_RSA ) |
411 | 0 | { |
412 | 0 | return SC_ERROR_NOT_SUPPORTED; |
413 | 0 | } |
414 | | |
415 | | /* Disable RSA:512bits */ |
416 | 0 | if ( ( keybits < 1024 ) || |
417 | 0 | ( keybits > 2048 ) || |
418 | 0 | ( keybits % 0x20 ) ) |
419 | 0 | { |
420 | 0 | sc_debug(card->ctx, |
421 | 0 | SC_LOG_DEBUG_NORMAL, |
422 | 0 | "Unsupported key size %"SC_FORMAT_LEN_SIZE_T"u\n", |
423 | 0 | keybits); |
424 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
425 | 0 | } |
426 | | |
427 | 0 | r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile); |
428 | 0 | if (r < 0) |
429 | 0 | return r; |
430 | 0 | acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE); |
431 | 0 | if (acl_entry->method != SC_AC_NONE) { |
432 | 0 | r = sc_pkcs15init_authenticate(profile, p15card, tfile, SC_AC_OP_UPDATE); |
433 | 0 | if(r<0) |
434 | 0 | r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; |
435 | 0 | } |
436 | 0 | sc_file_free(tfile); |
437 | 0 | LOG_TEST_RET(card->ctx, r, "can't verify pin"); |
438 | | |
439 | | /* generate key pair */ |
440 | 0 | gendat.key_id = (u8) kinfo->key_reference; |
441 | 0 | gendat.key_length = (size_t) kinfo->modulus_length; |
442 | 0 | gendat.modulus = NULL; |
443 | 0 | r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_GENERATE_KEY, &gendat); |
444 | 0 | LOG_TEST_RET(card->ctx, r, "EnterSafe generate RSA key pair failed"); |
445 | | |
446 | | /* get the modulus via READ PUBLIC KEY */ |
447 | 0 | if (pubkey) { |
448 | 0 | u8 *buf; |
449 | 0 | struct sc_pkcs15_pubkey_rsa *rsa = &pubkey->u.rsa; |
450 | | /* set the modulus */ |
451 | 0 | rsa->modulus.data = gendat.modulus; |
452 | 0 | rsa->modulus.len = kinfo->modulus_length >> 3; |
453 | | /* set the exponent (always 0x10001) */ |
454 | 0 | buf = malloc(3); |
455 | 0 | if (!buf) |
456 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
457 | 0 | buf[0] = 0x01; |
458 | 0 | buf[1] = 0x00; |
459 | 0 | buf[2] = 0x01; |
460 | 0 | rsa->exponent.data = buf; |
461 | 0 | rsa->exponent.len = 3; |
462 | |
|
463 | 0 | pubkey->algorithm = SC_ALGORITHM_RSA; |
464 | 0 | } else |
465 | | /* free public key */ |
466 | 0 | free(gendat.modulus); |
467 | | |
468 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); |
469 | 0 | } |
470 | | |
471 | | |
472 | | static int entersafe_sanity_check(sc_profile_t *profile, sc_pkcs15_card_t *p15card) |
473 | 0 | { |
474 | 0 | struct sc_context *ctx = p15card->card->ctx; |
475 | 0 | struct sc_pkcs15_auth_info profile_auth = {0}; |
476 | 0 | struct sc_pkcs15_object *objs[32]; |
477 | 0 | int rv, nn, ii, update_df = 0; |
478 | |
|
479 | 0 | SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); |
480 | |
|
481 | 0 | sc_log(ctx, "Check and if needed update PinFlags"); |
482 | 0 | rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 32); |
483 | 0 | LOG_TEST_RET(ctx, rv, "Failed to get PINs"); |
484 | 0 | nn = rv; |
485 | |
|
486 | 0 | sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &profile_auth); |
487 | 0 | LOG_TEST_RET(ctx, rv, "Failed to get PIN info"); |
488 | | |
489 | 0 | for (ii=0; ii<nn; ii++) { |
490 | 0 | struct sc_pkcs15_auth_info *ainfo = (struct sc_pkcs15_auth_info *) objs[ii]->data; |
491 | 0 | struct sc_pkcs15_pin_attributes *pin_attrs = &ainfo->attrs.pin; |
492 | |
|
493 | 0 | if (ainfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) |
494 | 0 | continue; |
495 | | |
496 | 0 | if (pin_attrs->reference == profile_auth.attrs.pin.reference |
497 | 0 | && pin_attrs->flags != profile_auth.attrs.pin.flags) { |
498 | 0 | sc_log(ctx, "Set flags of '%s'(flags:%X,ref:%i,id:%s) to %X", objs[ii]->label, |
499 | 0 | pin_attrs->flags, pin_attrs->reference, sc_pkcs15_print_id(&ainfo->auth_id), |
500 | 0 | profile_auth.attrs.pin.flags); |
501 | 0 | pin_attrs->flags = profile_auth.attrs.pin.flags; |
502 | 0 | update_df = 1; |
503 | 0 | } |
504 | 0 | } |
505 | 0 | if (update_df) { |
506 | 0 | struct sc_pkcs15_df *df = p15card->df_list; |
507 | |
|
508 | 0 | while (df != NULL && df->type != SC_PKCS15_AODF) |
509 | 0 | df = df->next; |
510 | 0 | if (!df) |
511 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_FOUND, "Cannot find AODF"); |
512 | 0 | rv = sc_pkcs15init_update_any_df(p15card, profile, df, 0); |
513 | 0 | LOG_TEST_RET(ctx, rv, "Update AODF error"); |
514 | 0 | } |
515 | | |
516 | 0 | SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, rv); |
517 | 0 | } |
518 | | |
519 | | static struct sc_pkcs15init_operations sc_pkcs15init_entersafe_operations = { |
520 | | entersafe_erase_card, |
521 | | entersafe_init_card, |
522 | | entersafe_create_dir, |
523 | | NULL, /* create_domain */ |
524 | | entersafe_pin_reference, |
525 | | entersafe_create_pin, |
526 | | entersafe_key_reference, |
527 | | entersafe_create_key, |
528 | | entersafe_store_key, |
529 | | entersafe_generate_key, |
530 | | NULL, NULL, /* encode private/public key */ |
531 | | NULL, /* finalize */ |
532 | | NULL, /* delete_object */ |
533 | | NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ |
534 | | entersafe_sanity_check, |
535 | | }; |
536 | | |
537 | | struct sc_pkcs15init_operations *sc_pkcs15init_get_entersafe_ops(void) |
538 | 0 | { |
539 | 0 | return &sc_pkcs15init_entersafe_operations; |
540 | 0 | } |