1 /* ****************************************************************************
2 
3  * eID Middleware Project.
4  * Copyright (C) 2008-2012 FedICT.
5  *
6  * This is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License version
8  * 3.0 as published by the Free Software Foundation.
9  *
10  * This software is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this software; if not, see
17  * http://www.gnu.org/licenses/.
18 
19 **************************************************************************** */
20 /****************************************************************************************************/
21 
22 #include "globmdrv.h"
23 #include "log.h"
24 #include "smartcard.h"
25 #include "externalpinui.h"
26 
27 #include <commctrl.h>
28 /****************************************************************************************************/
29 
30 #define CHALLENGE_DATA_SIZE         16
31 
32 #define BELPIC_MAX_FILE_SIZE        65535
33 #define BELPIC_PIN_BUF_SIZE         8
34 #define BELPIC_MIN_USER_PIN_LEN     4
35 #define BELPIC_MAX_USER_PIN_LEN     12
36 #define BELPIC_PAD_CHAR			    0xFF
37 #define BELPIC_KEY_REF_NONREP		0x83
38 
39 /****************************************************************************************************/
40 
41 #define WHERE "BeidParsePrKDF"
BeidParsePrKDF(PCARD_DATA pCardData,DWORD * cbStream,BYTE * pbStream,WORD * cbKeySize)42 DWORD BeidParsePrKDF(PCARD_DATA  pCardData, DWORD *cbStream, BYTE *pbStream, WORD *cbKeySize)
43 {
44 	DWORD dwReturn  = 0;
45 	DWORD dwCounter = 0;
46 	DWORD dwInc = 0;
47 	*cbKeySize = 0;
48 
49 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
50 	/********************/
51    /* Check Parameters */
52    /********************/
53    if ( pCardData == NULL )
54    {
55       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pCardData]");
56       CLEANUP(SCARD_E_INVALID_PARAMETER);
57    }
58    if ( pbStream == NULL )
59    {
60       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [ppbStream]");
61       CLEANUP(SCARD_E_INVALID_PARAMETER);
62    }
63 	if ( cbStream == NULL )
64    {
65       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [cbStream]");
66       CLEANUP(SCARD_E_INVALID_PARAMETER);
67 	 }
68 
69 	 if(pbStream[dwCounter] == 0x30) //0x30 means sequence
70 	 {
71 		 LogTrace(LOGTYPE_TRACE, WHERE, "sequence [0x30]");
72 		 dwCounter++; //jump to sequence length
73 		 LogTrace(LOGTYPE_TRACE, WHERE, "sequence length [0x%.2X]",pbStream[dwCounter]);
74 		 dwInc = pbStream[dwCounter];
75 		 dwCounter += dwInc; //add length (to jump over sequence)
76 		 if( dwCounter < (*cbStream))
77 		 {
78 			 //the last 2 bytes are the key size
79 			 *cbKeySize = (pbStream[dwCounter-1])*256;
80 			 *cbKeySize += (pbStream[dwCounter]);
81 			 LogTrace(LOGTYPE_INFO, WHERE, "rsa key size is %d",*cbKeySize);
82 		 }
83 		 else
84 		 {
85 			 LogTrace(LOGTYPE_ERROR, WHERE, "*cbStream = %d dwCounter = %d",*cbStream,dwCounter);
86 			 LogDump(*cbStream,pbStream);
87 			 CLEANUP(PEERDIST_ERROR_CANNOT_PARSE_CONTENTINFO);
88 		 }
89 	 }
90 	 else
91 	 {
92 		 LogTrace(LOGTYPE_ERROR, WHERE, "Expected 0x30 instead of ox%.2x",pbStream[dwCounter]);
93 		 LogDump(*cbStream,pbStream);
94 		 CLEANUP(PEERDIST_ERROR_CANNOT_PARSE_CONTENTINFO);
95 	 }
96 
97 cleanup:
98 
99 	 LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
100 	 return(dwReturn);
101 }
102 #undef WHERE
103 
104 
105 
106 #define WHERE "BeidDelayAndRecover"
BeidDelayAndRecover(PCARD_DATA pCardData,BYTE SW1,BYTE SW2,DWORD dwReturn)107 void BeidDelayAndRecover(PCARD_DATA  pCardData,
108 						 BYTE   SW1,
109 						 BYTE   SW2,
110 						 DWORD  dwReturn)
111 {
112 
113 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
114 
115 	if( (dwReturn == SCARD_E_COMM_DATA_LOST) || (dwReturn == SCARD_E_NOT_TRANSACTED) )
116 	{
117 		DWORD ap = 0;
118 		int i = 0;
119 
120 		LogTrace(LOGTYPE_WARNING, WHERE, "Card is confused, trying to recover...");
121 
122 		for (i = 0; (i < 10) && (dwReturn != SCARD_S_SUCCESS); i++)
123 		{
124 			if (i != 0)
125 				Sleep(1000);
126 
127 			dwReturn = SCardReconnect(pCardData->hScard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &ap);
128 
129 			LogTrace(LOGTYPE_TRACE, WHERE, "  [%d] SCardReconnect errorcode: [0x%08X]", i, dwReturn);
130 
131 			if ( dwReturn != SCARD_S_SUCCESS )
132 			{
133 				if(dwReturn == SCARD_W_REMOVED_CARD)
134 				{
135 					LogTrace(LOGTYPE_INFO, WHERE, "SCARD_W_REMOVED_CARD");
136 					LogTrace(LOGTYPE_INFO, WHERE, "Exit API... ");
137 					return;
138 				}
139 				continue;
140 			}
141 			// transaction is lost after an SCardReconnect()
142 			dwReturn = SCardBeginTransaction(pCardData->hScard);
143 			LogTrace(LOGTYPE_TRACE, WHERE, "  [%d] SCardBeginTransaction errorcode: [0x%08X]", i, dwReturn);
144 
145 			if ( dwReturn != SCARD_S_SUCCESS )
146 			{
147 				continue;
148 			}
149 			dwReturn = BeidSelectApplet(pCardData);
150 			LogTrace(LOGTYPE_TRACE, WHERE, "  [%d] BeidSelectApplet errorcode: [0x%08X]", i, dwReturn);
151 
152 			if ( dwReturn != SCARD_S_SUCCESS )
153 			{
154 				continue;
155 			}
156 
157 			LogTrace(LOGTYPE_INFO, WHERE, "  Card recovered in loop %d", i);
158 		}
159 		if(i >=10)
160 		{
161 			LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X], Failed to recover", dwReturn);
162 		}
163 	}
164 	if ( (( SW1 == 0x90 ) && ( SW2 == 0x00 )) ||
165 		 ( SW1 == 0x61 ) ||
166 		 ( SW1 == 0x6c ) )
167 	{
168 		;//no error received, no sleep needed
169 	}
170 	else
171 	{
172 		Sleep(25);
173 	}
174 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
175 }
176 #undef WHERE
177 
178 
179 
180 #define WHERE "BeidAuthenticate"
BeidAuthenticate(PCARD_DATA pCardData,PBYTE pbPin,DWORD cbPin,PDWORD pcAttemptsRemaining)181 DWORD BeidAuthenticate(PCARD_DATA   pCardData,
182                        PBYTE        pbPin,
183                        DWORD        cbPin,
184                        PDWORD       pcAttemptsRemaining)
185 {
186    DWORD             dwReturn  = 0;
187 
188    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
189    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
190 
191    unsigned char     Cmd[128];
192    unsigned int      uiCmdLg   = 0;
193    unsigned char     recvbuf[256];
194    unsigned long     recvlen   = sizeof(recvbuf);
195    BYTE              SW1, SW2;
196    unsigned int      i         = 0;
197 
198    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
199 
200    /********************/
201    /* Check Parameters */
202    /********************/
203    if ( pCardData == NULL )
204    {
205       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pCardData]");
206       CLEANUP(SCARD_E_INVALID_PARAMETER);
207    }
208    if ( pbPin == NULL )
209    {
210       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbPin]");
211       CLEANUP(SCARD_E_INVALID_PARAMETER);
212    }
213 
214    /* Don't allow zero-length PIN */
215    if ( ( cbPin < BELPIC_MIN_USER_PIN_LEN ) ||
216         ( cbPin > BELPIC_MAX_USER_PIN_LEN ) )
217    {
218       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [cbPin]");
219       CLEANUP(SCARD_W_WRONG_CHV);
220    }
221 
222 	 for ( i = 0 ; i < (unsigned char) cbPin ; i++ )
223 	 {
224 		 /* Don't allow non-numerical PIN entries */
225 		 if ( ( pbPin[i] < 0x30 ) || ( pbPin[i] > 0x39 ) )
226 		 {
227 			 LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbPin[i]]");
228 			 CLEANUP(SCARD_W_WRONG_CHV);
229 		 }
230 	 }
231 
232    /**********/
233    /* Log On */
234    /**********/
235    Cmd [0] = 0x00;
236    Cmd [1] = 0x20; /* VERIFY COMMAND */
237    Cmd [2] = 0x00;
238    Cmd [3] = 0x01;
239    Cmd [4] = 0x08;
240 
241    /* Fill verification data with padding character */
242    for ( i = 0 ; i < 0x08 ; i++ )
243    {
244       Cmd [5 + i] = BELPIC_PAD_CHAR;
245    }
246 
247    Cmd [5] = 0x20 + (unsigned char)cbPin;  /* 0x20 + length of pin */
248    for ( i = 0 ; i < (unsigned char) cbPin ; i++ )
249    {
250       if ( (i % 2) == 0 )
251       {
252 			// 0x30 = ASCII '0'
253 			Cmd [6 + (i/2)] = (((pbPin[i] - 0x30) << 4) | 0x0F);
254       }
255       else
256       {
257 		  // 0x30 = ASCII '0'
258           Cmd [6 + (i/2)] = (Cmd[6 + (i/2)] & 0xF0) + ((pbPin[i] - 0x30) & 0x0F);
259       }
260    }
261    uiCmdLg = 13;
262    recvlen = sizeof(recvbuf);
263 
264    dwReturn = SCardTransmit(pCardData->hScard,
265                             &ioSendPci,
266                             Cmd,
267                             uiCmdLg,
268                             &ioRecvPci,
269                             recvbuf,
270                             &recvlen);
271 
272    memset(Cmd, 0, uiCmdLg);
273 
274    SW1 = recvbuf[recvlen-2];
275    SW2 = recvbuf[recvlen-1];
276    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit returncode: [0x%08X]", dwReturn);
277    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
278    if ( dwReturn != SCARD_S_SUCCESS )
279    {
280 	  LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
281       CLEANUP(dwReturn);
282    }
283 
284    if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
285    {
286       dwReturn = SCARD_W_WRONG_CHV;
287       LogTrace(LOGTYPE_ERROR, WHERE, "CardAuthenticatePin Failed: [0x%02X][0x%02X]", SW1, SW2);
288 
289       if ( ((SW1 == 0x63) && ((SW2 & 0xF0) == 0xC0)) )
290       {
291          if ( pcAttemptsRemaining != NULL )
292          {
293             /* -1: Don't support returning the count of remaining authentication attempts */
294             *pcAttemptsRemaining = (SW2 & 0x0F);
295          }
296       }
297       else if ( (SW1 == 0x69) && (SW2 == 0x83) )
298       {
299          dwReturn = SCARD_W_CHV_BLOCKED;
300       }
301    }
302    else
303    {
304       LogTrace(LOGTYPE_INFO, WHERE, "Logged on...");
305    }
306 
307 cleanup:
308 
309    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
310 
311    return(dwReturn);
312 }
313 #undef WHERE
314 
315 /****************************************************************************************************/
316 
317 #define WHERE "BeidAuthenticateExternal"
BeidAuthenticateExternal(PCARD_DATA pCardData,PDWORD pcAttemptsRemaining,BOOL bSilent)318 DWORD BeidAuthenticateExternal(
319 	PCARD_DATA   pCardData,
320 	PDWORD       pcAttemptsRemaining,
321 	BOOL		 bSilent
322 	)
323 {
324 	DWORD						dwReturn  = 0;
325 	SCARD_IO_REQUEST			ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
326 	SCARD_IO_REQUEST			ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
327 
328 	PIN_VERIFY_STRUCTURE		verifyCommand;
329 
330 	unsigned int				uiCmdLg   = 0;
331 	unsigned char				recvbuf[256];
332 	unsigned char				ucLastKey;
333 	unsigned long				recvlen     = sizeof(recvbuf);
334 	BYTE						SW1, SW2;
335 	int							i           = 0;
336 	int							offset		= 0;
337 	DWORD						dwDataLen;
338 	BOOL						bRetry      = TRUE;
339 	int							nButton;
340 
341 	EXTERNAL_PIN_INFORMATION	externalPinInfo;
342 	HANDLE						DialogThreadHandle;
343 
344 #ifndef NO_DIALOGS
345 	DWORD						dwRetriesLeft;
346 
347 	wchar_t						wchErrorMessage[500];
348 	wchar_t						wchMainInstruction[100];
349 #endif
350 
351 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
352 
353 	/********************/
354 	/* Check Parameters */
355 	/********************/
356 	if ( pCardData == NULL )
357 	{
358 		LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pCardData]");
359 		CLEANUP(SCARD_E_INVALID_PARAMETER);
360 	}
361 
362 
363 	/*********************/
364 	/* External PIN Info */
365 	/*********************/
366 	externalPinInfo.hCardHandle = pCardData->hScard;
367 	CCIDgetFeatures(&(externalPinInfo.features), externalPinInfo.hCardHandle);
368 
369 	/*********************/
370 	/* Get Parent Window */
371 	/*********************/
372 	dwReturn = CardGetProperty(pCardData,
373 		CP_PARENT_WINDOW,
374 		(PBYTE) &(externalPinInfo.hwndParentWindow),
375 		sizeof(externalPinInfo.hwndParentWindow),
376 		&dwDataLen,
377 		0);
378 	if (dwReturn != 0) {
379 		LogTrace(LOGTYPE_ERROR, WHERE, "CardGetProperty Failed: %02X", dwReturn);
380 		externalPinInfo.hwndParentWindow = NULL;
381 	}
382 
383 
384 	/*********************/
385 	/* Get Pin Context String */
386 	/*********************/
387 	dwReturn = CardGetProperty(pCardData,
388 		CP_PIN_CONTEXT_STRING,
389 		(PBYTE) externalPinInfo.lpstrPinContextString,
390 		sizeof(externalPinInfo.lpstrPinContextString),
391 		&dwDataLen,
392 		0);
393 	if (dwReturn != 0) {
394 		LogTrace(LOGTYPE_ERROR, WHERE, "CardGetProperty Failed: %02X", dwReturn);
395 		wcscpy(externalPinInfo.lpstrPinContextString, L"");
396 	}
397 
398 	/**********/
399 	/* Log On */
400 	/**********/
401 
402 	createVerifyCommand(&verifyCommand);
403 
404 	uiCmdLg = sizeof(verifyCommand);
405 	recvlen = sizeof(recvbuf);
406 
407 	while (bRetry) {
408 		bRetry = FALSE;
409 		nButton = -1;
410 
411 		// We introduce a short sleep before starting the PIN VERIFY procedure
412 		// Reason: we do this for users with a combined keyboard/secure PIN pad smartcard reader
413 		//   "enter" key far right on the keyboard ==  "OK" button of the PIN pad
414 		//   Problem: key becomes PIN-pad button before key is released. Result: the keyup event is not sent.
415 		//   This sleep gives the user some time to release the Enter key.
416 
417 		Sleep(100);
418 
419 		if(externalPinInfo.features.VERIFY_PIN_DIRECT != 0)
420 		{
421 			externalPinInfo.iPinCharacters = 0;
422 			externalPinInfo.cardState = CS_PINENTRY;
423 			// show dialog
424 			if (!bSilent)
425 				DialogThreadHandle = CreateThread(NULL, 0, DialogThreadPinEntry, &externalPinInfo, 0, NULL);
426 
427 			if(externalPinInfo.features.USE_PPDU == 0)
428 			{
429 				dwReturn = SCardControl(pCardData->hScard,
430 					externalPinInfo.features.VERIFY_PIN_DIRECT,
431 					&verifyCommand,
432 					uiCmdLg,
433 					recvbuf,
434 					recvlen,
435 					&recvlen);
436 
437 				LogTrace(LOGTYPE_TRACE, WHERE, "SCardControl return code: [0x%08X]", dwReturn);
438 				externalPinInfo.cardState = CS_PINENTERED;
439 				if ( dwReturn != SCARD_S_SUCCESS )
440 				{
441 					LogTrace(LOGTYPE_ERROR, WHERE, "SCardControl errorcode: [0x%08X]", dwReturn);
442 					CLEANUP(dwReturn);
443 				}
444 			}
445 			else{
446 				BYTE pbSendBufferVerifyPINDirect[256];// = {0xFF ,0xC2 ,0x01 ,0x06 , 0x00};
447 				BYTE bSendBufferVerifyPINDirectLength = 5;
448 
449 				pbSendBufferVerifyPINDirect[0] = 0xFF;
450 				pbSendBufferVerifyPINDirect[1] = 0xC2;
451 				pbSendBufferVerifyPINDirect[2] = 0x01;
452 				pbSendBufferVerifyPINDirect[3] = 0x06;
453 				pbSendBufferVerifyPINDirect[4] = sizeof(verifyCommand);
454 
455 				if(sizeof(verifyCommand) < (sizeof(pbSendBufferVerifyPINDirect)+5) )
456 				{
457 					memcpy(&pbSendBufferVerifyPINDirect[5],&verifyCommand,sizeof(verifyCommand));
458 					bSendBufferVerifyPINDirectLength += sizeof(verifyCommand);
459 				}
460 				LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit PPDU");
461 
462 				dwReturn = SCardTransmit(pCardData->hScard,
463 					&ioSendPci,
464 					pbSendBufferVerifyPINDirect,
465 					bSendBufferVerifyPINDirectLength,
466 					&ioRecvPci,
467 					recvbuf,
468 					&recvlen);
469 
470 				LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit PPDU return code: [0x%08X]", dwReturn);
471 				externalPinInfo.cardState = CS_PINENTERED;
472 				if ( dwReturn != SCARD_S_SUCCESS )
473 				{
474 					LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit PPDU errorcode: [0x%08X]", dwReturn);
475 					CLEANUP(dwReturn);
476 				}
477 
478 			}
479 		}
480 		else
481 		{
482 			dwReturn = SCardControl(pCardData->hScard,
483 				externalPinInfo.features.VERIFY_PIN_START,
484 				&verifyCommand,
485 				uiCmdLg,
486 				recvbuf,
487 				recvlen,
488 				&recvlen);
489 			LogTrace(LOGTYPE_TRACE, WHERE, "SCardControl return code: [0x%08X]", dwReturn);
490 			if ( dwReturn != SCARD_S_SUCCESS )
491 			{
492 				LogTrace(LOGTYPE_ERROR, WHERE, "SCardControl errorcode: [0x%08X]", dwReturn);
493 				CLEANUP(dwReturn);
494 			}
495 			externalPinInfo.iPinCharacters = 0;
496 			externalPinInfo.cardState = CS_PINENTRY;
497 
498 			// show dialog
499 			if (!bSilent)
500 				DialogThreadHandle = CreateThread(NULL, 0, DialogThreadPinEntry, &externalPinInfo, 0, NULL);
501 			while (1) {
502 				dwReturn = SCardControl(pCardData->hScard,
503 					externalPinInfo.features.GET_KEY_PRESSED,
504 					NULL,
505 					0,
506 					recvbuf,
507 					recvlen,
508 					&recvlen);
509 				LogTrace(LOGTYPE_TRACE, WHERE, "SCardControl return code: [0x%08X]", dwReturn);
510 				if ( dwReturn != SCARD_S_SUCCESS )
511 				{
512 					LogTrace(LOGTYPE_ERROR, WHERE, "SCardControl errorcode: [0x%08X]", dwReturn);
513 					CLEANUP(dwReturn);
514 				}
515 				ucLastKey = recvbuf[0];
516 				switch (recvbuf[0]) {
517 				case 0x00:
518 					// No key
519 					Sleep(200);
520 					break;
521 				case 0x0d:
522 					// OK button
523 					goto endkeypress;
524 				case 0x1b:
525 					// Cancel button
526 					goto endkeypress;
527 				case 0x40:
528 					// Aborted/timeout
529 					goto endkeypress;
530 				case 0x2b:
531 					// 0-9
532 					externalPinInfo.iPinCharacters++;
533 					break;
534 				case 0x08:
535 					// Backspace
536 					externalPinInfo.iPinCharacters--;
537 					break;
538 				case 0x0a:
539 					// Clear
540 					externalPinInfo.iPinCharacters = 0;
541 					break;
542 				default:
543 					//printf("Key pressed: 0x%x\n", bRecvBuffer[0]);
544 					;
545 				}
546 
547 			}
548 endkeypress:
549 
550 			externalPinInfo.cardState = CS_PINENTERED;
551 			dwReturn = SCardControl(pCardData->hScard,
552 				externalPinInfo.features.VERIFY_PIN_FINISH,
553 				NULL,
554 				0,
555 				recvbuf,
556 				sizeof(recvbuf),
557 				&recvlen);
558 			LogTrace(LOGTYPE_TRACE, WHERE, "SCardControl return code: [0x%08X]", dwReturn);
559 			if ( dwReturn != SCARD_S_SUCCESS )
560 			{
561 				LogTrace(LOGTYPE_ERROR, WHERE, "SCardControl errorcode: [0x%08X]", dwReturn);
562 				CLEANUP(dwReturn);
563 			}
564 			SW1 = recvbuf[recvlen-2];
565 			SW2 = recvbuf[recvlen-1];
566 			if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
567 			{
568 				dwReturn = SCARD_W_WRONG_CHV;
569 				LogTrace(LOGTYPE_ERROR, WHERE, "CardAuthenticateEx Failed: [0x%02X][0x%02X]", SW1, SW2);
570 #ifndef NO_DIALOGS
571 				if (SW1 == 0x64) {
572 					//error during pin entry
573 					switch(SW2){
574 					case 0x00:
575 						// Timeout
576 						if (ucLastKey == 0x0d) {
577 							// OK button preceded by no other keys also results in 0x64 0x00
578 
579 							swprintf(wchMainInstruction, t[PIN_TOO_SHORT_MAININSTRUCTIONS][getLanguage()]);
580 							swprintf(wchErrorMessage, t[PIN_TOO_SHORT_CONTENT][getLanguage()] );
581 						} else {
582 							swprintf(wchMainInstruction, t[PIN_TIMED_OUT_MAININSTRUCTIONS][getLanguage()]);
583 							// the user entered something but probably forgot to push OK.
584 							swprintf(wchErrorMessage, t[PIN_TIMED_OUT_CONTENT][getLanguage()]);
585 						}
586 						break;
587 					case 0x01:
588 						// Cancelled
589 						swprintf(wchMainInstruction, t[PIN_CANCELLED_MAININSTRUCTIONS][getLanguage()]);
590 						swprintf(wchErrorMessage, t[PIN_CANCELLED_CONTENT][getLanguage()]);
591 						break;
592 					case 0x02:
593 						// PINs do not match
594 						swprintf(wchMainInstruction, t[PIN_DO_NOT_MATCH_MAININSTRUCTIONS][getLanguage()]);
595 						swprintf(wchErrorMessage, t[PIN_DO_NOT_MATCH_CONTENT][getLanguage()]);
596 						break;
597 					case 0x03:
598 						// PIN size error
599 						if (externalPinInfo.iPinCharacters > 0 && externalPinInfo.iPinCharacters < BELPIC_MIN_USER_PIN_LEN) {
600 							// PIN too short
601 							swprintf(wchMainInstruction, t[PIN_TOO_SHORT_MAININSTRUCTIONS][getLanguage()]);
602 							swprintf(wchErrorMessage, t[PIN_TOO_SHORT_CONTENT][getLanguage()]);
603 						} else {
604 							if (externalPinInfo.iPinCharacters >= BELPIC_MAX_USER_PIN_LEN) {
605 								// PIN too long
606 								swprintf(wchMainInstruction, t[PIN_TOO_LONG_MAININSTRUCTIONS][getLanguage()]);
607 								swprintf(wchErrorMessage, t[PIN_TOO_LONG_CONTENT][getLanguage()]);
608 							} else {
609 								// no info about PIN chars
610 								swprintf(wchMainInstruction,  t[PIN_SIZE_MAININSTRUCTIONS][getLanguage()]);
611 								swprintf(wchErrorMessage, t[PIN_SIZE_CONTENT][getLanguage()]);
612 							}
613 						}
614 						break;
615 					default:
616 						// Should not happen
617 						swprintf(wchMainInstruction, t[PIN_UNKNOWN_MAININSTRUCTIONS][getLanguage()]);
618 						swprintf(wchErrorMessage,  t[PIN_UNKNOWN_CONTENT][getLanguage()], SW1,SW2);
619 						break;
620 					}
621 					if (externalPinInfo.uiState == US_PINENTRY && !bSilent)
622 						TaskDialog(externalPinInfo.hwndParentWindow,
623 						NULL,
624 						t[WINDOW_TITLE][getLanguage()],
625 						wchMainInstruction,
626 						wchErrorMessage,
627 						TDCBF_RETRY_BUTTON  | TDCBF_CANCEL_BUTTON ,
628 						TD_ERROR_ICON,
629 						&nButton);
630 
631 				}
632 				if (SW1 == 0x63) {
633 					// Invalid PIN
634 					dwRetriesLeft = SW2 & 0x0F;
635 					if ( pcAttemptsRemaining != NULL )
636 					{
637 						/* -1: Don't support returning the count of remaining authentication attempts */
638 						*pcAttemptsRemaining = dwRetriesLeft;
639 					}
640 					swprintf(wchMainInstruction, t[PIN_INVALID_MAININSTRUCTIONS][getLanguage()]);
641 					swprintf(wchErrorMessage, t[PIN_INVALID_CONTENT][getLanguage()], dwRetriesLeft);
642 
643 					if (externalPinInfo.uiState == US_PINENTRY && !bSilent)
644 						TaskDialog(externalPinInfo.hwndParentWindow,
645 						NULL,
646 						t[WINDOW_TITLE][getLanguage()],
647 						wchMainInstruction,
648 						wchErrorMessage,
649 						TDCBF_RETRY_BUTTON  | TDCBF_CANCEL_BUTTON,
650 						TD_ERROR_ICON,
651 						&nButton);
652 				}
653 
654 				if (SW1 == 0x69 && SW2 == 0x83) {
655 					// PIN blocked
656 					swprintf(wchMainInstruction, t[PIN_BLOCKED_MAININSTRUCTIONS][getLanguage()]);
657 					swprintf(wchErrorMessage, t[PIN_BLOCKED_CONTENT][getLanguage()]);
658 					if (externalPinInfo.uiState == US_PINENTRY && !bSilent)
659 						TaskDialog(externalPinInfo.hwndParentWindow,
660 						NULL,
661 						t[WINDOW_TITLE][getLanguage()],
662 						wchMainInstruction,
663 						wchErrorMessage,
664 						TDCBF_OK_BUTTON,
665 						TD_ERROR_ICON,
666 						&nButton);
667 					dwReturn = SCARD_W_CHV_BLOCKED;
668 				}
669 				bRetry = (nButton == IDRETRY);
670 #endif
671 			}
672 			else
673 			{
674 				LogTrace(LOGTYPE_INFO, WHERE, "Logged on...");
675 			}
676 		}
677 	}
678 
679 cleanup:
680 
681 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
682 	return(dwReturn);
683 }
684 #undef WHERE
685 
686 /****************************************************************************************************/
687 
688 #define WHERE "BeidDeAuthenticate"
BeidDeAuthenticate(PCARD_DATA pCardData)689 DWORD BeidDeAuthenticate(PCARD_DATA    pCardData)
690 {
691    DWORD             dwReturn  = 0;
692 
693    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
694    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
695 
696    unsigned char     Cmd[128];
697    unsigned int      uiCmdLg   = 0;
698    unsigned char     recvbuf[256];
699    unsigned long     recvlen   = sizeof(recvbuf);
700    BYTE              SW1, SW2;
701    int               i         = 0;
702 
703    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
704 
705    /********************/
706    /* Check Parameters */
707    /********************/
708    if ( pCardData == NULL )
709    {
710       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pCardData]");
711       CLEANUP(SCARD_E_INVALID_PARAMETER);
712    }
713 
714    /***********/
715    /* Log Off */
716    /***********/
717    Cmd [0] = 0x80;
718    Cmd [1] = 0xE6; /* LOG OFF */
719    Cmd [2] = 0x00;
720    Cmd [3] = 0x00;
721    uiCmdLg = 4;
722    recvlen = sizeof(recvbuf);
723 
724    dwReturn = SCardTransmit(pCardData->hScard,
725                             &ioSendPci,
726                             Cmd,
727                             uiCmdLg,
728                             &ioRecvPci,
729                             recvbuf,
730                             &recvlen);
731    SW1 = recvbuf[recvlen-2];
732    SW2 = recvbuf[recvlen-1];
733    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
734    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
735    if ( dwReturn != SCARD_S_SUCCESS )
736    {
737       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
738       CLEANUP(dwReturn);
739    }
740    if ( (SW1 != 0x90) || (SW2 != 0x00) )
741    {
742       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit status bytes: [0x%02X][0x%02X]", SW1, SW2);
743       CLEANUP(SCARD_E_UNEXPECTED);
744    }
745 
746 cleanup:
747    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
748    return(dwReturn);
749 }
750 #undef WHERE
751 
752 /****************************************************************************************************/
753 
754 #define WHERE "BeidMSE"
BeidMSE(PCARD_DATA pCardData,BYTE bKey,BYTE bAlgo)755 DWORD BeidMSE(PCARD_DATA		pCardData,
756               BYTE					bKey,
757 							BYTE					bAlgo)
758 {
759    DWORD             dwReturn = 0;
760 
761    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
762    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
763 
764    unsigned char     Cmd[128];
765    unsigned int      uiCmdLg = 0;
766    unsigned char     recvbuf[256];
767    unsigned long     recvlen = sizeof(recvbuf);
768    BYTE              SW1, SW2;
769 
770    int               i = 0;
771 
772    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
773 
774 	 if ( (bKey != 0x82) && (bKey != 0x83) )
775 	 {
776       LogTrace(LOGTYPE_INFO, WHERE, "SET COMMAND: undefined key [0x%.2x]", bKey);
777       CLEANUP(SCARD_E_UNEXPECTED);
778    }
779 	 if ( (bAlgo != 0x01) && (bAlgo != 0x02) && (bAlgo != 0x04) && (bAlgo != 0x08) && (bAlgo != 0x10) && (bAlgo != 0x20) && (bAlgo != 0x40) )
780 	 {
781 		  LogTrace(LOGTYPE_INFO, WHERE, "SET COMMAND: undefined algo [0x%.2x]", bAlgo);
782       CLEANUP(SCARD_E_UNEXPECTED);
783 	 }
784 
785    /*
786     * The MSE: SET Command will fail with error 0x000006f7
787     * if the command is executed too fast after an command which resulted in an error condition
788     */
789    Sleep(20);
790 
791    /* Prepare SET COMMAND before a VERIFY PIN */
792    Cmd [0] = 0x00;
793    Cmd [1] = 0x22;   /* MSE: SET COMMAND */
794    Cmd [2] = 0x41;
795    Cmd [3] = 0xB6;
796    Cmd [4] = 0x05;
797    Cmd [5] = 0x04;   /* Length of following data      */
798    Cmd [6] = 0x80;   /* ALGO Rreference               */
799    Cmd [7] = bAlgo;//0x01;   /* RSA PKCS#1                    */
800    Cmd [8] = 0x84;   /* TAG for private key reference */
801 	 Cmd [9] = bKey;	/*0x82 for AUTH, 0x83 for NONREP*/
802 
803    uiCmdLg = 10;
804 
805    dwReturn = SCardTransmit(pCardData->hScard,
806                             &ioSendPci,
807                             Cmd,
808                             uiCmdLg,
809                             &ioRecvPci,
810                             recvbuf,
811                             &recvlen);
812    SW1 = recvbuf[recvlen-2];
813    SW2 = recvbuf[recvlen-1];
814    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
815    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
816    if ( dwReturn != SCARD_S_SUCCESS )
817    {
818       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit (SET) errorcode: [0x%08X]", dwReturn);
819       CLEANUP(dwReturn);
820    }
821    if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
822    {
823       LogTrace(LOGTYPE_ERROR, WHERE, "SET Failed: [0x%02X][0x%02X]", SW1, SW2);
824       CLEANUP(SCARD_E_UNEXPECTED);
825    }
826 
827 cleanup:
828    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
829    return(dwReturn);
830 }
831 #undef WHERE
832 
833 /****************************************************************************************************/
834 
835 #define WHERE "BeidChangePIN"
BeidChangePIN(PCARD_DATA pCardData,PBYTE pbCurrentAuthenticator,DWORD cbCurrentAuthenticator,PBYTE pbNewAuthenticator,DWORD cbNewAuthenticator,PDWORD pcAttemptsRemaining)836 DWORD    BeidChangePIN
837          (
838             PCARD_DATA  pCardData,
839             PBYTE       pbCurrentAuthenticator,
840             DWORD       cbCurrentAuthenticator,
841             PBYTE       pbNewAuthenticator,
842             DWORD       cbNewAuthenticator,
843             PDWORD      pcAttemptsRemaining
844          )
845 {
846    DWORD             dwReturn = 0;
847 
848    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
849    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
850 
851    unsigned char     Cmd[128];
852    unsigned int      uiCmdLg = 0;
853    unsigned char     recvbuf[256];
854    unsigned long     recvlen = sizeof(recvbuf);
855    BYTE              SW1, SW2;
856 
857    unsigned int      i        = 0;
858    int               offset   = 0;
859 
860    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
861 
862    /********************/
863    /* Check Parameters */
864    /********************/
865    if ( pCardData == NULL )
866    {
867       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pCardData]");
868       CLEANUP(SCARD_E_INVALID_PARAMETER);
869    }
870    if ( pbCurrentAuthenticator == NULL )
871    {
872       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbCurrentAuthenticator]");
873       CLEANUP(SCARD_E_INVALID_PARAMETER);
874    }
875    if ( pbNewAuthenticator == NULL )
876    {
877       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbNewAuthenticator]");
878       CLEANUP(SCARD_E_INVALID_PARAMETER);
879    }
880    if ( ( cbCurrentAuthenticator < BELPIC_MIN_USER_PIN_LEN ) ||
881         ( cbCurrentAuthenticator > BELPIC_MAX_USER_PIN_LEN ) )
882    {
883       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [cbCurrentAuthenticator]");
884       CLEANUP(SCARD_W_WRONG_CHV);
885    }
886    if ( ( cbNewAuthenticator < BELPIC_MIN_USER_PIN_LEN ) ||
887         ( cbNewAuthenticator > BELPIC_MAX_USER_PIN_LEN ) )
888    {
889       LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [cbCurrentAuthenticator]");
890       CLEANUP(SCARD_W_WRONG_CHV);
891    }
892 
893 	 for ( i = 0 ; i < (unsigned char) cbCurrentAuthenticator ; i++ )
894 	 {
895 		 /* Don't allow non-numerical PIN entries */
896 		 if ( ( pbCurrentAuthenticator[i] < 0x30 ) || ( pbCurrentAuthenticator[i] > 0x39 ) )
897 		 {
898 			 LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbCurrentAuthenticator[i]]");
899 			 CLEANUP(SCARD_W_WRONG_CHV);
900 		 }
901 	 }
902 
903 	 for ( i = 0 ; i < (unsigned char) cbNewAuthenticator ; i++ )
904 	 {
905 		 /* Don't allow non-numerical PIN entries */
906 		 if ( ( pbNewAuthenticator[i] < 0x30 ) || ( pbNewAuthenticator[i] > 0x39 ) )
907 		 {
908 			 LogTrace(LOGTYPE_ERROR, WHERE, "Invalid parameter [pbNewAuthenticator[i]]");
909 			 CLEANUP(SCARD_W_WRONG_CHV);
910 		 }
911 	 }
912 
913    /* Change PIN code */
914    Cmd [0] = 0x00;
915    Cmd [1] = 0x24;   /* CHANGE REFERENCE DATA COMMAND    */
916    Cmd [2] = 0x00;   /* Support 'USER' password change   */
917    Cmd [3] = 0x01;
918    Cmd [4] = 0x10;
919 
920    /* Fill verification data with padding character */
921    for ( i = 0 ; i < 0x10 ; i++ )
922    {
923       Cmd [5 + i] = BELPIC_PAD_CHAR;
924    }
925 
926    Cmd [5] = 0x20 + (unsigned char)cbCurrentAuthenticator;  /* 0x20 + length of pin */
927    for ( i = 0 ; i < (unsigned char) cbCurrentAuthenticator ; i++ )
928    {
929     offset = 6 + (i/2);
930 
931       if ( (i % 2) == 0 )
932       {
933          Cmd [offset] = (((pbCurrentAuthenticator[i] - 48) << 4) & 0xF0);
934       }
935       else
936       {
937          Cmd [offset] = (Cmd[offset] & 0xF0) + ((pbCurrentAuthenticator[i] - 48) & 0x0F);
938       }
939    }
940    Cmd [13] = 0x20 + (unsigned char)cbNewAuthenticator;  /* 0x20 + length of pin */
941    for ( i = 0 ; i < (unsigned char) cbNewAuthenticator ; i++ )
942    {
943     offset = 14 + (i/2);
944 
945       if ( (i % 2) == 0 )
946       {
947          Cmd [offset] = (((pbNewAuthenticator[i] - 48) << 4) & 0xF0);
948       }
949       else
950       {
951          Cmd [offset] = (Cmd[offset] & 0xF0) + ((pbNewAuthenticator[i] - 48) & 0x0F);
952       }
953    }
954 
955    uiCmdLg = 21;
956    recvlen = sizeof(recvbuf);
957 
958    dwReturn = SCardTransmit(pCardData->hScard,
959                             &ioSendPci,
960                             Cmd,
961                             uiCmdLg,
962                             &ioRecvPci,
963                             recvbuf,
964                             &recvlen);
965 
966    memset(Cmd, 0, uiCmdLg);
967 
968    SW1 = recvbuf[recvlen-2];
969    SW2 = recvbuf[recvlen-1];
970    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
971    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
972    if ( dwReturn != SCARD_S_SUCCESS )
973    {
974       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
975       CLEANUP(dwReturn);
976    }
977 
978    if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
979    {
980       dwReturn = SCARD_W_WRONG_CHV;
981       LogTrace(LOGTYPE_ERROR, WHERE, "CardChangeAuthenticator Failed: [0x%02X][0x%02X]", SW1, SW2);
982 
983       if ( ((SW1 == 0x63) && ((SW2 & 0xF0) == 0xC0)) )
984       {
985          if ( pcAttemptsRemaining != NULL )
986          {
987             /* -1: Don't support returning the count of remaining authentication attempts */
988             *pcAttemptsRemaining = (SW2 & 0x0F);
989          }
990       }
991       else if ( (SW1 == 0x69) && (SW2 == 0x83) )
992       {
993          dwReturn = SCARD_W_CHV_BLOCKED;
994       }
995    }
996    else
997    {
998       LogTrace(LOGTYPE_INFO, WHERE, "Changed PIN...");
999    }
1000 
1001 cleanup:
1002    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1003    return(dwReturn);
1004 }
1005 #undef WHERE
1006 
1007 /****************************************************************************************************/
1008 
1009 #define WHERE "BeidGetCardSN"
BeidGetCardSN(PCARD_DATA pCardData,PBYTE pbSerialNumber,DWORD cbSerialNumber,PDWORD pdwSerialNumber)1010 DWORD BeidGetCardSN(PCARD_DATA  pCardData,
1011 					PBYTE pbSerialNumber,
1012 					DWORD cbSerialNumber,
1013 					PDWORD pdwSerialNumber)
1014 {
1015 	DWORD                   dwReturn = 0;
1016 
1017 	SCARD_IO_REQUEST        ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1018 	SCARD_IO_REQUEST        ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1019 
1020 	unsigned char           Cmd[128];
1021 	unsigned int            uiCmdLg = 0;
1022 
1023 	unsigned char           recvbuf[256];
1024 	unsigned long           recvlen = sizeof(recvbuf);
1025 	BYTE                    SW1 = 0;
1026 	BYTE                    SW2 = 0;
1027 
1028 	int                     i = 0;
1029 	int                     iWaitApdu = 100;
1030 	int   				      bRetry = 0;
1031 
1032 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1033 	if (cbSerialNumber < 16) {
1034 		CLEANUP(ERROR_INSUFFICIENT_BUFFER);
1035 	}
1036 
1037 	*pdwSerialNumber = 0;
1038 
1039 	Cmd [0] = 0x80;
1040 	Cmd [1] = 0xE4;
1041 	Cmd [2] = 0x00;
1042 	Cmd [3] = 0x00;
1043 	Cmd [4] = 0x1C;//10 we only need 16 bytes, asking for 28 would help out some readers in combination with default ccid driver (if it weren't for certprop service, which also asks 16 bytes)
1044 	uiCmdLg = 5;
1045 
1046 	do {
1047 		i++;
1048 		bRetry = 0;
1049 
1050 		Sleep(iWaitApdu);
1051 		recvlen = sizeof(recvbuf);
1052 		dwReturn = SCardTransmit(pCardData->hScard, &ioSendPci, Cmd, uiCmdLg, &ioRecvPci, recvbuf, &recvlen);
1053 		if (recvlen >= 2)
1054 		{
1055 			SW1 = recvbuf[recvlen-2];
1056 			SW2 = recvbuf[recvlen-1];
1057 			LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1058 			BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1059 
1060 			if (dwReturn == SCARD_E_COMM_DATA_LOST)
1061 			{
1062 				bRetry++;
1063 				LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit failed with SCARD_E_COMM_DATA_LOST. Sleep %d ms and try again", iWaitApdu);
1064 			}
1065 			if (dwReturn == SCARD_S_SUCCESS)
1066 			{
1067 				// 6d = "command not available in current life cycle"
1068 				if ( SW1 == 0x6d )
1069 				{
1070 					LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit returned SW1 = 6d. Sleep %d ms and try again", iWaitApdu);
1071 					bRetry++;
1072 				}
1073 			}
1074 		}
1075 		else
1076 		{
1077 			LogTrace(LOGTYPE_ERROR, WHERE, "GetCardData recvlen = %d\n", recvlen);
1078 		}
1079 	} while (bRetry != 0 && i < 10);
1080 
1081 
1082 	if(dwReturn == SCARD_S_SUCCESS )
1083 	{
1084 //		if (SW1 == 0x6c)
1085 //		{
1086 //			//SW2 contains length of the carddata (1C)
1087 //			Cmd [4] = SW2;
1088 //			uiCmdLg = 5;
1089 //			recvlen = sizeof(recvbuf);
1090 //			dwReturn = SCardTransmit(pCardData->hScard, &ioSendPci, Cmd, uiCmdLg, &ioRecvPci, recvbuf, &recvlen);
1091 //			if (recvlen >= 2)
1092 //			{
1093 //				SW1 = recvbuf[recvlen-2];
1094 //				SW2 = recvbuf[recvlen-1];
1095 //			}
1096 //			else
1097 //			{
1098 //				LogTrace(LOGTYPE_ERROR, WHERE, "GetCardData recvlen = %d\n", recvlen);
1099 //			}
1100 //		}
1101 		if(recvlen >= 18)
1102 		{
1103 			if( (( SW1 == 0x90 ) && ( SW2 == 0x00 )) || (( SW1 == 0x61 ) && ( SW2 == 0x0C )) )
1104 			{
1105 				*pdwSerialNumber = 16;
1106 				memcpy(pbSerialNumber, recvbuf, 16);
1107 			}
1108 			else
1109 			{
1110 				LogTrace(LOGTYPE_ERROR, WHERE, "Bad status bytes: [0x%02X][0x%02X]", SW1, SW2);
1111 				CLEANUP(SCARD_E_UNEXPECTED);
1112 			}
1113 		}
1114 		else
1115 		{
1116 			LogTrace(LOGTYPE_ERROR, WHERE, "Serial number too short, status bytes: [0x%02X][0x%02X]", SW1, SW2);
1117 			CLEANUP(SCARD_E_UNEXPECTED);
1118 		}
1119 	}
1120 	else //dwReturn == SCARD_S_SUCCESS
1121 	{
1122 		LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit (GET_CARD_DATA) errorcode: [0x%08X]", dwReturn);
1123 		CLEANUP(dwReturn);
1124 	}
1125 
1126 cleanup:
1127 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1128 	return (dwReturn);
1129 }
1130 #undef WHERE
1131 
1132 /****************************************************************************************************/
1133 
1134 #define WHERE "BeidSignData"
BeidSignData(PCARD_DATA pCardData,unsigned int HashAlgo,DWORD cbToBeSigned,PBYTE pbToBeSigned,DWORD * pcbSignature,PBYTE * ppbSignature)1135 DWORD BeidSignData(PCARD_DATA  pCardData, unsigned int HashAlgo, DWORD cbToBeSigned, PBYTE pbToBeSigned, DWORD *pcbSignature, PBYTE *ppbSignature)
1136 {
1137 	DWORD                   dwReturn = 0;
1138 
1139 	SCARD_IO_REQUEST        ioSendPci = { 1, sizeof(SCARD_IO_REQUEST) };
1140 	SCARD_IO_REQUEST        ioRecvPci = { 1, sizeof(SCARD_IO_REQUEST) };
1141 
1142 	unsigned char           Cmd[128];
1143 	unsigned int            uiCmdLg = 0;
1144 
1145 	unsigned char           recvbuf[1024];
1146 	unsigned long           recvlen = sizeof(recvbuf);
1147 	BYTE                    SW1, SW2;
1148 	VENDOR_SPECIFIC*		pVendorSpec;
1149 
1150 	static const unsigned char MD2_AID[] = {
1151 	   0x30, 0x20,
1152 		  0x30, 0x0c,
1153 			 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02,
1154 			 0x05, 0x00,
1155 		  0x04, 0x10
1156 	};
1157 	static const unsigned char MD4_AID[] = {
1158 	   0x30, 0x20,
1159 		  0x30, 0x0c,
1160 			 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04,
1161 			 0x05, 0x00,
1162 		  0x04, 0x10
1163 	};
1164 	static const unsigned char MD5_AID[] = {
1165 		0x30, 0x20,
1166 			0x30, 0x0c,
1167 				0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,
1168 				0x05, 0x00,
1169 			0x04, 0x10
1170 	};
1171 	static const unsigned char SHA1_AID[] = {
1172 		0x30, 0x21,
1173 			0x30, 0x09,
1174 				0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
1175 			0x05, 0x00,
1176 			0x04, 0x14
1177 	};
1178 	static const unsigned char SHA256_AID[] = {
1179 		0x30, 0x31,
1180 			0x30, 0x0d,
1181 				0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
1182 			0x05, 0x00,
1183 			0x04, 0x20
1184 	};
1185 	static const unsigned char SHA384_AID[] = {
1186 		0x30, 0x41,
1187 			0x30, 0x0d,
1188 				0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
1189 			0x05,0x00,
1190 			0x04, 0x30
1191 	};
1192 	static const unsigned char SHA512_AID[] = {
1193 		0x30, 0x51,
1194 			0x30, 0x0d,
1195 				0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
1196 			0x05, 0x00,
1197 			0x04, 0x40
1198 	};
1199 	static const unsigned char RIPEMD160_AID[] = {
1200 		0x30, 0x21,
1201 			0x30, 0x09,
1202 				0x06, 0x05, 0x2B, 0x24,	0x03, 0x02, 0x01,
1203 			0x05, 0x00,
1204 			0x04, 0x14
1205 	};
1206 
1207 	unsigned int            i = 0;
1208 	unsigned int            cbHdrHash = 0;
1209 	const unsigned char     *pbHdrHash = NULL;
1210 
1211 	/* Sign Command */
1212 	Cmd[0] = 0x00;
1213 	Cmd[1] = 0x2A;   /* PSO: Compute Digital Signature COMMAND */
1214 	Cmd[2] = 0x9E;
1215 	Cmd[3] = 0x9A;
1216 
1217 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1218 	/* Length of data to be signed   */
1219 	switch (HashAlgo)
1220 	{
1221 	case HASH_ALGO_NONE:
1222 		LogTrace(LOGTYPE_INFO, WHERE, "NONE");
1223 		cbHdrHash = 0;
1224 		pbHdrHash = NULL;
1225 		break;
1226 
1227 	case HASH_ALGO_MD2:
1228 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_MD2");
1229 		cbHdrHash = sizeof(MD2_AID);
1230 		pbHdrHash = MD2_AID;
1231 		break;
1232 	case HASH_ALGO_MD4:
1233 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_MD4");
1234 		cbHdrHash = sizeof(MD4_AID);
1235 		pbHdrHash = MD4_AID;
1236 		break;
1237 	case HASH_ALGO_MD5:
1238 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_MD5");
1239 		cbHdrHash = sizeof(MD5_AID);
1240 		pbHdrHash = MD5_AID;
1241 		break;
1242 	case HASH_ALGO_SHA1:
1243 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_SHA1");
1244 		cbHdrHash = sizeof(SHA1_AID);
1245 		pbHdrHash = SHA1_AID;
1246 		break;
1247 	case HASH_ALGO_SHA_256:
1248 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_SHA_256");
1249 		cbHdrHash = sizeof(SHA256_AID);
1250 		pbHdrHash = SHA256_AID;
1251 		break;
1252 	case HASH_ALGO_SHA_384:
1253 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_SHA_384");
1254 		cbHdrHash = sizeof(SHA384_AID);
1255 		pbHdrHash = SHA384_AID;
1256 		break;
1257 	case HASH_ALGO_SHA_512:
1258 		LogTrace(LOGTYPE_INFO, WHERE, "CALG_SHA_512");
1259 		cbHdrHash = sizeof(SHA512_AID);
1260 		pbHdrHash = SHA512_AID;
1261 		break;
1262 	default:
1263 		break;
1264 	}
1265 	if (HashAlgo == HASH_ALGO_NONE)
1266 	{
1267 		Cmd[4] = (BYTE)(cbToBeSigned);
1268 		memcpy(Cmd + 5, pbToBeSigned, cbToBeSigned);
1269 		uiCmdLg = 5 + cbToBeSigned;
1270 	}
1271 	else
1272 	{
1273 		Cmd[4] = (BYTE)(cbToBeSigned + cbHdrHash);
1274 		memcpy(Cmd + 5, pbHdrHash, cbHdrHash);
1275 		memcpy(Cmd + 5 + cbHdrHash, pbToBeSigned, cbToBeSigned);
1276 		uiCmdLg = 5 + cbHdrHash + cbToBeSigned;
1277 	}
1278 
1279 #ifdef _DEBUG
1280 	LogDumpBin("C:\\SmartCardMinidriverTest\\signdata.bin", cbHdrHash + cbToBeSigned, (char *)&Cmd[5]);
1281 #endif
1282 
1283 	recvlen = sizeof(recvbuf);
1284 	dwReturn = SCardTransmit(pCardData->hScard,
1285 		&ioSendPci,
1286 		Cmd,
1287 		uiCmdLg,
1288 		&ioRecvPci,
1289 		recvbuf,
1290 		&recvlen);
1291 	SW1 = recvbuf[recvlen - 2];
1292 	SW2 = recvbuf[recvlen - 1];
1293 	LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1294 	BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1295 	if (dwReturn != SCARD_S_SUCCESS)
1296 	{
1297 		LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit (SIGN) errorcode: [0x%08X]", dwReturn);
1298 		CLEANUP(dwReturn);
1299 	}
1300 	LogTrace(LOGTYPE_TRACE, WHERE, "ADPU response: [0x%02X][0x%02X]", SW1, SW2);
1301 	LogTrace(LOGTYPE_TRACE, WHERE, "recvlen = %d", recvlen, SW2);
1302 	if (SW1 == 0x61)
1303 	{
1304 		/* Retrieve signature Command */
1305 		Cmd[0] = 0x00;
1306 		Cmd[1] = 0xC0;   /* PSO: GET RESPONSE COMMAND */
1307 		Cmd[2] = 0x00;
1308 		Cmd[3] = 0x00;
1309 		Cmd[4] = SW2;   /* Length of response */
1310 		uiCmdLg = 5;
1311 
1312 		recvlen = sizeof(recvbuf);
1313 		dwReturn = SCardTransmit(pCardData->hScard,
1314 			&ioSendPci,
1315 			Cmd,
1316 			uiCmdLg,
1317 			&ioRecvPci,
1318 			recvbuf,
1319 			&recvlen);
1320 		SW1 = recvbuf[recvlen - 2];
1321 		SW2 = recvbuf[recvlen - 1];
1322 		LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1323 		BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1324 		if (dwReturn != SCARD_S_SUCCESS)
1325 		{
1326 			LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit (Get Response) errorcode: [0x%08X]", dwReturn);
1327 			CLEANUP(dwReturn);
1328 		}
1329 		if ((SW1 != 0x90) || (SW2 != 0x00))
1330 		{
1331 			LogTrace(LOGTYPE_ERROR, WHERE, "Get Response Failed: [0x%02X][0x%02X]", SW1, SW2);
1332 			CLEANUP(SCARD_E_UNEXPECTED);
1333 		}
1334 	}//end of get response handling
1335 	else if ((SW1 != 0x90) || (SW2 != 0x00))
1336 	{
1337 		LogTrace(LOGTYPE_ERROR, WHERE, "Sign Failed: [0x%02X][0x%02X]", SW1, SW2);
1338 
1339 		if (SW1 == 0x69)
1340 		{
1341 			CLEANUP(SCARD_W_SECURITY_VIOLATION);
1342 		}
1343 		else
1344 		{
1345 			CLEANUP(SCARD_E_UNEXPECTED);
1346 		}
1347 	}
1348 	pVendorSpec = pCardData->pvVendorSpecific;
1349 	if (pVendorSpec->bBEIDCardType == BEID_ECC_CARD)
1350 	{
1351 		if ((recvlen - 2) == 0x60)
1352 		{
1353 			*pcbSignature = 0x60; //48d * 2
1354 		}
1355 		else //not supported
1356 		{
1357 			LogTrace(LOGTYPE_ERROR, WHERE, "Invalid length received: [0x%02X]", recvlen - 2);
1358 			CLEANUP(SCARD_E_UNEXPECTED);
1359 		}
1360 	}
1361 	else
1362 	{
1363 		if ((recvlen - 2) == 0x80)
1364 		{
1365 			*pcbSignature = 0x80; //128d
1366 		}
1367 		else if ((recvlen - 2) == 0x100)
1368 		{
1369 			*pcbSignature = 0x100; //256d
1370 		}
1371 		else //not supported
1372 		{
1373 			LogTrace(LOGTYPE_ERROR, WHERE, "Invalid length received: [0x%02X]", recvlen - 2);
1374 			CLEANUP(SCARD_E_UNEXPECTED);
1375 		}
1376 	}
1377 	/* Allocate memory for the target buffer */
1378 	*ppbSignature = (PBYTE)(pCardData->pfnCspAlloc(*pcbSignature));
1379 	if (*ppbSignature == NULL)
1380 	{
1381 		LogTrace(LOGTYPE_ERROR, WHERE, "Error allocating memory for [*ppbSignature]");
1382 		CLEANUP(SCARD_E_NO_MEMORY);
1383 	}
1384 	/* Copy the signature */
1385 	if (pVendorSpec->bBEIDCardType == BEID_RSA_CARD)
1386 	{
1387 		//for RSA, revert byte order
1388 		for (i = 0; i < *pcbSignature; i++)
1389 		{
1390 			(*ppbSignature)[i] = recvbuf[*pcbSignature - i - 1];
1391 		}
1392 	}
1393 	else
1394 	{
1395 		for (i = 0; i < *pcbSignature; i++)
1396 		{
1397 			(*ppbSignature)[i] = recvbuf[i];
1398 		}
1399 	}
1400 
1401 cleanup:
1402    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1403    return (dwReturn);
1404 }
1405 #undef WHERE
1406 
1407 /****************************************************************************************************/
1408 // read up to *cbStream bytes from the currently selected file, starting at offset dwOffset
1409 // and store them in pbStream
1410 /****************************************************************************************************/
1411 #define WHERE "BeidReadFile"
BeidReadFile(PCARD_DATA pCardData,DWORD dwOffset,DWORD * cbStream,PBYTE pbStream)1412 DWORD BeidReadFile(PCARD_DATA  pCardData, DWORD dwOffset, DWORD *cbStream, PBYTE pbStream)
1413 {
1414    DWORD             dwReturn = 0;
1415    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1416    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1417 
1418    unsigned char     Cmd[128];
1419    unsigned int      uiCmdLg = 0;
1420    unsigned char     recvbuf[256];
1421    unsigned long     recvlen = sizeof(recvbuf);
1422    BYTE              SW1, SW2;
1423    DWORD             cbRead      = 0;
1424    DWORD             cbPartRead  = 0;
1425 
1426    /***************/
1427    /* Read File */
1428    /***************/
1429    Cmd [0] = 0x00;
1430    Cmd [1] = 0xB0; /* READ BINARY COMMAND */
1431    Cmd [2] = 0x00;
1432    Cmd [3] = 0x00;
1433    Cmd [4] = 0x00;
1434    uiCmdLg = 5;
1435    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1436 
1437 	 while ( ( *cbStream - cbRead ) > 0 )
1438 	 {
1439 		 Cmd[2] = (BYTE)((dwOffset + cbRead) >> 8);   /* set reading startpoint     */
1440 		Cmd[3] = (BYTE)( (dwOffset + cbRead)&(0xFF) );
1441 
1442 		 cbPartRead = *cbStream - cbRead;
1443 		 if(cbPartRead > BEID_READ_BINARY_MAX_LEN)    /*if more than maximum length */
1444 		 {
1445 			 Cmd[4] = BEID_READ_BINARY_MAX_LEN;        /* is requested, than read    */
1446 		 }
1447 		 else                                         /* maximum length             */
1448 		 {
1449 			 Cmd[4] = (BYTE)(cbPartRead);
1450 		 }
1451 		 recvlen = sizeof(recvbuf);
1452 #ifdef _DEBUG
1453 		 LogDump(uiCmdLg,Cmd);
1454 #endif
1455 		 dwReturn = SCardTransmit(pCardData->hScard,
1456 			 &ioSendPci,
1457 			 Cmd,
1458 			 uiCmdLg,
1459 			 &ioRecvPci,
1460 			 recvbuf,
1461 			 &recvlen);
1462 		 SW1 = recvbuf[recvlen-2];
1463 		 SW2 = recvbuf[recvlen-1];
1464 		 LogTrace(LOGTYPE_TRACE, WHERE, "recvlen = %d SW1 = 0x%.02X SW2 = 0x%.02X", recvlen,SW1,SW2);
1465 #ifdef _DEBUG
1466 		 LogDump(recvlen,recvbuf);
1467 #endif
1468 		 LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1469 		 BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1470 		 if ( dwReturn != SCARD_S_SUCCESS )
1471 		 {
1472 			 LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1473 			 CLEANUP(dwReturn);
1474 		 }
1475 
1476 		 /* Special case: when SW1 == 0x6C (=incorrect value of Le), we will
1477 		 retransmit with SW2 as Le, if SW2 is smaller then the
1478 		 BEID_READ_BINARY_MAX_LEN */
1479 		 if ( ( SW1 == 0x6c ) && ( SW2 <= BEID_READ_BINARY_MAX_LEN ) )
1480 		 {
1481 			 Cmd[4] = SW2;
1482 			 recvlen = sizeof(recvbuf);
1483 #ifdef _DEBUG
1484 			 LogDump(uiCmdLg,Cmd);
1485 #endif
1486 			 dwReturn = SCardTransmit(pCardData->hScard,
1487 				 &ioSendPci,
1488 				 Cmd,
1489 				 uiCmdLg,
1490 				 &ioRecvPci,
1491 				 recvbuf,
1492 				 &recvlen);
1493 			 LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1494 			 if ( dwReturn != SCARD_S_SUCCESS )
1495 			 {
1496 				 LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1497 				 CLEANUP(dwReturn);
1498 			 }
1499 			 SW1 = recvbuf[recvlen - 2];
1500 			 SW2 = recvbuf[recvlen - 1];
1501 
1502 			 memcpy (pbStream + cbRead, recvbuf, recvlen - 2);
1503 			 cbRead += recvlen - 2;
1504 			 break; //stop reading, we already had the length corrected
1505 		 }
1506 
1507 		 if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
1508 		 {
1509 			 LogTrace(LOGTYPE_ERROR, WHERE, "Read Binary Failed: [0x%02X][0x%02X]", SW1, SW2);
1510 			 break; //stop reading, something ain't right
1511 		 }
1512 
1513 		 memcpy (pbStream + cbRead, recvbuf, recvlen - 2);
1514 		 cbRead += recvlen - 2;
1515 	 }
1516 	*cbStream = cbRead;
1517 	LogTrace(LOGTYPE_TRACE, WHERE, "cbRead = %d",cbRead);
1518 cleanup:
1519 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1520    return (dwReturn);
1521 }
1522 #undef WHERE
1523 
1524 /****************************************************************************************************/
1525 
1526 #define WHERE "BeidSelectAndReadFile"
BeidSelectAndReadFile(PCARD_DATA pCardData,DWORD dwOffset,BYTE cbFileID,PBYTE pbFileID,DWORD * cbStream,PBYTE * ppbStream)1527 DWORD BeidSelectAndReadFile(PCARD_DATA  pCardData, DWORD dwOffset, BYTE cbFileID, PBYTE pbFileID, DWORD *cbStream, PBYTE * ppbStream)
1528 {
1529    DWORD             dwReturn = 0;
1530 
1531    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1532    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1533 
1534    unsigned char     Cmd[128];
1535    unsigned int      uiCmdLg = 0;
1536 
1537    unsigned char     recvbuf[256];
1538    unsigned long     recvlen = sizeof(recvbuf);
1539    BYTE              SW1, SW2;
1540    DWORD             cbReadBuf;
1541 
1542    /***************/
1543    /* Select File */
1544    /***************/
1545    Cmd [0] = 0x00;
1546    Cmd [1] = 0xA4; /* SELECT COMMAND */
1547    Cmd [2] = 0x08;
1548    Cmd [3] = 0x0C;
1549    Cmd [4] = cbFileID;
1550    uiCmdLg = 5;
1551    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1552 
1553 
1554    memcpy(&Cmd[5], pbFileID, cbFileID);
1555    uiCmdLg += cbFileID;
1556 
1557 #ifdef _DEBUG
1558 	 LogDump(uiCmdLg,Cmd);
1559 #endif
1560    dwReturn = SCardTransmit(pCardData->hScard,
1561                             &ioSendPci,
1562                             Cmd,
1563                             uiCmdLg,
1564                             &ioRecvPci,
1565                             recvbuf,
1566                             &recvlen);
1567    SW1 = recvbuf[recvlen-2];
1568    SW2 = recvbuf[recvlen-1];
1569    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1570    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1571    if ( dwReturn != SCARD_S_SUCCESS )
1572    {
1573       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1574       CLEANUP(dwReturn);
1575    }
1576    if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
1577    {
1578       LogTrace(LOGTYPE_ERROR, WHERE, "Select Failed: [0x%02X][0x%02X]", SW1, SW2);
1579       CLEANUP(dwReturn);
1580    }
1581 
1582 	*cbStream = 0;
1583 	*ppbStream = NULL;
1584 	cbReadBuf = 1024;
1585 	//read the file in chunks of 1024 bytes
1586 	while (cbReadBuf == 1024)
1587 	{
1588 		if (*ppbStream == NULL)
1589 			*ppbStream = (PBYTE) pCardData->pfnCspAlloc(cbReadBuf);
1590 		else
1591 			*ppbStream = (PBYTE) pCardData->pfnCspReAlloc(*ppbStream, *cbStream + cbReadBuf);
1592 
1593 		if (*ppbStream == NULL) {
1594 			LogTrace(LOGTYPE_ERROR, WHERE, "pfnCsp(Re)Alloc failed");
1595 			CLEANUP(dwReturn);
1596 		}
1597 		LogTrace(LOGTYPE_ERROR, WHERE, "dwOffset = %d", dwOffset);
1598 		dwReturn = BeidReadFile(pCardData, dwOffset, &cbReadBuf, *ppbStream + (*cbStream * sizeof(BYTE)));
1599 		if ( dwReturn != SCARD_S_SUCCESS )
1600 		{
1601 			LogTrace(LOGTYPE_ERROR, WHERE, "BeidReadFile errorcode: [0x%08X]", dwReturn);
1602 			pCardData->pfnCspFree(*ppbStream);
1603 			*ppbStream = NULL;
1604 			*cbStream = 0;
1605 			CLEANUP(dwReturn);
1606 		}
1607 		dwOffset += cbReadBuf;
1608 		*cbStream += cbReadBuf;
1609 	}
1610 cleanup:
1611 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1612    return (dwReturn);
1613 }
1614 #undef WHERE
1615 /****************************************************************************************************/
1616 
1617 #define WHERE "BeidReadCert"
BeidReadCert(PCARD_DATA pCardData,DWORD dwCertSpec,DWORD * pcbCertif,PBYTE * ppbCertif)1618 DWORD BeidReadCert(PCARD_DATA  pCardData, DWORD dwCertSpec, DWORD *pcbCertif, PBYTE *ppbCertif)
1619 {
1620    DWORD             dwReturn = 0;
1621 
1622    SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1623    SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1624 
1625    unsigned char     Cmd[128];
1626    unsigned int      uiCmdLg = 0;
1627 
1628    unsigned char     recvbuf[256];
1629    unsigned long     recvlen = sizeof(recvbuf);
1630    BYTE              SW1, SW2;
1631 
1632    BYTE              bFileID[6] = {0x3F, 0x00, 0xDF, 0x00, 0x50, 0x00};
1633    BYTE              cbFileID   = (BYTE)sizeof(bFileID);
1634 
1635    BYTE              bRead [255];
1636    DWORD             cbRead;
1637 
1638    DWORD             cbCertif;
1639 
1640    /***************/
1641    /* Select File */
1642    /***************/
1643    Cmd [0] = 0x00;
1644    Cmd [1] = 0xA4; /* SELECT COMMAND */
1645    Cmd [2] = 0x08;
1646    Cmd [3] = 0x0C;
1647    Cmd [4] = cbFileID;
1648    uiCmdLg = 5;
1649 
1650    LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1651 
1652    switch (dwCertSpec)
1653    {
1654    case CERT_AUTH:
1655       bFileID [5] = 0x38;
1656       break;
1657    case CERT_NONREP:
1658       bFileID [5] = 0x39;
1659       break;
1660    case CERT_CA:
1661       bFileID [5] = 0x3a;
1662       break;
1663    case CERT_ROOTCA:
1664       bFileID [5] = 0x3b;
1665       break;
1666    }
1667 
1668    memcpy(&Cmd[5], bFileID, cbFileID);
1669    uiCmdLg += cbFileID;
1670 #ifdef _DEBUG
1671 	 LogDump(uiCmdLg,Cmd);
1672 #endif
1673    dwReturn = SCardTransmit(pCardData->hScard,
1674                             &ioSendPci,
1675                             Cmd,
1676                             uiCmdLg,
1677                             &ioRecvPci,
1678                             recvbuf,
1679                             &recvlen);
1680    SW1 = recvbuf[recvlen-2];
1681    SW2 = recvbuf[recvlen-1];
1682    LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1683    BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1684    if ( dwReturn != SCARD_S_SUCCESS )
1685    {
1686       LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1687       CLEANUP(dwReturn);
1688    }
1689    if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
1690    {
1691       LogTrace(LOGTYPE_ERROR, WHERE, "Select Failed: [0x%02X][0x%02X]", SW1, SW2);
1692       CLEANUP(dwReturn);
1693    }
1694 
1695    /* Read First 4 bytes */
1696    cbRead = 4;
1697    dwReturn = BeidReadFile(pCardData, 0, &cbRead, bRead);
1698    if ( dwReturn != SCARD_S_SUCCESS )
1699    {
1700       LogTrace(LOGTYPE_ERROR, WHERE, "BeidReadFile errorcode: [0x%08X]", dwReturn);
1701       CLEANUP(dwReturn);
1702    }
1703 
1704    cbCertif = (bRead[2] << 8) + bRead[3] + 4;
1705    if (ppbCertif == NULL)
1706    {
1707 	   // we will only return the file length
1708 	   if (pcbCertif != NULL)
1709 		   *pcbCertif = cbCertif;
1710 	   LogTrace(LOGTYPE_INFO, WHERE, "returning filelength = %d", cbCertif);
1711 	   CLEANUP(SCARD_S_SUCCESS);
1712    }
1713    cbRead = cbCertif;
1714 
1715    *ppbCertif = pCardData->pfnCspAlloc(cbCertif);
1716    if ( *ppbCertif == NULL )
1717    {
1718       LogTrace(LOGTYPE_ERROR, WHERE, "Error allocating memory for [*ppbCertif]");
1719       CLEANUP(SCARD_E_NO_MEMORY);
1720    }
1721 
1722    dwReturn = BeidReadFile(pCardData, 0, &cbCertif, *ppbCertif);
1723    if ( ( dwReturn != SCARD_S_SUCCESS ) ||
1724         ( cbCertif != cbRead          ) )
1725    {
1726       LogTrace(LOGTYPE_ERROR, WHERE, "BeidReadFile errorcode: [0x%08X]", dwReturn);
1727       CLEANUP(dwReturn);
1728    }
1729 
1730    /* Certificate Length */
1731    *pcbCertif = cbCertif;
1732 
1733 cleanup:
1734    LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1735    return (dwReturn);
1736 }
1737 #undef WHERE
1738 
1739 
1740 #define WHERE "BeidSelectApplet"
BeidSelectApplet(PCARD_DATA pCardData)1741 DWORD BeidSelectApplet(PCARD_DATA  pCardData)
1742 {
1743 	DWORD             dwReturn = 0;
1744 
1745 	SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1746 	SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1747 
1748 	unsigned char     Cmd[128];
1749 	unsigned int      uiCmdLg = 0;
1750 
1751 	unsigned char     recvbuf[256];
1752 	unsigned long     recvlen = sizeof(recvbuf);
1753 	BYTE              SW1, SW2;
1754 	BYTE              bBELPIC_AID[12] = { 0xA0, 0x00, 0x00, 0x01, 0x77, 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
1755 	BYTE              cbBELPIC_AID = sizeof(bBELPIC_AID);
1756 	BYTE			  bAPPLET_AID[15] = { 0xA0, 0x00, 0x00, 0x00, 0x30, 0x29, 0x05, 0x70, 0x00, 0xAD, 0x13, 0x10, 0x01, 0x01, 0xFF };
1757 	BYTE              cbAPPLET_AID = sizeof(bAPPLET_AID);
1758 
1759 	int               i = 0;
1760 
1761 	/***************/
1762 	/* Select File */
1763 	/***************/
1764 	Cmd [0] = 0x00;
1765 	Cmd [1] = 0xA4; /* SELECT COMMAND */
1766 	Cmd [2] = 0x04;
1767 	Cmd [3] = 0x0C;
1768 	Cmd [4] = cbBELPIC_AID;
1769 
1770 	LogTrace(LOGTYPE_INFO, WHERE, "Enter API...");
1771 
1772 	memcpy(&Cmd[5], bBELPIC_AID, cbBELPIC_AID);
1773 
1774 	uiCmdLg = 5 + cbBELPIC_AID;
1775 
1776 	dwReturn = SCardTransmit(pCardData->hScard,
1777 		&ioSendPci,
1778 		Cmd,
1779 		uiCmdLg,
1780 		&ioRecvPci,
1781 		recvbuf,
1782 		&recvlen);
1783 	SW1 = recvbuf[recvlen-2];
1784 	SW2 = recvbuf[recvlen-1];
1785 	LogTrace(LOGTYPE_TRACE, WHERE, "SCardTransmit return code: [0x%08X]", dwReturn);
1786 	BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1787 	if ( dwReturn != SCARD_S_SUCCESS )
1788 	{
1789 		LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1790 		CLEANUP(dwReturn);
1791     }
1792 
1793 	if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
1794 	{
1795 		LogTrace(LOGTYPE_ERROR, WHERE, "Select Failed: [0x%02X][0x%02X]", SW1, SW2);
1796 
1797 		Cmd [0] = 0x00;
1798 		Cmd [1] = 0xA4; /* SELECT COMMAND */
1799 		Cmd [2] = 0x04;
1800 		Cmd [3] = 0x00;
1801 		Cmd [4] = cbAPPLET_AID;
1802 		memcpy(&Cmd[5], bAPPLET_AID, cbAPPLET_AID);
1803 
1804 		uiCmdLg = 5 + cbAPPLET_AID;
1805 		recvlen = sizeof(recvbuf);
1806 		dwReturn = SCardTransmit(pCardData->hScard,
1807 			&ioSendPci,
1808 			Cmd,
1809 			uiCmdLg,
1810 			&ioRecvPci,
1811 			recvbuf,
1812 			&recvlen);
1813 		SW1 = recvbuf[recvlen-2];
1814 		SW2 = recvbuf[recvlen-1];
1815 		BeidDelayAndRecover(pCardData, SW1, SW2, dwReturn);
1816 		if ( dwReturn != SCARD_S_SUCCESS )
1817 		{
1818 			LogTrace(LOGTYPE_ERROR, WHERE, "SCardTransmit errorcode: [0x%08X]", dwReturn);
1819 			CLEANUP(dwReturn);
1820 		}
1821 
1822 		if ( ( SW1 != 0x90 ) || ( SW2 != 0x00 ) )
1823 		{
1824 			LogTrace(LOGTYPE_ERROR, WHERE, "Select Failed: [0x%02X][0x%02X]", SW1, SW2);
1825 			CLEANUP(dwReturn);
1826 		}
1827 	}
1828 
1829 
1830 cleanup:
1831 	LogTrace(LOGTYPE_INFO, WHERE, "Exit API...");
1832 	return (dwReturn);
1833 }
1834 #undef WHERE
1835 
1836 
1837 
1838 /****************************************************************************************************/
1839 
1840 /****************************************************************************************************/
1841 
1842 #define WHERE "CCIDgetPPDUFeatures"
CCIDgetPPDUFeatures(PFEATURES pFeatures,SCARDHANDLE hCard)1843 DWORD CCIDgetPPDUFeatures(PFEATURES pFeatures, SCARDHANDLE hCard)
1844 {
1845 	DWORD             dwReturn = SCARD_S_SUCCESS;
1846 	SCARD_IO_REQUEST  ioSendPci = {1, sizeof(SCARD_IO_REQUEST)};
1847   SCARD_IO_REQUEST  ioRecvPci = {1, sizeof(SCARD_IO_REQUEST)};
1848 	BYTE pbRecvBuffer[200];
1849 	DWORD cbRecvLength = sizeof(pbRecvBuffer);
1850 
1851 	wchar_t szReaderName[1024];
1852 	DWORD dwReaderLen = 1024;
1853 	DWORD dwState;
1854 	DWORD dwProtocol;
1855 	BYTE bAttribute[32];
1856 	DWORD dwAtrLen = 32;
1857 
1858 	dwReturn = SCardStatus(hCard, szReaderName, &dwReaderLen, &dwState, &dwProtocol, &bAttribute[0], &dwAtrLen);
1859 
1860 	if ((dwReaderLen > 1024) || dwReturn != SCARD_S_SUCCESS)
1861 	{
1862 		return dwReturn;
1863 	}
1864 	//add friendlynames of readers that support PPDU over transmit here
1865 	if ((_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"VASCO DIGIPASS 870", wcslen(L"VASCO DIGIPASS 870")) == 0) ||
1866 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"VASCO DIGIPASS 875", wcslen(L"VASCO DIGIPASS 875")) == 0) ||
1867 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"VASCO DIGIPASS 920", wcslen(L"VASCO DIGIPASS 920")) == 0) ||
1868 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"VASCO DIGIPASS 876", wcslen(L"VASCO DIGIPASS 876")) == 0) ||
1869 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"VASCO DIGIPASS 840", wcslen(L"VASCO DIGIPASS 840")) == 0) ||
1870 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"Gemalto ING Shield Pro", wcslen(L"Gemalto ING Shield Pro")) == 0) ||
1871 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"ETSWW eKrypto PINPhab", wcslen(L"ETSWW eKrypto PINPhab")) == 0) ||
1872 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"ETSWW eKrypto PINPad", wcslen(L"ETSWW eKrypto PINPad")) == 0) ||
1873 		(_wcsnicmp((wchar_t*)szReaderName, (const wchar_t*)L"DIOSS pinpad", wcslen(L"DIOSS pinpad")) == 0))
1874 	{
1875 		BYTE Cmd[] = { 0xFF ,0xC2 ,0x01 ,0x00 , 0x00 };
1876 		DWORD uiCmdLg = sizeof(Cmd);
1877 
1878 		dwReturn = SCardTransmit(hCard, &ioSendPci, Cmd, uiCmdLg, &ioRecvPci, pbRecvBuffer, &cbRecvLength);
1879 		//Sleep(25);//checked by whitelist, goes to reader, not card
1880 		LogTrace(LOGTYPE_TRACE, WHERE, "CCIDgetPPDUFeatures returncode: [0x%08X]", dwReturn);
1881 		if (dwReturn == SCARD_S_SUCCESS)
1882 		{
1883 			if ((pbRecvBuffer[cbRecvLength - 2] == 0x90) && (pbRecvBuffer[cbRecvLength - 1] == 0x00))
1884 			{
1885 				BYTE bsupportedFeatureIndex = 0;
1886 				pFeatures->USE_PPDU = 1;
1887 				for (bsupportedFeatureIndex = 0; bsupportedFeatureIndex < (cbRecvLength - 2); bsupportedFeatureIndex++)
1888 				{
1889 					switch (pbRecvBuffer[bsupportedFeatureIndex])
1890 					{
1891 					case 0x06:
1892 						pFeatures->VERIFY_PIN_DIRECT = 1;
1893 						break;
1894 					default:
1895 						break;
1896 					}
1897 				}//end of for
1898 			}
1899 			dwReturn = SCARD_F_INTERNAL_ERROR;
1900 		}
1901 	}
1902 	return dwReturn;
1903 }
1904 #undef WHERE
1905 
1906 /* CCID Features */
1907 #define WHERE "CCIDfindFeature"
CCIDfindFeature(BYTE featureTag,BYTE * features,DWORD featuresLength)1908 DWORD CCIDfindFeature(BYTE featureTag, BYTE* features, DWORD featuresLength) {
1909     DWORD idx = 0;
1910     int count;
1911     while (idx < featuresLength) {
1912         BYTE tag = features[idx];
1913         idx++;
1914         idx++;
1915         if (featureTag == tag) {
1916             DWORD feature = 0;
1917             for (count = 0; count < 3; count++) {
1918                 feature |= features[idx] & 0xff;
1919                 idx++;
1920                 feature <<= 8;
1921             }
1922             feature |= features[idx] & 0xff;
1923             return feature;
1924         }
1925         idx += 4;
1926     }
1927     return 0;
1928 }
1929 #undef WHERE
1930 
1931 /****************************************************************************************************/
1932 
1933 #define WHERE "CCIDgetFeatures"
CCIDgetFeatures(PFEATURES pFeatures,SCARDHANDLE hCard)1934 DWORD CCIDgetFeatures(PFEATURES pFeatures, SCARDHANDLE hCard) {
1935 	BYTE pbRecvBuffer[200];
1936 	DWORD dwRecvLength, dwReturn;
1937 	pFeatures->VERIFY_PIN_START = 0;
1938 	pFeatures->VERIFY_PIN_FINISH = 0;
1939 	pFeatures->VERIFY_PIN_DIRECT = 0;
1940 	pFeatures->MODIFY_PIN_START = 0;
1941 	pFeatures->MODIFY_PIN_FINISH = 0;
1942 	pFeatures->MODIFY_PIN_DIRECT = 0;
1943 	pFeatures->GET_KEY_PRESSED = 0;
1944 	pFeatures->ABORT = 0;
1945 	pFeatures->USE_PPDU = 0;
1946 
1947 	dwReturn = SCardControl(hCard,
1948 		SCARD_CTL_CODE(3400),
1949 		NULL,
1950 		0,
1951 		pbRecvBuffer,
1952 		sizeof(pbRecvBuffer),
1953 		&dwRecvLength);
1954 	LogTrace(LOGTYPE_TRACE, WHERE, "CCIDgetFeatures returncode: [0x%08X]", dwReturn);
1955 
1956 	if ( (SCARD_S_SUCCESS != dwReturn) || (dwRecvLength == 0) ) {
1957 		dwReturn = CCIDgetPPDUFeatures(pFeatures,hCard);
1958 		if ( SCARD_S_SUCCESS != dwReturn ){
1959 			LogTrace(LOGTYPE_ERROR, WHERE, "CCIDgetFeatures errorcode: [0x%08X]", dwReturn);
1960 		}
1961 		CLEANUP(dwReturn);
1962 	}
1963 	pFeatures->VERIFY_PIN_START = CCIDfindFeature(FEATURE_VERIFY_PIN_START, pbRecvBuffer, dwRecvLength);
1964 	pFeatures->VERIFY_PIN_FINISH = CCIDfindFeature(FEATURE_VERIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
1965 	pFeatures->VERIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_VERIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
1966 	pFeatures->MODIFY_PIN_START = CCIDfindFeature(FEATURE_MODIFY_PIN_START, pbRecvBuffer, dwRecvLength);
1967 	pFeatures->MODIFY_PIN_FINISH = CCIDfindFeature(FEATURE_MODIFY_PIN_FINISH, pbRecvBuffer, dwRecvLength);
1968 	pFeatures->MODIFY_PIN_DIRECT = CCIDfindFeature(FEATURE_MODIFY_PIN_DIRECT, pbRecvBuffer, dwRecvLength);
1969 	pFeatures->GET_KEY_PRESSED = CCIDfindFeature(FEATURE_GET_KEY_PRESSED, pbRecvBuffer, dwRecvLength);
1970 	pFeatures->ABORT = CCIDfindFeature(FEATURE_ABORT, pbRecvBuffer, dwRecvLength);
1971 cleanup:
1972    return (dwReturn);
1973 }
1974 
1975 #undef WHERE
1976 
createVerifyCommand(PPIN_VERIFY_STRUCTURE pVerifyCommand)1977 DWORD createVerifyCommand(PPIN_VERIFY_STRUCTURE pVerifyCommand) {
1978 		LANGUAGES displayLanguage = en;
1979     pVerifyCommand->bTimeOut = 30;
1980     pVerifyCommand->bTimeOut2 = 30;
1981     pVerifyCommand->bmFormatString = 0x80 | 0x08 | 0x00 | 0x01;
1982     /*
1983      * bmFormatString.
1984      *  01234567
1985      *  10001001
1986      *
1987      * bit 7: 1 = system units are bytes
1988      *
1989      * bit 6-3: 1 = PIN position in APDU command after Lc, so just after the
1990      * 0x20 | pinSize.
1991      *
1992      * bit 2: 0 = left justify data
1993      *
1994      * bit 1-0: 01 = BCD
1995      */
1996 
1997     pVerifyCommand->bmPINBlockString = 0x47;
1998     /*
1999      * bmPINBlockString
2000      *
2001      * bit 7-4: 4 = PIN length
2002      *
2003      * bit 3-0: 7 = PIN block size (7 times 0xff)
2004      */
2005 
2006     pVerifyCommand->bmPINLengthFormat = 0x04;
2007     /*
2008      * bmPINLengthFormat. weird... the values do not make any sense to me.
2009      *
2010      * bit 7-5: 0 = RFU
2011      *
2012      * bit 4: 0 = system units are bits
2013      *
2014      * bit 3-0: 4 = PIN length position in APDU
2015      */
2016 
2017 
2018     pVerifyCommand->wPINMaxExtraDigit = BELPIC_MIN_USER_PIN_LEN << 8 | BELPIC_MAX_USER_PIN_LEN ;
2019     /*
2020      * First byte:  maximum PIN size in digit
2021      *
2022      * Second byte: minimum PIN size in digit
2023      */
2024 
2025     pVerifyCommand->bEntryValidationCondition = 0x02;
2026     /*
2027      * 0x02 = validation key pressed. So the user must press the green
2028      * button on his pinpad.
2029      */
2030 
2031     pVerifyCommand->bNumberMessage = 0x01;
2032     /*
2033      * 0x01 = message with index in bMsgIndex
2034      */
2035 
2036     pVerifyCommand->wLangId = getLangID();
2037     /*
2038      * We support multiple languages for CCID devices with LCD screen
2039      */
2040 
2041     pVerifyCommand->bMsgIndex = 0x00;
2042     /*
2043      * 0x00 = PIN insertion prompt
2044      */
2045 
2046     pVerifyCommand->bTeoPrologue[0] = 0x00;
2047     pVerifyCommand->bTeoPrologue[1] = 0x00;
2048     pVerifyCommand->bTeoPrologue[2] = 0x00;
2049     /*
2050      * bTeoPrologue : only significant for T=1 protocol.
2051      */
2052 
2053     pVerifyCommand->abData[0] = 0x00; // CLA
2054     pVerifyCommand->abData[1] = 0x20; // INS Verify
2055     pVerifyCommand->abData[2] = 0x00; // P1
2056     pVerifyCommand->abData[3] = 0x01; // P2
2057     pVerifyCommand->abData[4] = 0x08; // Lc = 8 bytes in command data
2058     pVerifyCommand->abData[5] = 0x20 ; //
2059     pVerifyCommand->abData[6] = BELPIC_PAD_CHAR; // Pin[1]
2060     pVerifyCommand->abData[7] = BELPIC_PAD_CHAR; // Pin[2]
2061     pVerifyCommand->abData[8] = BELPIC_PAD_CHAR; // Pin[3]
2062     pVerifyCommand->abData[9] = BELPIC_PAD_CHAR; // Pin[4]
2063     pVerifyCommand->abData[10] = BELPIC_PAD_CHAR; // Pin[5]
2064     pVerifyCommand->abData[11] = BELPIC_PAD_CHAR; // Pin[6]
2065     pVerifyCommand->abData[12] = BELPIC_PAD_CHAR; // Pin[7]
2066 
2067     pVerifyCommand->ulDataLength = 13;
2068 
2069     return 0;
2070 }
2071 /****************************************************************************************************/
2072