1 /*
2 * minidriver.c: OpenSC minidriver
3 *
4 * Copyright (C) 2009,2010 francois.leblanc@cev-sa.com
5 * Copyright (C) 2015 vincent.letoux@mysmartlogon.com
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 /*
23 * This module requires "cardmod.h" from CNG SDK or platform SDK to build.
24 */
25
26 #include "config.h"
27 #ifdef ENABLE_MINIDRIVER
28
29 #ifdef _MANAGED
30 #pragma managed(push, off)
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37
38 #include <windows.h>
39 #include <Commctrl.h>
40 #include <timeapi.h>
41 #include "cardmod.h"
42
43 #include "common/compat_strlcpy.h"
44 #include "libopensc/asn1.h"
45 #include "libopensc/cardctl.h"
46 #include "libopensc/opensc.h"
47 #include "libopensc/pkcs15.h"
48 #include "libopensc/log.h"
49 #include "libopensc/internal.h"
50 #include "libopensc/aux-data.h"
51 #include "libopensc/sc-ossl-compat.h"
52 #include "ui/notify.h"
53 #include "ui/strings.h"
54 #include "ui/wchar_from_char_str.h"
55 #include "pkcs15init/pkcs15-init.h"
56
57 #ifdef ENABLE_OPENSSL
58 #include <openssl/opensslv.h>
59 #include <openssl/pem.h>
60 #endif
61
62 #ifdef ENABLE_OPENPACE
63 #include <eac/eac.h>
64 #endif
65
66 #if defined(__MINGW32__)
67 #include "cardmod-mingw-compat.h"
68 #endif
69
70 #include "cardmod.h"
71
72 #define MD_FUNC_CALLED(pCardData, level) do { \
73 logprintf(pCardData, level, "MD_Function:%s:%d called\n",__FUNCTION__, __LINE__); \
74 } while(0)
75
76
77 #define MD_FUNC_CALLED_EXT(pCardData, level) do { \
78 logprintf(pCardData, level, "\nP:%lu T:%lu MD_Function:%s:%d called\n", \
79 (unsigned long)GetCurrentProcessId(),\
80 (unsigned long)GetCurrentThreadId(), \
81 __FUNCTION__, __LINE__); \
82 } while(0)
83
84 #define MD_FUNC_RETURN(pCardData, level, ...) do { \
85 DWORD _ret = __VA_ARGS__; \
86 logprintf(pCardData, level,\
87 "MD_Function:%s:%d returning with: 0x%08X\n", __FUNCTION__, __LINE__, _ret); \
88 return _ret; \
89 } while(0)
90
91 /* store the instance given at DllMain when attached to access internal resources */
92 HINSTANCE g_inst;
93
94 #define MD_MINIMUM_VERSION_SUPPORTED 4
95 #define MD_CURRENT_VERSION_SUPPORTED 7
96
97 #define NULLSTR(a) (a == NULL ? "<NULL>" : a)
98 #define NULLWSTR(a) (a == NULL ? L"<NULL>" : a)
99
100 #define MD_MAX_KEY_CONTAINERS 12
101 #define MD_CARDID_SIZE 16
102
103 #define MD_ROLE_USER_SIGN (ROLE_ADMIN + 1)
104 /*
105 * must be higher than MD_ROLE_USER_SIGN and
106 * less than or equal MAX_PINS
107 */
108 #define MD_MAX_PINS MAX_PINS
109
110 #define MD_CARDCF_LENGTH (sizeof(CARD_CACHE_FILE_FORMAT))
111
112 #define MD_KEY_USAGE_KEYEXCHANGE \
113 SC_PKCS15INIT_X509_KEY_ENCIPHERMENT | \
114 SC_PKCS15INIT_X509_DATA_ENCIPHERMENT | \
115 SC_PKCS15INIT_X509_DIGITAL_SIGNATURE
116 #define MD_KEY_USAGE_KEYEXCHANGE_ECC \
117 SC_PKCS15INIT_X509_KEY_AGREEMENT| \
118 SC_PKCS15INIT_X509_DIGITAL_SIGNATURE
119 #define MD_KEY_USAGE_SIGNATURE \
120 SC_PKCS15INIT_X509_DIGITAL_SIGNATURE | \
121 SC_PKCS15INIT_X509_KEY_CERT_SIGN | \
122 SC_PKCS15INIT_X509_CRL_SIGN
123 #define MD_KEY_ACCESS \
124 SC_PKCS15_PRKEY_ACCESS_SENSITIVE | \
125 SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | \
126 SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | \
127 SC_PKCS15_PRKEY_ACCESS_LOCAL
128
129 /* copied from pkcs15-cardos.c */
130 #define USAGE_ANY_SIGN (SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)
131 #define USAGE_ANY_DECIPHER (SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP)
132 #define USAGE_ANY_AGREEMENT (SC_PKCS15_PRKEY_USAGE_DERIVE)
133
134 /* if use of internal-winscard.h */
135 #ifndef SCARD_E_INVALID_PARAMETER
136 #define SCARD_E_INVALID_PARAMETER 0x80100004L
137 #define SCARD_E_UNSUPPORTED_FEATURE 0x80100022L
138 #define SCARD_E_NO_MEMORY 0x80100006L
139 #define SCARD_W_WRONG_CHV 0x8010006BL
140 #define SCARD_E_FILE_NOT_FOUND 0x80100024L
141 #define SCARD_E_UNKNOWN_CARD 0x8010000DL
142 #define SCARD_F_UNKNOWN_ERROR 0x80100014L
143 #endif
144
145 /* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */
146 #define IDI_SMARTCARD 102
147
148 #define SUBKEY_ENABLE_CANCEL "Software\\OpenSC Project\\OpenSC\\md_pinpad_dlg_enable_cancel"
149
150 /* magic to determine previous pinpad authentication */
151 #define MAGIC_SESSION_PIN "opensc-minidriver"
152
153 #define TLS1_0_PROTOCOL_VERSION 0x0301
154 #define TLS1_1_PROTOCOL_VERSION 0x0302
155 #define TLS1_2_PROTOCOL_VERSION 0x0303
156 #define TLS_DERIVE_KEY_SIZE 48
157
158 struct md_directory {
159 unsigned char name[9];
160
161 CARD_DIRECTORY_ACCESS_CONDITION acl;
162
163 struct md_file *files;
164 struct md_directory *subdirs;
165
166 struct md_directory *next;
167 };
168
169 struct md_file {
170 unsigned char name[9];
171
172 CARD_FILE_ACCESS_CONDITION acl;
173
174 unsigned char *blob;
175 size_t size;
176
177 struct md_file *next;
178 };
179
180 struct md_pkcs15_container {
181 int index;
182 struct sc_pkcs15_id id;
183 char guid[MAX_CONTAINER_NAME_LEN + 1];
184 unsigned char flags;
185 size_t size_key_exchange, size_sign;
186
187 struct sc_pkcs15_object *cert_obj, *prkey_obj, *pubkey_obj;
188 // BOOL guid_overwrite;
189 };
190
191 struct md_dh_agreement {
192 DWORD dwSize;
193 PBYTE pbAgreement;
194 };
195
196 struct md_guid_conversion {
197 CHAR szOpenSCGuid[MAX_CONTAINER_NAME_LEN+1];
198 CHAR szWindowsGuid[MAX_CONTAINER_NAME_LEN+1];
199 };
200
201 #define MD_MAX_CONVERSIONS 50
202 struct md_guid_conversion md_static_conversions[MD_MAX_CONVERSIONS] = {0};
203
204 typedef struct _VENDOR_SPECIFIC
205 {
206 BOOL initialized;
207
208 struct sc_pkcs15_object *pin_objs[MD_MAX_PINS];
209
210 struct sc_context *ctx;
211 struct sc_reader *reader;
212 struct sc_card *card;
213 struct sc_pkcs15_card *p15card;
214
215 struct md_pkcs15_container p15_containers[MD_MAX_KEY_CONTAINERS];
216
217 struct md_directory root;
218
219 SCARDCONTEXT hSCardCtx;
220 SCARDHANDLE hScard;
221
222 /* These will be used in CardAuthenticateEx to display a dialog box when doing
223 * external PIN verification.
224 */
225 HWND hwndParent;
226 LPWSTR wszPinContext;
227 /* these will be used to store intermediate dh agreements results */
228 struct md_dh_agreement* dh_agreements;
229 BYTE allocatedAgreements;
230
231 CRITICAL_SECTION hScard_lock;
232 } VENDOR_SPECIFIC;
233
234 static DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror,
235 DWORD dwDefaulCode);
236 static DWORD associate_card(PCARD_DATA pCardData);
237 static void disassociate_card(PCARD_DATA pCardData);
238 static DWORD md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj);
239 static DWORD md_fs_init(PCARD_DATA pCardData);
240 static void md_fs_finalize(PCARD_DATA pCardData);
241
242 #if defined(__GNUC__)
243 static void logprintf(PCARD_DATA pCardData, int level, const char* format, ...)
244 __attribute__ ((format (SC_PRINTF_FORMAT, 3, 4)));
245 #endif
246
logprintf(PCARD_DATA pCardData,int level,_Printf_format_string_ const char * format,...)247 static void logprintf(PCARD_DATA pCardData, int level, _Printf_format_string_ const char* format, ...)
248 {
249 va_list arg;
250 VENDOR_SPECIFIC *vs;
251 /* Use a simplified log to get all messages including messages
252 * before opensc is loaded. The file must be modifiable by all
253 * users as we maybe called under lsa or user. Note data from
254 * multiple process and threads may get intermingled.
255 * flush to get last message before any crash
256 * close so as the file is not left open during any wait.
257 */
258 DWORD md_debug = 0;
259 size_t sz = sizeof(md_debug);
260 int rv;
261
262 rv = sc_ctx_win32_get_config_value("CARDMOD_LOW_LEVEL_DEBUG",
263 "MiniDriverDebug", "Software\\OpenSC Project\\OpenSC",
264 (char *)(&md_debug), &sz);
265 if (rv == SC_SUCCESS && md_debug != 0) {
266 FILE *lldebugfp = fopen("C:\\tmp\\md.log","a+");
267 if (lldebugfp) {
268 va_start(arg, format);
269 vfprintf(lldebugfp, format, arg);
270 va_end(arg);
271 fflush(lldebugfp);
272 fclose(lldebugfp);
273 }
274 }
275
276 va_start(arg, format);
277 if(pCardData != NULL) {
278 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
279 if(vs != NULL && vs->ctx != NULL)
280 sc_do_log_noframe(vs->ctx, level, format, arg);
281 }
282 va_end(arg);
283 }
284
loghex(PCARD_DATA pCardData,int level,PBYTE data,size_t len)285 static void loghex(PCARD_DATA pCardData, int level, PBYTE data, size_t len)
286 {
287 char line[74];
288 char *c;
289 unsigned int i, a;
290 unsigned char * p;
291
292 logprintf(pCardData, level, "--- %p:%"SC_FORMAT_LEN_SIZE_T"u\n",
293 data, len);
294
295 if (data == NULL || len <= 0) return;
296
297 p = data;
298 c = line;
299 i = 0;
300 a = 0;
301 memset(line, 0, sizeof(line));
302
303 while(i < len) {
304 snprintf(c, sizeof(line) - (size_t)(c - line), "%02X", *p);
305 line[sizeof(line) - 1] = 0;
306 p++;
307 c += 2;
308 i++;
309 if (i%32 == 0) {
310 logprintf(pCardData, level, " %04X %s\n", a, line);
311 a +=32;
312 memset(line, 0, sizeof(line));
313 c = line;
314 } else {
315 if (i%4 == 0) *(c++) = ' ';
316 if (i%16 == 0) *(c++) = ' ';
317 }
318 }
319 if (i%32 != 0)
320 logprintf(pCardData, level, " %04X %s\n", a, line);
321 }
322
reinit_card(PCARD_DATA pCardData)323 static DWORD reinit_card(PCARD_DATA pCardData)
324 {
325 VENDOR_SPECIFIC *vs;
326 DWORD r;
327
328 if (!pCardData)
329 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
330
331 vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific);
332 if (!vs)
333 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
334
335 if (vs->initialized) {
336 disassociate_card(pCardData);
337 md_fs_finalize(pCardData);
338 }
339
340 r = associate_card(pCardData);
341 if (r != SCARD_S_SUCCESS)
342 MD_FUNC_RETURN(pCardData, 1, r);
343
344 r = md_fs_init(pCardData);
345 if (r != SCARD_S_SUCCESS) {
346 logprintf(pCardData, 1,
347 "reinit_card md_fs_init failed, r = 0x%lX\n",
348 (unsigned long)r);
349 disassociate_card(pCardData);
350 MD_FUNC_RETURN(pCardData, 1, r);
351 }
352
353 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
354 }
355
lock(PCARD_DATA pCardData)356 static BOOL lock(PCARD_DATA pCardData)
357 {
358 if (pCardData) {
359 VENDOR_SPECIFIC *vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
360 if (vs) {
361 EnterCriticalSection(&vs->hScard_lock);
362 return TRUE;
363 }
364 }
365
366 return FALSE;
367 }
368
unlock(PCARD_DATA pCardData)369 static void unlock(PCARD_DATA pCardData)
370 {
371 if (pCardData) {
372 VENDOR_SPECIFIC *vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
373 if (vs) {
374 LeaveCriticalSection(&vs->hScard_lock);
375 }
376 }
377 }
378
reinit_card_for(PCARD_DATA pCardData,const char * name)379 static DWORD reinit_card_for(PCARD_DATA pCardData, const char *name)
380 {
381 DWORD r;
382
383 r = reinit_card(pCardData);
384 if (r != SCARD_S_SUCCESS)
385 logprintf(pCardData, 1,
386 "%s was called, but unable to initialize card, r = %u\n",
387 name, (unsigned int)r);
388
389 MD_FUNC_RETURN(pCardData, 1, r);
390 }
391
check_card_status(PCARD_DATA pCardData,const char * name)392 static DWORD check_card_status(PCARD_DATA pCardData, const char *name)
393 {
394 VENDOR_SPECIFIC *vs;
395
396 MD_FUNC_CALLED(pCardData, 3);
397
398 if (!pCardData)
399 MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER);
400
401 vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific);
402 if (!vs)
403 MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER);
404
405 if (vs->initialized)
406 MD_FUNC_RETURN(pCardData, 3, SCARD_S_SUCCESS);
407
408 MD_FUNC_RETURN(pCardData, 3, reinit_card_for(pCardData, name));
409 }
410
411 /*
412 * check if the card is OK, has been removed, or the
413 * caller has changed the handles.
414 * if so, then try to reinit card
415 */
416 static DWORD
check_card_reader_status(PCARD_DATA pCardData,const char * name)417 check_card_reader_status(PCARD_DATA pCardData, const char *name)
418 {
419 VENDOR_SPECIFIC *vs = NULL;
420 DWORD dwRet;
421 int r;
422
423 logprintf(pCardData, 1, "check_reader_status for %s\n", name);
424 if(!pCardData)
425 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
426
427 dwRet = check_card_status(pCardData, name);
428 if (dwRet != SCARD_S_SUCCESS)
429 MD_FUNC_RETURN(pCardData, 3, dwRet);
430
431 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
432 if(!vs)
433 MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER);
434
435 logprintf(pCardData, 7, "sizeof(size_t):%d sizeof(ULONG_PTR):%d sizeof(__int3264):%d sizeof pCardData->hSCardCtx:%d\n",
436 sizeof(size_t), sizeof(ULONG_PTR), sizeof(__int3264), sizeof pCardData->hSCardCtx);
437
438 logprintf(pCardData, 1, "pCardData->hSCardCtx:0x%08"SC_FORMAT_LEN_SIZE_T"X hScard:0x%08"SC_FORMAT_LEN_SIZE_T"X\n",
439 (size_t)pCardData->hSCardCtx,
440 (size_t)pCardData->hScard);
441
442 if (pCardData->hSCardCtx != vs->hSCardCtx || pCardData->hScard != vs->hScard) {
443 logprintf(pCardData, 1, "HANDLES CHANGED from vs->hSCardCtx:0x%08"SC_FORMAT_LEN_SIZE_T"X vs->hScard:0x%08"SC_FORMAT_LEN_SIZE_T"X\n",
444 (size_t)vs->hSCardCtx,
445 (size_t)vs->hScard);
446 if (vs->ctx) {
447 vs->hScard = pCardData->hScard;
448 vs->hSCardCtx = pCardData->hSCardCtx;
449 r = sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard);
450 logprintf(pCardData, 1, "sc_ctx_use_reader returned %d\n", r);
451 if (r)
452 MD_FUNC_RETURN(pCardData, 1, SCARD_F_INTERNAL_ERROR);
453 }
454 }
455
456 /* This should always work, as BaseCSP should be checking for removal too */
457 r = sc_detect_card_presence(vs->reader);
458 logprintf(pCardData, 2,
459 "check_reader_status r=%d flags 0x%08X\n", r,
460 (unsigned int)vs->reader->flags);
461 if (r < 0)
462 MD_FUNC_RETURN(pCardData, 1,
463 md_translate_OpenSC_to_Windows_error(r, SCARD_F_INTERNAL_ERROR));
464
465 if (!(r & SC_READER_CARD_PRESENT)) {
466 /*
467 * if there is really no card present it may not make sense to
468 * try initializing the card but since it won't hurt let's try
469 * it anyway for completeness
470 */
471 logprintf(pCardData, 1, "no card present? trying to reinit\n");
472 MD_FUNC_RETURN(pCardData, 1, reinit_card_for(pCardData, name));
473 }
474
475 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
476 }
477
478 static DWORD
md_get_pin_by_role(PCARD_DATA pCardData,PIN_ID role,struct sc_pkcs15_object ** ret_obj)479 md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object **ret_obj)
480 {
481 VENDOR_SPECIFIC *vs;
482 int rv;
483
484 MD_FUNC_CALLED(pCardData, 1);
485
486 if (!pCardData)
487 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
488
489 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
490 if (!ret_obj)
491 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
492
493 /* please keep me in sync with _get_auth_object_by_name() in pkcs11/framework-pkcs15.c */
494 if (role == ROLE_USER) {
495 /* Get 'global' User PIN; if no, get the 'local' one */
496 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL,
497 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
498 if (rv)
499 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
500 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
501 }
502 else if (role == MD_ROLE_USER_SIGN) {
503 int idx = 0;
504
505 /* Get the 'global' user PIN */
506 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL,
507 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
508 if (!rv) {
509 /* Global (user) PIN exists, get the local one -- sign PIN */
510 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
511 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
512 }
513 else {
514 /* No global PIN, try to get first local one -- user PIN */
515 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
516 SC_PKCS15_PIN_TYPE_FLAGS_MASK, &idx, ret_obj);
517 if (!rv) {
518 /* User PIN is local, try to get the second local -- sign PIN */
519 idx++;
520 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL,
521 SC_PKCS15_PIN_TYPE_FLAGS_MASK, &idx, ret_obj);
522 }
523 }
524 }
525 else if (role == ROLE_ADMIN) {
526 /* Get SO PIN; if no, get the 'global' PUK; if no get the 'local' one */
527 rv = sc_pkcs15_find_so_pin(vs->p15card, ret_obj);
528 if (rv)
529 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_GLOBAL,
530 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
531 if (rv)
532 rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_LOCAL,
533 SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj);
534 }
535 else {
536 logprintf(pCardData, 2,
537 "cannot get PIN object: unsupported role %u\n",
538 (unsigned int)role);
539 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
540 }
541
542 if (rv)
543 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
544
545 if (*ret_obj)
546 logprintf(pCardData, 7, "Returning PIN '%.*s' for role %u\n",
547 (int) sizeof (*ret_obj)->label, (*ret_obj)->label,
548 (unsigned int)role);
549
550 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
551 }
552
553 static const char *
md_get_config_str(PCARD_DATA pCardData,enum ui_str id)554 md_get_config_str(PCARD_DATA pCardData, enum ui_str id)
555 {
556 VENDOR_SPECIFIC *vs;
557 const char *ret = NULL;
558
559 if (!pCardData)
560 return ret;
561
562 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
563 if (vs->ctx && vs->reader) {
564 const char *preferred_language = NULL;
565 struct sc_atr atr;
566 atr.len = pCardData->cbAtr;
567 memcpy(atr.value, pCardData->pbAtr, atr.len);
568 if (vs->p15card && vs->p15card->tokeninfo
569 && vs->p15card->tokeninfo->preferred_language) {
570 preferred_language = vs->p15card->tokeninfo->preferred_language;
571 }
572 ret = ui_get_str(vs->ctx, &atr, vs->p15card, id);
573 }
574
575 return ret;
576 }
577
578
579 static HICON
md_get_config_icon(PCARD_DATA pCardData,char * flag_name,HICON ret_default)580 md_get_config_icon(PCARD_DATA pCardData, char *flag_name, HICON ret_default)
581 {
582 VENDOR_SPECIFIC *vs;
583 HICON ret = ret_default;
584
585 if (!pCardData)
586 return ret;
587
588 logprintf(pCardData, 2, "Get '%s' option\n", flag_name);
589
590 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
591 if (vs->ctx && vs->reader) {
592 struct sc_atr atr;
593 scconf_block *atrblock;
594 atr.len = pCardData->cbAtr;
595 memcpy(atr.value, pCardData->pbAtr, atr.len);
596 atrblock = _sc_match_atr_block(vs->ctx, NULL, &atr);
597 logprintf(pCardData, 2, "Match ATR:\n");
598 loghex(pCardData, 3, atr.value, atr.len);
599
600 if (atrblock) {
601 const char *filename = scconf_get_str(atrblock, flag_name, NULL);
602 if (filename) {
603 ret = (HICON) LoadImage(g_inst, filename, IMAGE_ICON, 0, 0,
604 LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_SHARED);
605 }
606 if (!ret)
607 ret = ret_default;
608 }
609 }
610
611
612 return ret;
613 }
614
615
616 static HICON
md_get_pinpad_dlg_icon(PCARD_DATA pCardData)617 md_get_pinpad_dlg_icon(PCARD_DATA pCardData)
618 {
619 return md_get_config_icon(pCardData, "md_pinpad_dlg_icon", NULL);
620 }
621
622
623 static int
md_get_config_int(PCARD_DATA pCardData,char * flag_name,int ret_default)624 md_get_config_int(PCARD_DATA pCardData, char *flag_name, int ret_default)
625 {
626 VENDOR_SPECIFIC *vs;
627 int ret = ret_default;
628
629 if (!pCardData)
630 return ret;
631
632 logprintf(pCardData, 2, "Get '%s' option\n", flag_name);
633
634 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
635 if (vs->ctx && vs->reader) {
636 struct sc_atr atr;
637 scconf_block *atrblock;
638 atr.len = pCardData->cbAtr;
639 memcpy(atr.value, pCardData->pbAtr, atr.len);
640 atrblock = _sc_match_atr_block(vs->ctx, NULL, &atr);
641 logprintf(pCardData, 2, "Match ATR:\n");
642 loghex(pCardData, 3, atr.value, atr.len);
643
644 if (atrblock)
645 ret = scconf_get_int(atrblock, flag_name, ret_default);
646 }
647
648 return ret;
649 }
650
651
652 static int
md_get_pinpad_dlg_timeout(PCARD_DATA pCardData)653 md_get_pinpad_dlg_timeout(PCARD_DATA pCardData)
654 {
655 return md_get_config_int(pCardData, "md_pinpad_dlg_timeout", 30);
656 }
657
658
659 static BOOL
md_get_config_bool(PCARD_DATA pCardData,char * flag_name,BOOL ret_default)660 md_get_config_bool(PCARD_DATA pCardData, char *flag_name, BOOL ret_default)
661 {
662 VENDOR_SPECIFIC *vs;
663 BOOL ret = ret_default;
664
665 if (!pCardData)
666 return ret;
667
668 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
669 if (!vs)
670 return ret;
671
672 if (vs->ctx && vs->reader) {
673 struct sc_atr atr;
674 scconf_block *atrblock;
675 atr.len = pCardData->cbAtr;
676 memcpy(atr.value, pCardData->pbAtr, atr.len);
677 atrblock = _sc_match_atr_block(vs->ctx, NULL, &atr);
678 logprintf(pCardData, 2, "Match ATR:\n");
679 loghex(pCardData, 3, atr.value, atr.len);
680
681 if (atrblock)
682 ret = scconf_get_bool(atrblock, flag_name, ret_default) ? TRUE : FALSE;
683 }
684
685 logprintf(pCardData, 2, "flag_name:%s:%s\n", flag_name, ret ? "TRUE": "FALSE");
686 return ret;
687 }
688
689
690 /* 'cancellation' mode can be enabled from the OpenSC configuration file*/
691 static BOOL
md_is_pinpad_dlg_enable_cancel(PCARD_DATA pCardData)692 md_is_pinpad_dlg_enable_cancel(PCARD_DATA pCardData)
693 {
694 TCHAR path[MAX_PATH]={0};
695
696 logprintf(pCardData, 2, "Is cancelling the PIN pad dialog enabled?\n");
697
698 if (GetModuleFileName(NULL, path, ARRAYSIZE(path))) {
699 DWORD enable_cancel;
700 size_t sz = sizeof enable_cancel;
701
702 if (SC_SUCCESS == sc_ctx_win32_get_config_value(NULL, path,
703 SUBKEY_ENABLE_CANCEL,
704 (char *)(&enable_cancel), &sz)) {
705 switch (enable_cancel) {
706 case 0:
707 return FALSE;
708 case 1:
709 return TRUE;
710 }
711 }
712 }
713
714 return md_get_config_bool(pCardData, "md_pinpad_dlg_enable_cancel", FALSE);
715 }
716
717
718 /* 'Write' mode can be enabled from the OpenSC configuration file*/
719 static BOOL
md_is_read_only(PCARD_DATA pCardData)720 md_is_read_only(PCARD_DATA pCardData)
721 {
722 BOOL ret = TRUE;
723
724 logprintf(pCardData, 2, "Is read-only?\n");
725
726 if (pCardData && pCardData->pvVendorSpecific) {
727 VENDOR_SPECIFIC *vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
728 if (vs->p15card && vs->p15card->tokeninfo) {
729 if (vs->p15card->tokeninfo->flags & SC_PKCS15_TOKEN_READONLY) {
730 ret = TRUE;
731 } else {
732 ret = FALSE;
733 }
734 }
735 }
736
737 return md_get_config_bool(pCardData, "read_only", ret);
738 }
739
740
741 /* 'Write' mode can be enabled from the OpenSC configuration file*/
742 static BOOL
md_is_supports_X509_enrollment(PCARD_DATA pCardData)743 md_is_supports_X509_enrollment(PCARD_DATA pCardData)
744 {
745 BOOL defaultvalue = !md_is_read_only(pCardData);
746 logprintf(pCardData, 2, "Is supports X509 enrollment?\n");
747 return md_get_config_bool(pCardData, "md_supports_X509_enrollment", defaultvalue);
748 }
749
750
751 /* Get know if the GUID has to used as ID of crypto objects */
752 static BOOL
md_is_guid_as_id(PCARD_DATA pCardData)753 md_is_guid_as_id(PCARD_DATA pCardData)
754 {
755 logprintf(pCardData, 2, "Is GUID has to be used as ID of crypto objects?\n");
756 return md_get_config_bool(pCardData, "md_guid_as_id", FALSE);
757 }
758
759
760 /* Get know if the GUID has to used as label of crypto objects */
761 static BOOL
md_is_guid_as_label(PCARD_DATA pCardData)762 md_is_guid_as_label(PCARD_DATA pCardData)
763 {
764 logprintf(pCardData, 2, "Is GUID has to be used as label of crypto objects?\n");
765 return md_get_config_bool(pCardData, "md_guid_as_label", FALSE);
766 }
767
768
769 /* Get know if disabled CARD_CREATE_CONTAINER_KEY_GEN mechanism */
770 static BOOL
md_is_supports_container_key_gen(PCARD_DATA pCardData)771 md_is_supports_container_key_gen(PCARD_DATA pCardData)
772 {
773 logprintf(pCardData, 2, "Is supports 'key generation' create_container mechanism?\n");
774 return md_get_config_bool(pCardData, "md_supports_container_key_gen", TRUE);
775 }
776
777
778 /* Get know if disabled CARD_CREATE_CONTAINER_KEY_IMPORT mechanism */
779 static BOOL
md_is_supports_container_key_import(PCARD_DATA pCardData)780 md_is_supports_container_key_import(PCARD_DATA pCardData)
781 {
782 logprintf(pCardData, 2, "Is supports 'key import' create container mechanism?\n");
783 return md_get_config_bool(pCardData, "md_supports_container_key_import", TRUE);
784 }
785
786 /* generate unique key label (GUID)*/
787 static VOID md_generate_guid( __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid) {
788 RPC_CSTR szRPCGuid = NULL;
789 GUID Label = {0};
790 UuidCreate(&Label);
791 if (UuidToStringA(&Label, &szRPCGuid) == RPC_S_OK && szRPCGuid) {
792 strlcpy(szGuid, (PSTR)szRPCGuid, MAX_CONTAINER_NAME_LEN + 1);
793 RpcStringFreeA(&szRPCGuid);
794 } else
795 szGuid[0] = 0;
796 }
797
798 static DWORD
799 md_contguid_get_guid_from_card(PCARD_DATA pCardData, struct sc_pkcs15_object *prkey, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid)
800 {
801 int rv;
802 VENDOR_SPECIFIC *vs;
803 size_t guid_len = MAX_CONTAINER_NAME_LEN+1;
804
805 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
806 if (!vs)
807 return SCARD_E_INVALID_PARAMETER;
808
809 rv = sc_pkcs15_get_object_guid(vs->p15card, prkey, 1, (unsigned char*) szGuid, &guid_len);
810 if (rv) {
811 logprintf(pCardData, 2, "md_contguid_get_guid_from_card(): error %d\n", rv);
812 return SCARD_F_INTERNAL_ERROR;
813 }
814
815 return SCARD_S_SUCCESS;
816 }
817
818 /* add a new entry in the guid conversion table */
819 static DWORD
820 md_contguid_add_conversion(PCARD_DATA pCardData, struct sc_pkcs15_object *prkey,
821 __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szWindowsGuid)
822 {
823 DWORD ret;
824 int i;
825 CHAR szOpenSCGuid[MAX_CONTAINER_NAME_LEN+1] = "";
826
827 ret = md_contguid_get_guid_from_card(pCardData, prkey, szOpenSCGuid);
828 if (ret != SCARD_S_SUCCESS)
829 return ret;
830
831 if (strcmp(szOpenSCGuid, szWindowsGuid) == 0)
832 return ret;
833
834 for (i = 0; i < MD_MAX_CONVERSIONS; i++) {
835 if (md_static_conversions[i].szWindowsGuid[0] == 0) {
836 strlcpy(md_static_conversions[i].szWindowsGuid,
837 szWindowsGuid, MAX_CONTAINER_NAME_LEN + 1);
838 strlcpy(md_static_conversions[i].szOpenSCGuid,
839 szOpenSCGuid, MAX_CONTAINER_NAME_LEN + 1);
840 logprintf(pCardData, 0, "md_contguid_add_conversion(): Registering conversion '%s' '%s'\n", szWindowsGuid, szOpenSCGuid);
841 return SCARD_S_SUCCESS;;
842 }
843 }
844 logprintf(pCardData, 0, "md_contguid_add_conversion(): Unable to add a new conversion with guid %s.\n", szWindowsGuid);
845 return SCARD_F_INTERNAL_ERROR;;
846 }
847
848 /* remove an entry in the guid conversion table*/
849 static VOID
850 md_contguid_delete_conversion(PCARD_DATA pCardData, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szWindowsGuid)
851 {
852 int i;
853 for (i = 0; i < MD_MAX_CONVERSIONS; i++) {
854 if (strcmp(md_static_conversions[i].szWindowsGuid,szWindowsGuid) == 0) {
855 memset(md_static_conversions + i, 0, sizeof(struct md_guid_conversion));
856 }
857 }
858 }
859
860 /* build key args from the minidriver guid */
861 static VOID
862 md_contguid_build_key_args_from_cont_guid(PCARD_DATA pCardData, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid,
863 struct sc_pkcs15init_prkeyargs *prkey_args)
864 {
865 /* strlen(szGuid) <= MAX_CONTAINER_NAME */
866 logprintf(pCardData, 3, "Using the guid '%s'\n", szGuid);
867 if (szGuid[0] != 0) {
868 prkey_args->guid = (unsigned char*) szGuid;
869 prkey_args->guid_len = strlen(szGuid);
870 }
871
872 if (md_is_guid_as_id(pCardData)) {
873 memcpy(prkey_args->id.value, szGuid, strlen(szGuid));
874 prkey_args->id.len = strlen(szGuid);
875 }
876 if (md_is_guid_as_label(pCardData)) {
877 prkey_args->label = szGuid;
878 }
879 }
880
881 /* build minidriver guid from the key */
882 static DWORD
883 md_contguid_build_cont_guid_from_key(PCARD_DATA pCardData, struct sc_pkcs15_object *key_obj, __in_ecount(MAX_CONTAINER_NAME_LEN+1) PSTR szGuid)
884 {
885 struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
886 DWORD dwret = SCARD_S_SUCCESS;
887
888 szGuid[0] = '\0';
889 /* prioritize the use of the key id over the key label as a container name */
890 if (md_is_guid_as_id(pCardData) && prkey_info->id.len > 0 && prkey_info->id.len <= MAX_CONTAINER_NAME_LEN) {
891 memcpy(szGuid, prkey_info->id.value, prkey_info->id.len);
892 szGuid[prkey_info->id.len] = 0;
893 } else if (md_is_guid_as_label(pCardData) && key_obj->label[0] != 0) {
894 strlcpy(szGuid, key_obj->label, MAX_CONTAINER_NAME_LEN + 1);
895 } else {
896 dwret = md_contguid_get_guid_from_card(pCardData, key_obj, szGuid);
897 }
898
899 return dwret;
900 }
901
902
903 static DWORD
md_cont_flags_from_key(PCARD_DATA pCardData,struct sc_pkcs15_object * key_obj,unsigned char * cont_flags)904 md_cont_flags_from_key(PCARD_DATA pCardData, struct sc_pkcs15_object *key_obj, unsigned char *cont_flags)
905 {
906 struct sc_pkcs15_prkey_info *prkey_info = NULL;
907 VENDOR_SPECIFIC *vs;
908 int rv;
909
910 vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
911 if (!vs)
912 return SCARD_E_INVALID_PARAMETER;
913
914 prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
915
916 *cont_flags = CONTAINER_MAP_VALID_CONTAINER;
917 if (prkey_info->aux_data) {
918 rv = sc_aux_data_get_md_flags(vs->ctx, prkey_info->aux_data, cont_flags);
919 if (rv != SC_ERROR_NOT_SUPPORTED && rv != SC_SUCCESS)
920 return SCARD_F_INTERNAL_ERROR;
921 }
922
923 return SCARD_S_SUCCESS;
924 }
925
926
927 /* Search directory by name and optionally by name of it's parent */
928 static DWORD
md_fs_find_directory(PCARD_DATA pCardData,struct md_directory * parent,char * name,struct md_directory ** out)929 md_fs_find_directory(PCARD_DATA pCardData, struct md_directory *parent, char *name, struct md_directory **out)
930 {
931 VENDOR_SPECIFIC *vs;
932 struct md_directory *dir = NULL;
933
934 if (out)
935 *out = NULL;
936
937 if (!pCardData)
938 return SCARD_E_INVALID_PARAMETER;
939
940 vs = pCardData->pvVendorSpecific;
941 if (!vs)
942 return SCARD_E_INVALID_PARAMETER;
943
944 if (!parent)
945 parent = &vs->root;
946
947 if (!name) {
948 dir = parent;
949 }
950 else {
951 dir = parent->subdirs;
952 while(dir) {
953 if (strlen(name) > sizeof dir->name
954 || !strncmp((char *)dir->name, name, sizeof dir->name))
955 break;
956 dir = dir->next;
957 }
958 }
959
960 if (!dir)
961 return SCARD_E_DIR_NOT_FOUND;
962
963 if (out)
964 *out = dir;
965
966 logprintf(pCardData, 3, "MD virtual file system: found '%s' directory\n", name);
967 return SCARD_S_SUCCESS;
968 }
969
970
971 static DWORD
md_fs_add_directory(PCARD_DATA pCardData,struct md_directory ** head,char * name,CARD_FILE_ACCESS_CONDITION acl,struct md_directory ** out)972 md_fs_add_directory(PCARD_DATA pCardData, struct md_directory **head, char *name,
973 CARD_FILE_ACCESS_CONDITION acl,
974 struct md_directory **out)
975 {
976 struct md_directory *new_dir = NULL;
977
978 if (!pCardData || !head || !name)
979 return SCARD_E_INVALID_PARAMETER;
980
981 new_dir = pCardData->pfnCspAlloc(sizeof(struct md_directory));
982 if (!new_dir)
983 return SCARD_E_NO_MEMORY;
984 memset(new_dir, 0, sizeof(struct md_directory));
985
986 strlcpy((char *)new_dir->name, name, sizeof(new_dir->name));
987 new_dir->acl = acl;
988
989 if (*head == NULL) {
990 *head = new_dir;
991 }
992 else {
993 struct md_directory *last = *head;
994 while (last->next)
995 last = last->next;
996 last->next = new_dir;
997 }
998
999 if (out)
1000 *out = new_dir;
1001
1002 logprintf(pCardData, 3, "MD virtual file system: directory '%s' added\n", name);
1003 return SCARD_S_SUCCESS;
1004 }
1005
1006
1007 static DWORD
md_fs_find_file(PCARD_DATA pCardData,char * parent,char * name,struct md_file ** out)1008 md_fs_find_file(PCARD_DATA pCardData, char *parent, char *name, struct md_file **out)
1009 {
1010 struct md_file *file = NULL;
1011 struct md_directory *dir = NULL;
1012 DWORD dwret;
1013
1014 if (out)
1015 *out = NULL;
1016
1017 if (!pCardData || !name)
1018 return SCARD_E_INVALID_PARAMETER;
1019
1020 dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
1021 if (dwret != SCARD_S_SUCCESS) {
1022 logprintf(pCardData, 2, "find directory '%s' error: %lX\n",
1023 parent ? parent : "<null>", (unsigned long)dwret);
1024 return dwret;
1025 }
1026 else if (!dir) {
1027 logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
1028 return SCARD_E_INVALID_PARAMETER;
1029 }
1030
1031 for (file = dir->files; file!=NULL;) {
1032 if (sizeof file->name < strlen(name)
1033 || !strncmp((char *)file->name, name, sizeof file->name))
1034 break;
1035 file = file->next;
1036 }
1037 if (!file)
1038 return SCARD_E_FILE_NOT_FOUND;
1039
1040 if (out)
1041 *out = file;
1042
1043 logprintf(pCardData, 3, "MD virtual file system: found '%s' file\n", name);
1044 return SCARD_S_SUCCESS;
1045 }
1046
1047
1048 static DWORD
md_fs_add_file(PCARD_DATA pCardData,struct md_file ** head,char * name,CARD_FILE_ACCESS_CONDITION acl,unsigned char * blob,size_t size,struct md_file ** out)1049 md_fs_add_file(PCARD_DATA pCardData, struct md_file **head, char *name, CARD_FILE_ACCESS_CONDITION acl,
1050 unsigned char *blob, size_t size, struct md_file **out)
1051 {
1052 struct md_file *new_file = NULL;
1053
1054 if (!pCardData || !head || !name)
1055 return SCARD_E_INVALID_PARAMETER;
1056
1057 new_file = pCardData->pfnCspAlloc(sizeof(struct md_file));
1058 if (!new_file)
1059 return SCARD_E_NO_MEMORY;
1060 memset(new_file, 0, sizeof(struct md_file));
1061
1062 strlcpy((char *)new_file->name, name, sizeof(new_file->name));
1063 new_file->size = size;
1064 new_file->acl = acl;
1065
1066 if (size) {
1067 new_file->blob = pCardData->pfnCspAlloc(size);
1068 if (!new_file->blob) {
1069 pCardData->pfnCspFree(new_file);
1070 return SCARD_E_NO_MEMORY;
1071 }
1072
1073 if (blob)
1074 CopyMemory(new_file->blob, blob, size);
1075 else
1076 memset(new_file->blob, 0, size);
1077 }
1078
1079 if (*head == NULL) {
1080 *head = new_file;
1081 }
1082 else {
1083 struct md_file *last = *head;
1084 while (last->next)
1085 last = last->next;
1086 last->next = new_file;
1087 }
1088
1089 if (out)
1090 *out = new_file;
1091
1092 logprintf(pCardData, 3, "MD virtual file system: file '%s' added\n", name);
1093 return SCARD_S_SUCCESS;
1094 }
1095
1096
1097 static void
md_fs_free_file(PCARD_DATA pCardData,struct md_file * file)1098 md_fs_free_file(PCARD_DATA pCardData, struct md_file *file)
1099 {
1100 if (!file)
1101 return;
1102 if (file->blob)
1103 pCardData->pfnCspFree(file->blob);
1104 file->blob = NULL;
1105 file->size = 0;
1106 pCardData->pfnCspFree(file);
1107 }
1108
1109
1110 static DWORD
md_fs_delete_file(PCARD_DATA pCardData,char * parent,char * name)1111 md_fs_delete_file(PCARD_DATA pCardData, char *parent, char *name)
1112 {
1113 VENDOR_SPECIFIC *vs;
1114 struct md_file *file = NULL, *file_to_rm = NULL;
1115 struct md_directory *dir = NULL;
1116 int deleted = 0;
1117 DWORD dwret;
1118
1119 if (!pCardData || !name)
1120 return SCARD_E_INVALID_PARAMETER;
1121
1122 vs = pCardData->pvVendorSpecific;
1123 if (!vs)
1124 return SCARD_E_INVALID_PARAMETER;
1125
1126 dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
1127 if (dwret != SCARD_S_SUCCESS) {
1128 logprintf(pCardData, 2, "find directory '%s' error: %lX\n",
1129 parent ? parent : "<null>", (unsigned long)dwret);
1130 return dwret;
1131 }
1132 else if (!dir) {
1133 logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
1134 return SCARD_E_INVALID_PARAMETER;
1135 }
1136 else if (!dir->files) {
1137 logprintf(pCardData, 2, "no files in '%s' directory\n", parent ? parent : "<null>");
1138 return SCARD_E_FILE_NOT_FOUND;
1139 }
1140
1141 if (sizeof dir->files->name < strlen(name)
1142 || !strncmp((char *)dir->files->name, name, sizeof dir->files->name)) {
1143 file_to_rm = dir->files;
1144 dir->files = dir->files->next;
1145 md_fs_free_file(pCardData, file_to_rm);
1146 dwret = SCARD_S_SUCCESS;
1147 }
1148 else {
1149 for (file = dir->files; file!=NULL; file = file->next) {
1150 if (!file->next)
1151 break;
1152 if (sizeof file->next->name < strlen(name)
1153 || !strncmp((char *)file->next->name, name, sizeof file->next->name)) {
1154 file_to_rm = file->next;
1155 file->next = file->next->next;
1156 md_fs_free_file(pCardData, file_to_rm);
1157 deleted = 1;
1158 break;
1159 }
1160 }
1161 dwret = deleted ? SCARD_S_SUCCESS : SCARD_E_FILE_NOT_FOUND;
1162 }
1163
1164 if (!strcmp(parent, "mscp")) {
1165 int idx = -1;
1166
1167 if(sscanf(name, "ksc%d", &idx) > 0) {
1168 }
1169 else if(sscanf(name, "kxc%d", &idx) > 0) {
1170 }
1171
1172 if (idx >= 0 && idx < MD_MAX_KEY_CONTAINERS) {
1173 dwret = md_pkcs15_delete_object(pCardData, vs->p15_containers[idx].cert_obj);
1174 vs->p15_containers[idx].cert_obj = NULL;
1175 if(dwret != SCARD_S_SUCCESS)
1176 logprintf(pCardData, 2,
1177 "Cannot delete certificate PKCS#15 object #%i: dwret 0x%lX\n",
1178 idx, (unsigned long)dwret);
1179 }
1180 }
1181
1182 return dwret;
1183 }
1184
1185 static void
md_fs_finalize(PCARD_DATA pCardData)1186 md_fs_finalize(PCARD_DATA pCardData)
1187 {
1188 VENDOR_SPECIFIC *vs;
1189 struct md_file *file = NULL, *file_to_rm;
1190 struct md_directory *dir = NULL, *dir_to_rm;
1191
1192 if (!pCardData)
1193 return;
1194
1195 vs = pCardData->pvVendorSpecific;
1196 if (!vs)
1197 return;
1198
1199 file = vs->root.files;
1200 while (file != NULL) {
1201 file_to_rm = file;
1202 file = file->next;
1203 md_fs_free_file(pCardData, file_to_rm);
1204 }
1205 vs->root.files = NULL;
1206
1207 dir = vs->root.subdirs;
1208 while(dir) {
1209 file = dir->files;
1210 while (file != NULL) {
1211 file_to_rm = file;
1212 file = file->next;
1213 md_fs_free_file(pCardData, file_to_rm);
1214 }
1215 dir_to_rm = dir;
1216 dir = dir->next;
1217 pCardData->pfnCspFree(dir_to_rm);
1218 }
1219 vs->root.subdirs = NULL;
1220 }
1221
1222 /*
1223 * Update 'soft' containers.
1224 * Called each time when 'WriteFile' is called for 'cmapfile'.
1225 */
1226 static DWORD
md_pkcs15_update_containers(PCARD_DATA pCardData,unsigned char * blob,size_t size)1227 md_pkcs15_update_containers(PCARD_DATA pCardData, unsigned char *blob, size_t size)
1228 {
1229 VENDOR_SPECIFIC *vs;
1230 CONTAINER_MAP_RECORD *pp;
1231 int nn_records, idx;
1232
1233 if (!pCardData || !blob || size < sizeof(CONTAINER_MAP_RECORD))
1234 return SCARD_E_INVALID_PARAMETER;
1235
1236 vs = pCardData->pvVendorSpecific;
1237 if (!vs)
1238 return SCARD_E_INVALID_PARAMETER;
1239
1240 nn_records = (int) size/sizeof(CONTAINER_MAP_RECORD);
1241 if (nn_records > MD_MAX_KEY_CONTAINERS)
1242 nn_records = MD_MAX_KEY_CONTAINERS;
1243
1244 for (idx=0, pp = (CONTAINER_MAP_RECORD *)blob; idx<nn_records; idx++, pp++) {
1245 struct md_pkcs15_container *cont = &(vs->p15_containers[idx]);
1246 size_t count;
1247 CHAR szGuid[MAX_CONTAINER_NAME_LEN+1] = "";
1248
1249 count = wcstombs(szGuid, pp->wszGuid, sizeof(cont->guid));
1250 if (!count) {
1251 if (cont->guid[0] != 0) {
1252 md_contguid_delete_conversion(pCardData, cont->guid);
1253 }
1254 memset(cont, 0, sizeof(CONTAINER_MAP_RECORD));
1255 }
1256 else {
1257 strlcpy(cont->guid, szGuid, MAX_CONTAINER_NAME_LEN + 1);
1258 cont->index = idx;
1259 cont->flags = pp->bFlags;
1260 cont->size_sign = pp->wSigKeySizeBits;
1261 cont->size_key_exchange = pp->wKeyExchangeKeySizeBits;
1262 logprintf(pCardData, 3, "update P15 containers: touch container (idx:%i,id:%s,guid:%.*s,flags:%X)\n",
1263 idx, sc_pkcs15_print_id(&cont->id),
1264 (int)sizeof cont->guid, cont->guid, cont->flags);
1265 }
1266 }
1267
1268 return SCARD_S_SUCCESS;
1269 }
1270
1271
1272 static DWORD
md_pkcs15_delete_object(PCARD_DATA pCardData,struct sc_pkcs15_object * obj)1273 md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj)
1274 {
1275 VENDOR_SPECIFIC *vs;
1276 struct sc_profile *profile = NULL;
1277 struct sc_card *card = NULL;
1278 struct sc_app_info *app_info = NULL;
1279 DWORD dwret = SCARD_F_INTERNAL_ERROR;
1280 int rv;
1281
1282 if (!pCardData)
1283 return SCARD_E_INVALID_PARAMETER;
1284 vs = pCardData->pvVendorSpecific;
1285 if (!vs)
1286 return SCARD_E_INVALID_PARAMETER;
1287
1288 card = vs->p15card->card;
1289
1290 if (!obj)
1291 return SCARD_S_SUCCESS;
1292 logprintf(pCardData, 3, "MdDeleteObject('%.*s',type:0x%X) called\n", (int) sizeof obj->label, obj->label, obj->type);
1293
1294 rv = sc_lock(card);
1295 if (rv) {
1296 logprintf(pCardData, 3, "MdDeleteObject(): cannot lock card\n");
1297 return SCARD_F_INTERNAL_ERROR;
1298 }
1299
1300 app_info = vs->p15card->app;
1301 rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
1302 if (rv) {
1303 logprintf(pCardData, 3, "MdDeleteObject(): PKCS#15 bind failed\n");
1304 sc_unlock(card);
1305 return SCARD_F_INTERNAL_ERROR;
1306 }
1307
1308 rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
1309 if (rv) {
1310 logprintf(pCardData, 3, "MdDeleteObject(): cannot finalize profile\n");
1311 goto done;
1312 }
1313
1314 sc_pkcs15init_set_p15card(profile, vs->p15card);
1315
1316 rv = sc_pkcs15init_delete_object(vs->p15card, profile, obj);
1317 if (rv) {
1318 logprintf(pCardData, 2, "MdDeleteObject(): pkcs15init delete object failed %d\n", rv);
1319 goto done;
1320 }
1321
1322 dwret = SCARD_S_SUCCESS;
1323 logprintf(pCardData, 3, "MdDeleteObject() returns OK\n");
1324 done:
1325 sc_pkcs15init_unbind(profile);
1326 sc_unlock(card);
1327 return dwret;
1328 }
1329
1330
1331 /* Set 'soft' file contents,
1332 * and update data associated to 'cardcf' and 'cmapfile'.
1333 */
1334 static DWORD
md_fs_set_content(PCARD_DATA pCardData,struct md_file * file,unsigned char * blob,size_t size)1335 md_fs_set_content(PCARD_DATA pCardData, struct md_file *file, unsigned char *blob, size_t size)
1336 {
1337 if (!pCardData || !file)
1338 return SCARD_E_INVALID_PARAMETER;
1339
1340 if (file->blob)
1341 pCardData->pfnCspFree(file->blob);
1342
1343 file->blob = pCardData->pfnCspAlloc(size);
1344 if (!file->blob)
1345 return SCARD_E_NO_MEMORY;
1346 CopyMemory(file->blob, blob, size);
1347 file->size = size;
1348
1349 if (!strcmp((char *)file->name, "cmapfile"))
1350 return md_pkcs15_update_containers(pCardData, blob, size);
1351
1352 return SCARD_S_SUCCESS;
1353 }
1354
1355 /*
1356 * Set 'cardid' from the 'serialNumber' attribute of the 'tokenInfo'
1357 */
1358 static DWORD
md_set_cardid(PCARD_DATA pCardData,struct md_file * file)1359 md_set_cardid(PCARD_DATA pCardData, struct md_file *file)
1360 {
1361 VENDOR_SPECIFIC *vs;
1362 DWORD dwret;
1363
1364 if (!pCardData || !file)
1365 return SCARD_E_INVALID_PARAMETER;
1366
1367 vs = pCardData->pvVendorSpecific;
1368 if (!vs)
1369 return SCARD_E_INVALID_PARAMETER;
1370
1371 if (vs->p15card->tokeninfo && vs->p15card->tokeninfo->serial_number) {
1372 unsigned char sn_bin[SC_MAX_SERIALNR];
1373 unsigned char cardid_bin[MD_CARDID_SIZE];
1374 size_t offs, wr, sn_len = sizeof(sn_bin);
1375 int rv;
1376
1377 rv = sc_hex_to_bin(vs->p15card->tokeninfo->serial_number, sn_bin, &sn_len);
1378 if (rv) {
1379 sn_len = strlen(vs->p15card->tokeninfo->serial_number);
1380 if (sn_len > SC_MAX_SERIALNR) {
1381 sn_len = SC_MAX_SERIALNR;
1382 }
1383 memcpy(sn_bin, vs->p15card->tokeninfo->serial_number, sn_len);
1384 }
1385
1386 if (sn_len > 0) {
1387 for (offs=0; offs < MD_CARDID_SIZE; ) {
1388 wr = MD_CARDID_SIZE - offs;
1389 if (wr > sn_len)
1390 wr = sn_len;
1391 memcpy(cardid_bin + offs, sn_bin, wr);
1392 offs += wr;
1393 }
1394 } else {
1395 memset(cardid_bin, 0, MD_CARDID_SIZE);
1396 }
1397
1398 dwret = md_fs_set_content(pCardData, file, cardid_bin, MD_CARDID_SIZE);
1399 if (dwret != SCARD_S_SUCCESS)
1400 return dwret;
1401 }
1402
1403 logprintf(pCardData, 3, "cardid(%"SC_FORMAT_LEN_SIZE_T"u)\n",
1404 file->size);
1405 loghex(pCardData, 3, file->blob, file->size);
1406 return SCARD_S_SUCCESS;
1407 }
1408
1409 /* fill the msroots file from root certificates */
1410 static DWORD
md_fs_read_msroots_file(PCARD_DATA pCardData,struct md_file * file)1411 md_fs_read_msroots_file(PCARD_DATA pCardData, struct md_file *file)
1412 {
1413 CERT_BLOB dbStore = {0};
1414 HCERTSTORE hCertStore;
1415 VENDOR_SPECIFIC *vs;
1416 int rv, ii, cert_num;
1417 struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
1418 DWORD dwret = SCARD_F_INTERNAL_ERROR;
1419
1420 if (!pCardData || !file)
1421 return SCARD_E_INVALID_PARAMETER;
1422
1423 vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific;
1424 if (!vs)
1425 return SCARD_E_INVALID_PARAMETER;
1426
1427 hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, (HCRYPTPROV_LEGACY)NULL, 0, NULL);
1428 if (!hCertStore)
1429 goto Ret;
1430
1431 rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS);
1432 if (rv < 0) {
1433 logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv));
1434 dwret = md_translate_OpenSC_to_Windows_error(rv, dwret);
1435 goto Ret;
1436 }
1437 cert_num = rv;
1438 for(ii = 0; ii < cert_num; ii++) {
1439 struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data;
1440 struct sc_pkcs15_cert *cert = NULL;
1441 PCCERT_CONTEXT wincert = NULL;
1442 if (cert_info->authority) {
1443 rv = sc_pkcs15_read_certificate(vs->p15card, cert_info, &cert);
1444 if(rv) {
1445 logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", ii, rv);
1446 continue;
1447 }
1448 wincert = CertCreateCertificateContext(X509_ASN_ENCODING, cert->data.value, (DWORD) cert->data.len);
1449 if (wincert) {
1450 CertAddCertificateContextToStore(hCertStore, wincert, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
1451 CertFreeCertificateContext(wincert);
1452 }
1453 else {
1454 logprintf(pCardData, 2,
1455 "unable to load the certificate from Windows 0x%08X\n",
1456 (unsigned int)GetLastError());
1457 }
1458 sc_pkcs15_free_certificate(cert);
1459 }
1460 }
1461 if (FALSE == CertSaveStore( hCertStore,
1462 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
1463 CERT_STORE_SAVE_AS_PKCS7,
1464 CERT_STORE_SAVE_TO_MEMORY,
1465 &dbStore,
1466 0)) {
1467 goto Ret;
1468 }
1469
1470 dbStore.pbData = (PBYTE) pCardData->pfnCspAlloc(dbStore.cbData);
1471
1472 if (NULL == dbStore.pbData) {
1473 dwret = SCARD_E_NO_MEMORY;
1474 goto Ret;
1475 }
1476
1477 if (FALSE == CertSaveStore( hCertStore,
1478 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
1479 CERT_STORE_SAVE_AS_PKCS7,
1480 CERT_STORE_SAVE_TO_MEMORY,
1481 &dbStore,
1482 0))
1483 {
1484 goto Ret;
1485 }
1486 file->size = dbStore.cbData;
1487 file->blob = dbStore.pbData;
1488 dbStore.pbData = NULL;
1489 dwret = SCARD_S_SUCCESS;
1490
1491 Ret:
1492 if (dbStore.pbData)
1493 pCardData->pfnCspFree(dbStore.pbData);
1494 if (hCertStore)
1495 CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
1496
1497 return dwret;
1498 }
1499
1500 /*
1501 * Return content of the 'soft' file.
1502 */
1503 static DWORD
md_fs_read_content(PCARD_DATA pCardData,char * parent,struct md_file * file)1504 md_fs_read_content(PCARD_DATA pCardData, char *parent, struct md_file *file)
1505 {
1506 VENDOR_SPECIFIC *vs;
1507 struct md_directory *dir = NULL;
1508 DWORD dwret;
1509
1510 if (!pCardData || !file)
1511 return SCARD_E_INVALID_PARAMETER;
1512
1513 vs = pCardData->pvVendorSpecific;
1514 if (!vs || !vs->p15card)
1515 return SCARD_E_INVALID_PARAMETER;
1516
1517 dwret = md_fs_find_directory(pCardData, NULL, parent, &dir);
1518 if (dwret != SCARD_S_SUCCESS) {
1519 logprintf(pCardData, 2, "find directory '%s' error: %lX\n",
1520 parent ? parent : "<null>", (unsigned long)dwret);
1521 return dwret;
1522 }
1523 else if (!dir) {
1524 logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : "<null>");
1525 return SCARD_E_DIR_NOT_FOUND;
1526 }
1527
1528 if (!strcmp((char *)dir->name, "mscp")) {
1529 int idx, rv;
1530
1531 if(sscanf((char *)file->name, "ksc%d", &idx) > 0) {
1532 }
1533 else if(sscanf((char *)file->name, "kxc%d", &idx) > 0) {
1534 }
1535 else {
1536 idx = -1;
1537 }
1538
1539 if (idx >=0 && idx < MD_MAX_KEY_CONTAINERS && vs->p15_containers[idx].cert_obj) {
1540 struct sc_pkcs15_cert *cert = NULL;
1541 struct sc_pkcs15_object *cert_obj = vs->p15_containers[idx].cert_obj;
1542 struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *)cert_obj->data;
1543
1544 rv = sc_pkcs15_read_certificate(vs->p15card, cert_info, &cert);
1545 if(rv) {
1546 logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", idx, rv);
1547 logprintf(pCardData, 2, "set cardcf from 'DATA' pkcs#15 object\n");
1548 return md_translate_OpenSC_to_Windows_error(rv,
1549 SCARD_F_INTERNAL_ERROR);
1550 }
1551
1552 file->blob = pCardData->pfnCspAlloc(cert->data.len);
1553 if (file->blob) {
1554 CopyMemory(file->blob, cert->data.value, cert->data.len);
1555 file->size = cert->data.len;
1556 dwret = SCARD_S_SUCCESS;
1557 } else
1558 dwret = SCARD_E_NO_MEMORY;
1559
1560 sc_pkcs15_free_certificate(cert);
1561
1562 return dwret;
1563 } else if (!strcmp((char *)file->name, "msroots"))
1564 return md_fs_read_msroots_file(pCardData, file);
1565 }
1566
1567 return SCARD_E_FILE_NOT_FOUND;
1568 }
1569
1570 /*
1571 * Set content of 'cardcf',
1572 * for that look for the possible source in the following order:
1573 * - data from the dedicated PKCS#15 'DATA' object;
1574 * - 'lastUpdate' attribute of tokenInfo;
1575 * - random data.
1576 */
1577 static DWORD
md_set_cardcf(PCARD_DATA pCardData,struct md_file * file)1578 md_set_cardcf(PCARD_DATA pCardData, struct md_file *file)
1579 {
1580 CARD_CACHE_FILE_FORMAT empty = {0};
1581 DWORD dwret;
1582
1583 if (!pCardData || !file)
1584 return SCARD_E_INVALID_PARAMETER;
1585
1586 dwret = md_fs_set_content(pCardData, file, (unsigned char *)(&empty), MD_CARDCF_LENGTH);
1587 if (dwret != SCARD_S_SUCCESS)
1588 return dwret;
1589
1590 logprintf(pCardData, 3, "'cardcf' content(%"SC_FORMAT_LEN_SIZE_T"u)\n",
1591 file->size);
1592 loghex(pCardData, 3, file->blob, file->size);
1593 return SCARD_S_SUCCESS;
1594 }
1595
1596 static DWORD
md_set_cardapps(PCARD_DATA pCardData,struct md_file * file)1597 md_set_cardapps(PCARD_DATA pCardData, struct md_file *file)
1598 {
1599 DWORD dwret;
1600 unsigned char mscp[8] = {'m','s','c','p',0,0,0,0};
1601
1602 if (!pCardData || !file)
1603 return SCARD_E_INVALID_PARAMETER;
1604
1605 dwret = md_fs_set_content(pCardData, file, mscp, sizeof(mscp));
1606 if (dwret != SCARD_S_SUCCESS)
1607 return dwret;
1608
1609 logprintf(pCardData, 3, "mscp(%"SC_FORMAT_LEN_SIZE_T"u)\n", file->size);
1610 loghex(pCardData, 3, file->blob, file->size);
1611 return SCARD_S_SUCCESS;
1612 }
1613
1614 /* check if the card has root certificates. If yes, notify the base csp by creating the msroots file */
1615 static DWORD
md_fs_add_msroots(PCARD_DATA pCardData,struct md_file ** head)1616 md_fs_add_msroots(PCARD_DATA pCardData, struct md_file **head)
1617 {
1618 VENDOR_SPECIFIC *vs;
1619 int rv, ii, cert_num;
1620 DWORD dwret;
1621 struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
1622 if (!pCardData || !head)
1623 return SCARD_E_INVALID_PARAMETER;
1624
1625 vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific;
1626 if (!vs)
1627 return SCARD_E_INVALID_PARAMETER;
1628
1629 rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS);
1630 if (rv < 0) {
1631 logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv));
1632 return SCARD_S_SUCCESS;
1633 }
1634 cert_num = rv;
1635 for(ii = 0; ii < cert_num; ii++) {
1636 struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data;
1637 if (cert_info->authority) {
1638 dwret = md_fs_add_file(pCardData, head, "msroots", EveryoneReadUserWriteAc, NULL, 0, NULL);
1639 if (dwret != SCARD_S_SUCCESS)
1640 return dwret;
1641 return SCARD_S_SUCCESS;
1642 }
1643 }
1644 return SCARD_S_SUCCESS;
1645 }
1646
1647 /*
1648 * Set the content of the 'soft' 'cmapfile':
1649 * 1. Initialize internal p15_contaniers with the existing private keys PKCS#15 objects;
1650 * 2. Try to read the content of the PKCS#15 'DATA' object 'CSP':'cmapfile',
1651 * If some record from the 'DATA' object references an existing key:
1652 * 2a. Update the non-pkcs#15 attributes of the corresponding internal p15_container;
1653 * 2b. Change the index of internal p15_container according to the index from 'DATA' file.
1654 * Records from 'DATA' file are ignored is they do not have
1655 * the corresponding PKCS#15 private key object.
1656 * 3. Initialize the content of the 'soft' 'cmapfile' from the internal p15-containers.
1657 */
1658 static DWORD
md_set_cmapfile(PCARD_DATA pCardData,struct md_file * file)1659 md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file)
1660 {
1661 typedef enum { SCF_NONE,
1662 SCF_NONDEFAULT_SIGN_PIN,
1663 SCF_NONDEFAULT_OTHER_PIN,
1664 SCF_NONDEFAULT_USER_PIN,
1665 SCF_DEFAULT_SIGN_PIN,
1666 SCF_DEFAULT_OTHER_PIN,
1667 SCF_DEFAULT_USER_PIN
1668 } pin_mode_t;
1669 VENDOR_SPECIFIC *vs;
1670 PCONTAINER_MAP_RECORD p;
1671 unsigned char *cmap_buf = NULL;
1672 size_t cmap_len;
1673 DWORD dwret;
1674 int ii, rv, conts_num, found_default = 0;
1675 /* struct sc_pkcs15_data *data_object; */
1676 struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS];
1677 pin_mode_t pin_mode = SCF_NONE;
1678 int pin_cont_idx = -1;
1679
1680 if (!pCardData || !file)
1681 return SCARD_E_INVALID_PARAMETER;
1682
1683 logprintf(pCardData, 2, "set 'cmapfile'\n");
1684 vs = pCardData->pvVendorSpecific;
1685 if (!vs)
1686 return SCARD_E_INVALID_PARAMETER;
1687
1688 dwret = md_get_pin_by_role(pCardData, ROLE_USER, &vs->pin_objs[ROLE_USER]);
1689 if (dwret != SCARD_S_SUCCESS) {
1690 logprintf(pCardData, 2, "Cannot get User PIN object\n");
1691 return dwret;
1692 }
1693
1694 dwret = md_get_pin_by_role(pCardData, MD_ROLE_USER_SIGN, &vs->pin_objs[MD_ROLE_USER_SIGN]);
1695 if (dwret != SCARD_S_SUCCESS) {
1696 logprintf(pCardData, 2, "Cannot get Sign PIN object -- ignored\n");
1697 vs->pin_objs[MD_ROLE_USER_SIGN] = NULL;
1698 }
1699
1700 dwret = md_get_pin_by_role(pCardData, ROLE_ADMIN, &vs->pin_objs[ROLE_ADMIN]);
1701 if (dwret != SCARD_S_SUCCESS) {
1702 logprintf(pCardData, 2, "Cannot get Admin PIN object -- ignored\n");
1703 vs->pin_objs[ROLE_ADMIN] = NULL;
1704 }
1705
1706 cmap_len = MD_MAX_KEY_CONTAINERS*sizeof(CONTAINER_MAP_RECORD);
1707 cmap_buf = pCardData->pfnCspAlloc(cmap_len);
1708 if(!cmap_buf)
1709 return SCARD_E_NO_MEMORY;
1710 memset(cmap_buf, 0, cmap_len);
1711
1712 rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_PRKEY, prkey_objs, MD_MAX_KEY_CONTAINERS);
1713 if (rv < 0) {
1714 logprintf(pCardData, 0, "Private key enumeration failed: %s\n", sc_strerror(rv));
1715 return SCARD_F_UNKNOWN_ERROR;
1716 }
1717
1718 conts_num = rv;
1719 logprintf(pCardData, 2, "Found %d private key(s) in the card.\n", conts_num);
1720
1721 /* Initialize the P15 container array with the existing keys */
1722 for(ii = 0; ii < conts_num; ii++) {
1723 struct sc_pkcs15_object *key_obj = prkey_objs[ii];
1724 struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
1725 struct md_pkcs15_container *cont = &vs->p15_containers[ii];
1726
1727 if(key_obj->type != SC_PKCS15_TYPE_PRKEY_RSA && key_obj->type != SC_PKCS15_TYPE_PRKEY_EC) {
1728 logprintf(pCardData, 7, "Non 'RSA' 'EC' key (type:%X) are ignored\n", key_obj->type);
1729 continue;
1730 }
1731
1732 dwret = md_contguid_build_cont_guid_from_key(pCardData, key_obj, cont->guid);
1733 if (dwret != SCARD_S_SUCCESS)
1734 return dwret;
1735
1736 /* replace the OpenSC guid by a Windows Guid if needed
1737 Typically used in the certificate enrollment process.
1738 Windows create a new container with a Windows guid, close the context, then create a new context and look for the previous container.
1739 If we return our guid, it fails because the Windows guid can't be found.
1740 The overwrite is present to avoid this conversion been replaced by md_pkcs15_update_container_from_do*/
1741 // cont->guid_overwrite = md_contguid_find_conversion(pCardData, cont->guid);
1742
1743 // cont->flags = CONTAINER_MAP_VALID_CONTAINER;
1744 dwret = md_cont_flags_from_key(pCardData, key_obj, &cont->flags);
1745 if (dwret != SCARD_S_SUCCESS)
1746 return dwret;
1747
1748 logprintf(pCardData, 7, "Container[%i] is '%.*s' guid=%.*s\n", ii,
1749 (int) sizeof key_obj->label, key_obj->label,
1750 (int) sizeof cont->guid, cont->guid);
1751
1752 if (cont->flags & CONTAINER_MAP_VALID_CONTAINER &&
1753 key_obj->auth_id.len > 0) {
1754 struct sc_pkcs15_object *keypin_obj;
1755 struct sc_pkcs15_auth_info *userpin_info =
1756 (struct sc_pkcs15_auth_info *)vs->pin_objs[ROLE_USER]->data;
1757 struct sc_pkcs15_auth_info *signpin_info =
1758 vs->pin_objs[MD_ROLE_USER_SIGN] ?
1759 (struct sc_pkcs15_auth_info *)vs->pin_objs[MD_ROLE_USER_SIGN]->data :
1760 NULL;
1761 struct sc_pkcs15_auth_info *adminpin_info =
1762 vs->pin_objs[ROLE_ADMIN] ?
1763 (struct sc_pkcs15_auth_info *)vs->pin_objs[ROLE_ADMIN]->data :
1764 NULL;
1765
1766 if (sc_pkcs15_find_pin_by_auth_id(vs->p15card, &key_obj->auth_id, &keypin_obj))
1767 logprintf(pCardData, 2,
1768 "Container[%i] has an unknown auth id, might not work properly\n",
1769 ii);
1770 else {
1771 size_t pinidx;
1772 size_t pinidxempty = MD_MAX_PINS;
1773 for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) {
1774 struct sc_pkcs15_auth_info *pin_info;
1775
1776 if (!vs->pin_objs[pinidx]) {
1777 if (pinidxempty >= MD_MAX_PINS)
1778 pinidxempty = pinidx;
1779
1780 continue;
1781 }
1782
1783 pin_info =
1784 (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data;
1785
1786 if (sc_pkcs15_compare_id(&key_obj->auth_id,
1787 &pin_info->auth_id))
1788 break;
1789 }
1790
1791 if (pinidx >= MD_MAX_PINS) {
1792 if (pinidxempty >= MD_MAX_PINS)
1793 logprintf(pCardData, 2,
1794 "no free slot for container[%i] auth id, might not work properly\n",
1795 ii);
1796 else
1797 vs->pin_objs[pinidxempty] = keypin_obj;
1798 }
1799
1800 if (sc_pkcs15_compare_id(&key_obj->auth_id, &userpin_info->auth_id)) {
1801 pin_mode_t pin_mode_n =
1802 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1803 SCF_DEFAULT_USER_PIN : SCF_NONDEFAULT_USER_PIN;
1804
1805 logprintf(pCardData, 7,
1806 "Container[%i]%s is secured by User PIN\n",
1807 ii,
1808 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1809 " (default)" : "");
1810
1811 if (pin_mode < pin_mode_n) {
1812 pin_mode = pin_mode_n;
1813 pin_cont_idx = ii;
1814 }
1815 } else if (signpin_info != NULL &&
1816 sc_pkcs15_compare_id(&key_obj->auth_id, &signpin_info->auth_id)) {
1817 pin_mode_t pin_mode_n =
1818 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1819 SCF_DEFAULT_SIGN_PIN : SCF_NONDEFAULT_SIGN_PIN;
1820
1821 logprintf(pCardData, 7,
1822 "Container[%i]%s is secured by Sign PIN\n",
1823 ii,
1824 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1825 " (default)" : "");
1826
1827 if (pin_mode < pin_mode_n) {
1828 pin_mode = pin_mode_n;
1829 pin_cont_idx = ii;
1830 }
1831 } else if (adminpin_info != NULL &&
1832 sc_pkcs15_compare_id(&key_obj->auth_id, &adminpin_info->auth_id)) {
1833 logprintf(pCardData, 2,
1834 "Container[%i] is secured by Admin PIN, might not work properly\n",
1835 ii);
1836 } else {
1837 pin_mode_t pin_mode_n =
1838 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1839 SCF_DEFAULT_OTHER_PIN : SCF_NONDEFAULT_OTHER_PIN;
1840
1841 logprintf(pCardData, 7,
1842 "Container[%i]%s is secured by other PIN\n",
1843 ii,
1844 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ?
1845 " (default)" : "");
1846
1847 if (pin_mode < pin_mode_n) {
1848 pin_mode = pin_mode_n;
1849 pin_cont_idx = ii;
1850 }
1851 }
1852 }
1853 }
1854
1855 if (cont->flags & CONTAINER_MAP_VALID_CONTAINER &&
1856 cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER)
1857 found_default = 1;
1858
1859 /* AT_KEYEXCHANGE is more general key usage,
1860 * it allows 'decryption' as well as 'signature' key usage.
1861 * AT_SIGNATURE allows only 'signature' usage.
1862 */
1863 cont->size_key_exchange = cont->size_sign = 0;
1864 if (key_obj->type == SC_PKCS15_TYPE_PRKEY_RSA) {
1865 if (prkey_info->usage & USAGE_ANY_DECIPHER)
1866 cont->size_key_exchange = prkey_info->modulus_length;
1867 else if (prkey_info->usage & USAGE_ANY_SIGN)
1868 cont->size_sign = prkey_info->modulus_length;
1869 else
1870 cont->size_key_exchange = prkey_info->modulus_length;
1871 } else if (key_obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
1872 if (prkey_info->usage & USAGE_ANY_AGREEMENT)
1873 cont->size_key_exchange = prkey_info->field_length;
1874 else if (prkey_info->usage & USAGE_ANY_SIGN)
1875 cont->size_sign = prkey_info->field_length;
1876 else
1877 cont->size_key_exchange = prkey_info->field_length;
1878 }
1879
1880 logprintf(pCardData, 7,
1881 "Container[%i]'s key-exchange:%"SC_FORMAT_LEN_SIZE_T"u, sign:%"SC_FORMAT_LEN_SIZE_T"u\n",
1882 ii, cont->size_key_exchange, cont->size_sign);
1883
1884 cont->id = prkey_info->id;
1885 cont->prkey_obj = prkey_objs[ii];
1886
1887 /* Try to find the friend objects: certificate and public key */
1888 if (!sc_pkcs15_find_cert_by_id(vs->p15card, &cont->id, &cont->cert_obj))
1889 logprintf(pCardData, 2, "found certificate friend '%.*s'\n", (int) sizeof cont->cert_obj->label, cont->cert_obj->label);
1890
1891 if (!sc_pkcs15_find_pubkey_by_id(vs->p15card, &cont->id, &cont->pubkey_obj))
1892 logprintf(pCardData, 2, "found public key friend '%.*s'\n", (int) sizeof cont->pubkey_obj->label, cont->pubkey_obj->label);
1893 }
1894
1895 if (conts_num) {
1896 /* Read 'CMAPFILE' (Gemalto style) and update the attributes of P15 containers */
1897 #if 0
1898 struct sc_pkcs15_object *dobjs[MD_MAX_KEY_CONTAINERS + 1], *default_cont = NULL;
1899 int num_dobjs = MD_MAX_KEY_CONTAINERS + 1;
1900
1901 rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, num_dobjs);
1902 if (rv < 0) {
1903 logprintf(pCardData, 0, "'DATA' object enumeration failed: %s\n", sc_strerror(rv));
1904 return SCARD_F_UNKNOWN_ERROR;
1905 }
1906
1907 num_dobjs = rv;
1908 logprintf(pCardData, 2, "Found %d 'DATA' objects.\n", num_dobjs);
1909
1910 for (ii=0;ii<num_dobjs;ii++) {
1911 struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
1912
1913 if (strcmp(dinfo->app_label, "CSP"))
1914 continue;
1915
1916 logprintf(pCardData, 2, "Found 'DATA' object '%.*s'\n", (int) sizeof dobjs[ii]->label, dobjs[ii]->label);
1917 if (!strncmp(dobjs[ii]->label, "Default Key Container", sizeof dobjs[ii]->label)) {
1918 default_cont = dobjs[ii];
1919 continue;
1920 }
1921
1922 dwret = md_pkcs15_update_container_from_do(pCardData, dobjs[ii]);
1923 if (dwret != SCARD_S_SUCCESS) {
1924 logprintf(pCardData, 2, "Cannot update container from DO: %li", dwret);
1925 return dwret;
1926 }
1927 }
1928
1929 if (default_cont) {
1930 dwret = md_pkcs15_default_container_from_do(pCardData, default_cont);
1931 if (dwret != SCARD_S_SUCCESS) {
1932 logprintf(pCardData, 2, "Cannot set default container from DO: %li", dwret);
1933 return dwret;
1934 }
1935 }
1936 #endif
1937
1938 /* if no default container was found promote the best one (PIN-wise) to default */
1939 if (!found_default && (pin_mode == SCF_NONDEFAULT_SIGN_PIN ||
1940 pin_mode == SCF_NONDEFAULT_OTHER_PIN ||
1941 pin_mode == SCF_NONDEFAULT_USER_PIN)) {
1942 struct md_pkcs15_container *cont =
1943 &vs->p15_containers[pin_cont_idx];
1944 cont->flags |= CONTAINER_MAP_DEFAULT_CONTAINER;
1945
1946 found_default = 1;
1947
1948 logprintf(pCardData, 7,
1949 "Container[%i] promoted to default\n",
1950 pin_cont_idx);
1951
1952 if (pin_mode == SCF_NONDEFAULT_SIGN_PIN)
1953 pin_mode = SCF_DEFAULT_SIGN_PIN;
1954 else if (pin_mode == SCF_NONDEFAULT_OTHER_PIN)
1955 pin_mode = SCF_DEFAULT_OTHER_PIN;
1956 else
1957 pin_mode = SCF_DEFAULT_USER_PIN;
1958 }
1959
1960 /* if all containers use non-user PINs we need to make the best container PIN the user (primary) one */
1961 if (pin_mode == SCF_NONDEFAULT_SIGN_PIN ||
1962 pin_mode == SCF_DEFAULT_SIGN_PIN ||
1963 pin_mode == SCF_NONDEFAULT_OTHER_PIN ||
1964 pin_mode == SCF_DEFAULT_OTHER_PIN) {
1965 struct sc_pkcs15_object *user_pin_old =
1966 vs->pin_objs[ROLE_USER];
1967 struct sc_pkcs15_object *user_pin_new =
1968 NULL;
1969
1970 if (pin_mode == SCF_NONDEFAULT_SIGN_PIN ||
1971 pin_mode == SCF_DEFAULT_SIGN_PIN) {
1972 user_pin_new = vs->pin_objs[MD_ROLE_USER_SIGN];
1973 vs->pin_objs[MD_ROLE_USER_SIGN] = NULL;
1974
1975 logprintf(pCardData, 7,
1976 "Sign PIN%s promoted to user one\n",
1977 pin_mode == SCF_DEFAULT_SIGN_PIN ?
1978 " (from default container)" : "");
1979 } else {
1980 struct sc_pkcs15_object *key_obj =
1981 vs->p15_containers[pin_cont_idx].prkey_obj;
1982 struct sc_pkcs15_object *keypin_obj;
1983
1984 if (sc_pkcs15_find_pin_by_auth_id(vs->p15card, &key_obj->auth_id, &keypin_obj))
1985 logprintf(pCardData, 2,
1986 "Cannot find container[%i] auth id again, might not work properly\n",
1987 pin_cont_idx);
1988 else {
1989 size_t pinidx;
1990
1991 logprintf(pCardData, 7,
1992 "Container[%i]%s PIN will be made the user one\n",
1993 pin_cont_idx,
1994 pin_mode == SCF_DEFAULT_OTHER_PIN ?
1995 " (default)" : "");
1996
1997 for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) {
1998 struct sc_pkcs15_auth_info *pin_info;
1999
2000 if (!vs->pin_objs[pinidx])
2001 continue;
2002
2003 pin_info =
2004 (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data;
2005
2006 if (sc_pkcs15_compare_id(&key_obj->auth_id,
2007 &pin_info->auth_id)) {
2008 vs->pin_objs[pinidx] = NULL;
2009 break;
2010 }
2011 }
2012
2013 user_pin_new = keypin_obj;
2014 }
2015 }
2016
2017 if (user_pin_new) {
2018 size_t pinidx;
2019
2020 vs->pin_objs[ROLE_USER] = user_pin_new;
2021
2022 for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) {
2023 if (vs->pin_objs[pinidx])
2024 continue;
2025
2026 vs->pin_objs[pinidx] = user_pin_old;
2027 break;
2028 }
2029
2030 if (pinidx >= MD_MAX_PINS) {
2031 logprintf(pCardData, 2,
2032 "no free slot for previous User PIN, replacing last one\n");
2033
2034 vs->pin_objs[MD_MAX_PINS - 1] = user_pin_old;
2035 }
2036 }
2037 }
2038
2039 /* Initialize 'CMAPFILE' content from the P15 containers */
2040 p = (PCONTAINER_MAP_RECORD)cmap_buf;
2041 for (ii=0; ii<MD_MAX_KEY_CONTAINERS; ii++) {
2042 if (!(vs->p15_containers[ii].flags & CONTAINER_MAP_VALID_CONTAINER))
2043 continue;
2044
2045 if (!found_default) {
2046 vs->p15_containers[ii].flags |= CONTAINER_MAP_DEFAULT_CONTAINER;
2047 found_default = 1;
2048 }
2049
2050 mbstowcs((p+ii)->wszGuid, vs->p15_containers[ii].guid, MAX_CONTAINER_NAME_LEN + 1);
2051 (p+ii)->bFlags = vs->p15_containers[ii].flags;
2052 (p+ii)->wSigKeySizeBits = (WORD) vs->p15_containers[ii].size_sign;
2053 (p+ii)->wKeyExchangeKeySizeBits = (WORD) vs->p15_containers[ii].size_key_exchange;
2054
2055 if (vs->p15_containers[ii].cert_obj) {
2056 char k_name[6];
2057
2058 if (vs->p15_containers[ii].size_key_exchange) {
2059 snprintf(k_name, sizeof(k_name), "kxc%02i", ii);
2060 k_name[sizeof(k_name) - 1] = 0;
2061 dwret = md_fs_add_file(pCardData, &(file->next), k_name, file->acl, NULL, 0, NULL);
2062 if (dwret != SCARD_S_SUCCESS)
2063 return dwret;
2064 }
2065
2066 if (vs->p15_containers[ii].size_sign) {
2067 snprintf(k_name, sizeof(k_name), "ksc%02i", ii);
2068 k_name[sizeof(k_name) - 1] = 0;
2069 dwret = md_fs_add_file(pCardData, &(file->next), k_name, file->acl, NULL, 0, NULL);
2070 if (dwret != SCARD_S_SUCCESS)
2071 return dwret;
2072 }
2073 }
2074
2075 logprintf(pCardData, 7, "cmapfile entry(%d) '%s' ",ii, vs->p15_containers[ii].guid);
2076 loghex(pCardData, 7, (PBYTE) (p+ii), sizeof(CONTAINER_MAP_RECORD));
2077 }
2078 }
2079
2080 dwret = md_fs_add_msroots(pCardData, &(file->next));
2081 if (dwret != SCARD_S_SUCCESS)
2082 return dwret;
2083
2084 dwret = md_fs_set_content(pCardData, file, cmap_buf, cmap_len);
2085 pCardData->pfnCspFree(cmap_buf);
2086 if (dwret != SCARD_S_SUCCESS)
2087 return dwret;
2088
2089 logprintf(pCardData, 3, "cmap(%"SC_FORMAT_LEN_SIZE_T"u)\n", file->size);
2090 loghex(pCardData, 3, file->blob, file->size);
2091 return SCARD_S_SUCCESS;
2092 }
2093
2094 /*
2095 * Initialize internal 'soft' file system
2096 */
2097 static DWORD
md_fs_init(PCARD_DATA pCardData)2098 md_fs_init(PCARD_DATA pCardData)
2099 {
2100 VENDOR_SPECIFIC *vs;
2101 DWORD dwret;
2102 struct md_file *cardid, *cardcf, *cardapps, *cmapfile;
2103 struct md_directory *mscp;
2104
2105 if (!pCardData || !pCardData->pvVendorSpecific)
2106 return SCARD_E_INVALID_PARAMETER;
2107
2108 vs = pCardData->pvVendorSpecific;
2109
2110 dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardid", EveryoneReadAdminWriteAc, NULL, 0, &cardid);
2111 if (dwret != SCARD_S_SUCCESS)
2112 return dwret;
2113 dwret = md_set_cardid(pCardData, cardid);
2114 if (dwret != SCARD_S_SUCCESS)
2115 goto ret_cleanup;
2116
2117 dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardcf", EveryoneReadUserWriteAc, NULL, 0, &cardcf);
2118 if (dwret != SCARD_S_SUCCESS)
2119 goto ret_cleanup;
2120 dwret = md_set_cardcf(pCardData, cardcf);
2121 if (dwret != SCARD_S_SUCCESS)
2122 goto ret_cleanup;
2123
2124 dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardapps", EveryoneReadAdminWriteAc, NULL, 0, &cardapps);
2125 if (dwret != SCARD_S_SUCCESS)
2126 goto ret_cleanup;
2127 dwret = md_set_cardapps(pCardData, cardapps);
2128 if (dwret != SCARD_S_SUCCESS)
2129 goto ret_cleanup;
2130
2131 dwret = md_fs_add_directory(pCardData, &(vs->root.subdirs), "mscp", UserCreateDeleteDirAc, &mscp);
2132 if (dwret != SCARD_S_SUCCESS)
2133 goto ret_cleanup;
2134
2135 dwret = md_fs_add_file(pCardData, &(mscp->files), "cmapfile", EveryoneReadUserWriteAc, NULL, 0, &cmapfile);
2136 if (dwret != SCARD_S_SUCCESS)
2137 goto ret_cleanup;
2138 dwret = md_set_cmapfile(pCardData, cmapfile);
2139 if (dwret != SCARD_S_SUCCESS)
2140 goto ret_cleanup;
2141
2142 #ifdef OPENSSL_VERSION_NUMBER
2143 logprintf(pCardData, 3,
2144 "MD virtual file system initialized; OPENSSL_VERSION_NUMBER 0x%lX\n",
2145 OPENSSL_VERSION_NUMBER);
2146 #else
2147 logprintf(pCardData, 3,
2148 "MD virtual file system initialized; Without OPENSSL\n");
2149 #endif
2150 return SCARD_S_SUCCESS;
2151
2152 ret_cleanup:
2153 md_fs_finalize(pCardData);
2154 return dwret;
2155 }
2156
2157 /* Create SC context */
2158 static DWORD
md_create_context(PCARD_DATA pCardData,VENDOR_SPECIFIC * vs)2159 md_create_context(PCARD_DATA pCardData, VENDOR_SPECIFIC *vs)
2160 {
2161 sc_context_param_t ctx_param;
2162 int r;
2163
2164 if (!pCardData)
2165 return SCARD_E_INVALID_PARAMETER;
2166
2167 logprintf(pCardData, 3, "create sc ccontext\n");
2168 vs->ctx = NULL;
2169
2170 memset(&ctx_param, 0, sizeof(ctx_param));
2171 ctx_param.ver = 1;
2172 ctx_param.app_name = "cardmod";
2173
2174 r = sc_context_create(&(vs->ctx), &ctx_param);
2175 if (r) {
2176 logprintf(pCardData, 0, "Failed to establish context: %s\n", sc_strerror(r));
2177 return SCARD_F_UNKNOWN_ERROR;
2178 }
2179
2180 logprintf(pCardData, 3, "sc context created\n");
2181 return SCARD_S_SUCCESS;
2182 }
2183
2184 static DWORD
md_card_capabilities(PCARD_DATA pCardData,PCARD_CAPABILITIES pCardCapabilities)2185 md_card_capabilities(PCARD_DATA pCardData, PCARD_CAPABILITIES pCardCapabilities)
2186 {
2187 if (!pCardCapabilities)
2188 return SCARD_E_INVALID_PARAMETER;
2189
2190 if (pCardCapabilities->dwVersion != CARD_CAPABILITIES_CURRENT_VERSION && pCardCapabilities->dwVersion != 0)
2191 return ERROR_REVISION_MISMATCH;
2192
2193 pCardCapabilities->dwVersion = CARD_CAPABILITIES_CURRENT_VERSION;
2194 pCardCapabilities->fCertificateCompression = TRUE;
2195 /* a read only card cannot generate new keys */
2196 pCardCapabilities->fKeyGen = ! md_is_read_only(pCardData);
2197
2198 return SCARD_S_SUCCESS;
2199 }
2200
2201 static DWORD
md_free_space(PCARD_DATA pCardData,PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)2202 md_free_space(PCARD_DATA pCardData, PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
2203 {
2204 VENDOR_SPECIFIC *vs;
2205 int count, idx;
2206
2207 if (!pCardData || !pCardFreeSpaceInfo)
2208 return SCARD_E_INVALID_PARAMETER;
2209
2210 if (pCardFreeSpaceInfo->dwVersion > CARD_FREE_SPACE_INFO_CURRENT_VERSION )
2211 return ERROR_REVISION_MISMATCH;
2212
2213 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2214 if (!vs)
2215 return SCARD_E_INVALID_PARAMETER;
2216
2217 /* Count free containers */
2218 for (idx=0, count=0; idx<MD_MAX_KEY_CONTAINERS; idx++)
2219 if (!vs->p15_containers[idx].prkey_obj)
2220 count++;
2221
2222 pCardFreeSpaceInfo->dwVersion = CARD_FREE_SPACE_INFO_CURRENT_VERSION;
2223 pCardFreeSpaceInfo->dwBytesAvailable = CARD_DATA_VALUE_UNKNOWN;
2224 pCardFreeSpaceInfo->dwKeyContainersAvailable = count;
2225 pCardFreeSpaceInfo->dwMaxKeyContainers = MD_MAX_KEY_CONTAINERS;
2226
2227 return SCARD_S_SUCCESS;
2228 }
2229
2230 /* Check the new key to be created for the compatibility with card:
2231 * - for the key to be generated the card needs to support the mechanism and size;
2232 * - for the key to be imported checked also the validity of supplied key blob.
2233 */
2234 static DWORD
md_check_key_compatibility(PCARD_DATA pCardData,DWORD flags,DWORD key_type,DWORD key_size,BYTE * pbKeyData)2235 md_check_key_compatibility(PCARD_DATA pCardData, DWORD flags, DWORD key_type,
2236 DWORD key_size, BYTE *pbKeyData)
2237 {
2238 VENDOR_SPECIFIC *vs;
2239 struct sc_algorithm_info *algo_info;
2240 unsigned int count, key_algo;
2241
2242 if (!pCardData)
2243 return SCARD_E_INVALID_PARAMETER;
2244
2245 switch(key_type) {
2246 case AT_SIGNATURE:
2247 case AT_KEYEXCHANGE:
2248 key_algo = SC_ALGORITHM_RSA;
2249 break;
2250 case AT_ECDHE_P256 :
2251 case AT_ECDHE_P384 :
2252 case AT_ECDHE_P521 :
2253 case AT_ECDSA_P256 :
2254 case AT_ECDSA_P384 :
2255 case AT_ECDSA_P521 :
2256 key_algo = SC_ALGORITHM_EC;
2257 break;
2258 default:
2259 logprintf(pCardData, 3, "Unsupported key type: 0x%lX\n",
2260 (unsigned long)key_type);
2261 return SCARD_E_UNSUPPORTED_FEATURE;
2262 }
2263
2264 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2265 if (!vs)
2266 return SCARD_E_INVALID_PARAMETER;
2267
2268 if (flags & CARD_CREATE_CONTAINER_KEY_IMPORT) {
2269 if (key_algo == SC_ALGORITHM_RSA) {
2270 PUBLICKEYSTRUC *pub_struc = (PUBLICKEYSTRUC *)pbKeyData;
2271 RSAPUBKEY *pub_rsa = (RSAPUBKEY *)(pbKeyData + sizeof(PUBLICKEYSTRUC));
2272
2273 if (!pub_struc) {
2274 logprintf(pCardData, 3, "No data for the key import operation\n");
2275 return SCARD_E_INVALID_PARAMETER;
2276 }
2277 else if (pub_struc->bType != PRIVATEKEYBLOB) {
2278 logprintf(pCardData, 3, "Invalid blob data for the key import operation\n");
2279 return SCARD_E_INVALID_PARAMETER;
2280 }
2281 else if ((key_type == AT_KEYEXCHANGE) && (pub_struc->aiKeyAlg != CALG_RSA_KEYX)) {
2282 logprintf(pCardData, 3, "Expected KEYEXCHANGE type of blob\n");
2283 return SCARD_E_INVALID_PARAMETER;
2284 }
2285 else if ((key_type == AT_SIGNATURE) && (pub_struc->aiKeyAlg != CALG_RSA_SIGN)) {
2286 logprintf(pCardData, 3, "Expected KEYSIGN type of blob\n");
2287 return SCARD_E_INVALID_PARAMETER;
2288 }
2289
2290 if (pub_rsa->magic == BCRYPT_RSAPUBLIC_MAGIC || pub_rsa->magic == BCRYPT_RSAPRIVATE_MAGIC) {
2291 key_size = pub_rsa->bitlen;
2292 }
2293 else {
2294 logprintf(pCardData, 3, "'Magic' control failed\n");
2295 return SCARD_E_INVALID_PARAMETER;
2296 }
2297
2298 logprintf(pCardData, 3, "Set key size to %lu\n",
2299 (unsigned long)key_size);
2300 } else if (key_algo == SC_ALGORITHM_EC) {
2301 BCRYPT_ECCKEY_BLOB *pub_ecc = (BCRYPT_ECCKEY_BLOB *)pbKeyData;
2302 switch(key_type) {
2303 case AT_ECDSA_P256:
2304 if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P256_MAGIC) {
2305 logprintf(pCardData, 3, "Expected AT_ECDSA_P256 magic\n");
2306 return SCARD_E_INVALID_PARAMETER;
2307 }
2308 key_size = 256;
2309 break;
2310 case AT_ECDSA_P384:
2311 if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P384_MAGIC) {
2312 logprintf(pCardData, 3, "Expected AT_ECDSA_P384 magic\n");
2313 return SCARD_E_INVALID_PARAMETER;
2314 }
2315 key_size = 384;
2316 break;
2317 case AT_ECDSA_P521:
2318 if (pub_ecc->dwMagic != BCRYPT_ECDSA_PRIVATE_P521_MAGIC) {
2319 logprintf(pCardData, 3, "Expected AT_ECDSA_P521 magic\n");
2320 return SCARD_E_INVALID_PARAMETER;
2321 }
2322 key_size = 521;
2323 break;
2324 case AT_ECDHE_P256:
2325 if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P256_MAGIC) {
2326 logprintf(pCardData, 3, "Expected AT_ECDHE_P256 magic\n");
2327 return SCARD_E_INVALID_PARAMETER;
2328 }
2329 key_size = 256;
2330 break;
2331 case AT_ECDHE_P384:
2332 if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P384_MAGIC) {
2333 logprintf(pCardData, 3, "Expected AT_ECDHE_P384 magic\n");
2334 return SCARD_E_INVALID_PARAMETER;
2335 }
2336 key_size = 384;
2337 break;
2338 case AT_ECDHE_P521:
2339 if (pub_ecc->dwMagic != BCRYPT_ECDH_PRIVATE_P521_MAGIC) {
2340 logprintf(pCardData, 3, "Expected AT_ECDHE_P521 magic\n");
2341 return SCARD_E_INVALID_PARAMETER;
2342 }
2343 key_size = 521;
2344 break;
2345 }
2346 }
2347 logprintf(pCardData, 3, "Set key size to %lu\n",
2348 (unsigned long)key_size);
2349 }
2350
2351 count = vs->p15card->card->algorithm_count;
2352 for (algo_info = vs->p15card->card->algorithms; count--; algo_info++) {
2353 if (algo_info->algorithm != key_algo || algo_info->key_length != key_size)
2354 continue;
2355 logprintf(pCardData, 3, "Key compatible with the card capabilities\n");
2356 return SCARD_S_SUCCESS;
2357 }
2358
2359 logprintf(pCardData, 3,
2360 "No card support for key(type:0x%lX,size:0x%lX)\n",
2361 (unsigned long)key_type, (unsigned long)key_size);
2362 return SCARD_E_UNSUPPORTED_FEATURE;
2363 }
2364
2365
2366 static DWORD
md_pkcs15_generate_key(PCARD_DATA pCardData,DWORD idx,DWORD key_type,DWORD key_size,PIN_ID PinId)2367 md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD key_size, PIN_ID PinId)
2368 {
2369 VENDOR_SPECIFIC *vs;
2370 struct sc_card *card = NULL;
2371 struct sc_profile *profile = NULL;
2372 struct sc_pkcs15_object *pin_obj = NULL;
2373 struct sc_pkcs15_auth_info *auth_info = NULL;
2374 struct sc_app_info *app_info = NULL;
2375 struct sc_pkcs15init_keygen_args keygen_args;
2376 struct sc_pkcs15init_pubkeyargs pub_args;
2377 struct md_pkcs15_container *cont = NULL;
2378 int rv;
2379 DWORD dwret = SCARD_F_INTERNAL_ERROR;
2380 CHAR szGuid[MAX_CONTAINER_NAME_LEN +1] = "Default key label";
2381
2382 if (!pCardData)
2383 return SCARD_E_INVALID_PARAMETER;
2384
2385 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2386 if (!vs)
2387 return SCARD_E_INVALID_PARAMETER;
2388
2389 if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId])
2390 return SCARD_E_INVALID_PARAMETER;
2391
2392 card = vs->p15card->card;
2393
2394 memset(&pub_args, 0, sizeof(pub_args));
2395 memset(&keygen_args, 0, sizeof(keygen_args));
2396 keygen_args.prkey_args.label = szGuid;
2397 keygen_args.pubkey_label = szGuid;
2398
2399 if (key_type == AT_SIGNATURE) {
2400 keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
2401 pub_args.key.algorithm = SC_ALGORITHM_RSA;
2402 keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
2403 }
2404 else if (key_type == AT_KEYEXCHANGE) {
2405 keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA;
2406 pub_args.key.algorithm = SC_ALGORITHM_RSA;
2407 keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
2408 }
2409 else if ((key_type == AT_ECDSA_P256) || (key_type == AT_ECDSA_P384) || (key_type == AT_ECDSA_P521)) {
2410 keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
2411 pub_args.key.algorithm = SC_ALGORITHM_EC;
2412 keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
2413 }
2414 else if ((key_type == AT_ECDHE_P256) || (key_type == AT_ECDHE_P384) || (key_type == AT_ECDHE_P521)) {
2415 keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_EC;
2416 pub_args.key.algorithm = SC_ALGORITHM_EC;
2417 keygen_args.prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE_ECC;
2418 }
2419 else {
2420 logprintf(pCardData, 3,
2421 "MdGenerateKey(): unsupported key type: 0x%lX\n",
2422 (unsigned long)key_type);
2423 return SCARD_E_UNSUPPORTED_FEATURE;
2424 }
2425 if (pub_args.key.algorithm == SC_ALGORITHM_EC) {
2426 keygen_args.prkey_args.key.u.ec.params.field_length = key_size;
2427 if ((key_type == AT_ECDSA_P256)|| (key_type == AT_ECDHE_P256)) {
2428 keygen_args.prkey_args.key.u.ec.params.named_curve = "secp256r1";
2429 keygen_args.prkey_args.key.u.ec.params.der.len = 10;
2430 keygen_args.prkey_args.key.u.ec.params.der.value = (unsigned char *)"\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07";
2431 } else if ((key_type == AT_ECDSA_P384)|| (key_type == AT_ECDHE_P384)) {
2432 keygen_args.prkey_args.key.u.ec.params.named_curve = "secp384r1";
2433 keygen_args.prkey_args.key.u.ec.params.der.len = 7;
2434 keygen_args.prkey_args.key.u.ec.params.der.value = (unsigned char *)"\x06\x05\x2B\x81\x04\x00\x22";
2435 } else if ((key_type == AT_ECDSA_P521)|| (key_type == AT_ECDHE_P521)) {
2436 keygen_args.prkey_args.key.u.ec.params.named_curve = "secp521r1";
2437 keygen_args.prkey_args.key.u.ec.params.der.len = 7;
2438 keygen_args.prkey_args.key.u.ec.params.der.value = (unsigned char *)"\x06\x05\x2B\x81\x04\x00\x23";
2439 }
2440 }
2441
2442 keygen_args.prkey_args.access_flags = MD_KEY_ACCESS;
2443
2444 pin_obj = vs->pin_objs[PinId];
2445 auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data;
2446 keygen_args.prkey_args.auth_id = pub_args.auth_id = auth_info->auth_id;
2447
2448 rv = sc_lock(card);
2449 if (rv) {
2450 logprintf(pCardData, 3, "MdGenerateKey(): cannot lock card\n");
2451 return SCARD_F_INTERNAL_ERROR;
2452 }
2453
2454 app_info = vs->p15card->app;
2455 rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
2456 if (rv) {
2457 logprintf(pCardData, 3, "MdGenerateKey(): PKCS#15 bind failed\n");
2458 sc_unlock(card);
2459 return SCARD_F_INTERNAL_ERROR;
2460 }
2461
2462 rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
2463 if (rv) {
2464 logprintf(pCardData, 3, "MdGenerateKey(): cannot finalize profile\n");
2465 goto done;
2466 }
2467
2468 sc_pkcs15init_set_p15card(profile, vs->p15card);
2469 cont = &(vs->p15_containers[idx]);
2470
2471 /* use the Windows Guid as input to determine some characteristics of the key such as the label or the id */
2472 md_contguid_build_key_args_from_cont_guid(pCardData, cont->guid, &(keygen_args.prkey_args));
2473
2474 if (keygen_args.prkey_args.label == NULL) {
2475 md_generate_guid(szGuid);
2476 keygen_args.prkey_args.label = szGuid;
2477 }
2478 keygen_args.pubkey_label = keygen_args.prkey_args.label;
2479
2480 rv = sc_pkcs15init_generate_key(vs->p15card, profile, &keygen_args, key_size, &cont->prkey_obj);
2481 if (rv < 0) {
2482 logprintf(pCardData, 3, "MdGenerateKey(): key generation failed: sc-error %i\n", rv);
2483 goto done;
2484 }
2485
2486 dwret = md_contguid_add_conversion(pCardData, cont->prkey_obj, cont->guid);
2487 if (dwret != SCARD_S_SUCCESS)
2488 return dwret;
2489
2490 cont->id = ((struct sc_pkcs15_prkey_info *)cont->prkey_obj->data)->id;
2491 cont->index = idx;
2492 cont->flags = CONTAINER_MAP_VALID_CONTAINER;
2493
2494 logprintf(pCardData, 3,
2495 "MdGenerateKey(): generated key(idx:%lu,id:%s,guid:%.*s)\n",
2496 (unsigned long)idx, sc_pkcs15_print_id(&cont->id),
2497 (int) sizeof cont->guid, cont->guid);
2498
2499 done:
2500 sc_pkcs15init_unbind(profile);
2501 sc_unlock(card);
2502 return dwret;
2503 }
2504
2505 static DWORD
md_pkcs15_store_key(PCARD_DATA pCardData,DWORD idx,DWORD key_type,BYTE * blob,DWORD blob_size,PIN_ID PinId)2506 md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, DWORD blob_size, PIN_ID PinId)
2507 {
2508 #ifdef ENABLE_OPENSSL
2509 VENDOR_SPECIFIC *vs;
2510 struct sc_card *card = NULL;
2511 struct sc_profile *profile = NULL;
2512 struct sc_pkcs15_object *pin_obj = NULL;
2513 struct sc_app_info *app_info = NULL;
2514 struct md_pkcs15_container *cont = NULL;
2515 struct sc_pkcs15init_prkeyargs prkey_args;
2516 struct sc_pkcs15init_pubkeyargs pubkey_args;
2517 BYTE *ptr = blob;
2518 EVP_PKEY *pkey=NULL;
2519 int rv;
2520 DWORD dwret = SCARD_F_INTERNAL_ERROR;
2521 CHAR szGuid[MAX_CONTAINER_NAME_LEN +1] = "Default key label";
2522
2523 if (!pCardData)
2524 return SCARD_E_INVALID_PARAMETER;
2525
2526 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2527 if (!vs)
2528 return SCARD_E_INVALID_PARAMETER;
2529
2530 if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId])
2531 return SCARD_E_INVALID_PARAMETER;
2532
2533 card = vs->p15card->card;
2534
2535 pkey = b2i_PrivateKey((const unsigned char **)&ptr, blob_size);
2536 if (!pkey) {
2537 logprintf(pCardData, 1, "MdStoreKey() MSBLOB key parse error");
2538 return SCARD_E_INVALID_PARAMETER;
2539 }
2540
2541 memset(&prkey_args, 0, sizeof(prkey_args));
2542 rv = sc_pkcs15_convert_prkey(&prkey_args.key, pkey);
2543 if (rv) {
2544 logprintf(pCardData, 1, "MdStoreKey() cannot convert private key");
2545 return SCARD_E_INVALID_PARAMETER;
2546 }
2547
2548 memset(&pubkey_args, 0, sizeof(pubkey_args));
2549 rv = sc_pkcs15_convert_pubkey(&pubkey_args.key, pkey);
2550 if (rv) {
2551 logprintf(pCardData, 1, "MdStoreKey() cannot convert public key");
2552 return SCARD_E_INVALID_PARAMETER;
2553 }
2554
2555 if (key_type == AT_SIGNATURE) {
2556 prkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
2557 pubkey_args.x509_usage = MD_KEY_USAGE_SIGNATURE;
2558 }
2559 else if (key_type == AT_KEYEXCHANGE) {
2560 prkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
2561 pubkey_args.x509_usage = MD_KEY_USAGE_KEYEXCHANGE;
2562 }
2563 else {
2564 logprintf(pCardData, 3,
2565 "MdStoreKey(): unsupported key type: 0x%lX\n",
2566 (unsigned long)key_type);
2567 return SCARD_E_INVALID_PARAMETER;
2568 }
2569
2570 prkey_args.access_flags = MD_KEY_ACCESS;
2571
2572 pin_obj = vs->pin_objs[PinId];
2573 prkey_args.auth_id = ((struct sc_pkcs15_auth_info *) pin_obj->data)->auth_id;
2574
2575 rv = sc_lock(card);
2576 if (rv) {
2577 logprintf(pCardData, 3, "MdStoreKey(): cannot lock card\n");
2578 return SCARD_F_INTERNAL_ERROR;
2579 }
2580
2581 app_info = vs->p15card->app;
2582 rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
2583 if (rv) {
2584 logprintf(pCardData, 3, "MdStoreKey(): PKCS#15 bind failed\n");
2585 sc_unlock(card);
2586 return SCARD_F_INTERNAL_ERROR;
2587 }
2588
2589 rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
2590 if (rv) {
2591 logprintf(pCardData, 3, "MdStoreKey(): cannot finalize profile\n");
2592 goto done;
2593 }
2594
2595 sc_pkcs15init_set_p15card(profile, vs->p15card);
2596 cont = &(vs->p15_containers[idx]);
2597
2598 prkey_args.label = szGuid;
2599 /* use the Windows Guid as input to determine some characteristics of the key such as the label or the id */
2600 md_contguid_build_key_args_from_cont_guid(pCardData, cont->guid, &prkey_args);
2601
2602 memcpy(pubkey_args.id.value, prkey_args.id.value, prkey_args.id.len);
2603 pubkey_args.id.len = prkey_args.id.len;
2604 pubkey_args.label = prkey_args.label;
2605
2606 if (prkey_args.label == szGuid) {
2607 md_generate_guid(szGuid);
2608 }
2609 pubkey_args.label = prkey_args.label;
2610
2611 rv = sc_pkcs15init_store_private_key(vs->p15card, profile, &prkey_args, &cont->prkey_obj);
2612 if (rv < 0) {
2613 logprintf(pCardData, 3, "MdStoreKey(): private key store failed: sc-error %i\n", rv);
2614 goto done;
2615 }
2616
2617 rv = sc_pkcs15init_store_public_key(vs->p15card, profile, &pubkey_args, &cont->pubkey_obj);
2618 if (rv < 0) {
2619 logprintf(pCardData, 3, "MdStoreKey(): public key store failed: sc-error %i\n", rv);
2620 goto done;
2621 }
2622
2623 dwret = md_contguid_add_conversion(pCardData, cont->prkey_obj, cont->guid);
2624 if (dwret != SCARD_S_SUCCESS)
2625 return dwret;
2626
2627 cont->id = ((struct sc_pkcs15_prkey_info *)cont->prkey_obj->data)->id;
2628 cont->index = idx;
2629 cont->flags |= CONTAINER_MAP_VALID_CONTAINER;
2630
2631 logprintf(pCardData, 3,
2632 "MdStoreKey(): stored key(idx:%lu,id:%s,guid:%.*s)\n",
2633 (unsigned long)idx, sc_pkcs15_print_id(&cont->id),
2634 (int) sizeof cont->guid, cont->guid);
2635
2636 done:
2637 sc_pkcs15init_unbind(profile);
2638 sc_unlock(card);
2639 return dwret;
2640 #else
2641 logprintf(pCardData, 1, "MD store key not supported\n");
2642 return SCARD_E_UNSUPPORTED_FEATURE;
2643 #endif /* ENABLE_OPENSSL */
2644 }
2645
2646
2647 static DWORD
md_pkcs15_store_certificate(PCARD_DATA pCardData,char * file_name,unsigned char * blob,size_t len)2648 md_pkcs15_store_certificate(PCARD_DATA pCardData, char *file_name, unsigned char *blob, size_t len)
2649 {
2650 VENDOR_SPECIFIC *vs;
2651 struct md_pkcs15_container *cont = NULL;
2652 struct sc_card *card = NULL;
2653 struct sc_profile *profile = NULL;
2654 struct sc_app_info *app_info = NULL;
2655 struct sc_pkcs15_object *cert_obj;
2656 struct sc_pkcs15init_certargs args;
2657 int rv, idx;
2658 DWORD dwret = SCARD_F_INTERNAL_ERROR;
2659
2660 if (!pCardData)
2661 return SCARD_E_INVALID_PARAMETER;
2662
2663 logprintf(pCardData, 1, "MdStoreCert(): store certificate '%s'\n", file_name);
2664 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2665 if (!vs)
2666 return SCARD_E_INVALID_PARAMETER;
2667
2668 card = vs->p15card->card;
2669
2670 memset(&args, 0, sizeof(args));
2671 args.der_encoded.value = blob;
2672 args.der_encoded.len = len;
2673 args.update = 1;
2674
2675 /* use container's ID as ID of certificate to store */
2676 idx = -1;
2677 if(sscanf(file_name, "ksc%d", &idx) > 0) {
2678 } else if(sscanf(file_name, "kxc%d", &idx) > 0) {
2679 }
2680
2681 if (idx >= 0 && idx < MD_MAX_KEY_CONTAINERS) {
2682 cont = &(vs->p15_containers[idx]);
2683 args.id = cont->id;
2684 logprintf(pCardData, 3, "MdStoreCert(): store certificate(idx:%i,id:%s)\n", idx, sc_pkcs15_print_id(&cont->id));
2685 }
2686
2687 rv = sc_lock(card);
2688 if (rv) {
2689 logprintf(pCardData, 3, "MdStoreCert(): cannot lock card\n");
2690 return SCARD_F_INTERNAL_ERROR;
2691 }
2692
2693 app_info = vs->p15card->app;
2694 rv = sc_pkcs15init_bind(card, "pkcs15", NULL, NULL, &profile);
2695 if (rv) {
2696 logprintf(pCardData, 3, "MdStoreCert(): PKCS#15 bind failed\n");
2697 sc_unlock(card);
2698 return SCARD_F_INTERNAL_ERROR;
2699 }
2700
2701 rv = sc_pkcs15init_finalize_profile(card, profile, app_info ? &app_info->aid : NULL);
2702 if (rv) {
2703 logprintf(pCardData, 3, "MdStoreCert(): cannot finalize profile\n");
2704 goto done;
2705 }
2706
2707 sc_pkcs15init_set_p15card(profile, vs->p15card);
2708
2709 rv = sc_pkcs15init_store_certificate(vs->p15card, profile, &args, &cert_obj);
2710 if (rv < 0) {
2711 logprintf(pCardData, 3, "MdStoreCert(): cannot store certificate: sc-error %i\n", rv);
2712 goto done;
2713 }
2714
2715 dwret = SCARD_S_SUCCESS;
2716 done:
2717 sc_pkcs15init_unbind(profile);
2718 sc_unlock(card);
2719 return dwret;
2720 }
2721
2722 static DWORD
md_query_key_sizes(PCARD_DATA pCardData,DWORD dwKeySpec,CARD_KEY_SIZES * pKeySizes)2723 md_query_key_sizes(PCARD_DATA pCardData, DWORD dwKeySpec, CARD_KEY_SIZES *pKeySizes)
2724 {
2725 VENDOR_SPECIFIC *vs = NULL;
2726 struct sc_algorithm_info* algo_info;
2727 int count = 0, i, keysize = 0, flag;
2728 if (!pKeySizes)
2729 return SCARD_E_INVALID_PARAMETER;
2730
2731 if (pKeySizes->dwVersion != CARD_KEY_SIZES_CURRENT_VERSION && pKeySizes->dwVersion != 0)
2732 return ERROR_REVISION_MISMATCH;
2733
2734 logprintf(pCardData, 1, "md_query_key_sizes: store dwKeySpec '%lu'\n",
2735 (unsigned long)dwKeySpec);
2736 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
2737 if (!vs)
2738 return SCARD_E_INVALID_PARAMETER;
2739
2740 count = vs->p15card->card->algorithm_count;
2741
2742 pKeySizes->dwVersion = CARD_KEY_SIZES_CURRENT_VERSION;
2743 pKeySizes->dwMinimumBitlen = 0;
2744 pKeySizes->dwDefaultBitlen = 0;
2745 pKeySizes->dwMaximumBitlen = 0;
2746 pKeySizes->dwIncrementalBitlen = 0;
2747
2748 /* dwKeySpec=0 is a special value when the key size is queried without specifying the algorithm.
2749 Used on old minidriver version. In this case, it is RSA */
2750 if ((dwKeySpec == 0) || (dwKeySpec == AT_KEYEXCHANGE) || (dwKeySpec == AT_SIGNATURE)) {
2751 for (i = 0; i < count; i++) {
2752 algo_info = vs->p15card->card->algorithms + i;
2753 if (algo_info->algorithm == SC_ALGORITHM_RSA) {
2754 if (pKeySizes->dwMinimumBitlen == 0 || pKeySizes->dwMinimumBitlen > algo_info->key_length) {
2755 pKeySizes->dwMinimumBitlen = algo_info->key_length;
2756 }
2757 if (pKeySizes->dwMaximumBitlen == 0 || pKeySizes->dwMaximumBitlen < algo_info->key_length) {
2758 pKeySizes->dwMaximumBitlen = algo_info->key_length;
2759 }
2760 if (algo_info->key_length == 2048) {
2761 pKeySizes->dwDefaultBitlen = algo_info->key_length;
2762 }
2763 if (algo_info->key_length == 1536) {
2764 pKeySizes->dwIncrementalBitlen = 512;
2765 }
2766 }
2767 }
2768 if (pKeySizes->dwMinimumBitlen == 0) {
2769 logprintf(pCardData, 0, "No RSA key found\n");
2770 return SCARD_E_INVALID_PARAMETER;
2771 }
2772 if (pKeySizes->dwDefaultBitlen == 0) {
2773 logprintf(pCardData, 3, "No 2048 key found\n");
2774 pKeySizes->dwDefaultBitlen = pKeySizes->dwMaximumBitlen;
2775 }
2776 if (pKeySizes->dwIncrementalBitlen == 0) {
2777 pKeySizes->dwIncrementalBitlen = 1024;
2778 }
2779 } else {
2780 keysize = 0;
2781 for (i = 0; i < count; i++) {
2782 algo_info = vs->p15card->card->algorithms + i;
2783 if (algo_info->algorithm == SC_ALGORITHM_EC) {
2784 flag = SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_EXT_EC_NAMEDCURVE;
2785 /* ECDHE */
2786 if ((dwKeySpec == AT_ECDHE_P256) && (algo_info->key_length == 256) && (algo_info->flags & flag)) {
2787 keysize = 256;
2788 break;
2789 }
2790 if ((dwKeySpec == AT_ECDHE_P384) && (algo_info->key_length == 384) && (algo_info->flags & flag)) {
2791 keysize = 384;
2792 break;
2793 }
2794 if ((dwKeySpec == AT_ECDHE_P521) && (algo_info->key_length == 521) && (algo_info->flags & flag)) {
2795 keysize = 521;
2796 break;
2797 }
2798 /* ECDSA */
2799 flag = SC_ALGORITHM_ECDSA_HASH_NONE|
2800 SC_ALGORITHM_ECDSA_HASH_SHA1|
2801 SC_ALGORITHM_ECDSA_HASH_SHA224|
2802 SC_ALGORITHM_ECDSA_HASH_SHA256|
2803 SC_ALGORITHM_EXT_EC_NAMEDCURVE;
2804 if ((dwKeySpec == AT_ECDSA_P256) && (algo_info->key_length == 256) && (algo_info->flags & flag)) {
2805 keysize = 256;
2806 break;
2807 }
2808 if ((dwKeySpec == AT_ECDSA_P384) && (algo_info->key_length == 384) && (algo_info->flags & flag)) {
2809 keysize = 384;
2810 break;
2811 }
2812 if ((dwKeySpec == AT_ECDSA_P521) && (algo_info->key_length == 521) && (algo_info->flags & flag)) {
2813 keysize = 521;
2814 break;
2815 }
2816 }
2817 if (keysize) {
2818 pKeySizes->dwMinimumBitlen = keysize;
2819 pKeySizes->dwDefaultBitlen = keysize;
2820 pKeySizes->dwMaximumBitlen = keysize;
2821 pKeySizes->dwIncrementalBitlen = 1;
2822 } else {
2823 logprintf(pCardData, 0,
2824 "No ECC key found (keyspec=%lu)\n",
2825 (unsigned long)dwKeySpec);
2826 return SCARD_E_INVALID_PARAMETER;
2827 }
2828 }
2829 }
2830
2831 logprintf(pCardData, 3, "Key compatible with the card capabilities\n");
2832 logprintf(pCardData, 3, " dwMinimumBitlen: %lu\n",
2833 (unsigned long)pKeySizes->dwMinimumBitlen);
2834 logprintf(pCardData, 3, " dwDefaultBitlen: %lu\n",
2835 (unsigned long)pKeySizes->dwDefaultBitlen);
2836 logprintf(pCardData, 3, " dwMaximumBitlen: %lu\n",
2837 (unsigned long)pKeySizes->dwMaximumBitlen);
2838 logprintf(pCardData, 3, " dwIncrementalBitlen: %lu\n",
2839 (unsigned long)pKeySizes->dwIncrementalBitlen);
2840 return SCARD_S_SUCCESS;
2841 }
2842
2843 static DWORD WINAPI
md_dialog_perform_pin_operation_thread(PVOID lpParameter)2844 md_dialog_perform_pin_operation_thread(PVOID lpParameter)
2845 {
2846 /* unstack the parameters */
2847 LONG_PTR* parameter = (LONG_PTR*) lpParameter;
2848 int operation = (int) parameter[0];
2849 struct sc_pkcs15_card *p15card = (struct sc_pkcs15_card *) parameter[1];
2850 struct sc_pkcs15_object *pin_obj = (struct sc_pkcs15_object *) parameter[2];
2851 const u8 *pin1 = (const u8 *) parameter[3];
2852 size_t pin1len = parameter[4];
2853 const u8 *pin2 = (const u8 *) parameter[5];
2854 size_t *pin2len = (size_t *) parameter[6];
2855 int rv = 0;
2856 switch (operation)
2857 {
2858 case SC_PIN_CMD_VERIFY:
2859 rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin1, pin1len);
2860 break;
2861 case SC_PIN_CMD_GET_SESSION_PIN:
2862 rv = sc_pkcs15_verify_pin_with_session_pin(p15card, pin_obj, pin1, pin1len, pin2, pin2len);
2863 break;
2864 case SC_PIN_CMD_CHANGE:
2865 rv = sc_pkcs15_change_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len ? *pin2len : 0);
2866 break;
2867 case SC_PIN_CMD_UNBLOCK:
2868 rv = sc_pkcs15_unblock_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len ? *pin2len : 0);
2869 break;
2870 default:
2871 rv = (DWORD) ERROR_INVALID_PARAMETER;
2872 break;
2873 }
2874 if (parameter[10] != 0) {
2875 EndDialog((HWND) parameter[10], rv);
2876 }
2877 return (DWORD) rv;
2878 }
2879
md_get_ui_str(PCARD_DATA pCardData,enum ui_str id)2880 static const char *md_get_ui_str(PCARD_DATA pCardData, enum ui_str id)
2881 {
2882 const char *str = md_get_config_str(pCardData, id);
2883
2884 if (str && *str == '\0') {
2885 /* if the user used an empty string, remove the field by setting it to NULL */
2886 str = NULL;
2887 }
2888
2889 return str;
2890 }
2891
md_dialog_proc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam,LONG_PTR dwRefData)2892 static HRESULT CALLBACK md_dialog_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData)
2893 {
2894 LONG_PTR param;
2895
2896 UNREFERENCED_PARAMETER(lParam);
2897 switch (message) {
2898 case TDN_CREATED:
2899 {
2900 PCARD_DATA pCardData = (PCARD_DATA)((LONG_PTR*)dwRefData)[7];
2901 DWORD now = timeGetTime();
2902
2903 /* remove the icon from the window title */
2904 SendMessage(hWnd, WM_SETICON, (LPARAM) ICON_BIG, (LONG_PTR) NULL);
2905 SendMessage(hWnd, WM_SETICON, (LPARAM) ICON_SMALL, (LONG_PTR) NULL);
2906
2907 /* store parameter like pCardData for further use if needed */
2908 ((LONG_PTR*)dwRefData)[11] = (LONG_PTR) now;
2909 SetWindowLongPtr(hWnd, GWLP_USERDATA, dwRefData);
2910 ((LONG_PTR*)dwRefData)[10] = (LONG_PTR) hWnd;
2911
2912 if (!md_is_pinpad_dlg_enable_cancel(pCardData)) {
2913 int timeout = md_get_pinpad_dlg_timeout(pCardData);
2914 if (timeout > 0) {
2915 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(0, timeout*1000));
2916 }
2917
2918 /* disable "Close" */
2919 SendMessage(hWnd, TDM_ENABLE_BUTTON, IDCLOSE, 0);
2920
2921 /* launch the function in another thread context store the thread handle */
2922 ((LONG_PTR*)dwRefData)[9] = (LONG_PTR) CreateThread(NULL, 0, md_dialog_perform_pin_operation_thread, (LPVOID) dwRefData, 0, NULL);
2923 } else {
2924 int timeout = md_get_pinpad_dlg_timeout(pCardData);
2925 if (timeout > 0) {
2926 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, 0);
2927 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_STATE, PBST_PAUSED, 0);
2928 }
2929 }
2930 }
2931 return S_OK;
2932
2933 case TDN_TIMER:
2934 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_POS, wParam, 0L);
2935 return S_OK;
2936
2937 case TDN_BUTTON_CLICKED:
2938 switch(LOWORD(wParam)) {
2939 case IDCANCEL:
2940 DestroyWindow(hWnd);
2941 break;
2942
2943 case IDOK:
2944 param = GetWindowLongPtr(hWnd, GWLP_USERDATA);
2945 if (param) {
2946 PCARD_DATA pCardData = (PCARD_DATA)((LONG_PTR*)param)[7];
2947 VENDOR_SPECIFIC* vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific;
2948
2949 int timeout = md_get_pinpad_dlg_timeout(pCardData);
2950 if (timeout > 0) {
2951 DWORD start = (DWORD)((LONG_PTR*)dwRefData)[11];
2952 DWORD delta = timeGetTime() - start;
2953 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(delta, delta + timeout*1000));
2954 SendMessage(hWnd, TDM_SET_PROGRESS_BAR_STATE, PBST_NORMAL, 0);
2955 }
2956
2957 /* disable "OK" and "Cancel" */
2958 SendMessage(hWnd, TDM_ENABLE_BUTTON, IDOK, 0);
2959 SendMessage(hWnd, TDM_ENABLE_BUTTON, IDCANCEL, 0);
2960
2961 /* disable "x" */
2962 HMENU menu = GetSystemMenu(hWnd, FALSE);
2963 if (menu) {
2964 EnableMenuItem(menu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
2965 }
2966
2967 /* launch the function in another thread context store the thread handle */
2968 ((LONG_PTR*)dwRefData)[9] = (LONG_PTR) CreateThread(NULL, 0, md_dialog_perform_pin_operation_thread, (LPVOID) dwRefData, 0, NULL);
2969 }
2970 break;
2971
2972 default:
2973 return S_FALSE;
2974 }
2975 break;
2976
2977 case TDN_DESTROYED:
2978 /* clean resources used */
2979 param = GetWindowLongPtr(hWnd, GWLP_USERDATA);
2980 if (param) {
2981 HANDLE hThread = (HANDLE)((LONG_PTR*)param)[9];
2982 CloseHandle(hThread);
2983 }
2984 break;
2985 }
2986
2987 /* don't close the Task Dialog */
2988 return S_FALSE;
2989 }
2990
2991
2992
2993 static int
md_dialog_perform_pin_operation(PCARD_DATA pCardData,int operation,struct sc_pkcs15_card * p15card,struct sc_pkcs15_object * pin_obj,const u8 * pin1,size_t pin1len,const u8 * pin2,size_t * pin2len,BOOL displayUI,DWORD role)2994 md_dialog_perform_pin_operation(PCARD_DATA pCardData, int operation, struct sc_pkcs15_card *p15card,
2995 struct sc_pkcs15_object *pin_obj,
2996 const u8 *pin1, size_t pin1len,
2997 const u8 *pin2, size_t *pin2len, BOOL displayUI, DWORD role)
2998 {
2999 LONG_PTR parameter[12];
3000 INT_PTR result = 0;
3001 HWND hWndDlg = 0;
3002 TASKDIALOGCONFIG tc = {0};
3003 int rv = 0;
3004 BOOL checked, user_checked;
3005 VENDOR_SPECIFIC* pv = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
3006
3007 /* stack the parameters */
3008 parameter[0] = (LONG_PTR)operation;
3009 parameter[1] = (LONG_PTR)p15card;
3010 parameter[2] = (LONG_PTR)pin_obj;
3011 parameter[3] = (LONG_PTR)pin1;
3012 parameter[4] = (LONG_PTR)pin1len;
3013 parameter[5] = (LONG_PTR)pin2;
3014 parameter[6] = (LONG_PTR)pin2len;
3015 parameter[7] = (LONG_PTR)pCardData;
3016 parameter[8] = (LONG_PTR)role;
3017 parameter[9] = 0; /* place holder for thread handle */
3018 parameter[10] = 0; /* place holder for window handle */
3019 parameter[11] = 0; /* place holder for end of timer */
3020
3021 /* launch the function to perform in the same thread context */
3022 if (!displayUI) {
3023 rv = md_dialog_perform_pin_operation_thread(parameter);
3024 SecureZeroMemory(parameter, sizeof(parameter));
3025 return rv;
3026 }
3027
3028 /* launch the UI in the same thread context than the parent and the function to perform in another thread context
3029 this is the only way to display a modal dialog attached to a parent (hwndParent != 0) */
3030 tc.hwndParent = pv->hwndParent;
3031 tc.hInstance = g_inst;
3032
3033 tc.pszWindowTitle = wchar_from_char_str(md_get_ui_str(pCardData,
3034 MD_PINPAD_DLG_TITLE));
3035 tc.pszMainInstruction = wchar_from_char_str(md_get_ui_str(pCardData,
3036 MD_PINPAD_DLG_MAIN));
3037 tc.pszExpandedControlText = wchar_from_char_str(md_get_ui_str(pCardData,
3038 MD_PINPAD_DLG_CONTROL_EXPANDED));
3039 tc.pszCollapsedControlText = wchar_from_char_str(md_get_ui_str(pCardData,
3040 MD_PINPAD_DLG_CONTROL_COLLAPSED));
3041 tc.pszExpandedInformation = wchar_from_char_str(md_get_ui_str(pCardData,
3042 MD_PINPAD_DLG_EXPANDED));
3043 tc.pszVerificationText = wchar_from_char_str(md_get_ui_str(pCardData,
3044 MD_PINPAD_DLG_VERIFICATION));
3045 switch (role) {
3046 case ROLE_ADMIN:
3047 tc.pszContent = wchar_from_char_str(md_get_ui_str(pCardData,
3048 MD_PINPAD_DLG_CONTENT_ADMIN));
3049 break;
3050 case MD_ROLE_USER_SIGN:
3051 tc.pszContent = wchar_from_char_str(md_get_ui_str(pCardData,
3052 MD_PINPAD_DLG_CONTENT_USER_SIGN));
3053 break;
3054 case ROLE_USER:
3055 default:
3056 tc.pszContent = wchar_from_char_str(md_get_ui_str(pCardData,
3057 MD_PINPAD_DLG_CONTENT_USER));
3058 break;
3059 }
3060
3061 if (pv->wszPinContext) {
3062 /* overwrite the main instruction with the application's information if
3063 * possible */
3064 tc.pszMainInstruction = pv->wszPinContext;
3065 }
3066
3067 tc.dwFlags = TDF_POSITION_RELATIVE_TO_WINDOW;
3068 if (tc.pszExpandedInformation != NULL) {
3069 tc.dwFlags |= TDF_EXPAND_FOOTER_AREA;
3070 }
3071 if (md_get_pinpad_dlg_timeout(pCardData) > 0) {
3072 tc.dwFlags |= TDF_SHOW_PROGRESS_BAR | TDF_CALLBACK_TIMER;
3073 }
3074
3075 checked = !md_is_pinpad_dlg_enable_cancel(pCardData);
3076 if (checked) {
3077 tc.dwFlags |= TDF_VERIFICATION_FLAG_CHECKED;
3078 /* can't use TDCBF_CANCEL_BUTTON since this would implicitly set TDF_ALLOW_DIALOG_CANCELLATION */
3079 tc.dwCommonButtons = TDCBF_CLOSE_BUTTON;
3080 } else {
3081 tc.dwFlags |= TDF_ALLOW_DIALOG_CANCELLATION;
3082 tc.dwCommonButtons = TDCBF_CANCEL_BUTTON | TDCBF_OK_BUTTON;
3083 }
3084
3085 tc.hMainIcon = md_get_pinpad_dlg_icon(pCardData);
3086 if (tc.hMainIcon) {
3087 tc.dwFlags |= TDF_USE_HICON_MAIN;
3088 } else {
3089 tc.pszMainIcon = MAKEINTRESOURCEW(IDI_SMARTCARD);
3090 }
3091 tc.pfCallback = md_dialog_proc;
3092 tc.lpCallbackData = (LONG_PTR)parameter;
3093 tc.cbSize = sizeof(tc);
3094
3095 result = TaskDialogIndirect(&tc, NULL, NULL, &user_checked);
3096
3097 if (user_checked != checked) {
3098 TCHAR path[MAX_PATH]={0};
3099 if (GetModuleFileName(NULL, path, ARRAYSIZE(path))) {
3100 HKEY hKey;
3101 LSTATUS lstatus = RegOpenKeyExA(HKEY_CURRENT_USER,
3102 SUBKEY_ENABLE_CANCEL, 0, KEY_WRITE, &hKey);
3103 if (ERROR_SUCCESS != lstatus) {
3104 lstatus = RegCreateKeyExA(HKEY_CURRENT_USER,
3105 SUBKEY_ENABLE_CANCEL, 0, NULL, REG_OPTION_NON_VOLATILE,
3106 KEY_WRITE, NULL, &hKey, NULL);
3107 }
3108 if (ERROR_SUCCESS == lstatus) {
3109 DWORD enable_cancel = 0;
3110 if (user_checked == FALSE) {
3111 enable_cancel = 1;
3112 }
3113 lstatus = RegSetValueEx(hKey, path, 0, REG_DWORD,
3114 (const BYTE*)&enable_cancel, sizeof(enable_cancel));
3115 RegCloseKey(hKey);
3116 }
3117 }
3118 }
3119
3120 LocalFree((WCHAR *) tc.pszWindowTitle);
3121 LocalFree((WCHAR *) tc.pszMainInstruction);
3122 LocalFree((WCHAR *) tc.pszExpandedControlText);
3123 LocalFree((WCHAR *) tc.pszCollapsedControlText);
3124 LocalFree((WCHAR *) tc.pszExpandedInformation);
3125 LocalFree((WCHAR *) tc.pszContent);
3126
3127 SecureZeroMemory(parameter, sizeof(parameter));
3128
3129 return (int) result;
3130 }
3131
md_translate_OpenSC_to_Windows_error(int OpenSCerror,DWORD dwDefaulCode)3132 static DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror,
3133 DWORD dwDefaulCode)
3134 {
3135 switch(OpenSCerror)
3136 {
3137 /* Errors related to reader operation */
3138 case SC_ERROR_READER:
3139 return SCARD_E_PROTO_MISMATCH;
3140 case SC_ERROR_NO_READERS_FOUND:
3141 return SCARD_E_NO_READERS_AVAILABLE;
3142 case SC_ERROR_CARD_NOT_PRESENT:
3143 return SCARD_E_NO_SMARTCARD;
3144 case SC_ERROR_TRANSMIT_FAILED:
3145 return SCARD_E_NOT_TRANSACTED;
3146 case SC_ERROR_CARD_REMOVED:
3147 return SCARD_W_REMOVED_CARD;
3148 case SC_ERROR_CARD_RESET:
3149 return SCARD_W_RESET_CARD;
3150 case SC_ERROR_KEYPAD_CANCELLED:
3151 return SCARD_W_CANCELLED_BY_USER;
3152 case SC_ERROR_KEYPAD_MSG_TOO_LONG:
3153 return SCARD_W_CARD_NOT_AUTHENTICATED;
3154 case SC_ERROR_KEYPAD_PIN_MISMATCH:
3155 return SCARD_E_INVALID_CHV;
3156 case SC_ERROR_KEYPAD_TIMEOUT:
3157 return ERROR_TIMEOUT;
3158 case SC_ERROR_EVENT_TIMEOUT:
3159 return SCARD_E_TIMEOUT;
3160 case SC_ERROR_CARD_UNRESPONSIVE:
3161 return SCARD_W_UNRESPONSIVE_CARD;
3162 case SC_ERROR_READER_LOCKED:
3163 return SCARD_E_SHARING_VIOLATION;
3164
3165 /* Resulting from a card command or related to the card*/
3166 case SC_ERROR_INCORRECT_PARAMETERS:
3167 return SCARD_E_INVALID_PARAMETER;
3168 case SC_ERROR_MEMORY_FAILURE:
3169 case SC_ERROR_NOT_ENOUGH_MEMORY:
3170 return SCARD_E_NO_MEMORY;
3171 case SC_ERROR_NOT_ALLOWED:
3172 return SCARD_W_SECURITY_VIOLATION;
3173 case SC_ERROR_AUTH_METHOD_BLOCKED:
3174 return SCARD_W_CHV_BLOCKED;
3175 case SC_ERROR_PIN_CODE_INCORRECT:
3176 return SCARD_W_WRONG_CHV;
3177
3178 /* Returned by OpenSC library when called with invalid arguments */
3179 case SC_ERROR_INVALID_ARGUMENTS:
3180 return ERROR_INVALID_PARAMETER;
3181 case SC_ERROR_BUFFER_TOO_SMALL:
3182 return NTE_BUFFER_TOO_SMALL;
3183
3184 /* Resulting from OpenSC internal operation */
3185 case SC_ERROR_INTERNAL:
3186 return ERROR_INTERNAL_ERROR;
3187 case SC_ERROR_NOT_SUPPORTED:
3188 return SCARD_E_UNSUPPORTED_FEATURE;
3189 case SC_ERROR_NOT_IMPLEMENTED:
3190 return ERROR_CALL_NOT_IMPLEMENTED;
3191
3192 default:
3193 return dwDefaulCode;
3194 }
3195 }
3196
CardDeleteContext(__inout PCARD_DATA pCardData)3197 DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData)
3198 {
3199 VENDOR_SPECIFIC *vs = NULL;
3200 CRITICAL_SECTION hScard_lock;
3201
3202 MD_FUNC_CALLED(pCardData, 1);
3203
3204 if(!pCardData)
3205 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3206
3207 logprintf(pCardData, 1,
3208 "\nP:%lu T:%lu pCardData:%p hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X CardDeleteContext\n",
3209 (unsigned long)GetCurrentProcessId(),
3210 (unsigned long)GetCurrentThreadId(), pCardData,
3211 (size_t)pCardData->hScard,
3212 (size_t)pCardData->hSCardCtx);
3213
3214 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
3215 if(!vs)
3216 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3217
3218 hScard_lock = vs->hScard_lock;
3219 EnterCriticalSection(&hScard_lock);
3220
3221 disassociate_card(pCardData);
3222 md_fs_finalize(pCardData);
3223
3224 if(vs->ctx) {
3225 logprintf(pCardData, 6, "release context\n");
3226 sc_release_context(vs->ctx);
3227 vs->ctx = NULL;
3228 }
3229
3230 logprintf(pCardData, 1, "**********************************************************************\n");
3231
3232 pCardData->pfnCspFree(pCardData->pvVendorSpecific);
3233 pCardData->pvVendorSpecific = NULL;
3234
3235 LeaveCriticalSection(&hScard_lock);
3236 DeleteCriticalSection(&hScard_lock);
3237
3238 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
3239 }
3240
CardQueryCapabilities(__in PCARD_DATA pCardData,__inout PCARD_CAPABILITIES pCardCapabilities)3241 DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData,
3242 __inout PCARD_CAPABILITIES pCardCapabilities)
3243 {
3244 DWORD dwret;
3245
3246 MD_FUNC_CALLED(pCardData, 1);
3247
3248 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3249 (unsigned long)GetCurrentProcessId(),
3250 (unsigned long)GetCurrentThreadId(), pCardData);
3251 logprintf(pCardData, 1, "pCardCapabilities=%p\n", pCardCapabilities);
3252
3253 if (!pCardData || !pCardCapabilities || !lock(pCardData))
3254 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3255
3256 dwret = check_card_status(pCardData, "CardQueryCapabilities");
3257 if (dwret != SCARD_S_SUCCESS) {
3258 goto err;
3259 }
3260
3261 dwret = md_card_capabilities(pCardData, pCardCapabilities);
3262 if (dwret != SCARD_S_SUCCESS) {
3263 goto err;
3264 }
3265
3266 err:
3267 unlock(pCardData);
3268
3269 MD_FUNC_RETURN(pCardData, 1, dwret);
3270 }
3271
CardDeleteContainer(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in DWORD dwReserved)3272 DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData,
3273 __in BYTE bContainerIndex,
3274 __in DWORD dwReserved)
3275 {
3276 VENDOR_SPECIFIC *vs = NULL;
3277 DWORD dwret;
3278 struct md_pkcs15_container* cont;
3279
3280 MD_FUNC_CALLED(pCardData, 1);
3281
3282 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3283 (unsigned long)GetCurrentProcessId(),
3284 (unsigned long)GetCurrentThreadId(), pCardData);
3285 logprintf(pCardData, 1, "CardDeleteContainer(idx:%u)\n",
3286 (unsigned int)bContainerIndex);
3287
3288 if (!pCardData || !lock(pCardData))
3289 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3290
3291 dwret = check_card_reader_status(pCardData, "CardDeleteContainer");
3292 if (dwret != SCARD_S_SUCCESS) {
3293 goto err;
3294 }
3295
3296 if (bContainerIndex >= MD_MAX_KEY_CONTAINERS) {
3297 dwret = SCARD_E_INVALID_PARAMETER;
3298 goto err;
3299 }
3300
3301 if (!md_is_supports_container_key_gen(pCardData)) {
3302 logprintf(pCardData, 1, "Denied 'deletion' mechanism to delete container.\n");
3303 dwret = SCARD_E_UNSUPPORTED_FEATURE;
3304 goto err;
3305 }
3306
3307 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
3308 if(!vs) {
3309 dwret = SCARD_E_INVALID_PARAMETER;
3310 goto err;
3311 }
3312
3313 cont = &(vs->p15_containers[bContainerIndex]);
3314
3315 dwret = md_pkcs15_delete_object(pCardData, cont->prkey_obj);
3316 if (dwret != SCARD_S_SUCCESS) {
3317 logprintf(pCardData, 1, "private key deletion failed\n");
3318 goto err;
3319 }
3320
3321 dwret = md_pkcs15_delete_object(pCardData, cont->pubkey_obj);
3322 if (dwret != SCARD_S_SUCCESS) {
3323 logprintf(pCardData, 1, "public key deletion failed\n");
3324 goto err;
3325 }
3326
3327 ZeroMemory(cont, sizeof(struct md_pkcs15_container));
3328
3329 logprintf(pCardData, 1, "key deleted\n");
3330
3331 err:
3332 unlock(pCardData);
3333
3334 MD_FUNC_RETURN(pCardData, 1, dwret);
3335 }
3336
3337 /** The CardCreateContainerEx function creates a new key container that the
3338 container index identifies and the bContainerIndex parameter specifies. The function
3339 associates the key container with the PIN that the PinId parameter specified.
3340 This function is useful if the card-edge does not allow for changing the key attributes
3341 after the key container is created. This function replaces the need to call
3342 CardSetContainerProperty to set the CCP_PIN_IDENTIFIER property CardCreateContainer
3343 is called.
3344 The caller of this function can provide the key material that the card imports.
3345 This is useful in those situations in which the card either does not support internal
3346 key generation or the caller requests that the key be archived in the card.*/
CardCreateContainerEx(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in DWORD dwFlags,__in DWORD dwKeySpec,__in DWORD dwKeySize,__in PBYTE pbKeyData,__in PIN_ID PinId)3347 DWORD WINAPI CardCreateContainerEx(__in PCARD_DATA pCardData,
3348 __in BYTE bContainerIndex,
3349 __in DWORD dwFlags,
3350 __in DWORD dwKeySpec,
3351 __in DWORD dwKeySize,
3352 __in PBYTE pbKeyData,
3353 __in PIN_ID PinId)
3354 {
3355 DWORD dwret;
3356
3357 MD_FUNC_CALLED(pCardData, 1);
3358
3359 if (!pCardData || !lock(pCardData))
3360 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3361
3362 if (PinId == ROLE_ADMIN) {
3363 dwret = SCARD_W_SECURITY_VIOLATION;
3364 goto err;
3365 }
3366
3367 dwret = check_card_reader_status(pCardData, "CardCreateContainerEx");
3368 if (dwret != SCARD_S_SUCCESS)
3369 goto err;
3370
3371 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3372 (unsigned long)GetCurrentProcessId(),
3373 (unsigned long)GetCurrentThreadId(), pCardData);
3374 logprintf(pCardData, 1,
3375 "CardCreateContainerEx(idx:%u,flags:%lX,type:%lX,size:%lu,data:%p,pin:%u)\n",
3376 (unsigned int)bContainerIndex, (unsigned long)dwFlags,
3377 (unsigned long)dwKeySpec, (unsigned long)dwKeySize, pbKeyData,
3378 (unsigned int)PinId);
3379
3380 if (pbKeyData) {
3381 logprintf(pCardData, 7, "Key data\n");
3382 loghex(pCardData, 7, pbKeyData, dwKeySize);
3383 }
3384
3385 dwret = md_check_key_compatibility(pCardData, dwFlags, dwKeySpec, dwKeySize, pbKeyData);
3386 if (dwret != SCARD_S_SUCCESS) {
3387 logprintf(pCardData, 1, "check key compatibility failed\n");
3388 goto err;
3389 }
3390
3391 if (!md_is_supports_container_key_gen(pCardData)) {
3392 logprintf(pCardData, 1, "Denied 'generate key' mechanism to create container.\n");
3393 dwFlags &= ~CARD_CREATE_CONTAINER_KEY_GEN;
3394 }
3395
3396 if (!md_is_supports_container_key_import(pCardData)) {
3397 logprintf(pCardData, 1, "Denied 'import key' mechanism to create container.\n");
3398 dwFlags &= ~CARD_CREATE_CONTAINER_KEY_IMPORT;
3399 }
3400
3401 if (!dwFlags) {
3402 logprintf(pCardData, 1, "Unsupported create container mechanism.\n");
3403 dwret = SCARD_E_UNSUPPORTED_FEATURE;
3404 goto err;
3405 }
3406
3407 if (dwFlags & CARD_CREATE_CONTAINER_KEY_GEN) {
3408 dwret = md_pkcs15_generate_key(pCardData, bContainerIndex, dwKeySpec, dwKeySize, PinId);
3409 if (dwret != SCARD_S_SUCCESS) {
3410 logprintf(pCardData, 1, "key generation failed\n");
3411 goto err;
3412 }
3413 logprintf(pCardData, 1, "key generated\n");
3414 }
3415 else if ((dwFlags & CARD_CREATE_CONTAINER_KEY_IMPORT) && (pbKeyData != NULL)) {
3416 dwret = md_pkcs15_store_key(pCardData, bContainerIndex, dwKeySpec, pbKeyData, dwKeySize, PinId);
3417 if (dwret != SCARD_S_SUCCESS) {
3418 logprintf(pCardData, 1, "key store failed\n");
3419 goto err;
3420 }
3421 logprintf(pCardData, 1, "key imported\n");
3422 }
3423 else {
3424 logprintf(pCardData, 1, "Invalid dwFlags value: 0x%lX\n",
3425 (unsigned long)dwFlags);
3426 dwret = SCARD_E_INVALID_PARAMETER;
3427 goto err;
3428 }
3429
3430 err:
3431 unlock(pCardData);
3432
3433 MD_FUNC_RETURN(pCardData, 1, dwret);
3434 }
3435
CardCreateContainer(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in DWORD dwFlags,__in DWORD dwKeySpec,__in DWORD dwKeySize,__in PBYTE pbKeyData)3436 DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData,
3437 __in BYTE bContainerIndex,
3438 __in DWORD dwFlags,
3439 __in DWORD dwKeySpec,
3440 __in DWORD dwKeySize,
3441 __in PBYTE pbKeyData)
3442 {
3443 DWORD dwret;
3444
3445 MD_FUNC_CALLED(pCardData, 1);
3446
3447 dwret = CardCreateContainerEx(pCardData, bContainerIndex, dwFlags,
3448 dwKeySpec, dwKeySize, pbKeyData,
3449 ROLE_USER);
3450
3451 MD_FUNC_RETURN(pCardData, 1, dwret);
3452 }
3453
3454 typedef struct {
3455 PUBLICKEYSTRUC publickeystruc;
3456 RSAPUBKEY rsapubkey;
3457 } PUBRSAKEYSTRUCT_BASE;
3458
CardGetContainerInfo(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in DWORD dwFlags,__inout PCONTAINER_INFO pContainerInfo)3459 DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContainerIndex, __in DWORD dwFlags,
3460 __inout PCONTAINER_INFO pContainerInfo)
3461 {
3462 VENDOR_SPECIFIC *vs = NULL;
3463 DWORD sz = 0;
3464 DWORD ret;
3465 struct md_pkcs15_container *cont = NULL;
3466 struct sc_pkcs15_der pubkey_der;
3467 struct sc_pkcs15_prkey_info *prkey_info = NULL;
3468 int rv;
3469 pubkey_der.value = NULL;
3470 pubkey_der.len = 0;
3471
3472 MD_FUNC_CALLED(pCardData, 1);
3473
3474 if(!pCardData)
3475 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3476 if (!pContainerInfo || !lock(pCardData))
3477 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3478
3479 ret = check_card_reader_status(pCardData, "CardGetContainerInfo");
3480 if (ret != SCARD_S_SUCCESS)
3481 goto err;
3482
3483 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3484 (unsigned long)GetCurrentProcessId(),
3485 (unsigned long)GetCurrentThreadId(), pCardData);
3486 logprintf(pCardData, 1,
3487 "CardGetContainerInfo bContainerIndex=%u, dwFlags=0x%08X, dwVersion=%lu, cbSigPublicKey=%lu, cbKeyExPublicKey=%lu\n",
3488 (unsigned int)bContainerIndex, (unsigned int)dwFlags,
3489 (unsigned long)pContainerInfo->dwVersion,
3490 (unsigned long)pContainerInfo->cbSigPublicKey,
3491 (unsigned long)pContainerInfo->cbKeyExPublicKey);
3492
3493 if (dwFlags) {
3494 ret = SCARD_E_INVALID_PARAMETER;
3495 goto err;
3496 }
3497 if (bContainerIndex >= MD_MAX_KEY_CONTAINERS) {
3498 ret = SCARD_E_NO_KEY_CONTAINER;
3499 goto err;
3500 }
3501 if (pContainerInfo->dwVersion > CONTAINER_INFO_CURRENT_VERSION) {
3502 ret = ERROR_REVISION_MISMATCH;
3503 goto err;
3504 }
3505
3506 pContainerInfo->dwVersion = CONTAINER_INFO_CURRENT_VERSION;
3507
3508 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
3509 if (!vs) {
3510 ret = SCARD_E_INVALID_PARAMETER;
3511 goto err;
3512 }
3513
3514 cont = &vs->p15_containers[bContainerIndex];
3515
3516 if (!cont->prkey_obj) {
3517 logprintf(pCardData, 7, "Container %u is empty\n",
3518 (unsigned int)bContainerIndex);
3519 ret = SCARD_E_NO_KEY_CONTAINER;
3520 goto err;
3521 }
3522
3523 ret = SCARD_F_UNKNOWN_ERROR;
3524 prkey_info = (struct sc_pkcs15_prkey_info *)cont->prkey_obj->data;
3525
3526 if ((cont->prkey_obj->content.value != NULL) && (cont->prkey_obj->content.len > 0)) {
3527 sc_der_copy(&pubkey_der, &cont->prkey_obj->content);
3528 ret = SCARD_S_SUCCESS;
3529 }
3530
3531 if (!pubkey_der.value && cont->pubkey_obj) {
3532 struct sc_pkcs15_pubkey *pubkey = NULL;
3533
3534 logprintf(pCardData, 1, "now read public key '%.*s'\n", (int) sizeof cont->pubkey_obj->label, cont->pubkey_obj->label);
3535 rv = sc_pkcs15_read_pubkey(vs->p15card, cont->pubkey_obj, &pubkey);
3536 if (!rv) {
3537 rv = sc_pkcs15_encode_pubkey(vs->ctx, pubkey, &pubkey_der.value, &pubkey_der.len);
3538 if (rv) {
3539 logprintf(pCardData, 1, "encode public key error %d\n", rv);
3540 ret = SCARD_F_INTERNAL_ERROR;
3541 }
3542 else {
3543 logprintf(pCardData, 1, "public key encoded\n");
3544 ret = SCARD_S_SUCCESS;
3545 }
3546
3547 sc_pkcs15_free_pubkey(pubkey);
3548 }
3549 else {
3550 logprintf(pCardData, 1, "public key read error %d\n", rv);
3551 ret = SCARD_E_FILE_NOT_FOUND;
3552 }
3553 }
3554
3555 if (!pubkey_der.value && cont->cert_obj) {
3556 struct sc_pkcs15_cert *cert = NULL;
3557
3558 logprintf(pCardData, 1, "now read certificate '%.*s'\n", (int) sizeof cont->cert_obj->label, cont->cert_obj->label);
3559 rv = sc_pkcs15_read_certificate(vs->p15card, (struct sc_pkcs15_cert_info *)(cont->cert_obj->data), &cert);
3560 if(!rv) {
3561 rv = sc_pkcs15_encode_pubkey(vs->ctx, cert->key, &pubkey_der.value, &pubkey_der.len);
3562 if (rv) {
3563 logprintf(pCardData, 1, "encode certificate public key error %d\n", rv);
3564 ret = SCARD_F_INTERNAL_ERROR;
3565 }
3566 else {
3567 logprintf(pCardData, 1, "certificate public key encoded\n");
3568 ret = SCARD_S_SUCCESS;
3569 }
3570
3571 sc_pkcs15_free_certificate(cert);
3572 }
3573 else {
3574 logprintf(pCardData, 1,
3575 "certificate '%u' read error %d\n",
3576 (unsigned int)bContainerIndex, rv);
3577 ret = SCARD_E_FILE_NOT_FOUND;
3578 }
3579 }
3580
3581 if (!pubkey_der.value && (cont->size_sign || cont->size_key_exchange)) {
3582 logprintf(pCardData, 2, "cannot find public key\n");
3583 ret = SCARD_F_INTERNAL_ERROR;
3584 goto err;
3585 }
3586
3587 if (ret != SCARD_S_SUCCESS) {
3588 logprintf(pCardData, 7,
3589 "GetContainerInfo(idx:%u) failed; error %lX",
3590 (unsigned int)bContainerIndex, (unsigned long)ret);
3591 goto err;
3592 }
3593
3594 logprintf(pCardData, 7, "SubjectPublicKeyInfo:\n");
3595 loghex(pCardData, 7, pubkey_der.value, pubkey_der.len);
3596
3597 if (prkey_info->modulus_length > 0) {
3598 logprintf(pCardData, 7, "Encoding RSA public key");
3599 if (pubkey_der.len && pubkey_der.value) {
3600 sz = 0; /* get size */
3601 CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3602 pubkey_der.value, (DWORD) pubkey_der.len, 0, NULL, &sz);
3603
3604 if (cont->size_sign) {
3605 PUBRSAKEYSTRUCT_BASE *publicKey = (PUBRSAKEYSTRUCT_BASE *)pCardData->pfnCspAlloc(sz);
3606 if (!publicKey) {
3607 ret = SCARD_E_NO_MEMORY;
3608 goto err;
3609 }
3610
3611 CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3612 pubkey_der.value, (DWORD) pubkey_der.len, 0, publicKey, &sz);
3613
3614 publicKey->publickeystruc.aiKeyAlg = CALG_RSA_SIGN;
3615 pContainerInfo->cbSigPublicKey = sz;
3616 pContainerInfo->pbSigPublicKey = (PBYTE)publicKey;
3617
3618 logprintf(pCardData, 3,
3619 "return info on SIGN_CONTAINER_INDEX %u\n",
3620 (unsigned int)bContainerIndex);
3621 }
3622
3623 if (cont->size_key_exchange) {
3624 PUBRSAKEYSTRUCT_BASE *publicKey = (PUBRSAKEYSTRUCT_BASE*)pCardData->pfnCspAlloc(sz);
3625 if (!publicKey) {
3626 ret = SCARD_E_NO_MEMORY;
3627 goto err;
3628 }
3629
3630 CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3631 pubkey_der.value, (DWORD) pubkey_der.len, 0, publicKey, &sz);
3632
3633 publicKey->publickeystruc.aiKeyAlg = CALG_RSA_KEYX;
3634 pContainerInfo->cbKeyExPublicKey = sz;
3635 pContainerInfo->pbKeyExPublicKey = (PBYTE)publicKey;
3636
3637 logprintf(pCardData, 3,
3638 "return info on KEYX_CONTAINER_INDEX %u\n",
3639 (unsigned int)bContainerIndex);
3640 }
3641 }
3642 } else if (prkey_info->field_length > 0) {
3643 logprintf(pCardData, 7, "Encoding ECC public key");
3644
3645 if (pubkey_der.len > 2 && pubkey_der.value && pubkey_der.value[0] == 4 && pubkey_der.value[1] == pubkey_der.len -2) {
3646 BCRYPT_ECCKEY_BLOB *publicKey = NULL;
3647 DWORD dwMagic = 0;
3648 if (cont->size_sign) {
3649 sz = (DWORD) (sizeof(BCRYPT_ECCKEY_BLOB) + pubkey_der.len -3);
3650
3651 switch(cont->size_sign)
3652 {
3653 case 256:
3654 dwMagic = BCRYPT_ECDSA_PUBLIC_P256_MAGIC;
3655 break;
3656 case 384:
3657 dwMagic = BCRYPT_ECDSA_PUBLIC_P384_MAGIC;
3658 break;
3659 case 521:
3660 dwMagic = BCRYPT_ECDSA_PUBLIC_P521_MAGIC;
3661 break;
3662 default:
3663 logprintf(pCardData, 3,
3664 "Unable to match the ECC public size to one of Microsoft algorithm %"SC_FORMAT_LEN_SIZE_T"u\n",
3665 cont->size_sign);
3666 ret = SCARD_F_INTERNAL_ERROR;
3667 goto err;
3668 }
3669
3670 publicKey = (BCRYPT_ECCKEY_BLOB *)pCardData->pfnCspAlloc(sz);
3671 if (!publicKey) {
3672 ret = SCARD_E_NO_MEMORY;
3673 goto err;
3674 }
3675
3676 publicKey->cbKey = (DWORD)(pubkey_der.len -3) /2;
3677 publicKey->dwMagic = dwMagic;
3678
3679 pContainerInfo->cbSigPublicKey = sz;
3680 pContainerInfo->pbSigPublicKey = (PBYTE)publicKey;
3681 memcpy(((PBYTE)publicKey) + sizeof(BCRYPT_ECCKEY_BLOB), pubkey_der.value + 3, pubkey_der.len -3);
3682
3683 logprintf(pCardData, 3,
3684 "return info on ECC SIGN_CONTAINER_INDEX %u\n",
3685 (unsigned int)bContainerIndex);
3686 }
3687 if (cont->size_key_exchange) {
3688 sz = (DWORD) (sizeof(BCRYPT_ECCKEY_BLOB) + pubkey_der.len -3);
3689
3690 switch(cont->size_key_exchange)
3691 {
3692 case 256:
3693 dwMagic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
3694 break;
3695 case 384:
3696 dwMagic = BCRYPT_ECDH_PUBLIC_P384_MAGIC;
3697 break;
3698 case 521:
3699 dwMagic = BCRYPT_ECDH_PUBLIC_P521_MAGIC;
3700 break;
3701 default:
3702 logprintf(pCardData, 3,
3703 "Unable to match the ECC public size to one of Microsoft algorithm %"SC_FORMAT_LEN_SIZE_T"u\n",
3704 cont->size_key_exchange);
3705 ret = SCARD_F_INTERNAL_ERROR;
3706 goto err;
3707 }
3708
3709 publicKey = (BCRYPT_ECCKEY_BLOB *)pCardData->pfnCspAlloc(sz);
3710 if (!publicKey) {
3711 ret = SCARD_E_NO_MEMORY;
3712 goto err;
3713 }
3714
3715 publicKey->cbKey = (DWORD)(pubkey_der.len -3) /2;
3716 publicKey->dwMagic = dwMagic;
3717
3718 pContainerInfo->cbKeyExPublicKey = sz;
3719 pContainerInfo->pbKeyExPublicKey = (PBYTE)publicKey;
3720 memcpy(((PBYTE)publicKey) + sizeof(BCRYPT_ECCKEY_BLOB), pubkey_der.value + 3, pubkey_der.len -3);
3721
3722 logprintf(pCardData, 3,
3723 "return info on ECC KEYX_CONTAINER_INDEX %u\n",
3724 (unsigned int)bContainerIndex);
3725 }
3726 }
3727 }
3728 logprintf(pCardData, 7, "returns container(idx:%u) info\n",
3729 (unsigned int)bContainerIndex);
3730
3731 err:
3732 free(pubkey_der.value);
3733 unlock(pCardData);
3734
3735 MD_FUNC_RETURN(pCardData, 1, ret);
3736 }
3737
CardAuthenticatePin(__in PCARD_DATA pCardData,__in LPWSTR pwszUserId,__in_bcount (cbPin)PBYTE pbPin,__in DWORD cbPin,__out_opt PDWORD pcAttemptsRemaining)3738 DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData,
3739 __in LPWSTR pwszUserId,
3740 __in_bcount(cbPin) PBYTE pbPin,
3741 __in DWORD cbPin,
3742 __out_opt PDWORD pcAttemptsRemaining)
3743 {
3744 PIN_ID PinId = 0;
3745
3746 MD_FUNC_CALLED(pCardData, 1);
3747
3748 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3749 (unsigned long)GetCurrentProcessId(),
3750 (unsigned long)GetCurrentThreadId(), pCardData);
3751 logprintf(pCardData, 1, "CardAuthenticatePin '%S':%lu\n",
3752 NULLWSTR(pwszUserId), (unsigned long)cbPin);
3753
3754 if (wcscmp(pwszUserId, wszCARD_USER_USER) == 0) {
3755 PinId = ROLE_USER;
3756 }
3757 else if (wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0) {
3758 PinId = ROLE_ADMIN;
3759 }
3760 else {
3761 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3762 }
3763 if (pbPin == NULL)
3764 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3765
3766 MD_FUNC_RETURN(pCardData, 1, CardAuthenticateEx(pCardData, PinId, CARD_PIN_SILENT_CONTEXT, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining));
3767 }
3768
3769
CardGetChallenge(__in PCARD_DATA pCardData,__deref_out_bcount (* pcbChallengeData)PBYTE * ppbChallengeData,__out PDWORD pcbChallengeData)3770 DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData,
3771 __deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
3772 __out PDWORD pcbChallengeData)
3773 {
3774 VENDOR_SPECIFIC *vs;
3775 DWORD dwret;
3776 int rv;
3777
3778 MD_FUNC_CALLED(pCardData, 1);
3779
3780 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3781 (unsigned long)GetCurrentProcessId(),
3782 (unsigned long)GetCurrentThreadId(), pCardData);
3783 logprintf(pCardData, 1, "CardGetChallenge\n");
3784
3785 if(!pCardData)
3786 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3787 if (!ppbChallengeData || !pcbChallengeData || !lock(pCardData))
3788 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3789
3790 dwret = check_card_reader_status(pCardData, "CardGetChallenge");
3791 if (dwret != SCARD_S_SUCCESS) {
3792 goto err;
3793 }
3794
3795 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
3796 if (!vs) {
3797 dwret = SCARD_E_INVALID_PARAMETER;
3798 goto err;
3799 }
3800
3801 *pcbChallengeData = 8;
3802
3803 *ppbChallengeData = (PBYTE) pCardData->pfnCspAlloc(8);
3804 if (!*ppbChallengeData) {
3805 dwret = SCARD_E_NO_MEMORY;
3806 goto err;
3807 }
3808
3809 rv = sc_get_challenge(vs->p15card->card, *ppbChallengeData, 8);
3810 if (rv < 0) {
3811 logprintf(pCardData, 1, "Get challenge failed: %s\n", sc_strerror(rv));
3812 pCardData->pfnCspFree(*ppbChallengeData);
3813 *ppbChallengeData = NULL;
3814 dwret = SCARD_E_UNEXPECTED;
3815 goto err;
3816 }
3817 dwret = SCARD_S_SUCCESS;
3818
3819 logprintf(pCardData, 7, "returns %lu bytes:\n",
3820 (unsigned long)*pcbChallengeData);
3821 loghex(pCardData, 7, *ppbChallengeData, *pcbChallengeData);
3822
3823 err:
3824 unlock(pCardData);
3825 MD_FUNC_RETURN(pCardData, 1, dwret);
3826 }
3827
3828
CardAuthenticateChallenge(__in PCARD_DATA pCardData,__in_bcount (cbResponseData)PBYTE pbResponseData,__in DWORD cbResponseData,__out_opt PDWORD pcAttemptsRemaining)3829 DWORD WINAPI CardAuthenticateChallenge(__in PCARD_DATA pCardData,
3830 __in_bcount(cbResponseData) PBYTE pbResponseData,
3831 __in DWORD cbResponseData,
3832 __out_opt PDWORD pcAttemptsRemaining)
3833 {
3834 MD_FUNC_CALLED(pCardData, 1);
3835
3836 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3837 (unsigned long)GetCurrentProcessId(),
3838 (unsigned long)GetCurrentThreadId(), pCardData);
3839 logprintf(pCardData, 1, "CardAuthenticateChallenge - unsupported\n");
3840
3841 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
3842 }
3843
3844
CardUnblockPin(__in PCARD_DATA pCardData,__in LPWSTR pwszUserId,__in_bcount (cbAuthenticationData)PBYTE pbAuthenticationData,__in DWORD cbAuthenticationData,__in_bcount (cbNewPinData)PBYTE pbNewPinData,__in DWORD cbNewPinData,__in DWORD cRetryCount,__in DWORD dwFlags)3845 DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData,
3846 __in LPWSTR pwszUserId,
3847 __in_bcount(cbAuthenticationData) PBYTE pbAuthenticationData,
3848 __in DWORD cbAuthenticationData,
3849 __in_bcount(cbNewPinData) PBYTE pbNewPinData,
3850 __in DWORD cbNewPinData,
3851 __in DWORD cRetryCount,
3852 __in DWORD dwFlags)
3853 {
3854 DWORD r = SCARD_S_SUCCESS;
3855
3856 MD_FUNC_CALLED(pCardData, 1);
3857
3858 if(!pCardData || !lock(pCardData))
3859 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3860
3861 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3862 (unsigned long)GetCurrentProcessId(),
3863 (unsigned long)GetCurrentThreadId(), pCardData);
3864 logprintf(pCardData, 1, "CardUnblockPin\n");
3865
3866 if (pwszUserId == NULL) {
3867 logprintf(pCardData, 1, "no user ID\n");
3868 r = SCARD_E_INVALID_PARAMETER;
3869 goto err;
3870 }
3871 if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0) {
3872 logprintf(pCardData, 1, "unknown user ID %S\n", pwszUserId);
3873 r = SCARD_E_INVALID_PARAMETER;
3874 goto err;
3875 }
3876 if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) {
3877 logprintf(pCardData, 1, "unlocking admin not supported\n");
3878 r = SCARD_E_UNSUPPORTED_FEATURE;
3879 goto err;
3880 }
3881 if (dwFlags & CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE) {
3882 logprintf(pCardData, 1,
3883 "challenge / response not supported, we'll treat response as a PUK\n");
3884 logprintf(pCardData, 1,
3885 "note that you'll need to type PUK in hex (replace every PUK digit X with '3X') in Win CAD unblock dialog response field\n");
3886 dwFlags &= ~CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE;
3887 }
3888 if (dwFlags) {
3889 logprintf(pCardData, 1, "flags of %x not supported\n",
3890 (unsigned int)dwFlags);
3891 r = SCARD_E_INVALID_PARAMETER;
3892 goto err;
3893 }
3894
3895 logprintf(pCardData, 1,
3896 "UserID('%S'), AuthData(%p, %lu), NewPIN(%p, %lu), Retry(%lu), dwFlags(0x%lX)\n",
3897 pwszUserId, pbAuthenticationData,
3898 (unsigned long)cbAuthenticationData, pbNewPinData,
3899 (unsigned long)cbNewPinData, (unsigned long)cRetryCount,
3900 (unsigned long)dwFlags);
3901
3902 r = CardChangeAuthenticatorEx(pCardData,
3903 PIN_CHANGE_FLAG_UNBLOCK |
3904 CARD_PIN_SILENT_CONTEXT,
3905 ROLE_ADMIN, pbAuthenticationData,
3906 cbAuthenticationData, ROLE_USER,
3907 pbNewPinData, cbNewPinData,
3908 cRetryCount, NULL);
3909
3910 err:
3911 unlock(pCardData);
3912
3913 MD_FUNC_RETURN(pCardData, 1, r);
3914 }
3915
3916
CardChangeAuthenticator(__in PCARD_DATA pCardData,__in LPWSTR pwszUserId,__in_bcount (cbCurrentAuthenticator)PBYTE pbCurrentAuthenticator,__in DWORD cbCurrentAuthenticator,__in_bcount (cbNewAuthenticator)PBYTE pbNewAuthenticator,__in DWORD cbNewAuthenticator,__in DWORD cRetryCount,__in DWORD dwFlags,__out_opt PDWORD pcAttemptsRemaining)3917 DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData,
3918 __in LPWSTR pwszUserId,
3919 __in_bcount(cbCurrentAuthenticator) PBYTE pbCurrentAuthenticator,
3920 __in DWORD cbCurrentAuthenticator,
3921 __in_bcount(cbNewAuthenticator) PBYTE pbNewAuthenticator,
3922 __in DWORD cbNewAuthenticator,
3923 __in DWORD cRetryCount,
3924 __in DWORD dwFlags,
3925 __out_opt PDWORD pcAttemptsRemaining)
3926 {
3927 DWORD r = SCARD_S_SUCCESS;
3928 PIN_ID pinid;
3929
3930 MD_FUNC_CALLED(pCardData, 1);
3931
3932 if(!pCardData || !lock(pCardData))
3933 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
3934
3935 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
3936 (unsigned long)GetCurrentProcessId(),
3937 (unsigned long)GetCurrentThreadId(), pCardData);
3938 logprintf(pCardData, 1, "CardChangeAuthenticator\n");
3939
3940 if (pwszUserId == NULL) {
3941 r = SCARD_E_INVALID_PARAMETER;
3942 goto err;
3943 }
3944
3945 if (dwFlags == CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE) {
3946 logprintf(pCardData, 1, "Other then 'authentication' the PIN are not supported\n");
3947 r = SCARD_E_UNSUPPORTED_FEATURE;
3948 goto err;
3949 }
3950 else if (dwFlags != CARD_AUTHENTICATE_PIN_PIN){
3951 r = SCARD_E_INVALID_PARAMETER;
3952 goto err;
3953 }
3954
3955 if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN, pwszUserId) != 0) {
3956 r = SCARD_E_INVALID_PARAMETER;
3957 goto err;
3958 }
3959
3960 logprintf(pCardData, 1,
3961 "UserID('%S'), CurrentPIN(%p, %lu), NewPIN(%p, %lu), Retry(%lu), dwFlags(0x%lX)\n",
3962 pwszUserId, pbCurrentAuthenticator,
3963 (unsigned long)cbCurrentAuthenticator, pbNewAuthenticator,
3964 (unsigned long)cbNewAuthenticator, (unsigned long)cRetryCount,
3965 (unsigned long)dwFlags);
3966
3967 if (wcscmp(wszCARD_USER_USER, pwszUserId) == 0)
3968 pinid = ROLE_USER;
3969 else
3970 pinid = ROLE_ADMIN;
3971
3972 r = CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_CHANGEPIN |
3973 CARD_PIN_SILENT_CONTEXT, pinid,
3974 pbCurrentAuthenticator,
3975 cbCurrentAuthenticator, pinid,
3976 pbNewAuthenticator, cbNewAuthenticator,
3977 cRetryCount, pcAttemptsRemaining);
3978
3979 err:
3980 unlock(pCardData);
3981 MD_FUNC_RETURN(pCardData, 1, r);
3982 }
3983
3984 /* Note: the PIN freshness will be managed by the Base CSP */
CardDeauthenticate(__in PCARD_DATA pCardData,__in LPWSTR pwszUserId,__in DWORD dwFlags)3985 DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData,
3986 __in LPWSTR pwszUserId,
3987 __in DWORD dwFlags)
3988 {
3989 DWORD dwret;
3990 VENDOR_SPECIFIC* vs = NULL;
3991 int rv;
3992
3993 MD_FUNC_CALLED(pCardData, 1);
3994
3995 logprintf(pCardData, 1, "\nP:%ld T:%ld pCardData:%p ",
3996 (unsigned long)GetCurrentProcessId(),
3997 (unsigned long)GetCurrentThreadId(), pCardData);
3998 logprintf(pCardData, 1, "CardDeauthenticate(%S) %lu\n",
3999 NULLWSTR(pwszUserId), (unsigned long)dwFlags);
4000
4001 if(!pCardData || !lock(pCardData))
4002 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4003
4004 dwret = check_card_reader_status(pCardData, "CardDeauthenticate");
4005 if (dwret != SCARD_S_SUCCESS)
4006 goto err;
4007
4008 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
4009 if (!vs) {
4010 dwret = SCARD_E_INVALID_PARAMETER;
4011 goto err;
4012 }
4013
4014 sc_pkcs15_pincache_clear(vs->p15card);
4015
4016 rv = sc_logout(vs->p15card->card);
4017
4018 if (rv != SC_SUCCESS) {
4019 /* force a reset of a card - SCARD_S_SUCCESS do not lead to the reset
4020 * of the card and leave it still authenticated */
4021 dwret = SCARD_E_UNSUPPORTED_FEATURE;
4022 goto err;
4023 }
4024
4025 dwret = SCARD_S_SUCCESS;
4026
4027 err:
4028 unlock(pCardData);
4029
4030 MD_FUNC_RETURN(pCardData, 1, dwret);
4031 }
4032
CardCreateDirectory(__in PCARD_DATA pCardData,__in LPSTR pszDirectoryName,__in CARD_DIRECTORY_ACCESS_CONDITION AccessCondition)4033 DWORD WINAPI CardCreateDirectory(__in PCARD_DATA pCardData,
4034 __in LPSTR pszDirectoryName,
4035 __in CARD_DIRECTORY_ACCESS_CONDITION AccessCondition)
4036 {
4037 MD_FUNC_CALLED(pCardData, 1);
4038
4039 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4040 (unsigned long)GetCurrentProcessId(),
4041 (unsigned long)GetCurrentThreadId(), pCardData);
4042 logprintf(pCardData, 1, "CardCreateDirectory - unsupported\n");
4043
4044 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
4045 }
4046
CardDeleteDirectory(__in PCARD_DATA pCardData,__in LPSTR pszDirectoryName)4047 DWORD WINAPI CardDeleteDirectory(__in PCARD_DATA pCardData,
4048 __in LPSTR pszDirectoryName)
4049 {
4050 MD_FUNC_CALLED(pCardData, 1);
4051
4052 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4053 (unsigned long)GetCurrentProcessId(),
4054 (unsigned long)GetCurrentThreadId(), pCardData);
4055 logprintf(pCardData, 1, "CardDeleteDirectory(%s) - unsupported\n", NULLSTR(pszDirectoryName));
4056
4057 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
4058 }
4059
CardCreateFile(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__in LPSTR pszFileName,__in DWORD cbInitialCreationSize,__in CARD_FILE_ACCESS_CONDITION AccessCondition)4060 DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData,
4061 __in_opt LPSTR pszDirectoryName,
4062 __in LPSTR pszFileName,
4063 __in DWORD cbInitialCreationSize,
4064 __in CARD_FILE_ACCESS_CONDITION AccessCondition)
4065 {
4066 struct md_directory *dir = NULL;
4067 DWORD dwret;
4068
4069 MD_FUNC_CALLED(pCardData, 1);
4070
4071 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4072 (unsigned long)GetCurrentProcessId(),
4073 (unsigned long)GetCurrentThreadId(), pCardData);
4074 logprintf(pCardData, 1,
4075 "CardCreateFile(%s::%s, size %lu, acl:0x%X) called\n",
4076 NULLSTR(pszDirectoryName), NULLSTR(pszFileName),
4077 (unsigned long)cbInitialCreationSize, AccessCondition);
4078
4079 if (!lock(pCardData))
4080 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4081
4082 dwret = check_card_status(pCardData, "CardCreateFile");
4083 if (dwret != SCARD_S_SUCCESS)
4084 goto err;
4085
4086 dwret = md_fs_find_directory(pCardData, NULL, pszDirectoryName, &dir);
4087 if (dwret != SCARD_S_SUCCESS) {
4088 logprintf(pCardData, 1, "CardCreateFile() cannot find parent directory '%s'", NULLSTR(pszDirectoryName));
4089 goto err;
4090 }
4091
4092 dwret = md_fs_add_file(pCardData, &dir->files, pszFileName, AccessCondition, NULL, cbInitialCreationSize, NULL);
4093 if (dwret != SCARD_S_SUCCESS)
4094 goto err;
4095
4096 err:
4097 unlock(pCardData);
4098
4099 MD_FUNC_RETURN(pCardData, 1, dwret);
4100 }
4101
4102
CardReadFile(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__in LPSTR pszFileName,__in DWORD dwFlags,__deref_out_bcount_opt (* pcbData)PBYTE * ppbData,__out PDWORD pcbData)4103 DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData,
4104 __in_opt LPSTR pszDirectoryName,
4105 __in LPSTR pszFileName,
4106 __in DWORD dwFlags,
4107 __deref_out_bcount_opt(*pcbData) PBYTE *ppbData,
4108 __out PDWORD pcbData)
4109 {
4110 struct md_file *file = NULL;
4111 DWORD dwret;
4112
4113 MD_FUNC_CALLED(pCardData, 1);
4114
4115 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4116 (unsigned long)GetCurrentProcessId(),
4117 (unsigned long)GetCurrentThreadId(), pCardData);
4118 logprintf(pCardData, 1, "CardReadFile\n");
4119
4120 if(!pCardData || !lock(pCardData))
4121 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4122
4123 logprintf(pCardData, 2,
4124 "pszDirectoryName = %s, pszFileName = %s, dwFlags = %lX, pcbData=%p, ppbData=%p\n",
4125 NULLSTR(pszDirectoryName), NULLSTR(pszFileName),
4126 (unsigned long)dwFlags, pcbData, ppbData);
4127
4128 if (!pszFileName || !strlen(pszFileName) || dwFlags) {
4129 dwret = SCARD_E_INVALID_PARAMETER;
4130 goto err;
4131 }
4132
4133 dwret = check_card_reader_status(pCardData, "CardReadFile");
4134 if (dwret != SCARD_S_SUCCESS)
4135 goto err;
4136
4137 md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
4138 if (!file) {
4139 logprintf(pCardData, 2, "CardReadFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
4140 dwret = SCARD_E_FILE_NOT_FOUND;
4141 goto err;
4142 }
4143
4144 if (!file->blob) {
4145 dwret = md_fs_read_content(pCardData, pszDirectoryName, file);
4146 if (dwret != SCARD_S_SUCCESS)
4147 goto err;
4148 }
4149
4150 if (ppbData) {
4151 *ppbData = pCardData->pfnCspAlloc(file->size);
4152 if(!*ppbData) {
4153 dwret = SCARD_E_NO_MEMORY;
4154 goto err;
4155 }
4156
4157 memcpy(*ppbData, file->blob, file->size);
4158 }
4159
4160 if (pcbData)
4161 *pcbData = (DWORD)file->size;
4162
4163 logprintf(pCardData, 7, "returns '%s' content:\n", NULLSTR(pszFileName));
4164 loghex(pCardData, 7, file->blob, file->size);
4165
4166 err:
4167 unlock(pCardData);
4168
4169 MD_FUNC_RETURN(pCardData, 1, dwret);
4170 }
4171
4172
CardWriteFile(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__in LPSTR pszFileName,__in DWORD dwFlags,__in_bcount (cbData)PBYTE pbData,__in DWORD cbData)4173 DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData,
4174 __in_opt LPSTR pszDirectoryName,
4175 __in LPSTR pszFileName,
4176 __in DWORD dwFlags,
4177 __in_bcount(cbData) PBYTE pbData,
4178 __in DWORD cbData)
4179 {
4180 struct md_file *file = NULL;
4181 DWORD dwret;
4182
4183 MD_FUNC_CALLED(pCardData, 1);
4184
4185 if(!pCardData || !lock(pCardData))
4186 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4187
4188 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4189 (unsigned long)GetCurrentProcessId(),
4190 (unsigned long)GetCurrentThreadId(), pCardData);
4191 logprintf(pCardData, 1, "CardWriteFile() dirName:'%s', fileName:'%s' \n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName));
4192
4193 dwret = check_card_reader_status(pCardData, "CardWriteFile");
4194 if (dwret != SCARD_S_SUCCESS)
4195 goto err;
4196
4197 if (pbData && cbData) {
4198 logprintf(pCardData, 1, "CardWriteFile try to write (%lu):\n",
4199 (unsigned long)cbData);
4200 loghex(pCardData, 2, pbData, cbData);
4201 }
4202
4203 md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
4204 if (!file) {
4205 logprintf(pCardData, 2, "CardWriteFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
4206 dwret = SCARD_E_FILE_NOT_FOUND;
4207 goto err;
4208 }
4209
4210 logprintf(pCardData, 7, "set content of '%s' to:\n", NULLSTR(pszFileName));
4211 loghex(pCardData, 7, pbData, cbData);
4212
4213 dwret = md_fs_set_content(pCardData, file, pbData, cbData);
4214 if (dwret != SCARD_S_SUCCESS) {
4215 logprintf(pCardData, 1, "cannot set file content: %lu\n",
4216 (unsigned long)dwret);
4217 goto err;
4218 }
4219
4220 if (pszDirectoryName && !strcmp(pszDirectoryName, "mscp")) {
4221 if ((strstr(pszFileName, "kxc") == pszFileName) || (strstr(pszFileName, "ksc") == pszFileName)) {
4222 dwret = md_pkcs15_store_certificate(pCardData, pszFileName, pbData, cbData);
4223 if (dwret != SCARD_S_SUCCESS)
4224 goto err;
4225 logprintf(pCardData, 2, "md_pkcs15_store_certificate() OK\n");
4226 }
4227 }
4228
4229 logprintf(pCardData, 2, "write '%s' ok.\n", NULLSTR(pszFileName));
4230
4231 err:
4232 unlock(pCardData);
4233 MD_FUNC_RETURN(pCardData, 1, dwret);
4234 }
4235
CardDeleteFile(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__in LPSTR pszFileName,__in DWORD dwFlags)4236 DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData,
4237 __in_opt LPSTR pszDirectoryName,
4238 __in LPSTR pszFileName,
4239 __in DWORD dwFlags)
4240 {
4241 DWORD dwret;
4242
4243 MD_FUNC_CALLED(pCardData, 1);
4244
4245 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4246 (unsigned long)GetCurrentProcessId(),
4247 (unsigned long)GetCurrentThreadId(), pCardData);
4248 logprintf(pCardData, 1, "CardDeleteFile(%s, %s) called\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName));
4249
4250 if(!pCardData || !lock(pCardData))
4251 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4252
4253 dwret = check_card_reader_status(pCardData, "CardDeleteFile");
4254 if (dwret != SCARD_S_SUCCESS)
4255 goto err;
4256
4257 dwret = md_fs_delete_file(pCardData, pszDirectoryName, pszFileName);
4258 if (dwret != SCARD_S_SUCCESS) {
4259 logprintf(pCardData, 2,
4260 "CardDeleteFile(): delete file error: %lX\n",
4261 (unsigned long)dwret);
4262 goto err;
4263 }
4264
4265 err:
4266 unlock(pCardData);
4267 MD_FUNC_RETURN(pCardData, 1, dwret);
4268 }
4269
4270
CardEnumFiles(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__deref_out_ecount (* pdwcbFileName)LPSTR * pmszFileNames,__out LPDWORD pdwcbFileName,__in DWORD dwFlags)4271 DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData,
4272 __in_opt LPSTR pszDirectoryName,
4273 __deref_out_ecount(*pdwcbFileName) LPSTR *pmszFileNames,
4274 __out LPDWORD pdwcbFileName,
4275 __in DWORD dwFlags)
4276 {
4277 VENDOR_SPECIFIC *vs = NULL;
4278 DWORD dwret;
4279 char mstr[0x100];
4280 struct md_directory *dir = NULL;
4281 struct md_file *file = NULL;
4282 size_t offs;
4283
4284 MD_FUNC_CALLED(pCardData, 1);
4285
4286 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4287 (unsigned long)GetCurrentProcessId(),
4288 (unsigned long)GetCurrentThreadId(), pCardData);
4289 logprintf(pCardData, 1, "CardEnumFiles() directory '%s'\n", NULLSTR(pszDirectoryName));
4290
4291 if (!pCardData || !pmszFileNames || !pdwcbFileName || !lock(pCardData))
4292 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4293 if (dwFlags) {
4294 logprintf(pCardData, 1,
4295 "CardEnumFiles() dwFlags not 'zero' -- %lX\n",
4296 (unsigned long)dwFlags);
4297 dwret = SCARD_E_INVALID_PARAMETER;
4298 goto err;
4299 }
4300
4301 dwret = check_card_status(pCardData, "CardEnumFiles");
4302 if (dwret != SCARD_S_SUCCESS)
4303 goto err;
4304
4305 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
4306 if (!vs) {
4307 dwret = SCARD_E_INVALID_PARAMETER;
4308 goto err;
4309 }
4310
4311 memset(mstr, 0, sizeof(mstr));
4312
4313 if (!pszDirectoryName || !strlen(pszDirectoryName))
4314 dir = &vs->root;
4315 else
4316 md_fs_find_directory(pCardData, NULL, pszDirectoryName, &dir);
4317 if (!dir) {
4318 logprintf(pCardData, 2, "enum files() failed: directory '%s' not found\n", NULLSTR(pszDirectoryName));
4319 dwret = SCARD_E_FILE_NOT_FOUND;
4320 goto err;
4321 }
4322
4323 file = dir->files;
4324 for (offs = 0; file != NULL && offs < sizeof(mstr) - 10;) {
4325 logprintf(pCardData, 2, "enum files(): file name '%s'\n", file->name);
4326 strlcpy(mstr + offs, (char *)file->name, sizeof(mstr) - offs);
4327 offs += strlen((char *)file->name) + 1;
4328 file = file->next;
4329 }
4330 mstr[offs] = 0;
4331 offs += 1;
4332
4333 *pmszFileNames = (LPSTR)(*pCardData->pfnCspAlloc)(offs);
4334 if (*pmszFileNames == NULL) {
4335 dwret = SCARD_E_NO_MEMORY;
4336 goto err;
4337 }
4338
4339 CopyMemory(*pmszFileNames, mstr, offs);
4340 *pdwcbFileName = (DWORD) offs;
4341
4342 err:
4343 unlock(pCardData);
4344 MD_FUNC_RETURN(pCardData, 1, dwret);
4345 }
4346
4347
CardGetFileInfo(__in PCARD_DATA pCardData,__in_opt LPSTR pszDirectoryName,__in LPSTR pszFileName,__inout PCARD_FILE_INFO pCardFileInfo)4348 DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData,
4349 __in_opt LPSTR pszDirectoryName,
4350 __in LPSTR pszFileName,
4351 __inout PCARD_FILE_INFO pCardFileInfo)
4352 {
4353 DWORD dwret;
4354 struct md_file *file = NULL;
4355
4356 MD_FUNC_CALLED(pCardData, 1);
4357
4358 if(!pCardData || !lock(pCardData))
4359 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4360
4361 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4362 (unsigned long)GetCurrentProcessId(),
4363 (unsigned long)GetCurrentThreadId(), pCardData);
4364 logprintf(pCardData, 1, "CardGetFileInfo(dirName:'%s',fileName:'%s', out %p)\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName), pCardFileInfo);
4365
4366 dwret = check_card_status(pCardData, "CardGetFileInfo");
4367 if (dwret != SCARD_S_SUCCESS)
4368 goto err;
4369
4370 md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file);
4371 if (!file) {
4372 logprintf(pCardData, 2, "CardWriteFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName));
4373 dwret = SCARD_E_FILE_NOT_FOUND;
4374 goto err;
4375 }
4376
4377 pCardFileInfo->dwVersion = CARD_FILE_INFO_CURRENT_VERSION;
4378 pCardFileInfo->cbFileSize = (DWORD) file->size;
4379 pCardFileInfo->AccessCondition = file->acl;
4380
4381 err:
4382 unlock(pCardData);
4383 MD_FUNC_RETURN(pCardData, 1, dwret);
4384 }
4385
4386
CardQueryFreeSpace(__in PCARD_DATA pCardData,__in DWORD dwFlags,__inout PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)4387 DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags,
4388 __inout PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo)
4389 {
4390 DWORD dwret;
4391
4392 MD_FUNC_CALLED(pCardData, 1);
4393
4394 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4395 (unsigned long)GetCurrentProcessId(),
4396 (unsigned long)GetCurrentThreadId(), pCardData);
4397 logprintf(pCardData, 1,
4398 "CardQueryFreeSpace %p, dwFlags=%lX, version=%lX\n",
4399 pCardFreeSpaceInfo, (unsigned long)dwFlags,
4400 (unsigned long)pCardFreeSpaceInfo->dwVersion);
4401
4402 if (!pCardData || !lock(pCardData))
4403 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4404
4405 dwret = check_card_status(pCardData, "CardQueryFreeSpace");
4406 if (dwret != SCARD_S_SUCCESS)
4407 goto err;
4408
4409 dwret = md_free_space(pCardData, pCardFreeSpaceInfo);
4410 if (dwret != SCARD_S_SUCCESS) {
4411 logprintf(pCardData, 1, "CardQueryFreeSpace() md free space error");
4412 goto err;
4413 }
4414
4415 logprintf(pCardData, 7, "FreeSpace:\n");
4416 loghex(pCardData, 7, (BYTE *)pCardFreeSpaceInfo, sizeof(*pCardFreeSpaceInfo));
4417
4418 err:
4419 unlock(pCardData);
4420 MD_FUNC_RETURN(pCardData, 1, dwret);
4421 }
4422
4423
CardQueryKeySizes(__in PCARD_DATA pCardData,__in DWORD dwKeySpec,__in DWORD dwFlags,__inout PCARD_KEY_SIZES pKeySizes)4424 DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData,
4425 __in DWORD dwKeySpec,
4426 __in DWORD dwFlags,
4427 __inout PCARD_KEY_SIZES pKeySizes)
4428 {
4429 DWORD dwret;
4430
4431 MD_FUNC_CALLED(pCardData, 1);
4432
4433 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4434 (unsigned long)GetCurrentProcessId(),
4435 (unsigned long)GetCurrentThreadId(), pCardData);
4436 logprintf(pCardData, 1,
4437 "CardQueryKeySizes dwKeySpec=%lX, dwFlags=%lX, version=%lX\n",
4438 (unsigned long)dwKeySpec, (unsigned long)dwFlags,
4439 pKeySizes ? (unsigned long)pKeySizes->dwVersion : 0);
4440
4441 if (!pCardData || dwFlags != 0 || dwKeySpec == 0 || !lock(pCardData))
4442 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4443
4444 dwret = check_card_status(pCardData, "CardQueryKeySizes");
4445 if (dwret != SCARD_S_SUCCESS)
4446 goto err;
4447
4448 dwret = md_query_key_sizes(pCardData, dwKeySpec, pKeySizes);
4449 if (dwret != SCARD_S_SUCCESS)
4450 goto err;
4451
4452 logprintf(pCardData, 7, "pKeySizes:\n");
4453 loghex(pCardData, 7, (BYTE *)pKeySizes, sizeof(*pKeySizes));
4454
4455 err:
4456 unlock(pCardData);
4457 MD_FUNC_RETURN(pCardData, 1, dwret);
4458 }
4459
4460
CardRSADecrypt(__in PCARD_DATA pCardData,__inout PCARD_RSA_DECRYPT_INFO pInfo)4461 DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
4462 __inout PCARD_RSA_DECRYPT_INFO pInfo)
4463
4464 {
4465 DWORD dwret;
4466 int r, opt_crypt_flags = 0;
4467 unsigned ui;
4468 VENDOR_SPECIFIC *vs;
4469 struct sc_pkcs15_prkey_info *prkey_info;
4470 BYTE *pbuf = NULL, *pbuf2 = NULL;
4471 struct sc_pkcs15_object *pkey = NULL;
4472 struct sc_algorithm_info *alg_info = NULL;
4473
4474 MD_FUNC_CALLED(pCardData, 1);
4475
4476 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4477 (unsigned long)GetCurrentProcessId(),
4478 (unsigned long)GetCurrentThreadId(), pCardData);
4479 logprintf(pCardData, 1, "CardRSADecrypt\n");
4480
4481 if (!pCardData || !pInfo || pInfo->pbData == NULL)
4482 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4483 if (pInfo->dwVersion > CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION)
4484 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
4485 if ( pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION
4486 && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
4487 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
4488 if (pInfo->dwKeySpec != AT_KEYEXCHANGE)
4489 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4490
4491 if (!lock(pCardData))
4492 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4493
4494 dwret = check_card_reader_status(pCardData, "CardRSADecrypt");
4495 if (dwret != SCARD_S_SUCCESS)
4496 goto err;
4497
4498 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
4499 if (!vs) {
4500 dwret = SCARD_E_INVALID_PARAMETER;
4501 goto err;
4502 }
4503
4504 /* check if the container exists */
4505 if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) {
4506 dwret = SCARD_E_NO_KEY_CONTAINER;
4507 goto err;
4508 }
4509
4510 logprintf(pCardData, 2,
4511 "CardRSADecrypt dwVersion=%lu, bContainerIndex=%u, dwKeySpec=%lu pbData=%p, cbData=%lu\n",
4512 (unsigned long)pInfo->dwVersion,
4513 (unsigned int)pInfo->bContainerIndex,
4514 (unsigned long)pInfo->dwKeySpec, pInfo->pbData,
4515 (unsigned long)pInfo->cbData);
4516
4517 if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO)
4518 logprintf(pCardData, 2,
4519 " pPaddingInfo=%p dwPaddingType=0x%08X\n",
4520 pInfo->pPaddingInfo,
4521 (unsigned int)pInfo->dwPaddingType);
4522
4523 pkey = vs->p15_containers[pInfo->bContainerIndex].prkey_obj;
4524 if (!pkey) {
4525 logprintf(pCardData, 2, "CardRSADecrypt prkey not found\n");
4526 dwret = SCARD_E_NO_KEY_CONTAINER;
4527 goto err;
4528 }
4529
4530 /* input and output buffers are always the same size */
4531 pbuf = pCardData->pfnCspAlloc(pInfo->cbData);
4532 if (!pbuf) {
4533 dwret = SCARD_E_NO_MEMORY;
4534 goto err;
4535 }
4536
4537 pbuf2 = pCardData->pfnCspAlloc(pInfo->cbData);
4538 if (!pbuf2) {
4539 pCardData->pfnCspFree(pbuf);
4540 dwret = SCARD_E_NO_MEMORY;
4541 goto err;
4542 }
4543
4544 /*inversion donnees*/
4545 for(ui = 0; ui < pInfo->cbData; ui++)
4546 pbuf[ui] = pInfo->pbData[pInfo->cbData-ui-1];
4547 logprintf(pCardData, 2, "Data to be decrypted (inverted):\n");
4548 loghex(pCardData, 7, pbuf, pInfo->cbData);
4549
4550 prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data);
4551 alg_info = sc_card_find_rsa_alg(vs->p15card->card, (unsigned int) prkey_info->modulus_length);
4552 if (!alg_info) {
4553 logprintf(pCardData, 2,
4554 "Cannot get appropriate RSA card algorithm for key size %"SC_FORMAT_LEN_SIZE_T"u\n",
4555 prkey_info->modulus_length);
4556 pCardData->pfnCspFree(pbuf);
4557 pCardData->pfnCspFree(pbuf2);
4558 dwret = SCARD_F_INTERNAL_ERROR;
4559 goto err;
4560 }
4561
4562 /* filter bogus input: the data to decrypt is shorter than the RSA key ? */
4563 if ( pInfo->cbData < prkey_info->modulus_length / 8)
4564 {
4565 /* according to the minidriver specs, this is the error code to return
4566 (instead of invalid parameter when the call is forwarded to the card implementation) */
4567 pCardData->pfnCspFree(pbuf);
4568 pCardData->pfnCspFree(pbuf2);
4569 dwret = SCARD_E_INSUFFICIENT_BUFFER;
4570 goto err;
4571 }
4572
4573 if (alg_info->flags & SC_ALGORITHM_RSA_RAW) {
4574 logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
4575 r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
4576 logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
4577
4578 if (r > 0) {
4579 /* Need to handle padding */
4580 if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) {
4581 logprintf(pCardData, 2,
4582 "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n",
4583 (unsigned long)pInfo->dwVersion);
4584 if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
4585 size_t temp = pInfo->cbData;
4586 logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
4587 r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
4588 pInfo->cbData = (DWORD) temp;
4589 if (r < 0) {
4590 logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
4591 pCardData->pfnCspFree(pbuf);
4592 pCardData->pfnCspFree(pbuf2);
4593 dwret = SCARD_F_INTERNAL_ERROR;
4594 goto err;
4595 }
4596 }
4597 else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) {
4598 /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
4599 logprintf(pCardData, 2, "OAEP padding not implemented\n");
4600 pCardData->pfnCspFree(pbuf);
4601 pCardData->pfnCspFree(pbuf2);
4602 dwret = SCARD_F_INTERNAL_ERROR;
4603 goto err;
4604 }
4605 }
4606 }
4607 }
4608 else if (alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
4609 logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA_PAD_PKCS1 mechanism\n");
4610 r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags | SC_ALGORITHM_RSA_PAD_PKCS1,
4611 pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
4612 logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
4613 if (r > 0) {
4614 /* No padding info, or padding info none */
4615 if ((pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) ||
4616 ((pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) && (pInfo->dwPaddingType == CARD_PADDING_NONE))) {
4617 if ((unsigned)r <= pInfo->cbData - 9) {
4618 /* add pkcs1 02 padding */
4619 logprintf(pCardData, 2, "Add '%s' to the output data", "PKCS#1 BT02 padding");
4620 memset(pbuf, 0x30, pInfo->cbData);
4621 *(pbuf + 0) = 0;
4622 *(pbuf + 1) = 2;
4623 memcpy(pbuf + pInfo->cbData - r, pbuf2, r);
4624 *(pbuf + pInfo->cbData - r - 1) = 0;
4625 memcpy(pbuf2, pbuf, pInfo->cbData);
4626 }
4627 }
4628 else if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
4629 /* PKCS1 padding is already handled by the card... */
4630 pInfo->cbData = r;
4631 }
4632 /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
4633 }
4634 }
4635 else {
4636 logprintf(pCardData, 2, "CardRSADecrypt: no usable RSA algorithm\n");
4637 pCardData->pfnCspFree(pbuf);
4638 pCardData->pfnCspFree(pbuf2);
4639 dwret = SCARD_E_INVALID_PARAMETER;
4640 goto err;
4641 }
4642
4643 if ( r < 0) {
4644 logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
4645 pCardData->pfnCspFree(pbuf);
4646 pCardData->pfnCspFree(pbuf2);
4647 dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
4648 goto err;
4649 }
4650
4651 logprintf(pCardData, 2, "decrypted data(%lu):\n",
4652 (unsigned long)pInfo->cbData);
4653 loghex(pCardData, 7, pbuf2, pInfo->cbData);
4654
4655 /*inversion donnees */
4656 for(ui = 0; ui < pInfo->cbData; ui++)
4657 pInfo->pbData[ui] = pbuf2[pInfo->cbData-ui-1];
4658
4659 pCardData->pfnCspFree(pbuf);
4660 pCardData->pfnCspFree(pbuf2);
4661
4662 err:
4663 unlock(pCardData);
4664 MD_FUNC_RETURN(pCardData, 1, dwret);
4665 }
4666
4667
CardSignData(__in PCARD_DATA pCardData,__inout PCARD_SIGNING_INFO pInfo)4668 DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO pInfo)
4669 {
4670 DWORD dwret;
4671 VENDOR_SPECIFIC *vs;
4672 ALG_ID hashAlg;
4673 sc_pkcs15_prkey_info_t *prkey_info;
4674 BYTE dataToSign[0x200];
4675 int opt_crypt_flags;
4676 size_t dataToSignLen = sizeof(dataToSign);
4677 sc_pkcs15_object_t *pkey;
4678
4679 MD_FUNC_CALLED(pCardData, 1);
4680
4681 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4682 (unsigned long)GetCurrentProcessId(),
4683 (unsigned long)GetCurrentThreadId(), pCardData);
4684 logprintf(pCardData, 1, "CardSignData\n");
4685
4686 if (!pCardData || !pInfo)
4687 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4688 if ( ( pInfo->dwVersion != CARD_SIGNING_INFO_BASIC_VERSION ) &&
4689 ( pInfo->dwVersion != CARD_SIGNING_INFO_CURRENT_VERSION ) )
4690 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
4691 if ( pInfo->pbData == NULL )
4692 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4693 switch(pInfo->dwKeySpec)
4694 {
4695 case AT_SIGNATURE:
4696 case AT_KEYEXCHANGE:
4697 case AT_ECDSA_P256:
4698 case AT_ECDSA_P384:
4699 case AT_ECDSA_P521:
4700 case AT_ECDHE_P256:
4701 case AT_ECDHE_P384:
4702 case AT_ECDHE_P521:
4703 break;
4704 default:
4705 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4706 }
4707 if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_PADDING_NONE | CARD_BUFFER_SIZE_ONLY | CARD_PADDING_PKCS1 | CARD_PADDING_PSS | CARD_PADDING_OAEP))
4708 return SCARD_E_INVALID_PARAMETER;
4709
4710 if (!lock(pCardData))
4711 return SCARD_E_INVALID_PARAMETER;
4712
4713 dwret = check_card_reader_status(pCardData, "CardSignData");
4714 if (dwret != SCARD_S_SUCCESS)
4715 goto err;
4716
4717 logprintf(pCardData, 2,
4718 "CardSignData dwVersion=%lu, bContainerIndex=%u, dwKeySpec=%lu, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n",
4719 (unsigned long)pInfo->dwVersion,
4720 (unsigned int)pInfo->bContainerIndex,
4721 (unsigned long)pInfo->dwKeySpec,
4722 (unsigned int)pInfo->dwSigningFlags,
4723 (unsigned int)pInfo->aiHashAlg);
4724
4725 logprintf(pCardData, 7, "pInfo->pbData(%lu) ",
4726 (unsigned long)pInfo->cbData);
4727 loghex(pCardData, 7, pInfo->pbData, pInfo->cbData);
4728
4729 hashAlg = pInfo->aiHashAlg;
4730
4731 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
4732 if (!vs) {
4733 dwret = SCARD_E_INVALID_PARAMETER;
4734 goto err;
4735 }
4736
4737 if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) {
4738 dwret = SCARD_E_NO_KEY_CONTAINER;
4739 goto err;
4740 }
4741
4742 pkey = vs->p15_containers[pInfo->bContainerIndex].prkey_obj;
4743 if (!pkey) {
4744 dwret = SCARD_E_NO_KEY_CONTAINER;
4745 goto err;
4746 }
4747 prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data);
4748
4749 logprintf(pCardData, 2, "pInfo->dwVersion = %lu\n",
4750 (unsigned long)pInfo->dwVersion);
4751
4752 if (dataToSignLen < pInfo->cbData) {
4753 dwret = SCARD_E_INSUFFICIENT_BUFFER;
4754 goto err;
4755 }
4756 memcpy(dataToSign, pInfo->pbData, pInfo->cbData);
4757 dataToSignLen = pInfo->cbData;
4758
4759 if (0 == (CARD_PADDING_INFO_PRESENT & pInfo->dwSigningFlags)) {
4760 /* When CARD_PADDING_INFO_PRESENT is not set in dwSigningFlags, this is
4761 * the basic version of the signing structure. (If this is not the
4762 * basic version of the signing structure, the minidriver should return
4763 * ERROR_REVISION_MISMATCH.) The minidriver should only do PKCS1
4764 * padding and use the value in aiHashAlg. */
4765 logprintf(pCardData, 3, "CARD_PADDING_INFO_PRESENT not set\n");
4766
4767 opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PKCS1;
4768 if (hashAlg == CALG_MD5)
4769 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5;
4770 else if (hashAlg == CALG_SHA1)
4771 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
4772 else if (hashAlg == CALG_SSL3_SHAMD5)
4773 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1;
4774 else if (hashAlg == CALG_SHA_256)
4775 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256;
4776 else if (hashAlg == CALG_SHA_384)
4777 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384;
4778 else if (hashAlg == CALG_SHA_512)
4779 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512;
4780 else if (hashAlg == (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_RIPEMD160))
4781 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160;
4782 else if (hashAlg !=0) {
4783 logprintf(pCardData, 0, "bogus aiHashAlg %i\n", hashAlg);
4784 dwret = SCARD_E_UNSUPPORTED_FEATURE;
4785 goto err;
4786 }
4787 } else {
4788 switch (pInfo->dwPaddingType) {
4789 case CARD_PADDING_NONE:
4790 opt_crypt_flags = SC_ALGORITHM_RSA_PAD_NONE;
4791 break;
4792
4793 case CARD_PADDING_PKCS1:
4794 opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PKCS1;
4795 BCRYPT_PKCS1_PADDING_INFO *pkcs1_pinf = (BCRYPT_PKCS1_PADDING_INFO *)pInfo->pPaddingInfo;
4796
4797 if (!pkcs1_pinf->pszAlgId || wcscmp(pkcs1_pinf->pszAlgId, L"SHAMD5") == 0) {
4798 /* hashAlg = CALG_SSL3_SHAMD5; */
4799 logprintf(pCardData, 3, "Using CALG_SSL3_SHAMD5 hashAlg\n");
4800 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1;
4801 } else if (wcscmp(pkcs1_pinf->pszAlgId, BCRYPT_MD5_ALGORITHM) == 0)
4802 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5;
4803 else if (wcscmp(pkcs1_pinf->pszAlgId, BCRYPT_SHA1_ALGORITHM) == 0)
4804 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
4805 else if (wcscmp(pkcs1_pinf->pszAlgId, L"SHA224") == 0)
4806 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA224;
4807 else if (wcscmp(pkcs1_pinf->pszAlgId, BCRYPT_SHA256_ALGORITHM) == 0)
4808 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256;
4809 else if (wcscmp(pkcs1_pinf->pszAlgId, BCRYPT_SHA384_ALGORITHM) == 0)
4810 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384;
4811 else if (wcscmp(pkcs1_pinf->pszAlgId, BCRYPT_SHA512_ALGORITHM) == 0)
4812 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512;
4813 else if (wcscmp(pkcs1_pinf->pszAlgId, L"RIPEMD160") == 0)
4814 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160;
4815 else {
4816 logprintf(pCardData, 0,"unknown AlgId %S\n",NULLWSTR(pkcs1_pinf->pszAlgId));
4817 dwret = SCARD_E_UNSUPPORTED_FEATURE;
4818 goto err;
4819 }
4820 break;
4821
4822 case CARD_PADDING_PSS:
4823 opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PSS;
4824 BCRYPT_PSS_PADDING_INFO *pss_pinf = (BCRYPT_PSS_PADDING_INFO *)pInfo->pPaddingInfo;
4825 ULONG expected_salt_len;
4826
4827 if (!pss_pinf->pszAlgId || wcscmp(pss_pinf->pszAlgId, BCRYPT_SHA1_ALGORITHM) == 0) {
4828 /* hashAlg = CALG_SHA1; */
4829 logprintf(pCardData, 3, "Using CALG_SHA1 hashAlg\n");
4830 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_MGF1_SHA1;
4831 expected_salt_len = 160;
4832 } else if (wcscmp(pss_pinf->pszAlgId, L"SHA224") == 0) {
4833 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA224 | SC_ALGORITHM_MGF1_SHA224;
4834 expected_salt_len = 224;
4835 } else if (wcscmp(pss_pinf->pszAlgId, BCRYPT_SHA256_ALGORITHM) == 0) {
4836 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_MGF1_SHA256;
4837 expected_salt_len = 256;
4838 } else if (wcscmp(pss_pinf->pszAlgId, BCRYPT_SHA384_ALGORITHM) == 0) {
4839 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_MGF1_SHA384;
4840 expected_salt_len = 384;
4841 } else if (wcscmp(pss_pinf->pszAlgId, BCRYPT_SHA512_ALGORITHM) == 0) {
4842 opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512 | SC_ALGORITHM_MGF1_SHA512;
4843 expected_salt_len = 512;
4844 } else {
4845 logprintf(pCardData, 0,"unknown AlgId %S\n",NULLWSTR(pss_pinf->pszAlgId));
4846 dwret = SCARD_E_UNSUPPORTED_FEATURE;
4847 goto err;
4848 }
4849 /* We're strict, and only do PSS signatures with a salt length that
4850 * matches the digest length (any shorter is rubbish, any longer
4851 * is useless). */
4852 if (pss_pinf->cbSalt != expected_salt_len / 8) {
4853 dwret = SCARD_E_INVALID_PARAMETER;
4854 goto err;
4855 }
4856 break;
4857
4858 default:
4859 logprintf(pCardData, 0, "unsupported paddingtype\n");
4860 dwret = SCARD_E_INVALID_PARAMETER;
4861 goto err;
4862 }
4863 }
4864
4865
4866 /* Compute output size */
4867 if ( prkey_info->modulus_length > 0) {
4868 /* RSA */
4869 pInfo->cbSignedData = (DWORD) prkey_info->modulus_length / 8;
4870 } else if ( prkey_info->field_length > 0) {
4871 switch(prkey_info->field_length) {
4872 case 256:
4873 /* ECDSA_P256 */
4874 pInfo->cbSignedData = 256 / 8 * 2;
4875 break;
4876 case 384:
4877 /* ECDSA_P384 */
4878 pInfo->cbSignedData = 384 / 8 * 2;
4879 break;
4880 case 512:
4881 /* ECDSA_P512 : special case !!!*/
4882 pInfo->cbSignedData = 132;
4883 break;
4884 default:
4885 logprintf(pCardData, 0,
4886 "unknown ECC key size %"SC_FORMAT_LEN_SIZE_T"u\n",
4887 prkey_info->field_length);
4888 dwret = SCARD_E_INVALID_VALUE;
4889 goto err;
4890 }
4891 } else {
4892 logprintf(pCardData, 0, "invalid private key\n");
4893 dwret = SCARD_E_INVALID_VALUE;
4894 goto err;
4895 }
4896
4897 logprintf(pCardData, 3, "pInfo->cbSignedData = %lu\n",
4898 (unsigned long)pInfo->cbSignedData);
4899
4900 if(!(pInfo->dwSigningFlags&CARD_BUFFER_SIZE_ONLY)) {
4901 int r,i;
4902 BYTE *pbuf = NULL;
4903 DWORD lg;
4904
4905 lg = pInfo->cbSignedData;
4906 logprintf(pCardData, 3, "lg = %lu\n", (unsigned long)lg);
4907 pbuf = pCardData->pfnCspAlloc(lg);
4908 if (!pbuf) {
4909 dwret = SCARD_E_NO_MEMORY;
4910 goto err;
4911 }
4912
4913 logprintf(pCardData, 7, "Data to sign: ");
4914 loghex(pCardData, 7, dataToSign, dataToSignLen);
4915
4916 pInfo->pbSignedData = (PBYTE) pCardData->pfnCspAlloc(pInfo->cbSignedData);
4917 if (!pInfo->pbSignedData) {
4918 pCardData->pfnCspFree(pbuf);
4919 dwret = SCARD_E_NO_MEMORY;
4920 goto err;
4921 }
4922
4923 r = sc_pkcs15_compute_signature(vs->p15card, pkey, opt_crypt_flags, dataToSign, dataToSignLen, pbuf, lg);
4924 logprintf(pCardData, 2, "sc_pkcs15_compute_signature return %d\n", r);
4925 if(r < 0) {
4926 logprintf(pCardData, 2, "sc_pkcs15_compute_signature error %s\n", sc_strerror(r));
4927 pCardData->pfnCspFree(pbuf);
4928 dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_F_INTERNAL_ERROR);
4929 goto err;
4930 }
4931
4932 pInfo->cbSignedData = r;
4933
4934
4935 /*revert data only for RSA (Microsoft uses the big endian version while everyone is using little endian*/
4936 if ( prkey_info->modulus_length > 0) {
4937 for(i = 0; i < r; i++)
4938 pInfo->pbSignedData[i] = pbuf[r-i-1];
4939 } else {
4940 for(i = 0; i < r; i++)
4941 pInfo->pbSignedData[i] = pbuf[i];
4942 }
4943
4944 pCardData->pfnCspFree(pbuf);
4945
4946 logprintf(pCardData, 7, "Signature (inverted): ");
4947 loghex(pCardData, 7, pInfo->pbSignedData, pInfo->cbSignedData);
4948 }
4949
4950 logprintf(pCardData, 3,
4951 "CardSignData, dwVersion=%lu, name=%S, hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X, hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X\n",
4952 (unsigned long)pCardData->dwVersion,
4953 NULLWSTR(pCardData->pwszCardName),
4954 (size_t)pCardData->hScard,
4955 (size_t)pCardData->hSCardCtx);
4956
4957 err:
4958 unlock(pCardData);
4959 MD_FUNC_RETURN(pCardData, 1, dwret);
4960 }
4961
CardConstructDHAgreement(__in PCARD_DATA pCardData,__inout PCARD_DH_AGREEMENT_INFO pAgreementInfo)4962 DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData,
4963 __inout PCARD_DH_AGREEMENT_INFO pAgreementInfo)
4964 {
4965 DWORD dwret;
4966 VENDOR_SPECIFIC *vs;
4967 struct sc_pkcs15_object *pkey = NULL;
4968 int r, opt_derive_flags = SC_ALGORITHM_ECDH_CDH_RAW;
4969 u8* out = 0;
4970 size_t outlen = 0;
4971 PBYTE pbPublicKey = NULL;
4972 size_t publicKeySize = 0;
4973 struct md_dh_agreement* dh_agreement = NULL;
4974 struct md_dh_agreement* temp = NULL;
4975 BYTE i;
4976
4977 MD_FUNC_CALLED(pCardData, 1);
4978
4979 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
4980 (unsigned long)GetCurrentProcessId(),
4981 (unsigned long)GetCurrentThreadId(), pCardData);
4982 logprintf(pCardData, 1, "CardConstructDHAgreement\n");
4983
4984 if (!pCardData)
4985 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4986 if (!pAgreementInfo)
4987 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4988 if ( pAgreementInfo->pbPublicKey == NULL )
4989 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4990 if (pAgreementInfo->dwVersion > CARD_DH_AGREEMENT_INFO_VERSION)
4991 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
4992 if ( pAgreementInfo->dwVersion < CARD_DH_AGREEMENT_INFO_VERSION
4993 && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
4994 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
4995
4996 if (!lock(pCardData))
4997 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
4998
4999 dwret = check_card_reader_status(pCardData, "CardConstructDHAgreement");
5000 if (dwret != SCARD_S_SUCCESS)
5001 goto err;
5002
5003 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
5004 if (!vs) {
5005 dwret = SCARD_E_INVALID_PARAMETER;
5006 goto err;
5007 }
5008
5009 /* check if the container exists */
5010 if (pAgreementInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) {
5011 dwret = SCARD_E_NO_KEY_CONTAINER;
5012 goto err;
5013 }
5014
5015 logprintf(pCardData, 2, "CardConstructDHAgreement dwVersion=%lu, dwKeySpec=%u pbData=%p, cbData=%lu\n",
5016 (unsigned long)pAgreementInfo->dwVersion,
5017 (unsigned int)pAgreementInfo->bContainerIndex,
5018 pAgreementInfo->pbPublicKey,
5019 (unsigned long)pAgreementInfo->dwPublicKey);
5020
5021 pkey = vs->p15_containers[pAgreementInfo->bContainerIndex].prkey_obj;
5022 if (!pkey) {
5023 logprintf(pCardData, 2, "CardConstructDHAgreement prkey not found\n");
5024 dwret = SCARD_E_NO_KEY_CONTAINER;
5025 goto err;
5026 }
5027
5028 /* convert the Windows public key into an OpenSC public key */
5029 publicKeySize = pAgreementInfo->dwPublicKey - sizeof(BCRYPT_ECCKEY_BLOB) + 1;
5030 pbPublicKey = (PBYTE) pCardData->pfnCspAlloc(publicKeySize);
5031 if (!pbPublicKey) {
5032 dwret = ERROR_OUTOFMEMORY;
5033 goto err;
5034 }
5035
5036 pbPublicKey[0] = 4;
5037 memcpy(pbPublicKey+1, pAgreementInfo->pbPublicKey + sizeof(BCRYPT_ECCKEY_BLOB), publicKeySize-1);
5038
5039 /* derive the key using the OpenSC functions */
5040 r = sc_pkcs15_derive(vs->p15card, pkey, opt_derive_flags, pbPublicKey, publicKeySize, out, &outlen );
5041 logprintf(pCardData, 2, "sc_pkcs15_derive returned %d\n", r);
5042
5043 if ( r < 0) {
5044 logprintf(pCardData, 2, "sc_pkcs15_derive error(%i): %s\n", r, sc_strerror(r));
5045 pCardData->pfnCspFree(pbPublicKey);
5046 dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
5047 goto err;
5048 }
5049
5050 out = pCardData->pfnCspAlloc(outlen);
5051
5052 if (!out) {
5053 dwret = ERROR_OUTOFMEMORY;
5054 goto err;
5055 }
5056
5057 r = sc_pkcs15_derive(vs->p15card, pkey, opt_derive_flags, pbPublicKey, publicKeySize, out, &outlen );
5058 logprintf(pCardData, 2, "sc_pkcs15_derive returned %d\n", r);
5059
5060 pCardData->pfnCspFree(pbPublicKey);
5061
5062 if ( r < 0) {
5063 logprintf(pCardData, 2, "sc_pkcs15_derive error(%i): %s\n", r, sc_strerror(r));
5064 pCardData->pfnCspFree(out);
5065 dwret = md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE);
5066 goto err;
5067 }
5068
5069 /* save the dh agreement for later use */
5070
5071 /* try to find an empty index */
5072 for (i = 0; i < vs->allocatedAgreements; i++) {
5073 dh_agreement = vs->dh_agreements + i;
5074 if (dh_agreement->pbAgreement == NULL) {
5075 pAgreementInfo->bSecretAgreementIndex = i;
5076 dh_agreement->pbAgreement = out;
5077 dh_agreement->dwSize = outlen;
5078 dwret = SCARD_S_SUCCESS;
5079 goto err;
5080 }
5081 }
5082 /* no empty space => need to allocate memory */
5083 temp = (struct md_dh_agreement*) pCardData->pfnCspAlloc((vs->allocatedAgreements+1) * sizeof(struct md_dh_agreement));
5084 if (!temp) {
5085 pCardData->pfnCspFree(out);
5086 dwret = SCARD_E_NO_MEMORY;
5087 goto err;
5088 }
5089 if ((vs->allocatedAgreements) > 0) {
5090 memcpy(temp, vs->dh_agreements, sizeof(struct md_dh_agreement) * (vs->allocatedAgreements));
5091 pCardData->pfnCspFree(vs->dh_agreements);
5092 }
5093 vs->dh_agreements = temp;
5094 dh_agreement = vs->dh_agreements + (vs->allocatedAgreements);
5095 pAgreementInfo->bSecretAgreementIndex = (vs->allocatedAgreements);
5096 dh_agreement->pbAgreement = out;
5097 dh_agreement->dwSize = outlen;
5098 vs->allocatedAgreements++;
5099
5100 err:
5101 unlock(pCardData);
5102 MD_FUNC_RETURN(pCardData, 1, dwret);
5103 }
5104
5105
CardDeriveHashOrHMAC(__in PCARD_DATA pCardData,__inout PCARD_DERIVE_KEY pAgreementInfo,__in struct md_dh_agreement * agreement,__in PWSTR szAlgorithm,__in PBYTE pbHmacKey,__in DWORD dwHmacKeySize)5106 DWORD WINAPI CardDeriveHashOrHMAC(__in PCARD_DATA pCardData,
5107 __inout PCARD_DERIVE_KEY pAgreementInfo,
5108 __in struct md_dh_agreement* agreement,
5109 __in PWSTR szAlgorithm,
5110 __in PBYTE pbHmacKey, __in DWORD dwHmacKeySize
5111 )
5112 {
5113 DWORD dwReturn = 0;
5114 /* CNG variables */
5115 BCRYPT_ALG_HANDLE hAlgorithm = NULL;
5116 BCRYPT_HASH_HANDLE hHash = NULL;
5117 DWORD dwSize, dwHashSize;
5118 PBYTE pbBuffer = NULL;
5119 DWORD dwBufferSize = 0;
5120 ULONG i;
5121 NCryptBufferDesc* parameters = NULL;
5122
5123 MD_FUNC_CALLED(pCardData, 1);
5124
5125 dwReturn = BCryptOpenAlgorithmProvider(&hAlgorithm, szAlgorithm, NULL, (pbHmacKey?BCRYPT_ALG_HANDLE_HMAC_FLAG:0));
5126 if (dwReturn) {
5127 logprintf(pCardData, 0,
5128 "CardDeriveKey: unable to find a provider for the algorithm %S 0x%08X\n",
5129 szAlgorithm, (unsigned int)dwReturn);
5130 goto cleanup;
5131 }
5132 dwSize = sizeof(DWORD);
5133 dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&dwHashSize, dwSize, &dwSize, 0);
5134 if (dwReturn) {
5135 logprintf(pCardData, 0, "CardDeriveKey: unable to get the hash length\n");
5136 goto cleanup;
5137 }
5138 pAgreementInfo->cbDerivedKey = dwHashSize;
5139 if (pAgreementInfo->dwFlags & CARD_BUFFER_SIZE_ONLY) {
5140 dwReturn = SCARD_S_SUCCESS;
5141 goto cleanup;
5142 }
5143 pAgreementInfo->pbDerivedKey = (PBYTE)pCardData->pfnCspAlloc(dwHashSize);
5144 if (pAgreementInfo->pbDerivedKey == NULL) {
5145 dwReturn = SCARD_E_NO_MEMORY;
5146 goto cleanup;
5147 }
5148
5149 dwSize = sizeof(DWORD);
5150 dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&dwBufferSize, dwSize, &dwSize, 0);
5151 if (dwReturn) {
5152 logprintf(pCardData, 0,
5153 "CardDeriveKey: unable to get the buffer length 0x%08X\n",
5154 (unsigned int)dwReturn);
5155 goto cleanup;
5156 }
5157
5158 pbBuffer = (PBYTE)LocalAlloc(0, dwBufferSize);
5159 if (pbBuffer == NULL) {
5160 dwReturn = SCARD_E_NO_MEMORY;
5161 goto cleanup;
5162 }
5163 if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0) {
5164 dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, pbHmacKey, dwHmacKeySize, 0);
5165 }
5166 else {
5167 dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, NULL, 0, 0);
5168 }
5169 if (dwReturn) {
5170 logprintf(pCardData, 0,
5171 "CardDeriveKey: unable to create the alg object 0x%08X\n",
5172 (unsigned int)dwReturn);
5173 goto cleanup;
5174 }
5175
5176 parameters = (NCryptBufferDesc*) pAgreementInfo->pParameterList;
5177 if (parameters) {
5178 for (i = 0; i < parameters->cBuffers; i++) {
5179 NCryptBuffer* buffer = parameters->pBuffers + i;
5180 if (buffer->BufferType == KDF_SECRET_PREPEND) {
5181 dwReturn = BCryptHashData(hHash, (PUCHAR)buffer->pvBuffer, buffer->cbBuffer, 0);
5182 if (dwReturn) {
5183 logprintf(pCardData, 0,
5184 "CardDeriveKey: unable to hash data 0x%08X\n",
5185 (unsigned int)dwReturn);
5186 goto cleanup;
5187 }
5188 }
5189 }
5190 }
5191
5192 dwReturn = BCryptHashData(hHash, (PUCHAR)agreement->pbAgreement, agreement->dwSize, 0);
5193 if (dwReturn) {
5194 logprintf(pCardData, 0,
5195 "CardDeriveKey: unable to hash data 0x%08X\n",
5196 (unsigned int)dwReturn);
5197 goto cleanup;
5198 }
5199
5200 if (parameters) {
5201 for (i = 0; i < parameters->cBuffers; i++) {
5202 NCryptBuffer* buffer = parameters->pBuffers + i;
5203 if (buffer->BufferType == KDF_SECRET_APPEND) {
5204 dwReturn = BCryptHashData(hHash, (PUCHAR)buffer->pvBuffer, buffer->cbBuffer, 0);
5205 if (dwReturn) {
5206 logprintf(pCardData, 0,
5207 "CardDeriveKey: unable to hash data 0x%08X\n",
5208 (unsigned int)dwReturn);
5209 goto cleanup;
5210 }
5211 }
5212 }
5213 }
5214
5215 dwReturn = BCryptFinishHash(hHash, pAgreementInfo->pbDerivedKey, pAgreementInfo->cbDerivedKey, 0);
5216 if (dwReturn) {
5217 logprintf(pCardData, 0,
5218 "CardDeriveKey: unable to finish hash 0x%08X\n",
5219 (unsigned int)dwReturn);
5220 goto cleanup;
5221 }
5222
5223 cleanup:
5224
5225 if (hHash)
5226 BCryptDestroyHash(hHash);
5227 if (pbBuffer)
5228 LocalFree(pbBuffer);
5229 if (hAlgorithm)
5230 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
5231 MD_FUNC_RETURN(pCardData, 1, dwReturn);
5232 }
5233
5234 /* Generic function to perform hash. Could have been OpenSSL but used BCrypt* functions.
5235 BCrypt is loaded as a delay load library. The dll can be loaded into Windows XP until this code is called.
5236 Hopefully, ECC is not available in Windows XP and BCrypt functions are not called */
HashDataWithBCrypt(__in PCARD_DATA pCardData,BCRYPT_ALG_HANDLE hAlgorithm,PBYTE pbOuput,DWORD dwOutputSize,PBYTE pbSecret,DWORD dwSecretSize,PBYTE pbData1,DWORD dwDataSize1,PBYTE pbData2,DWORD dwDataSize2,PBYTE pbData3,DWORD dwDataSize3)5237 DWORD HashDataWithBCrypt(__in PCARD_DATA pCardData, BCRYPT_ALG_HANDLE hAlgorithm,
5238 PBYTE pbOuput, DWORD dwOutputSize, PBYTE pbSecret, DWORD dwSecretSize,
5239 PBYTE pbData1, DWORD dwDataSize1,
5240 PBYTE pbData2, DWORD dwDataSize2,
5241 PBYTE pbData3, DWORD dwDataSize3 )
5242 {
5243 DWORD dwReturn, dwSize, dwBufferSize;
5244 BCRYPT_HASH_HANDLE hHash = NULL;
5245 PBYTE pbBuffer = NULL;
5246
5247 dwSize = sizeof(DWORD);
5248 dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&dwBufferSize, dwSize, &dwSize, 0);
5249 if (dwReturn) {
5250 logprintf(pCardData, 0,
5251 "CardDeriveKey: unable to get the buffer length 0x%08X\n",
5252 (unsigned int)dwReturn);
5253 goto cleanup;
5254 }
5255 pbBuffer = (PBYTE)LocalAlloc(0, dwBufferSize);
5256 if (pbBuffer == NULL) {
5257 dwReturn = SCARD_E_NO_MEMORY;
5258 goto cleanup;
5259 }
5260 dwReturn = BCryptCreateHash(hAlgorithm, &hHash, pbBuffer, dwBufferSize, pbSecret, dwSecretSize, 0);
5261 if (dwReturn) {
5262 logprintf(pCardData, 0,
5263 "CardDeriveKey: unable to create the alg object 0x%08X\n",
5264 (unsigned int)dwReturn);
5265 goto cleanup;
5266 }
5267 if (pbData1) {
5268 dwReturn = BCryptHashData(hHash, pbData1, dwDataSize1, 0);
5269 if (dwReturn) {
5270 logprintf(pCardData, 0,
5271 "CardDeriveKey: unable to hash data 0x%08X\n",
5272 (unsigned int)dwReturn);
5273 goto cleanup;
5274 }
5275 }
5276 if (pbData2) {
5277 dwReturn = BCryptHashData(hHash, pbData2, dwDataSize2, 0);
5278 if (dwReturn) {
5279 logprintf(pCardData, 0,
5280 "CardDeriveKey: unable to hash data 0x%08X\n",
5281 (unsigned int)dwReturn);
5282 goto cleanup;
5283 }
5284 }
5285 if (pbData3) {
5286 dwReturn = BCryptHashData(hHash, pbData3, dwDataSize3, 0);
5287 if (dwReturn) {
5288 logprintf(pCardData, 0,
5289 "CardDeriveKey: unable to hash data 0x%08X\n",
5290 (unsigned int)dwReturn);
5291 goto cleanup;
5292 }
5293 }
5294 dwReturn = BCryptFinishHash(hHash, pbOuput, dwOutputSize, 0);
5295 if (dwReturn) {
5296 logprintf(pCardData, 0,
5297 "CardDeriveKey: unable to finish hash 0x%08X\n",
5298 (unsigned int)dwReturn);
5299 goto cleanup;
5300 }
5301 cleanup:
5302 if (hHash)
5303 BCryptDestroyHash(hHash);
5304 if (pbBuffer)
5305 LocalFree(pbBuffer);
5306 return dwReturn;
5307 }
5308
5309 /* Generic function for TLS PRF. Compute the P_HASH function */
DoTlsPrf(__in PCARD_DATA pCardData,__in PBYTE pbOutput,__in PBYTE pbSecret,__in DWORD dwSecretSize,__in PWSTR szAlgorithm,__in PBYTE pbLabel,__in DWORD dwLabelSize,__in PBYTE pbSeed)5310 DWORD WINAPI DoTlsPrf(__in PCARD_DATA pCardData,
5311 __in PBYTE pbOutput,
5312 __in PBYTE pbSecret,
5313 __in DWORD dwSecretSize,
5314 __in PWSTR szAlgorithm,
5315 __in PBYTE pbLabel, __in DWORD dwLabelSize,
5316 __in PBYTE pbSeed
5317 )
5318 {
5319 DWORD dwReturn = 0, i;
5320 /* CNG variables */
5321 BCRYPT_ALG_HANDLE hAlgorithm = NULL;
5322 DWORD dwSize, dwHashSize, dwNumberOfRounds, dwLastRoundSize;
5323 PBYTE pbBuffer = NULL;
5324 /* TLS intermediate results */
5325 PBYTE pbAx = NULL;
5326
5327 dwReturn = BCryptOpenAlgorithmProvider(&hAlgorithm, szAlgorithm, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
5328 if (dwReturn) {
5329 logprintf(pCardData, 0,
5330 "CardDeriveKey: unable to find a provider for the algorithm %S 0x%08X\n",
5331 szAlgorithm, (unsigned int)dwReturn);
5332 goto cleanup;
5333 }
5334 dwSize = sizeof(DWORD);
5335 dwReturn = BCryptGetProperty(hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&dwHashSize, dwSize, &dwSize, 0);
5336 if (dwReturn) {
5337 logprintf(pCardData, 0, "CardDeriveKey: unable to get the hash length\n");
5338 goto cleanup;
5339 }
5340
5341 /* size is always 48 */
5342 dwLastRoundSize = TLS_DERIVE_KEY_SIZE % dwHashSize;
5343 if (dwLastRoundSize == 0) dwLastRoundSize = dwHashSize;
5344 dwNumberOfRounds = (DWORD) (TLS_DERIVE_KEY_SIZE / dwHashSize) + (dwLastRoundSize == dwHashSize?0:1);
5345
5346 /* store TLS A1, A2 intermediate operations */
5347 pbAx = (PBYTE) LocalAlloc(0, dwNumberOfRounds * dwHashSize);
5348 if (pbAx == NULL) {
5349 dwReturn = SCARD_E_NO_MEMORY;
5350 goto cleanup;
5351 }
5352
5353 pbBuffer = (PBYTE) LocalAlloc(0, dwHashSize);
5354 if (pbBuffer == NULL) {
5355 dwReturn = SCARD_E_NO_MEMORY;
5356 goto cleanup;
5357 }
5358
5359 for (i = 0; i<dwNumberOfRounds; i++) {
5360 /* A1, A2, ... */
5361 if (i == 0) {
5362 /* A(1) = HMAC_hash(secret, label + seed)*/
5363 dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
5364 pbAx, dwHashSize, pbSecret, dwSecretSize,
5365 pbLabel, dwLabelSize,
5366 pbSeed, 64,
5367 NULL, 0);
5368 } else {
5369 /* A(i) = HMAC_hash(secret, A(i-1))*/
5370 dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
5371 pbAx + i * dwHashSize, dwHashSize, pbSecret, dwSecretSize,
5372 pbAx + (i-1) * dwHashSize, dwHashSize,
5373 NULL, 0,
5374 NULL, 0);
5375 }
5376 if (dwReturn) {
5377 logprintf(pCardData, 0,
5378 "CardDeriveKey: unable to hash %S 0x%08X\n",
5379 szAlgorithm, (unsigned int)dwReturn);
5380 goto cleanup;
5381 }
5382 if (dwNumberOfRounds -1 == i) {
5383 /* last round */
5384 dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
5385 pbBuffer, dwHashSize, pbSecret, dwSecretSize,
5386 pbAx + i * dwHashSize, dwHashSize,
5387 pbLabel, dwLabelSize,
5388 pbSeed, 64);
5389 memcpy(pbOutput + i * dwHashSize, pbBuffer, dwLastRoundSize);
5390 } else {
5391 dwReturn = HashDataWithBCrypt(pCardData, hAlgorithm,
5392 pbOutput + i * dwHashSize, dwHashSize, pbSecret, dwSecretSize,
5393 pbAx + i * dwHashSize, dwHashSize,
5394 pbLabel, dwLabelSize,
5395 pbSeed, 64);
5396 }
5397 if (dwReturn) {
5398 logprintf(pCardData, 0,
5399 "CardDeriveKey: unable to hash %S 0x%08X\n",
5400 szAlgorithm, (unsigned int)dwReturn);
5401 goto cleanup;
5402 }
5403 }
5404
5405 cleanup:
5406 if (pbBuffer)
5407 LocalFree(pbBuffer);
5408 if (pbAx)
5409 LocalFree(pbAx);
5410 if (hAlgorithm)
5411 BCryptCloseAlgorithmProvider(hAlgorithm, 0);
5412 return dwReturn;
5413 }
5414
5415 /* Implement TLS 1.0, 1.1 and 1.2 PRF */
CardDeriveTlsPrf(__in PCARD_DATA pCardData,__inout PCARD_DERIVE_KEY pAgreementInfo,__in struct md_dh_agreement * agreement,__in DWORD dwProtocol,__in PWSTR szAlgorithm,__in PBYTE pbLabel,__in DWORD dwLabelSize,__in PBYTE pbSeed)5416 DWORD WINAPI CardDeriveTlsPrf(__in PCARD_DATA pCardData,
5417 __inout PCARD_DERIVE_KEY pAgreementInfo,
5418 __in struct md_dh_agreement* agreement,
5419 __in DWORD dwProtocol,
5420 __in PWSTR szAlgorithm,
5421 __in PBYTE pbLabel, __in DWORD dwLabelSize,
5422 __in PBYTE pbSeed
5423 )
5424 {
5425 DWORD dwReturn = 0;
5426 PBYTE pbBuffer = NULL;
5427 DWORD i;
5428 if(dwProtocol == 0) {
5429 dwProtocol = TLS1_0_PROTOCOL_VERSION;
5430 } else if (dwProtocol == TLS1_0_PROTOCOL_VERSION || dwProtocol == TLS1_1_PROTOCOL_VERSION) {
5431 /* TLS 1.0 & 1.1 */
5432 } else if (dwProtocol == TLS1_2_PROTOCOL_VERSION) {
5433 /* TLS 1.2 */
5434 if (szAlgorithm && wcscmp(szAlgorithm, BCRYPT_SHA256_ALGORITHM) != 0 && wcscmp(szAlgorithm, BCRYPT_SHA384_ALGORITHM) != 0) {
5435 logprintf(pCardData, 0, "CardDeriveKey: The algorithm for TLS_PRF is invalid %S\n", szAlgorithm);
5436 return SCARD_E_INVALID_PARAMETER;
5437 }
5438 } else {
5439 logprintf(pCardData, 0,
5440 "CardDeriveTlsPrf: TLS protocol unknown 0x%08X\n",
5441 (unsigned int)dwReturn);
5442 return SCARD_E_INVALID_PARAMETER;
5443 }
5444 /* size is always 48 according to msdn */
5445 pAgreementInfo->cbDerivedKey = TLS_DERIVE_KEY_SIZE;
5446 if (pAgreementInfo->dwFlags & CARD_BUFFER_SIZE_ONLY) {
5447 return SCARD_S_SUCCESS;
5448 }
5449
5450 pAgreementInfo->pbDerivedKey = (PBYTE)pCardData->pfnCspAlloc(TLS_DERIVE_KEY_SIZE);
5451 if (pAgreementInfo->pbDerivedKey == NULL) {
5452 return SCARD_E_NO_MEMORY;
5453 }
5454
5455 if (dwProtocol == TLS1_0_PROTOCOL_VERSION || dwProtocol == TLS1_1_PROTOCOL_VERSION) {
5456 /* TLS 1.0 & 1.1 */
5457 DWORD dwNewSecretLength = (((agreement->dwSize) + (2) - 1) / (2));
5458 dwReturn = DoTlsPrf(pCardData,
5459 pAgreementInfo->pbDerivedKey,
5460 agreement->pbAgreement,
5461 dwNewSecretLength,
5462 BCRYPT_MD5_ALGORITHM,
5463 pbLabel, dwLabelSize,
5464 pbSeed);
5465 if (dwReturn) {
5466 logprintf(pCardData, 0,
5467 "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n",
5468 szAlgorithm, (unsigned int)dwReturn);
5469 pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
5470 pAgreementInfo->pbDerivedKey = NULL;
5471 return dwReturn;
5472 }
5473 pbBuffer = (PBYTE) LocalAlloc(0, TLS_DERIVE_KEY_SIZE);
5474 if (!pbBuffer) {
5475 pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
5476 pAgreementInfo->pbDerivedKey = NULL;
5477 return SCARD_E_NO_MEMORY;
5478 }
5479 dwReturn = DoTlsPrf(pCardData,
5480 pbBuffer,
5481 agreement->pbAgreement + dwNewSecretLength,
5482 dwNewSecretLength,
5483 BCRYPT_SHA1_ALGORITHM,
5484 pbLabel, dwLabelSize,
5485 pbSeed);
5486 if (dwReturn) {
5487 logprintf(pCardData, 0,
5488 "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n",
5489 szAlgorithm, (unsigned int)dwReturn);
5490 LocalFree(pbBuffer);
5491 pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
5492 pAgreementInfo->pbDerivedKey = NULL;
5493 return dwReturn;
5494 }
5495 for (i = 0; i< TLS_DERIVE_KEY_SIZE; i++) {
5496 pAgreementInfo->pbDerivedKey[i] = pAgreementInfo->pbDerivedKey[i] ^ pbBuffer[i];
5497 }
5498 LocalFree(pbBuffer);
5499
5500 } else if (dwProtocol == TLS1_2_PROTOCOL_VERSION) {
5501 dwReturn = DoTlsPrf(pCardData,
5502 pAgreementInfo->pbDerivedKey,
5503 agreement->pbAgreement,
5504 agreement->dwSize,
5505 szAlgorithm,
5506 pbLabel, dwLabelSize,
5507 pbSeed);
5508 if (dwReturn) {
5509 logprintf(pCardData, 0,
5510 "CardDeriveTlsPrf: unable to DoTlsPrf with %S 0x%08X\n",
5511 szAlgorithm, (unsigned int)dwReturn);
5512 pCardData->pfnCspFree(pAgreementInfo->pbDerivedKey );
5513 pAgreementInfo->pbDerivedKey = NULL;
5514 return dwReturn;
5515 }
5516 }
5517 return SCARD_S_SUCCESS;
5518 }
5519
CardDeriveKey(__in PCARD_DATA pCardData,__inout PCARD_DERIVE_KEY pAgreementInfo)5520 DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData,
5521 __inout PCARD_DERIVE_KEY pAgreementInfo)
5522 {
5523 VENDOR_SPECIFIC *vs;
5524 struct md_dh_agreement* agreement = NULL;
5525 NCryptBufferDesc* parameters = NULL;
5526 ULONG i;
5527 DWORD dwReturn = 0;
5528 /* store parameter references */
5529 PWSTR szAlgorithm = NULL;
5530 PBYTE pbHmacKey = NULL;
5531 DWORD dwHmacKeySize = 0;
5532 PBYTE pbLabel = NULL;
5533 DWORD dwLabelSize = 0;
5534 PBYTE pbSeed = NULL;
5535 DWORD dwProtocol = 0;
5536
5537 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
5538 (unsigned long)GetCurrentProcessId(),
5539 (unsigned long)GetCurrentThreadId(), pCardData);
5540 logprintf(pCardData, 1, "CardDeriveKey\n");
5541
5542 MD_FUNC_CALLED(pCardData, 1);
5543
5544 if (!pCardData)
5545 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5546 if (!pAgreementInfo)
5547 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5548 if (!pAgreementInfo->dwVersion)
5549 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
5550 if (pAgreementInfo->dwVersion > CARD_DERIVE_KEY_CURRENT_VERSION)
5551 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
5552 if (pAgreementInfo->pwszKDF == NULL)
5553 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5554 if (pAgreementInfo->dwFlags & ~(KDF_USE_SECRET_AS_HMAC_KEY_FLAG | CARD_RETURN_KEY_HANDLE | CARD_BUFFER_SIZE_ONLY))
5555 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5556
5557 /* according to the documentation, CARD_DERIVE_KEY_CURRENT_VERSION should be equal to 2.
5558 In practice it is not 2 but 1
5559
5560 if ( pAgreementInfo->dwVersion < CARD_DERIVE_KEY_CURRENT_VERSION
5561 && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION)
5562 return ERROR_REVISION_MISMATCH;*/
5563
5564 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
5565 if (!vs)
5566 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5567
5568 /* check if the agreement index is ok */
5569 if (pAgreementInfo->bSecretAgreementIndex >= vs->allocatedAgreements) {
5570 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5571 }
5572
5573 agreement = vs->dh_agreements + pAgreementInfo->bSecretAgreementIndex;
5574 if (agreement->pbAgreement == NULL) {
5575 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5576 }
5577
5578 if (pAgreementInfo->dwFlags & CARD_RETURN_KEY_HANDLE ) {
5579 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
5580 }
5581
5582 /* find the algorithm, checks parameters */
5583
5584 parameters = (NCryptBufferDesc*)pAgreementInfo->pParameterList;
5585
5586 if (parameters) {
5587 for (i = 0; i < parameters->cBuffers; i++) {
5588 NCryptBuffer* buffer = parameters->pBuffers + i;
5589 switch(buffer->BufferType) {
5590 case KDF_HASH_ALGORITHM:
5591 if (szAlgorithm != NULL) {
5592 logprintf(pCardData, 0, "CardDeriveKey: got more than one algorithm\n");
5593 return SCARD_E_INVALID_PARAMETER;
5594 }
5595 if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA1_ALGORITHM) == 0) {
5596 szAlgorithm = BCRYPT_SHA1_ALGORITHM;
5597 } else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA256_ALGORITHM) == 0) {
5598 szAlgorithm = BCRYPT_SHA256_ALGORITHM;
5599 } else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA384_ALGORITHM) == 0) {
5600 szAlgorithm = BCRYPT_SHA384_ALGORITHM;
5601 } else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_SHA512_ALGORITHM) == 0) {
5602 szAlgorithm = BCRYPT_SHA512_ALGORITHM;
5603 } else if (wcscmp((PWSTR) buffer->pvBuffer, BCRYPT_MD5_ALGORITHM) == 0) {
5604 szAlgorithm = BCRYPT_MD5_ALGORITHM;
5605 } else {
5606 logprintf(pCardData, 0,
5607 "CardDeriveKey: unsupported algorithm %S\n",
5608 (PWSTR)buffer->pvBuffer);
5609 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5610 }
5611 break;
5612 case KDF_HMAC_KEY:
5613 if (pbHmacKey != NULL) {
5614 logprintf(pCardData, 0, "CardDeriveKey: got more than one hhmac key\n");
5615 return SCARD_E_INVALID_PARAMETER;
5616 }
5617 pbHmacKey = (PBYTE) buffer->pvBuffer;
5618 dwHmacKeySize = buffer->cbBuffer;
5619 break;
5620 case KDF_SECRET_APPEND:
5621 case KDF_SECRET_PREPEND:
5622 /* do not throw an error for invalid arg*/
5623 break;
5624 case KDF_TLS_PRF_LABEL:
5625 if (pbLabel != NULL) {
5626 logprintf(pCardData, 0, "CardDeriveKey: got more than one Label\n");
5627 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5628 }
5629 pbLabel = (PBYTE)buffer->pvBuffer;
5630 dwLabelSize = buffer->cbBuffer;
5631 break;
5632 case KDF_TLS_PRF_SEED:
5633 if (pbSeed != NULL) {
5634 logprintf(pCardData, 0, "CardDeriveKey: got more than one Seed\n");
5635 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5636 }
5637 if (buffer->cbBuffer != 64)
5638 {
5639 logprintf(pCardData, 0,
5640 "CardDeriveKey: invalid seed size %lu\n",
5641 buffer->cbBuffer);
5642 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5643 }
5644 pbSeed = (PBYTE)buffer->pvBuffer;
5645 break;
5646 case KDF_TLS_PRF_PROTOCOL:
5647 dwProtocol = *((PDWORD)buffer->pvBuffer);
5648 break;
5649 /*case KDF_ALGORITHMID:
5650 case KDF_PARTYUINFO:
5651 case KDF_PARTYVINFO:
5652 case KDF_SUPPPUBINFO:
5653 case KDF_SUPPPRIVINFO:
5654 break;*/
5655 default:
5656 logprintf(pCardData, 0,
5657 "CardDeriveKey: unknown buffer type %lu\n",
5658 (parameters->pBuffers + i)->BufferType);
5659 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5660 }
5661 }
5662 }
5663 /* default parameters */
5664 if (szAlgorithm == NULL && wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) != 0) {
5665 szAlgorithm = BCRYPT_SHA1_ALGORITHM;
5666 }
5667
5668 /* check the values with the KDF chosen */
5669 if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HASH) == 0) {
5670 }
5671 else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0) {
5672 if (pbHmacKey == NULL) {
5673 logprintf(pCardData, 0, "CardDeriveKey: no hhmac key for hmac KDF\n");
5674 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5675 }
5676 }
5677 else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) {
5678 if (!pbSeed) {
5679 logprintf(pCardData, 0, "CardDeriveKey: No seed was provided\n");
5680 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5681 }
5682 if (!pbLabel) {
5683 logprintf(pCardData, 0, "CardDeriveKey: No label was provided\n");
5684 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5685 }
5686 } else {
5687 logprintf(pCardData, 0, "CardDeriveKey: unsupported KDF %S\n", pAgreementInfo->pwszKDF);
5688 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5689 }
5690
5691 /* do the job for the KDF Hash & Hmac */
5692 if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HASH) == 0 ||
5693 wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0 ) {
5694
5695 dwReturn = CardDeriveHashOrHMAC(pCardData, pAgreementInfo, agreement, szAlgorithm, pbHmacKey, dwHmacKeySize);
5696 if (dwReturn) {
5697 logprintf(pCardData, 0,
5698 "CardDeriveKey: got an error while deriving the Key (hash or HMAC) 0x%08X\n",
5699 (unsigned int)dwReturn);
5700 MD_FUNC_RETURN(pCardData, 1, dwReturn);
5701 }
5702
5703 } else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) {
5704 dwReturn = CardDeriveTlsPrf(pCardData, pAgreementInfo, agreement, dwProtocol, szAlgorithm, pbLabel, dwLabelSize, pbSeed);
5705 if (dwReturn) {
5706 logprintf(pCardData, 0,
5707 "CardDeriveKey: got an error while deriving the Key (TlsPrf) 0x%08X\n",
5708 (unsigned int)dwReturn);
5709 MD_FUNC_RETURN(pCardData, 1, dwReturn);
5710 }
5711 }
5712 /*else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_SP80056A_CONCAT ) == 0) {
5713 }*/
5714
5715
5716 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
5717
5718 }
5719
CardDestroyDHAgreement(__in PCARD_DATA pCardData,__in BYTE bSecretAgreementIndex,__in DWORD dwFlags)5720 DWORD WINAPI CardDestroyDHAgreement(
5721 __in PCARD_DATA pCardData,
5722 __in BYTE bSecretAgreementIndex,
5723 __in DWORD dwFlags)
5724 {
5725 VENDOR_SPECIFIC *vs;
5726 struct md_dh_agreement* agreement = NULL;
5727
5728 MD_FUNC_CALLED(pCardData, 1);
5729
5730 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
5731 (unsigned long)GetCurrentProcessId(),
5732 (unsigned long)GetCurrentThreadId(), pCardData);
5733 logprintf(pCardData, 1, "CardDestroyDHAgreement\n");
5734
5735 if (!pCardData)
5736 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5737 if (dwFlags)
5738 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5739 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
5740 if (!vs)
5741 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5742
5743 if (bSecretAgreementIndex >= vs->allocatedAgreements) {
5744 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5745 }
5746
5747 agreement = vs->dh_agreements + bSecretAgreementIndex;
5748 if (agreement->pbAgreement == NULL) {
5749 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5750 }
5751 SecureZeroMemory(agreement->pbAgreement, agreement->dwSize);
5752 pCardData->pfnCspFree(agreement->pbAgreement);
5753 agreement->pbAgreement = 0;
5754 agreement->dwSize = 0;
5755 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
5756 }
5757
CardGetChallengeEx(__in PCARD_DATA pCardData,__in PIN_ID PinId,__deref_out_bcount (* pcbChallengeData)PBYTE * ppbChallengeData,__out PDWORD pcbChallengeData,__in DWORD dwFlags)5758 DWORD WINAPI CardGetChallengeEx(__in PCARD_DATA pCardData,
5759 __in PIN_ID PinId,
5760 __deref_out_bcount(*pcbChallengeData) PBYTE *ppbChallengeData,
5761 __out PDWORD pcbChallengeData,
5762 __in DWORD dwFlags)
5763 {
5764 MD_FUNC_CALLED(pCardData, 1);
5765
5766 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
5767 (unsigned long)GetCurrentProcessId(),
5768 (unsigned long)GetCurrentThreadId(), pCardData);
5769 logprintf(pCardData, 1, "CardGetChallengeEx - unsupported\n");
5770
5771 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
5772 }
5773
CardAuthenticateEx(__in PCARD_DATA pCardData,__in PIN_ID PinId,__in DWORD dwFlags,__in_bcount (cbPinData)PBYTE pbPinData,__in DWORD cbPinData,__deref_opt_out_bcount (* pcbSessionPin)PBYTE * ppbSessionPin,__out_opt PDWORD pcbSessionPin,__out_opt PDWORD pcAttemptsRemaining)5774 DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData,
5775 __in PIN_ID PinId,
5776 __in DWORD dwFlags,
5777 __in_bcount(cbPinData) PBYTE pbPinData,
5778 __in DWORD cbPinData,
5779 __deref_opt_out_bcount(*pcbSessionPin) PBYTE *ppbSessionPin,
5780 __out_opt PDWORD pcbSessionPin,
5781 __out_opt PDWORD pcAttemptsRemaining)
5782 {
5783 DWORD dwret;
5784 VENDOR_SPECIFIC *vs;
5785 struct sc_pkcs15_object *pin_obj = NULL;
5786 struct sc_pkcs15_auth_info *auth_info = NULL;
5787 unsigned int auth_method;
5788 int r;
5789 BOOL DisplayPinpadUI = FALSE;
5790
5791 MD_FUNC_CALLED(pCardData, 1);
5792
5793 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
5794 (unsigned long)GetCurrentProcessId(),
5795 (unsigned long)GetCurrentThreadId(), pCardData);
5796 logprintf(pCardData, 1, "CardAuthenticateEx\n");
5797
5798 if (!pCardData)
5799 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5800
5801 dwret = check_card_reader_status(pCardData, "CardAuthenticateEx");
5802 if (dwret != SCARD_S_SUCCESS)
5803 MD_FUNC_RETURN(pCardData, 1, dwret);
5804
5805 logprintf(pCardData, 2,
5806 "CardAuthenticateEx: PinId=%u, dwFlags=0x%08X, cbPinData=%lu, Attempts %s\n",
5807 (unsigned int)PinId, (unsigned int)dwFlags,
5808 (unsigned long)cbPinData, pcAttemptsRemaining ? "YES" : "NO");
5809
5810 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
5811 if (!vs)
5812 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5813
5814 if (PinId >= MD_MAX_PINS)
5815 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5816
5817 pin_obj = vs->pin_objs[PinId];
5818 if (!pin_obj)
5819 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5820
5821 #if 0
5822 /* TODO do we need to return SCARD_E_UNSUPPORTED_FEATURE if the card
5823 * doesn't support it or if the minidriver doesn't support it in general?
5824 * */
5825 if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) {
5826 if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD
5827 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH))
5828 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
5829 }
5830 #endif
5831
5832 if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT))
5833 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5834
5835 if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN &&
5836 (ppbSessionPin == NULL || pcbSessionPin == NULL))
5837 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5838
5839 /* using a pin pad */
5840 if (NULL == pbPinData) {
5841 if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD
5842 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH))
5843 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5844 if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)
5845 && !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) {
5846 DisplayPinpadUI = TRUE;
5847 }
5848 }
5849
5850 if(pcAttemptsRemaining)
5851 (*pcAttemptsRemaining) = (DWORD) -1;
5852
5853 auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
5854 /* save the pin type */
5855 auth_method = auth_info->auth_method;
5856
5857 /* Do we need to display a prompt to enter PIN on pin pad? */
5858 logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n",
5859 vs->reader->capabilities & SC_READER_CAP_PIN_PAD
5860 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH
5861 ? "yes" : "no", pbPinData, vs->hwndParent);
5862
5863 if (dwFlags & CARD_AUTHENTICATE_SESSION_PIN) {
5864 /* check if the pin is the session pin generated by a previous authentication with a pinpad */
5865 if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) {
5866 logprintf(pCardData, 2, "use magic session pin");
5867 pbPinData = NULL;
5868 cbPinData = 0;
5869 } else {
5870 /* seems we have a real session pin, set the pin type accordingly */
5871 logprintf(pCardData, 2,
5872 "use real session pin with %lu bytes",
5873 (unsigned long)cbPinData);
5874 auth_info->auth_method = SC_AC_SESSION;
5875 }
5876 }
5877
5878 /* set the session pin according to the minidriver specification */
5879 if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN) {
5880 size_t session_pin_len = SC_MAX_PIN_SIZE;
5881
5882 logprintf(pCardData, 2, "generating session pin");
5883 *ppbSessionPin = pCardData->pfnCspAlloc(SC_MAX_PIN_SIZE);
5884 r = md_dialog_perform_pin_operation(pCardData,
5885 SC_PIN_CMD_GET_SESSION_PIN,
5886 vs->p15card, pin_obj,
5887 (const u8 *) pbPinData,
5888 cbPinData,
5889 *ppbSessionPin,
5890 *ppbSessionPin != NULL ?
5891 &session_pin_len : NULL,
5892 DisplayPinpadUI, PinId);
5893 if (r) {
5894 if (*ppbSessionPin != NULL) {
5895 pCardData->pfnCspFree(*ppbSessionPin);
5896 *ppbSessionPin = NULL;
5897 }
5898 *pcbSessionPin = 0;
5899 logprintf(pCardData, 2, "generating session pin failed");
5900 } else {
5901 if (*ppbSessionPin != NULL && session_pin_len > 0) {
5902 logprintf(pCardData, 2,
5903 "generated session pin with %"SC_FORMAT_LEN_SIZE_T"u bytes",
5904 session_pin_len);
5905
5906 *pcbSessionPin = session_pin_len;
5907 } else {
5908 logprintf(pCardData, 2, "session pin not supported");
5909 if (*ppbSessionPin != NULL) {
5910 pCardData->pfnCspFree(*ppbSessionPin);
5911 *ppbSessionPin = NULL;
5912 }
5913 *pcbSessionPin = 0;
5914 }
5915 }
5916 } else {
5917 if (pcbSessionPin) *pcbSessionPin = 0;
5918 if (ppbSessionPin) *ppbSessionPin = NULL;
5919 logprintf(pCardData, 2, "standard pin verification");
5920 r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, NULL, DisplayPinpadUI, PinId);
5921 }
5922
5923 /* restore the pin type */
5924 auth_info->auth_method = auth_method;
5925
5926 if (r) {
5927 logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left);
5928
5929 if (r == SC_ERROR_AUTH_METHOD_BLOCKED) {
5930 if(pcAttemptsRemaining)
5931 (*pcAttemptsRemaining) = 0;
5932 MD_FUNC_RETURN(pCardData, 1, SCARD_W_CHV_BLOCKED);
5933 }
5934
5935 if(pcAttemptsRemaining)
5936 (*pcAttemptsRemaining) = auth_info->tries_left;
5937 MD_FUNC_RETURN(pCardData, 1, md_translate_OpenSC_to_Windows_error(r, SCARD_W_WRONG_CHV));
5938 }
5939
5940 logprintf(pCardData, 2, "Pin code correct.\n");
5941
5942 /* set the session pin according to the minidriver specification */
5943 if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN
5944 && *pcbSessionPin == 0
5945 && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD
5946 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
5947 /* If we could not generate a real session PIN, set it to a special
5948 * value for pinpad authentication to force a new pinpad authentication */
5949 *ppbSessionPin = pCardData->pfnCspAlloc(sizeof(MAGIC_SESSION_PIN));
5950 if (*ppbSessionPin != NULL) {
5951 memcpy(*ppbSessionPin, MAGIC_SESSION_PIN, sizeof(MAGIC_SESSION_PIN));
5952 *pcbSessionPin = sizeof(MAGIC_SESSION_PIN);
5953 }
5954 }
5955
5956 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
5957 }
5958
5959
CardChangeAuthenticatorEx(__in PCARD_DATA pCardData,__in DWORD dwFlags,__in PIN_ID dwAuthenticatingPinId,__in_bcount (cbAuthenticatingPinData)PBYTE pbAuthenticatingPinData,__in DWORD cbAuthenticatingPinData,__in PIN_ID dwTargetPinId,__in_bcount (cbTargetData)PBYTE pbTargetData,__in DWORD cbTargetData,__in DWORD cRetryCount,__out_opt PDWORD pcAttemptsRemaining)5960 DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData,
5961 __in DWORD dwFlags,
5962 __in PIN_ID dwAuthenticatingPinId,
5963 __in_bcount(cbAuthenticatingPinData) PBYTE pbAuthenticatingPinData,
5964 __in DWORD cbAuthenticatingPinData,
5965 __in PIN_ID dwTargetPinId,
5966 __in_bcount(cbTargetData) PBYTE pbTargetData,
5967 __in DWORD cbTargetData,
5968 __in DWORD cRetryCount,
5969 __out_opt PDWORD pcAttemptsRemaining)
5970 {
5971 DWORD dwret;
5972 VENDOR_SPECIFIC *vs = NULL;
5973 struct sc_pkcs15_object *pin_obj = NULL;
5974 int rv;
5975 struct sc_pkcs15_auth_info *auth_info;
5976 BOOL DisplayPinpadUI = FALSE;
5977 size_t target_len = cbTargetData;
5978
5979 MD_FUNC_CALLED(pCardData, 1);
5980
5981 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
5982 (unsigned long)GetCurrentProcessId(),
5983 (unsigned long)GetCurrentThreadId(), pCardData);
5984 logprintf(pCardData, 1, "CardChangeAuthenticatorEx\n");
5985
5986 if (!pCardData)
5987 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5988
5989 dwret = check_card_reader_status(pCardData, "CardChangeAuthenticatorEx");
5990 if (dwret != SCARD_S_SUCCESS)
5991 MD_FUNC_RETURN(pCardData, 1, dwret);
5992
5993 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
5994 if (!vs)
5995 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
5996
5997 if (!(dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && !(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)){
5998 logprintf(pCardData, 1, "Unknown flag\n");
5999 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6000 }
6001 if ((dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN))
6002 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6003 if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId)
6004 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6005 if (dwAuthenticatingPinId >= MD_MAX_PINS || dwTargetPinId >= MD_MAX_PINS)
6006 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6007 if (!vs->pin_objs[dwAuthenticatingPinId] || !vs->pin_objs[dwTargetPinId])
6008 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6009
6010 /* according to the spec: cRetryCount MUST be zero */
6011 if (cRetryCount)
6012 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6013
6014 logprintf(pCardData, 2,
6015 "CardChangeAuthenticatorEx: AuthenticatingPinId=%u, dwFlags=0x%08X, cbAuthenticatingPinData=%lu, TargetPinId=%u, cbTargetData=%lu, Attempts %s\n",
6016 (unsigned int)dwAuthenticatingPinId, (unsigned int)dwFlags,
6017 (unsigned long)cbAuthenticatingPinData,
6018 (unsigned int)dwTargetPinId, (unsigned long)cbTargetData,
6019 pcAttemptsRemaining ? "YES" : "NO");
6020
6021 if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD
6022 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) {
6023 if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) {
6024 logprintf(pCardData, 1, "Invalid current PIN data\n");
6025 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6026 }
6027
6028 if (pbTargetData == NULL || cbTargetData == 0) {
6029 logprintf(pCardData, 1, "Invalid new PIN data\n");
6030 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6031 }
6032 }
6033 /* using a pin pad */
6034 if (NULL == pbAuthenticatingPinData) {
6035 if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)
6036 && !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) {
6037 DisplayPinpadUI = TRUE;
6038 }
6039 }
6040
6041 pin_obj = vs->pin_objs[dwTargetPinId];
6042
6043 if(pcAttemptsRemaining)
6044 (*pcAttemptsRemaining) = (DWORD) -1;
6045
6046 /* FIXME: this does not enforce dwAuthenticatingPinId */
6047 rv = md_dialog_perform_pin_operation(pCardData,
6048 (dwFlags & PIN_CHANGE_FLAG_UNBLOCK ?
6049 SC_PIN_CMD_UNBLOCK :
6050 SC_PIN_CMD_CHANGE),
6051 vs->p15card, pin_obj,
6052 (const u8 *) pbAuthenticatingPinData,
6053 cbAuthenticatingPinData,
6054 pbTargetData, &target_len,
6055 DisplayPinpadUI, dwTargetPinId);
6056
6057 if (rv) {
6058 logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n",
6059 (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"),
6060 (dwTargetPinId==ROLE_ADMIN?"admin":"user"), sc_strerror(rv), rv);
6061 auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
6062 if (rv == SC_ERROR_AUTH_METHOD_BLOCKED) {
6063 if(pcAttemptsRemaining)
6064 (*pcAttemptsRemaining) = 0;
6065 MD_FUNC_RETURN(pCardData, 1, SCARD_W_CHV_BLOCKED);
6066 }
6067
6068 if(pcAttemptsRemaining)
6069 (*pcAttemptsRemaining) = auth_info->tries_left;
6070 MD_FUNC_RETURN(pCardData, 1, md_translate_OpenSC_to_Windows_error(rv, SCARD_W_WRONG_CHV));
6071 }
6072
6073 logprintf(pCardData, 7, "returns success\n");
6074 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6075 }
6076
CardDeauthenticateEx(__in PCARD_DATA pCardData,__in PIN_SET PinId,__in DWORD dwFlags)6077 DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData,
6078 __in PIN_SET PinId,
6079 __in DWORD dwFlags)
6080 {
6081 MD_FUNC_CALLED(pCardData, 1);
6082
6083 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6084 (unsigned long)GetCurrentProcessId(),
6085 (unsigned long)GetCurrentThreadId(), pCardData);
6086 logprintf(pCardData, 1,
6087 "CardDeauthenticateEx PinId=%u dwFlags=0x%08X\n",
6088 (unsigned int)PinId, (unsigned int)dwFlags);
6089
6090 MD_FUNC_RETURN(pCardData, 1, CardDeauthenticate(pCardData, wszCARD_USER_USER, 0));
6091 }
6092
CardGetContainerProperty(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in LPCWSTR wszProperty,__out_bcount_part_opt (cbData,* pdwDataLen)PBYTE pbData,__in DWORD cbData,__out PDWORD pdwDataLen,__in DWORD dwFlags)6093 DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData,
6094 __in BYTE bContainerIndex,
6095 __in LPCWSTR wszProperty,
6096 __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
6097 __in DWORD cbData,
6098 __out PDWORD pdwDataLen,
6099 __in DWORD dwFlags)
6100 {
6101 DWORD dwret;
6102 VENDOR_SPECIFIC *vs = NULL;
6103 struct md_pkcs15_container *cont = NULL;
6104
6105 MD_FUNC_CALLED(pCardData, 1);
6106
6107 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6108 (unsigned long)GetCurrentProcessId(),
6109 (unsigned long)GetCurrentThreadId(), pCardData);
6110 logprintf(pCardData, 1, "CardGetContainerProperty\n");
6111
6112 if (!pCardData)
6113 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6114
6115 dwret = check_card_status(pCardData, "CardGetContainerProperty");
6116 if (dwret != SCARD_S_SUCCESS)
6117 MD_FUNC_RETURN(pCardData, 1, dwret);
6118
6119 logprintf(pCardData, 2,
6120 "CardGetContainerProperty bContainerIndex=%u, wszProperty=%S, cbData=%lu, dwFlags=0x%08X\n",
6121 (unsigned int)bContainerIndex, NULLWSTR(wszProperty),
6122 (unsigned long)cbData, (unsigned int)dwFlags);
6123 if (!wszProperty)
6124 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6125 if (dwFlags)
6126 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6127 if (!pbData || !pdwDataLen)
6128 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6129 if (bContainerIndex >= MD_MAX_KEY_CONTAINERS)
6130 MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_KEY_CONTAINER);
6131
6132 /* the test for the existence of containers is redundant with the one made in CardGetContainerInfo but CCP_PIN_IDENTIFIER does not do it */
6133 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
6134 if (!vs)
6135 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6136
6137 cont = &vs->p15_containers[bContainerIndex];
6138
6139 if (!cont->prkey_obj) {
6140 logprintf(pCardData, 7, "Container %u is empty\n",
6141 (unsigned int)bContainerIndex);
6142 MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_KEY_CONTAINER);
6143 }
6144
6145 if (wcscmp(CCP_CONTAINER_INFO,wszProperty) == 0) {
6146 PCONTAINER_INFO p = (PCONTAINER_INFO) pbData;
6147 if (pdwDataLen) *pdwDataLen = sizeof(*p);
6148 if (cbData >= sizeof(DWORD))
6149 if (p->dwVersion != CONTAINER_INFO_CURRENT_VERSION && p->dwVersion != 0 )
6150 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
6151 if (cbData < sizeof(*p))
6152 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6153 MD_FUNC_RETURN(pCardData, 1, CardGetContainerInfo(pCardData,bContainerIndex,0,p));
6154 }
6155
6156 if (wcscmp(CCP_PIN_IDENTIFIER,wszProperty) == 0) {
6157 PPIN_ID p = (PPIN_ID) pbData;
6158 if (pdwDataLen)
6159 *pdwDataLen = sizeof(*p);
6160 if (cbData < sizeof(*p))
6161 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6162
6163 if (cont->prkey_obj->auth_id.len == 0)
6164 *p = ROLE_EVERYONE;
6165 else {
6166 size_t pinidx;
6167 for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) {
6168 struct sc_pkcs15_auth_info *pin_info;
6169
6170 if (!vs->pin_objs[pinidx])
6171 continue;
6172
6173 pin_info =
6174 (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data;
6175
6176 if (sc_pkcs15_compare_id(&cont->prkey_obj->auth_id,
6177 &pin_info->auth_id))
6178 break;
6179 }
6180
6181 if (pinidx >= MD_MAX_PINS) {
6182 logprintf(pCardData, 2,
6183 "Could not find container %i PIN, returning no PIN needed, might not work properly\n",
6184 bContainerIndex);
6185 *p = ROLE_EVERYONE;
6186 } else
6187 *p = (PIN_ID)pinidx;
6188 }
6189
6190 logprintf(pCardData, 2, "Return Pin id %u\n",
6191 (unsigned int)*p);
6192 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6193 }
6194
6195 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6196 }
6197
CardSetContainerProperty(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in LPCWSTR wszProperty,__in_bcount (cbDataLen)PBYTE pbData,__in DWORD cbDataLen,__in DWORD dwFlags)6198 DWORD WINAPI CardSetContainerProperty(__in PCARD_DATA pCardData,
6199 __in BYTE bContainerIndex,
6200 __in LPCWSTR wszProperty,
6201 __in_bcount(cbDataLen) PBYTE pbData,
6202 __in DWORD cbDataLen,
6203 __in DWORD dwFlags)
6204 {
6205 MD_FUNC_CALLED(pCardData, 1);
6206
6207 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6208 (unsigned long)GetCurrentProcessId(),
6209 (unsigned long)GetCurrentThreadId(), pCardData);
6210 logprintf(pCardData, 1, "CardSetContainerProperty - unsupported\n");
6211
6212 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6213 }
6214
6215
CardGetProperty(__in PCARD_DATA pCardData,__in LPCWSTR wszProperty,__out_bcount_part_opt (cbData,* pdwDataLen)PBYTE pbData,__in DWORD cbData,__out PDWORD pdwDataLen,__in DWORD dwFlags)6216 DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData,
6217 __in LPCWSTR wszProperty,
6218 __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
6219 __in DWORD cbData,
6220 __out PDWORD pdwDataLen,
6221 __in DWORD dwFlags)
6222 {
6223 VENDOR_SPECIFIC *vs;
6224 DWORD dwret;
6225
6226 MD_FUNC_CALLED(pCardData, 1);
6227
6228 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6229 (unsigned long)GetCurrentProcessId(),
6230 (unsigned long)GetCurrentThreadId(), pCardData);
6231 logprintf(pCardData, 2,
6232 "CardGetProperty('%S',cbData=%lu,dwFlags=%lu) called\n",
6233 NULLWSTR(wszProperty), (unsigned long)cbData,
6234 (unsigned long)dwFlags);
6235
6236 if (!pCardData || !wszProperty)
6237 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6238 if (!pbData || !pdwDataLen)
6239 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6240
6241 dwret = check_card_reader_status(pCardData, "CardGetProperty");
6242 if (dwret != SCARD_S_SUCCESS)
6243 MD_FUNC_RETURN(pCardData, 1, dwret);
6244
6245 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
6246 if (!vs)
6247 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6248
6249 if (wcscmp(CP_CARD_FREE_SPACE,wszProperty) == 0) {
6250 PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo = (PCARD_FREE_SPACE_INFO )pbData;
6251 if (pdwDataLen)
6252 *pdwDataLen = sizeof(*pCardFreeSpaceInfo);
6253 if (cbData < sizeof(*pCardFreeSpaceInfo))
6254 MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_MEMORY);
6255
6256 dwret = md_free_space(pCardData, pCardFreeSpaceInfo);
6257 if (dwret != SCARD_S_SUCCESS) {
6258 logprintf(pCardData, 1, "Get free space error");
6259 MD_FUNC_RETURN(pCardData, 1, dwret);
6260 }
6261 }
6262 else if (wcscmp(CP_CARD_CAPABILITIES, wszProperty) == 0) {
6263 PCARD_CAPABILITIES pCardCapabilities = (PCARD_CAPABILITIES )pbData;
6264
6265 if (pdwDataLen)
6266 *pdwDataLen = sizeof(*pCardCapabilities);
6267 if (cbData < sizeof(*pCardCapabilities))
6268 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6269 dwret = md_card_capabilities(pCardData, pCardCapabilities);
6270 if (dwret != SCARD_S_SUCCESS)
6271 MD_FUNC_RETURN(pCardData, 1, dwret);
6272 }
6273 else if (wcscmp(CP_CARD_KEYSIZES,wszProperty) == 0) {
6274 PCARD_KEY_SIZES pKeySizes = (PCARD_KEY_SIZES )pbData;
6275 if (pdwDataLen)
6276 *pdwDataLen = sizeof(*pKeySizes);
6277 if (cbData < sizeof(*pKeySizes))
6278 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6279
6280 dwret = md_query_key_sizes(pCardData, 0, pKeySizes);
6281 if (dwret != SCARD_S_SUCCESS)
6282 MD_FUNC_RETURN(pCardData, 1, dwret);
6283 }
6284 else if (wcscmp(CP_CARD_READ_ONLY, wszProperty) == 0) {
6285 BOOL *p = (BOOL *)pbData;
6286 if (pdwDataLen)
6287 *pdwDataLen = sizeof(*p);
6288 if (cbData < sizeof(*p))
6289 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6290
6291 *p = md_is_read_only(pCardData);
6292 }
6293 else if (wcscmp(CP_CARD_CACHE_MODE, wszProperty) == 0) {
6294 DWORD *p = (DWORD *)pbData;
6295 if (pdwDataLen)
6296 *pdwDataLen = sizeof(*p);
6297 if (cbData < sizeof(*p))
6298 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6299 *p = CP_CACHE_MODE_NO_CACHE;
6300 }
6301 else if (wcscmp(CP_SUPPORTS_WIN_X509_ENROLLMENT, wszProperty) == 0) {
6302 BOOL *p = (BOOL *)pbData;
6303 if (pdwDataLen)
6304 *pdwDataLen = sizeof(*p);
6305 if (cbData < sizeof(*p))
6306 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6307 *p = md_is_supports_X509_enrollment(pCardData);
6308 }
6309 else if (wcscmp(CP_CARD_GUID, wszProperty) == 0) {
6310 struct md_file *cardid = NULL;
6311
6312 md_fs_find_file(pCardData, NULL, "cardid", &cardid);
6313 if (!cardid) {
6314 logprintf(pCardData, 2, "file 'cardid' not found\n");
6315 MD_FUNC_RETURN(pCardData, 1, SCARD_E_FILE_NOT_FOUND);
6316 }
6317
6318 if (pdwDataLen)
6319 *pdwDataLen = (DWORD) cardid->size;
6320 if (cbData < cardid->size)
6321 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6322
6323 CopyMemory(pbData, cardid->blob, cardid->size);
6324 }
6325 else if (wcscmp(CP_CARD_SERIAL_NO, wszProperty) == 0) {
6326 unsigned char buf[64];
6327 size_t buf_len = sizeof(buf);
6328
6329 if (sc_hex_to_bin(vs->p15card->tokeninfo->serial_number, buf, &buf_len)) {
6330 buf_len = strlen(vs->p15card->tokeninfo->serial_number);
6331 if (buf_len > SC_MAX_SERIALNR) {
6332 buf_len = SC_MAX_SERIALNR;
6333 }
6334 memcpy(buf, vs->p15card->tokeninfo->serial_number, buf_len);
6335 }
6336
6337 if (pdwDataLen)
6338 *pdwDataLen = (DWORD) buf_len;
6339 if (cbData < buf_len)
6340 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6341
6342 CopyMemory(pbData, buf, buf_len);
6343 }
6344 else if (wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0) {
6345 PPIN_INFO p = (PPIN_INFO) pbData;
6346
6347 if (pdwDataLen)
6348 *pdwDataLen = sizeof(*p);
6349
6350 if (cbData < sizeof(*p))
6351 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6352
6353 if (p->dwVersion != PIN_INFO_CURRENT_VERSION)
6354 MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH);
6355
6356 if (dwFlags >= MD_MAX_PINS)
6357 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6358
6359 if (!vs->pin_objs[dwFlags])
6360 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6361
6362 p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD
6363 || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH
6364 ? ExternalPinType : AlphaNumericPinType;
6365 p->dwFlags = 0;
6366 switch (dwFlags) {
6367 case ROLE_ADMIN:
6368 logprintf(pCardData, 2,
6369 "returning info on PIN ROLE_ADMIN ( Unblock ) [%lu]\n",
6370 (unsigned long)dwFlags);
6371 p->PinPurpose = UnblockOnlyPin;
6372 p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
6373 p->PinCachePolicy.dwPinCachePolicyInfo = 0;
6374 p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
6375 p->dwChangePermission = CREATE_PIN_SET(ROLE_ADMIN);
6376 p->dwUnblockPermission = 0;
6377 break;
6378 default:
6379 logprintf(pCardData, 2,
6380 "returning info on normal PIN [%lu]\n",
6381 (unsigned long)dwFlags);
6382
6383 if (dwFlags == ROLE_USER)
6384 p->PinPurpose = PrimaryCardPin;
6385 else if (dwFlags == MD_ROLE_USER_SIGN)
6386 p->PinPurpose = DigitalSignaturePin;
6387 else
6388 p->PinPurpose = AuthenticationPin;
6389
6390 p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION;
6391 p->PinCachePolicy.dwPinCachePolicyInfo = 0;
6392 p->PinCachePolicy.PinCachePolicyType = PinCacheNormal;
6393 p->dwChangePermission = CREATE_PIN_SET(dwFlags);
6394 p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN);
6395 break;
6396 }
6397 }
6398 else if (wcscmp(CP_CARD_LIST_PINS,wszProperty) == 0) {
6399 PPIN_SET p = (PPIN_SET) pbData;
6400 size_t pinidx;
6401 if (pdwDataLen)
6402 *pdwDataLen = sizeof(*p);
6403 if (cbData < sizeof(*p))
6404 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6405
6406 memset(p, 0, sizeof(*p));
6407 for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) {
6408 if (!vs->pin_objs[pinidx])
6409 continue;
6410
6411 SET_PIN(*p, (PIN_ID)pinidx);
6412 }
6413 }
6414 else if (wcscmp(CP_CARD_AUTHENTICATED_STATE,wszProperty) == 0) {
6415 PPIN_SET p = (PPIN_SET) pbData;
6416 if (pdwDataLen)
6417 *pdwDataLen = sizeof(*p);
6418 if (cbData < sizeof(*p))
6419 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6420
6421 logprintf(pCardData, 7, "CARD_AUTHENTICATED_STATE invalid\n");
6422 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6423 }
6424 else if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY,wszProperty) == 0) {
6425 DWORD *p = (DWORD *)pbData;
6426
6427 if (dwFlags >= MD_MAX_PINS)
6428 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6429
6430 if (!vs->pin_objs[dwFlags])
6431 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6432
6433 if (pdwDataLen)
6434 *pdwDataLen = sizeof(*p);
6435 if (cbData < sizeof(*p))
6436 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6437 *p = CARD_PIN_STRENGTH_PLAINTEXT;
6438 if (vs->p15card->card->caps & SC_CARD_CAP_SESSION_PIN) {
6439 *p |= CARD_PIN_STRENGTH_SESSION_PIN;
6440 }
6441 }
6442 else if (wcscmp(CP_KEY_IMPORT_SUPPORT, wszProperty) == 0) {
6443 DWORD *p = (DWORD *)pbData;
6444 if (pdwDataLen)
6445 *pdwDataLen = sizeof(*p);
6446 if (cbData < sizeof(*p))
6447 MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER);
6448 *p = 0;
6449 }
6450 else if (wcscmp(CP_ENUM_ALGORITHMS, wszProperty) == 0) {
6451 logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
6452 //TODO
6453 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6454 }
6455 else if (wcscmp(CP_PADDING_SCHEMES, wszProperty) == 0) {
6456 logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
6457 //TODO
6458 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6459 }
6460 else if (wcscmp(CP_CHAINING_MODES, wszProperty) == 0) {
6461 logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
6462 //TODO
6463 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6464 }
6465 else {
6466 logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty);
6467 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6468
6469 }
6470
6471 logprintf(pCardData, 7, "returns '%S' ", wszProperty);
6472 loghex(pCardData, 7, pbData, *pdwDataLen);
6473 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6474 }
6475
CardSetProperty(__in PCARD_DATA pCardData,__in LPCWSTR wszProperty,__in_bcount (cbDataLen)PBYTE pbData,__in DWORD cbDataLen,__in DWORD dwFlags)6476 DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData,
6477 __in LPCWSTR wszProperty,
6478 __in_bcount(cbDataLen) PBYTE pbData,
6479 __in DWORD cbDataLen,
6480 __in DWORD dwFlags)
6481 {
6482 VENDOR_SPECIFIC *vs;
6483
6484 MD_FUNC_CALLED(pCardData, 1);
6485
6486 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6487 (unsigned long)GetCurrentProcessId(),
6488 (unsigned long)GetCurrentThreadId(), pCardData);
6489 logprintf(pCardData, 1, "CardSetProperty\n");
6490
6491 if (!pCardData)
6492 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6493
6494 logprintf(pCardData, 2,
6495 "CardSetProperty wszProperty=%S, pbData=%p, cbDataLen=%lu, dwFlags=%lu",
6496 NULLWSTR(wszProperty), pbData, (unsigned long)cbDataLen,
6497 (unsigned long)dwFlags);
6498
6499 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
6500 if (!vs)
6501 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6502
6503 if (!wszProperty)
6504 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6505
6506 if (dwFlags)
6507 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6508
6509 if (!cbDataLen)
6510 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6511
6512 /* the following properties cannot be set according to the minidriver specifications */
6513 if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0 ||
6514 wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0 ||
6515 wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0 ||
6516 wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0 ||
6517 wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0 ||
6518 wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0 ||
6519 wcscmp(wszProperty,CP_ENUM_ALGORITHMS) == 0 ||
6520 wcscmp(wszProperty,CP_PADDING_SCHEMES) == 0 ||
6521 wcscmp(wszProperty,CP_CHAINING_MODES) == 0 ||
6522 wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0 ||
6523 wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0 ||
6524 wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0
6525 ) {
6526 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6527 }
6528
6529 /* the following properties can be set, but are not implemented by the minidriver */
6530 if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY, wszProperty) == 0 ||
6531 wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0 ||
6532 wcscmp(CP_CARD_GUID, wszProperty) == 0 ) {
6533 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6534 }
6535
6536 /* This property and CP_PIN_CONTEXT_STRING are set just prior to a call to
6537 * CardAuthenticateEx if the PIN required is declared of type ExternalPinType.
6538 */
6539 if (wcscmp(CP_PARENT_WINDOW, wszProperty) == 0) {
6540 if (cbDataLen != sizeof(HWND) || !pbData) {
6541 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6542 }
6543 else {
6544 HWND cp = *((HWND *) pbData);
6545 if (cp!=0 && !IsWindow(cp))
6546 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6547 vs->hwndParent = cp;
6548 }
6549 logprintf(pCardData, 3, "Saved parent window (%p)\n", vs->hwndParent);
6550 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6551 }
6552
6553 if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) {
6554 vs->wszPinContext = (PWSTR) pbData;
6555 logprintf(pCardData, 3, "Saved PIN context string: %S\n", (PWSTR) pbData);
6556 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6557 }
6558 logprintf(pCardData, 3, "INVALID PARAMETER\n");
6559 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6560 }
6561
6562
6563 // 4.8 Secure key injection
6564
6565
6566 /** The CardImportSessionKey function imports a temporary session key to the card.
6567 The session key is encrypted with a key exchange key, and the function returns a
6568 handle of the imported session key to the caller.*/
6569
CardImportSessionKey(__in PCARD_DATA pCardData,__in BYTE bContainerIndex,__in VOID * pPaddingInfo,__in LPCWSTR pwszBlobType,__in LPCWSTR pwszAlgId,__out CARD_KEY_HANDLE * phKey,__in_bcount (cbInput)PBYTE pbInput,__in DWORD cbInput,__in DWORD dwFlags)6570 DWORD WINAPI CardImportSessionKey(
6571 __in PCARD_DATA pCardData,
6572 __in BYTE bContainerIndex,
6573 __in VOID *pPaddingInfo,
6574 __in LPCWSTR pwszBlobType,
6575 __in LPCWSTR pwszAlgId,
6576 __out CARD_KEY_HANDLE *phKey,
6577 __in_bcount(cbInput) PBYTE pbInput,
6578 __in DWORD cbInput,
6579 __in DWORD dwFlags
6580 )
6581 {
6582 UNREFERENCED_PARAMETER(pCardData);
6583 UNREFERENCED_PARAMETER(bContainerIndex);
6584 UNREFERENCED_PARAMETER(pCardData);
6585 UNREFERENCED_PARAMETER(pPaddingInfo);
6586 UNREFERENCED_PARAMETER(pwszBlobType);
6587 UNREFERENCED_PARAMETER(pwszAlgId);
6588 UNREFERENCED_PARAMETER(phKey);
6589 UNREFERENCED_PARAMETER(pbInput);
6590 UNREFERENCED_PARAMETER(cbInput);
6591 UNREFERENCED_PARAMETER(dwFlags);
6592
6593 MD_FUNC_CALLED(pCardData, 1);
6594
6595 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6596 (unsigned long)GetCurrentProcessId(),
6597 (unsigned long)GetCurrentThreadId(), pCardData);
6598 logprintf(pCardData, 1, "CardImportSessionKey - unsupported\n");
6599 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6600 }
6601
6602 /** The MDImportSessionKey function imports a temporary session key to the card minidriver
6603 and returns a key handle to the caller.*/
6604
MDImportSessionKey(__in PCARD_DATA pCardData,__in LPCWSTR pwszBlobType,__in LPCWSTR pwszAlgId,__out PCARD_KEY_HANDLE phKey,__in_bcount (cbInput)PBYTE pbInput,__in DWORD cbInput)6605 DWORD WINAPI MDImportSessionKey(
6606 __in PCARD_DATA pCardData,
6607 __in LPCWSTR pwszBlobType,
6608 __in LPCWSTR pwszAlgId,
6609 __out PCARD_KEY_HANDLE phKey,
6610 __in_bcount(cbInput) PBYTE pbInput,
6611 __in DWORD cbInput
6612 )
6613 {
6614 UNREFERENCED_PARAMETER(pCardData);
6615 UNREFERENCED_PARAMETER(pwszBlobType);
6616 UNREFERENCED_PARAMETER(pwszAlgId);
6617 UNREFERENCED_PARAMETER(phKey);
6618 UNREFERENCED_PARAMETER(pbInput);
6619 UNREFERENCED_PARAMETER(cbInput);
6620
6621 MD_FUNC_CALLED(pCardData, 1);
6622
6623 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6624 (unsigned long)GetCurrentProcessId(),
6625 (unsigned long)GetCurrentThreadId(), pCardData);
6626 logprintf(pCardData, 1, "MDImportSessionKey - unsupported\n");
6627 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6628 }
6629
6630 /** The MDEncryptData function uses a key handle to encrypt data with a symmetric key.
6631 The data is encrypted in a format that the smart card supports.*/
6632
MDEncryptData(__in PCARD_DATA pCardData,__in CARD_KEY_HANDLE hKey,__in LPCWSTR pwszSecureFunction,__in_bcount (cbInput)PBYTE pbInput,__in DWORD cbInput,__in DWORD dwFlags,__deref_out_ecount (* pcEncryptedData)PCARD_ENCRYPTED_DATA * ppEncryptedData,__out PDWORD pcEncryptedData)6633 DWORD WINAPI MDEncryptData(
6634 __in PCARD_DATA pCardData,
6635 __in CARD_KEY_HANDLE hKey,
6636 __in LPCWSTR pwszSecureFunction,
6637 __in_bcount(cbInput) PBYTE pbInput,
6638 __in DWORD cbInput,
6639 __in DWORD dwFlags,
6640 __deref_out_ecount(*pcEncryptedData)
6641 PCARD_ENCRYPTED_DATA *ppEncryptedData,
6642 __out PDWORD pcEncryptedData
6643 )
6644 {
6645 UNREFERENCED_PARAMETER(pCardData);
6646 UNREFERENCED_PARAMETER(hKey);
6647 UNREFERENCED_PARAMETER(pwszSecureFunction);
6648 UNREFERENCED_PARAMETER(pbInput);
6649 UNREFERENCED_PARAMETER(cbInput);
6650 UNREFERENCED_PARAMETER(dwFlags);
6651 UNREFERENCED_PARAMETER(ppEncryptedData);
6652 UNREFERENCED_PARAMETER(pcEncryptedData);
6653
6654 MD_FUNC_CALLED(pCardData, 1);
6655
6656 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6657 (unsigned long)GetCurrentProcessId(),
6658 (unsigned long)GetCurrentThreadId(), pCardData);
6659 logprintf(pCardData, 1, "MDEncryptData - unsupported\n");
6660 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6661 }
6662
6663
6664 /** The CardGetSharedKeyHandle function returns a session key handle to the caller.
6665 Note: The manner in which this session key has been established is outside the
6666 scope of this specification. For example, the session key could be established
6667 by either a permanent shared key or a key derivation algorithm that has occurred
6668 before the call to CardGetSharedKeyHandle.*/
6669
CardGetSharedKeyHandle(__in PCARD_DATA pCardData,__in_bcount (cbInput)PBYTE pbInput,__in DWORD cbInput,__deref_opt_out_bcount (* pcbOutput)PBYTE * ppbOutput,__out_opt PDWORD pcbOutput,__out PCARD_KEY_HANDLE phKey)6670 DWORD WINAPI CardGetSharedKeyHandle(
6671 __in PCARD_DATA pCardData,
6672 __in_bcount(cbInput) PBYTE pbInput,
6673 __in DWORD cbInput,
6674 __deref_opt_out_bcount(*pcbOutput)
6675 PBYTE *ppbOutput,
6676 __out_opt PDWORD pcbOutput,
6677 __out PCARD_KEY_HANDLE phKey
6678 )
6679 {
6680 UNREFERENCED_PARAMETER(pCardData);
6681 UNREFERENCED_PARAMETER(pbInput);
6682 UNREFERENCED_PARAMETER(cbInput);
6683 UNREFERENCED_PARAMETER(ppbOutput);
6684 UNREFERENCED_PARAMETER(pcbOutput);
6685 UNREFERENCED_PARAMETER(phKey);
6686
6687 MD_FUNC_CALLED(pCardData, 1);
6688
6689 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6690 (unsigned long)GetCurrentProcessId(),
6691 (unsigned long)GetCurrentThreadId(), pCardData);
6692 logprintf(pCardData, 1, "CardGetSharedKeyHandle - unsupported\n");
6693 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6694
6695 }
6696
6697 /** The CardDestroyKey function releases a temporary key on the card. The card
6698 should delete all of the key material that is associated with that key handle.*/
6699
CardDestroyKey(__in PCARD_DATA pCardData,__in CARD_KEY_HANDLE hKey)6700 DWORD WINAPI CardDestroyKey(
6701 __in PCARD_DATA pCardData,
6702 __in CARD_KEY_HANDLE hKey
6703 )
6704 {
6705 UNREFERENCED_PARAMETER(pCardData);
6706 UNREFERENCED_PARAMETER(hKey);
6707
6708 MD_FUNC_CALLED(pCardData, 1);
6709
6710 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6711 (unsigned long)GetCurrentProcessId(),
6712 (unsigned long)GetCurrentThreadId(), pCardData);
6713 logprintf(pCardData, 1, "CardDestroyKey - unsupported\n");
6714 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6715 }
6716
6717 /** This function can be used to get properties for a cryptographic algorithm.*/
CardGetAlgorithmProperty(__in PCARD_DATA pCardData,__in LPCWSTR pwszAlgId,__in LPCWSTR pwszProperty,__out_bcount_part_opt (cbData,* pdwDataLen)PBYTE pbData,__in DWORD cbData,__out PDWORD pdwDataLen,__in DWORD dwFlags)6718 DWORD WINAPI CardGetAlgorithmProperty (
6719 __in PCARD_DATA pCardData,
6720 __in LPCWSTR pwszAlgId,
6721 __in LPCWSTR pwszProperty,
6722 __out_bcount_part_opt(cbData, *pdwDataLen)
6723 PBYTE pbData,
6724 __in DWORD cbData,
6725 __out PDWORD pdwDataLen,
6726 __in DWORD dwFlags
6727 )
6728 {
6729 UNREFERENCED_PARAMETER(pCardData);
6730 UNREFERENCED_PARAMETER(pwszAlgId);
6731 UNREFERENCED_PARAMETER(pwszProperty);
6732 UNREFERENCED_PARAMETER(pbData);
6733 UNREFERENCED_PARAMETER(cbData);
6734 UNREFERENCED_PARAMETER(pdwDataLen);
6735 UNREFERENCED_PARAMETER(dwFlags);
6736
6737 MD_FUNC_CALLED(pCardData, 1);
6738
6739 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6740 (unsigned long)GetCurrentProcessId(),
6741 (unsigned long)GetCurrentThreadId(), pCardData);
6742 logprintf(pCardData, 1, "CardGetAlgorithmProperty - unsupported\n");
6743 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6744 }
6745
6746 /** This function is used to get the properties of a key.*/
CardGetKeyProperty(__in PCARD_DATA pCardData,__in CARD_KEY_HANDLE hKey,__in LPCWSTR pwszProperty,__out_bcount_part_opt (cbData,* pdwDataLen)PBYTE pbData,__in DWORD cbData,__out PDWORD pdwDataLen,__in DWORD dwFlags)6747 DWORD WINAPI CardGetKeyProperty(
6748 __in PCARD_DATA pCardData,
6749 __in CARD_KEY_HANDLE hKey,
6750 __in LPCWSTR pwszProperty,
6751 __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData,
6752 __in DWORD cbData,
6753 __out PDWORD pdwDataLen,
6754 __in DWORD dwFlags
6755 )
6756 {
6757 UNREFERENCED_PARAMETER(pCardData);
6758 UNREFERENCED_PARAMETER(hKey);
6759 UNREFERENCED_PARAMETER(pwszProperty);
6760 UNREFERENCED_PARAMETER(pbData);
6761 UNREFERENCED_PARAMETER(cbData);
6762 UNREFERENCED_PARAMETER(pdwDataLen);
6763 UNREFERENCED_PARAMETER(dwFlags);
6764
6765 MD_FUNC_CALLED(pCardData, 1);
6766
6767 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6768 (unsigned long)GetCurrentProcessId(),
6769 (unsigned long)GetCurrentThreadId(), pCardData);
6770 logprintf(pCardData, 1, "CardGetKeyProperty - unsupported\n");
6771 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6772 }
6773
6774 /** This function is used to set the properties of a key.*/
CardSetKeyProperty(__in PCARD_DATA pCardData,__in CARD_KEY_HANDLE hKey,__in LPCWSTR pwszProperty,__in_bcount (cbInput)PBYTE pbInput,__in DWORD cbInput,__in DWORD dwFlags)6775 DWORD WINAPI CardSetKeyProperty(
6776 __in PCARD_DATA pCardData,
6777 __in CARD_KEY_HANDLE hKey,
6778 __in LPCWSTR pwszProperty,
6779 __in_bcount(cbInput) PBYTE pbInput,
6780 __in DWORD cbInput,
6781 __in DWORD dwFlags
6782 )
6783 {
6784 UNREFERENCED_PARAMETER(pCardData);
6785 UNREFERENCED_PARAMETER(dwFlags);
6786 UNREFERENCED_PARAMETER(hKey);
6787 UNREFERENCED_PARAMETER(pwszProperty);
6788 UNREFERENCED_PARAMETER(pbInput);
6789 UNREFERENCED_PARAMETER(cbInput);
6790 UNREFERENCED_PARAMETER(dwFlags);
6791
6792 MD_FUNC_CALLED(pCardData, 1);
6793
6794 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6795 (unsigned long)GetCurrentProcessId(),
6796 (unsigned long)GetCurrentThreadId(), pCardData);
6797 logprintf(pCardData, 1, "CardSetKeyProperty - unsupported\n");
6798 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6799
6800 }
6801
6802 /** CardProcessEncryptedData processes a set of encrypted data BLOBs by
6803 sending them to the card where the data BLOBs are decrypted.*/
6804
CardProcessEncryptedData(__in PCARD_DATA pCardData,__in CARD_KEY_HANDLE hKey,__in LPCWSTR pwszSecureFunction,__in_ecount (cEncryptedData)PCARD_ENCRYPTED_DATA pEncryptedData,__in DWORD cEncryptedData,__out_bcount_part_opt (cbOutput,* pdwOutputLen)PBYTE pbOutput,__in DWORD cbOutput,__out_opt PDWORD pdwOutputLen,__in DWORD dwFlags)6805 DWORD WINAPI CardProcessEncryptedData(
6806 __in PCARD_DATA pCardData,
6807 __in CARD_KEY_HANDLE hKey,
6808 __in LPCWSTR pwszSecureFunction,
6809 __in_ecount(cEncryptedData)
6810 PCARD_ENCRYPTED_DATA pEncryptedData,
6811 __in DWORD cEncryptedData,
6812 __out_bcount_part_opt(cbOutput, *pdwOutputLen)
6813 PBYTE pbOutput,
6814 __in DWORD cbOutput,
6815 __out_opt PDWORD pdwOutputLen,
6816 __in DWORD dwFlags
6817 )
6818 {
6819 UNREFERENCED_PARAMETER(pCardData);
6820 UNREFERENCED_PARAMETER(hKey);
6821 UNREFERENCED_PARAMETER(pwszSecureFunction);
6822 UNREFERENCED_PARAMETER(pEncryptedData);
6823 UNREFERENCED_PARAMETER(cEncryptedData);
6824 UNREFERENCED_PARAMETER(pbOutput);
6825 UNREFERENCED_PARAMETER(cbOutput);
6826 UNREFERENCED_PARAMETER(pdwOutputLen);
6827 UNREFERENCED_PARAMETER(dwFlags);
6828
6829 MD_FUNC_CALLED(pCardData, 1);
6830
6831 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6832 (unsigned long)GetCurrentProcessId(),
6833 (unsigned long)GetCurrentThreadId(), pCardData);
6834 logprintf(pCardData, 1, "CardProcessEncryptedData - unsupported\n");
6835
6836 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6837 }
6838
CardAcquireContext(__inout PCARD_DATA pCardData,__in DWORD dwFlags)6839 DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags)
6840 {
6841 VENDOR_SPECIFIC *vs;
6842 DWORD dwret, suppliedVersion = 0;
6843 CRITICAL_SECTION hScard_lock;
6844
6845 if (!pCardData)
6846 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6847
6848 MD_FUNC_CALLED(pCardData, 1);
6849
6850 if (dwFlags & ~CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)
6851 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6852
6853 if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)) {
6854 if( pCardData->hSCardCtx == 0) {
6855 logprintf(pCardData, 0, "Invalid handle.\n");
6856 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_HANDLE);
6857 }
6858 if( pCardData->hScard == 0) {
6859 logprintf(pCardData, 0, "Invalid handle.\n");
6860 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_HANDLE);
6861 }
6862 }
6863 else
6864 {
6865 /* secure key injection not supported */
6866 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE);
6867 }
6868
6869 if (pCardData->pbAtr == NULL)
6870 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6871 if ( pCardData->pwszCardName == NULL )
6872 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6873 /* <2 length or >0x22 are not ISO compliant */
6874 if (pCardData->cbAtr > 0x22 || pCardData->cbAtr < 0x2)
6875 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6876 /* ATR beginning by 0x00 or 0xFF are not ISO compliant */
6877 if (pCardData->pbAtr[0] == 0xFF || pCardData->pbAtr[0] == 0x00)
6878 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD);
6879 /* Memory management functions */
6880 if ( ( pCardData->pfnCspAlloc == NULL ) ||
6881 ( pCardData->pfnCspReAlloc == NULL ) ||
6882 ( pCardData->pfnCspFree == NULL ) )
6883 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
6884
6885 /* The lowest supported version is 4 - maximum is 7. */
6886 if (pCardData->dwVersion < MD_MINIMUM_VERSION_SUPPORTED)
6887 MD_FUNC_RETURN(pCardData, 1, (DWORD) ERROR_REVISION_MISMATCH);
6888
6889 suppliedVersion = pCardData->dwVersion;
6890
6891 /* VENDOR SPECIFIC */
6892 vs = pCardData->pvVendorSpecific = pCardData->pfnCspAlloc(sizeof(VENDOR_SPECIFIC));
6893 if (!vs)
6894 MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_MEMORY);
6895 memset(vs, 0, sizeof(VENDOR_SPECIFIC));
6896
6897 InitializeCriticalSection(&vs->hScard_lock);
6898 lock(pCardData);
6899
6900 logprintf(pCardData, 1, "==================================================================\n");
6901 logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ",
6902 (unsigned long)GetCurrentProcessId(),
6903 (unsigned long)GetCurrentThreadId(), pCardData);
6904 logprintf(pCardData, 1,
6905 "CardAcquireContext, dwVersion=%lu, name=%S,hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X, hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X\n",
6906 (unsigned long)pCardData->dwVersion,
6907 NULLWSTR(pCardData->pwszCardName),
6908 (size_t)pCardData->hScard,
6909 (size_t)pCardData->hSCardCtx);
6910
6911 vs->hScard = pCardData->hScard;
6912 vs->hSCardCtx = pCardData->hSCardCtx;
6913
6914 logprintf(pCardData, 2, "request version pCardData->dwVersion = %lu\n",
6915 (unsigned long)pCardData->dwVersion);
6916 pCardData->dwVersion = min(pCardData->dwVersion, MD_CURRENT_VERSION_SUPPORTED);
6917 logprintf(pCardData, 2, "pCardData->dwVersion = %lu\n",
6918 (unsigned long)pCardData->dwVersion);
6919
6920 dwret = md_create_context(pCardData, vs);
6921 if (dwret != SCARD_S_SUCCESS)
6922 goto ret_free;
6923
6924 pCardData->pfnCardDeleteContext = CardDeleteContext;
6925 pCardData->pfnCardQueryCapabilities = CardQueryCapabilities;
6926 pCardData->pfnCardDeleteContainer = CardDeleteContainer;
6927 pCardData->pfnCardCreateContainer = CardCreateContainer;
6928 pCardData->pfnCardGetContainerInfo = CardGetContainerInfo;
6929 pCardData->pfnCardAuthenticatePin = CardAuthenticatePin;
6930 pCardData->pfnCardGetChallenge = CardGetChallenge;
6931 pCardData->pfnCardAuthenticateChallenge = CardAuthenticateChallenge;
6932 pCardData->pfnCardUnblockPin = CardUnblockPin;
6933 pCardData->pfnCardChangeAuthenticator = CardChangeAuthenticator;
6934 pCardData->pfnCardDeauthenticate = CardDeauthenticate;
6935 pCardData->pfnCardCreateDirectory = CardCreateDirectory;
6936 pCardData->pfnCardDeleteDirectory = CardDeleteDirectory;
6937 pCardData->pvUnused3 = NULL;
6938 pCardData->pvUnused4 = NULL;
6939 pCardData->pfnCardCreateFile = CardCreateFile;
6940 pCardData->pfnCardReadFile = CardReadFile;
6941 pCardData->pfnCardWriteFile = CardWriteFile;
6942 pCardData->pfnCardDeleteFile = CardDeleteFile;
6943 pCardData->pfnCardEnumFiles = CardEnumFiles;
6944 pCardData->pfnCardGetFileInfo = CardGetFileInfo;
6945 pCardData->pfnCardQueryFreeSpace = CardQueryFreeSpace;
6946 pCardData->pfnCardQueryKeySizes = CardQueryKeySizes;
6947 pCardData->pfnCardSignData = CardSignData;
6948 pCardData->pfnCardRSADecrypt = CardRSADecrypt;
6949 pCardData->pfnCardConstructDHAgreement = CardConstructDHAgreement;
6950
6951 dwret = associate_card(pCardData);
6952 if (dwret != SCARD_S_SUCCESS)
6953 goto ret_release;
6954
6955 dwret = md_fs_init(pCardData);
6956 if (dwret != SCARD_S_SUCCESS)
6957 goto ret_disassoc;
6958
6959 logprintf(pCardData, 1, "OpenSC init done.\n");
6960 logprintf(pCardData, 1, "Supplied version %lu - version used %lu.\n",
6961 (unsigned long)suppliedVersion,
6962 (unsigned long)pCardData->dwVersion);
6963
6964 if (pCardData->dwVersion >= CARD_DATA_VERSION_FIVE) {
6965 pCardData->pfnCardDeriveKey = CardDeriveKey;
6966 pCardData->pfnCardDestroyDHAgreement = CardDestroyDHAgreement;
6967
6968 if (pCardData->dwVersion >= CARD_DATA_VERSION_SIX) {
6969
6970 pCardData->pfnCardGetChallengeEx = CardGetChallengeEx;
6971 pCardData->pfnCardAuthenticateEx = CardAuthenticateEx;
6972 pCardData->pfnCardChangeAuthenticatorEx = CardChangeAuthenticatorEx;
6973 pCardData->pfnCardDeauthenticateEx = CardDeauthenticateEx;
6974 pCardData->pfnCardGetContainerProperty = CardGetContainerProperty;
6975 pCardData->pfnCardSetContainerProperty = CardSetContainerProperty;
6976 pCardData->pfnCardGetProperty = CardGetProperty;
6977 pCardData->pfnCardSetProperty = CardSetProperty;
6978 if (pCardData->dwVersion >= CARD_DATA_VERSION_SEVEN) {
6979
6980 pCardData->pfnMDImportSessionKey = MDImportSessionKey;
6981 pCardData->pfnMDEncryptData = MDEncryptData;
6982 pCardData->pfnCardImportSessionKey = CardImportSessionKey;
6983 pCardData->pfnCardGetSharedKeyHandle = CardGetSharedKeyHandle;
6984 pCardData->pfnCardGetAlgorithmProperty = CardGetAlgorithmProperty;
6985 pCardData->pfnCardGetKeyProperty = CardGetKeyProperty;
6986 pCardData->pfnCardSetKeyProperty = CardSetKeyProperty;
6987 pCardData->pfnCardProcessEncryptedData = CardProcessEncryptedData;
6988 pCardData->pfnCardDestroyKey = CardDestroyKey;
6989 pCardData->pfnCardCreateContainerEx = CardCreateContainerEx;
6990 }
6991 }
6992 }
6993
6994 unlock(pCardData);
6995
6996 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
6997
6998 ret_disassoc:
6999 disassociate_card(pCardData);
7000
7001 ret_release:
7002 sc_release_context(vs->ctx);
7003
7004 ret_free:
7005 hScard_lock = vs->hScard_lock;
7006 pCardData->pfnCspFree(pCardData->pvVendorSpecific);
7007 pCardData->pvVendorSpecific = NULL;
7008 LeaveCriticalSection(&hScard_lock);
7009 DeleteCriticalSection(&hScard_lock);
7010 MD_FUNC_RETURN(pCardData, 1, dwret);
7011 }
7012
associate_card(PCARD_DATA pCardData)7013 static DWORD associate_card(PCARD_DATA pCardData)
7014 {
7015 VENDOR_SPECIFIC *vs;
7016 int r;
7017 struct sc_app_info *app_generic;
7018 struct sc_aid *aid;
7019
7020 MD_FUNC_CALLED(pCardData, 1);
7021 if (!pCardData)
7022 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
7023
7024 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
7025 if (!vs)
7026 MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER);
7027
7028 /*
7029 * set the addresses of the reader and card handles
7030 * Our pcsc code will use these when we call sc_ctx_use_reader
7031 * We use the address of the handles as provided in the pCardData
7032 */
7033 vs->hSCardCtx = pCardData->hSCardCtx;
7034 vs->hScard = pCardData->hScard;
7035
7036 /* set the provided reader and card handles into ctx */
7037 r = sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard);
7038 if (r != SC_SUCCESS) {
7039 logprintf(pCardData, 1, "sc_ctx_use_reader() failed with %d\n", r);
7040 MD_FUNC_RETURN(pCardData, 1, SCARD_E_COMM_DATA_LOST);
7041 }
7042
7043 /* should be only one reader */
7044 logprintf(pCardData, 5, "sc_ctx_get_reader_count(ctx): %d\n", sc_ctx_get_reader_count(vs->ctx));
7045
7046 vs->reader = sc_ctx_get_reader(vs->ctx, 0);
7047 if (!vs->reader)
7048 MD_FUNC_RETURN(pCardData, 1, SCARD_E_COMM_DATA_LOST);
7049
7050 r = sc_connect_card(vs->reader, &(vs->card));
7051 if (r != SC_SUCCESS) {
7052 logprintf(pCardData, 0, "Cannot connect card in reader '%s'\n", NULLSTR(vs->reader->name));
7053 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD);
7054 }
7055 logprintf(pCardData, 3, "Connected card in '%s'\n", NULLSTR(vs->reader->name));
7056
7057 app_generic = sc_pkcs15_get_application_by_type(vs->card, "generic");
7058 if (app_generic)
7059 logprintf(pCardData, 3, "Use generic application '%s'\n", app_generic->label);
7060 aid = app_generic ? &app_generic->aid : NULL;
7061
7062 r = sc_pkcs15_bind(vs->card, aid, &(vs->p15card));
7063 logprintf(pCardData, 2, "PKCS#15 initialization result: %d, %s\n", r, sc_strerror(r));
7064 if (r != SC_SUCCESS) {
7065 logprintf(pCardData, 0, "PKCS#15 init failed.\n");
7066 sc_disconnect_card(vs->card);
7067 MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD);
7068 }
7069
7070 vs->initialized = TRUE;
7071
7072 MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS);
7073 }
7074
disassociate_card(PCARD_DATA pCardData)7075 static void disassociate_card(PCARD_DATA pCardData)
7076 {
7077 VENDOR_SPECIFIC *vs;
7078
7079 if (!pCardData) {
7080 logprintf(pCardData, 1,
7081 "disassociate_card called without card data\n");
7082 return;
7083 }
7084
7085 logprintf(pCardData, 1, "disassociate_card\n");
7086
7087 vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific);
7088 if (!vs) {
7089 logprintf(pCardData, 1,
7090 "disassociate_card called without vendor specific data\n");
7091 return;
7092 }
7093
7094 memset(vs->pin_objs, 0, sizeof(vs->pin_objs));
7095 memset(vs->p15_containers, 0, sizeof(vs->p15_containers));
7096
7097 if(vs->p15card) {
7098 logprintf(pCardData, 6, "sc_pkcs15_unbind\n");
7099 sc_pkcs15_unbind(vs->p15card);
7100 vs->p15card = NULL;
7101 }
7102
7103 if(vs->card) {
7104 logprintf(pCardData, 6, "sc_disconnect_card\n");
7105 sc_disconnect_card(vs->card);
7106 vs->card = NULL;
7107 }
7108
7109 vs->reader = NULL;
7110
7111 vs->hSCardCtx = -1;
7112 vs->hScard = -1;
7113 vs->initialized = FALSE;
7114 }
7115
7116
DllMain(HINSTANCE hinstDLL,DWORD ul_reason_for_call,LPVOID lpReserved)7117 BOOL APIENTRY DllMain( HINSTANCE hinstDLL,
7118 DWORD ul_reason_for_call,
7119 LPVOID lpReserved
7120 )
7121 {
7122 CHAR name[MAX_PATH + 1] = "\0";
7123 char *reason = "";
7124
7125 GetModuleFileNameA(GetModuleHandle(NULL),name,MAX_PATH);
7126
7127 switch (ul_reason_for_call) {
7128 case DLL_PROCESS_ATTACH:
7129 reason = "Attach Process";
7130 break;
7131 case DLL_THREAD_ATTACH:
7132 reason = "Attach Thread";
7133 break;
7134 case DLL_THREAD_DETACH:
7135 reason = "Detach Thread";
7136 break;
7137 case DLL_PROCESS_DETACH:
7138 reason = "Detach Process";
7139 break;
7140 }
7141
7142 logprintf(NULL, 8,
7143 "\n********** DllMain Module(handle:0x%p) '%s'; reason='%s'; Reserved=%p; P:%lu; T:%lu\n",
7144 hinstDLL, name, reason, lpReserved,
7145 (unsigned long)GetCurrentProcessId(),
7146 (unsigned long)GetCurrentThreadId());
7147 switch (ul_reason_for_call)
7148 {
7149 case DLL_PROCESS_ATTACH:
7150 g_inst = hinstDLL;
7151 sc_notify_instance = hinstDLL;
7152 sc_notify_init();
7153 break;
7154 case DLL_PROCESS_DETACH:
7155 sc_notify_close();
7156 if (lpReserved == NULL) {
7157 #if defined(ENABLE_OPENSSL) && defined(OPENSSL_SECURE_MALLOC_SIZE)
7158 CRYPTO_secure_malloc_done();
7159 #endif
7160 #ifdef ENABLE_OPENPACE
7161 EAC_cleanup();
7162 #endif
7163 }
7164 break;
7165 }
7166 return TRUE;
7167 }
7168
7169 #ifdef _MANAGED
7170 #pragma managed(pop)
7171 #endif
7172 #endif
7173