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