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