Statistics
| Branch: | Revision:

m2u-upass-core / src / my / com / upass / gemalto / GemaltoTokenControllerImpl.java @ 30:aec0089bb43e

History | View | Annotate | Download (15.9 KB)

1
/*
2
 * Copyright (c) 2012 Penril Datability (M) Sdn Bhd All rights reserved.
3
 *
4
 * This software is copyrighted. Under the copyright laws, this software
5
 * may not be copied, in whole or in part, without prior written consent
6
 * of Penril Datability (M) Sdn Bhd or its assignees. This software is
7
 * provided under the terms of a license between Penril Datability (M)
8
 * Sdn Bhd and the recipient, and its use is subject to the terms of that
9
 * license.
10
 */
11
package my.com.upass.gemalto;
12

    
13
import java.util.Date;
14
import java.util.HashMap;
15
import ocra.Ocra;
16
import my.com.upass.Constants;
17
import my.com.upass.TokenBean;
18
import my.com.upass.vasco.TokenController;
19

    
20
/*
21
 * <pre>
22
 * PROGRAMMER: Enson Yeoh
23
 * CHANGE-NO:
24
 * TASK-NO:
25
 * DATE CREATED: Oct 5, 2012
26
 * TAG AS:
27
 * REASON(S):
28
 * MODIFICATION:
29
 * </pre>
30
 * 
31
 * 
32
 * Requirements:
33
 * 1) Retrieve the tokenBean and override the existing tokenBean object.
34
 * 2) Override the existing serial number with the given tokenBean.
35
 * 3) Override the existing authentication mode with the given tokenBean.
36
 * 4) Override the existing blob with the given tokenBean.
37
 * 5) Update useCount (total number of usage of the given token)
38
 * 6) Update errorCount (total number of errors attempted by the given token)
39
 * 7) Update last first time (the first usage date of the given token)
40
 * 8) Update last used time (the last usage date of the given token)
41
 * 9) Update the tokenBean object whenever there is changes.
42
 * 10) Verify token with the given password (OTP)
43
 * 11) Blob synchronization.
44
 * 12) Check last authentication
45
 * 
46
 * 
47
 */
48

    
49
public class GemaltoTokenControllerImpl implements TokenController
50
{
51
        private Ocra myocra = new Ocra();
52

    
53
        private TokenBean tb;
54
        private int retCode;
55
        private String serialNumber;
56
        private String authMode;
57
        private byte[] blob;
58
        private int useCount;
59
        private int errorCount;
60
        private Date lastTimeUsed;
61
        private Date firstTimeUsed;
62
        private Date lastAuthentication;
63
        private Date tokenExpectedDateTime;
64

    
65
        /**
66
         * this will override the existing tokenBean object
67
         * this will override the existing serial number, authentication mode and blob
68
         * 
69
         * @param tokenBean
70
         */
71
        public GemaltoTokenControllerImpl(TokenBean tokenBean)
72
        {
73
                this.tb = tokenBean;
74
                setSerialNumber();
75
                setAuthMode();
76
                setBlob();
77
        }
78

    
79
        /**
80
         * this will override the existing last authentication date
81
         * 
82
         * @param LastAuthentication
83
         */
84
        public void setLastAuthentication(Date lastAuthentication)
85
        {
86
                this.lastAuthentication = lastAuthentication;
87
        }
88

    
89
        /**
90
         * this will return updated last authentication date
91
         * 
92
         * @return
93
         */
94
        public Date getLastAuthentication()
95
        {
96
                return lastAuthentication;
97
        }
98

    
99
        /**
100
         * this will override the existing token expected date and time
101
         * 
102
         * @param LastAuthentication
103
         */
104
        public void setTokenExpectedDateTime(Date tokenExpectedDateTime)
105
        {
106
                this.tokenExpectedDateTime = tokenExpectedDateTime;
107
        }
108

    
109
        /**
110
         * this will return updated token expected date and time
111
         * 
112
         * @return
113
         */
114
        public Date getTokenExpectedDateTime()
115
        {
116
                return tokenExpectedDateTime;
117
        }
118

    
119
        /**
120
         * this will override the existing tokenBean
121
         * 
122
         */
123
        public void setObject(TokenBean tokenBean)
124
        {
125
                this.tb = tokenBean;
126
        }
127

    
128
        /**
129
         * this will return the updated object (tokenBean)
130
         * 
131
         */
132
        public TokenBean getUpdatedObject()
133
        {
134
                return tb;
135
        }
136

    
137
        /**
138
         * this will override the existing serial number
139
         * 
140
         */
141
        private void setSerialNumber()
142
        {
143
                this.serialNumber = tb.getVserialNumber();
144
        }
145

    
146
        /**
147
         * this will override the existing authentication mode
148
         * 
149
         */
150
        private void setAuthMode()
151
        {
152
                this.authMode = tb.getVdpAuthMode();
153
        }
154

    
155
        /**
156
         * this will override the existing blob
157
         * 
158
         */
159
        private void setBlob()
160
        {
161
                this.blob = tb.getVdpCipherText();
162
        }
163

    
164
        /**
165
         * this will return the updated blob
166
         * 
167
         */
168
        public byte[] getUpdatedBlob()
169
        {
170
                return this.blob;
171
        }
172

    
173
        /**
174
         * this will override the existing useCount
175
         * 
176
         */
177
        public void setUseCount()
178
        {
179
                this.useCount = tb.getVuseCount();
180
        }
181

    
182
        /**
183
         * this will increase the existing useCount by 1 whenever it is invoked.
184
         * 
185
         */
186
        public void increaseUseCount()
187
        {
188
                this.useCount++;
189
        }
190

    
191
        /**
192
         * this will return the updated useCount
193
         * 
194
         */
195
        public int getUseCount()
196
        {
197
                return this.useCount;
198
        }
199

    
200
        /**
201
         * this will override the existing errorCount
202
         * 
203
         */
204
        public void setErrorCount()
205
        {
206
                this.errorCount = tb.getVerrorCount();
207
        }
208

    
209
        /**
210
         * this will increase the existing errorCount by 1 whenever it is invoked.
211
         * 
212
         */
213
        public void increaseErrorCount()
214
        {
215
                this.errorCount++;
216
        }
217

    
218
        /**
219
         * this will return the updated errorCount
220
         * 
221
         */
222
        public int getErrorCount()
223
        {
224
                return this.errorCount;
225
        }
226

    
227
        /**
228
         * this will override the existing first used date
229
         * 
230
         */
231
        public void setFirstTimeUsed()
232
        {
233
                this.firstTimeUsed = tb.getVdateFirstUsed();
234
        }
235

    
236
        /**
237
         * case 1: if first used date is null, then first used date will be override by current date.
238
         * case 2: throw exception if first used date is after last used date.
239
         * 
240
         * @param currentDate
241
         * @throws Exception
242
         */
243
        public void setFirstTimeUsed(Date currentDate) throws Exception
244
        {
245
                if (this.firstTimeUsed == null)
246
                {
247
                        this.firstTimeUsed = currentDate;
248
                }
249
                else if (this.firstTimeUsed.compareTo(this.lastTimeUsed) > 0)
250
                {
251
                        throw new Exception("Invalid date. First used date cannot be after last used date.");
252
                }
253
        }
254

    
255
        /**
256
         * this will return the updated first used date
257
         * 
258
         */
259
        public Date getFirstTimeUsed()
260
        {
261
                return firstTimeUsed;
262
        }
263

    
264
        /**
265
         * this will override the existing last used date.
266
         * 
267
         */
268
        public void setLastTimeUsed()
269
        {
270
                this.lastTimeUsed = tb.getVdateFirstUsed();
271
        }
272

    
273
        /**
274
         * case 1: if last used date is null, then last used date will be override by current date.
275
         * case 2: if last used date is before the current date, then last used date will be override by current date.
276
         * case 3: throw exception if last used date is after the current date.
277
         * case 4: throw exception if last used date is before first used date.
278
         * 
279
         * @param currentDate
280
         * @throws Exception
281
         */
282
        public void setLastTimeUsed(Date currentDate) throws Exception
283
        {
284
                if (this.lastTimeUsed == null)
285
                {
286
                        this.lastTimeUsed = currentDate;
287
                }
288
                else if (this.lastTimeUsed.compareTo(currentDate) < 0)
289
                {
290
                        this.lastTimeUsed = currentDate;
291
                }
292
                else if (this.lastTimeUsed.compareTo(currentDate) > 0)
293
                {
294
                        throw new Exception("Invalid date. Last used date cannot be after current date.");
295
                }
296
                else if (this.lastTimeUsed.compareTo(this.firstTimeUsed) < 0)
297
                {
298
                        throw new Exception("Invalid date. Last used date cannot be before first used date.");
299
                }
300
        }
301

    
302
        /**
303
         * this will return the updated last used date
304
         * 
305
         */
306
        public Date getLastTimeUsed()
307
        {
308
                return lastTimeUsed;
309
        }
310

    
311
        /**
312
         * this will return the updated returned code by each invoked method
313
         * it also acts as last returned error code.
314
         * 
315
         */
316
        public int getRetCode()
317
        {
318
                return retCode;
319
        }
320

    
321
        /**
322
         * this will return the updated error text based on the error code
323
         * 
324
         */
325
        public String getLastError()
326
        {
327
                String code = null;
328

    
329
                switch (this.retCode)
330
                {
331
                case 0:
332
                        code = "0";
333
                case 1:
334
                        code = "1";
335
                case 2:
336
                        code = "18";
337
                case 3:
338
                        code = "19";
339
                case 4:
340
                        code = "20";
341
                case 5:
342
                        code = "21";
343
                case 6:
344
                        code = "22";
345
                case 7:
346
                        code = "3";
347
                case 8:
348
                        code = "23";
349
                case 9:
350
                        code = "24";
351
                case 10:
352
                        code = "25";
353
                case 11:
354
                        code = "26";
355
                default:
356
                        try
357
                        {
358
                                throw new Exception("Invalid error code.");
359
                        } catch (Exception e)
360
                        {
361
                                e.printStackTrace();
362
                        }
363
                }
364

    
365
                return (String) Constants.getErrText(code).get(code);
366
        }
367

    
368
        /**
369
         * Verify the entered On Time Password (OTP/password) for the given token
370
         * 
371
         */
372
        public int verifyToken(String otp, String userAlias, String pin) throws Exception
373
        {
374
                return verifyToken(otp);
375
        }
376

    
377
        /**
378
         * Verify the entered On Time Password (OTP/password) for the given token
379
         * 
380
         */
381

    
382
        public int verifyToken(String password)
383
        {
384
                int[] blobLen = new int[1];
385
                blobLen[0] = 500;
386

    
387
                String[] blobInString = new String[1];
388
                blobInString[0] = new String(this.blob);
389

    
390
                // Time based OTP verification
391
                // Authentication window need to be bigger for first OTP verification.
392
                int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode), 20, 1,
393
                                100,
394
                                new byte[0], 0,
395
                                new byte[0], 0,
396
                                new byte[0], 0,
397
                                6, password,
398
                                blobInString, blobLen);
399

    
400
                this.useCount++;
401
                this.firstTimeUsed = new Date();
402
                this.lastTimeUsed = new Date();
403

    
404
                if (result == 0)
405
                {
406
                        this.blob = blobInString[0].getBytes();
407
                        this.retCode = result;
408
                        updateTokenObject();
409
                }
410
                else
411
                {
412
                        try
413
                        {
414
                                this.errorCount++;
415
                                this.retCode = result;
416
                                updateTokenObject();
417
                                return errorCodeConversion(result);
418
                        } catch (Exception e)
419
                        {
420
                                e.printStackTrace();
421
                        }
422
                }
423

    
424
                return Constants.ERR_SUCCESS;
425
        }
426

    
427
        /**
428
         * Check last successful authentication
429
         * 
430
         * @return
431
         */
432
        public int checkLastAuthentication()
433
        {
434
                String[] blobInString = new String[1];
435
                blobInString[0] = new String(this.blob);
436
                int[] LastAuthTime = new int[1];
437
                int[] TokenExpectedTime = new int[1];
438

    
439
                int result = myocra.comGetInfo(0, 0, serialNumber, Constants.getAuthenticationMode("AUTH_OCRA"), blobInString,
440
                                blobInString[0].length(), LastAuthTime, TokenExpectedTime);
441

    
442
                if (result == 0)
443
                {
444
                        // For first use of blob, LastAuthTimeDate returns a value of 0 or in Date format, Thu Jan 01 07:30:00 SGT
445
                        // 1970.
446
                        if (LastAuthTime[0] == 0)
447
                        {
448
                                System.out.println("No Last authentication.");
449
                        }
450
                        else
451
                        {
452
                                this.blob = blobInString[0].getBytes();
453
                                this.lastAuthentication = new Date(Long.parseLong("" + LastAuthTime[0]) * 1000);
454
                                this.tokenExpectedDateTime = new Date(Long.parseLong("" + TokenExpectedTime[0]) * 1000);
455
                                this.retCode = result;
456
                        }
457
                }
458
                else
459
                {
460
                        try
461
                        {
462
                                this.errorCount++;
463
                                this.retCode = result;
464
                                updateTokenObject();
465
                                return errorCodeConversion(result);
466
                        } catch (Exception e)
467
                        {
468
                                e.printStackTrace();
469
                        }
470
                }
471

    
472
                return Constants.ERR_SUCCESS;
473
        }
474

    
475
        /**
476
         * In order to perform blob synchronization, 2 token verifications shall be performed .
477
         * First token verification must have larger time drift windows then the second's.
478
         * First token verification must be executed first before execute the second.
479
         * Second token verification must use new password (OTP) and lesser time drift window.
480
         * If the returned result of first verification is successful or 0, then second verification will be executed.
481
         * If the returned results of both first and second verifications are successful or 0, then blobSynchronization is
482
         * successful,
483
         * otherwise, it is failed.
484
         * 
485
         * 
486
         * @param timeDriftWindow
487
         * @param password
488
         * @return
489
         */
490
        public int blobSynchronization(int timeDriftWindow1, String password1, int timeDriftWindow2, String password2)
491
        {
492
                int result = blobSynchronizationTokenVerification(timeDriftWindow1, password1);
493

    
494
                if (result == 0)
495
                {
496
                        result = blobSynchronizationTokenVerification(timeDriftWindow2, password2);
497

    
498
                        if (result == 0)
499
                        {
500
                                this.retCode = result;
501
                                updateTokenObject();
502
                        }
503
                        else
504
                        {
505
                                try
506
                                {
507
                                        this.errorCount++;
508
                                        this.retCode = result;
509
                                        updateTokenObject();
510
                                        return errorCodeConversion(result);
511
                                } catch (Exception e)
512
                                {
513
                                        e.printStackTrace();
514
                                }
515
                        }
516
                }
517
                else
518
                {
519
                        try
520
                        {
521
                                this.retCode = result;
522
                                return errorCodeConversion(result);
523
                        } catch (Exception e)
524
                        {
525
                                e.printStackTrace();
526
                        }
527
                }
528

    
529
                return Constants.ERR_SUCCESS;
530
        }
531

    
532
        /**
533
         * This method will be used in blobSynchronization to verify the token and blob synchronization
534
         * 
535
         * @param timeDriftWindow
536
         * @param password
537
         * @return
538
         */
539
        private int blobSynchronizationTokenVerification(int timeDriftWindow, String password)
540
        {
541
                if (this.retCode == 0)
542
                {
543
                        int[] blobLen = new int[1];
544
                        blobLen[0] = 500;
545

    
546
                        String[] blobInString = new String[1];
547
                        blobInString[0] = new String(this.blob);
548

    
549
                        // Time based OTP verification
550
                        // Authentication window need to be bigger for first OTP verification.
551
                        int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode),
552
                                        timeDriftWindow, 1, 100,
553
                                        new byte[0], 0,
554
                                        new byte[0], 0,
555
                                        new byte[0], 0,
556
                                        6, password,
557
                                        blobInString, blobLen);
558

    
559
                        this.useCount++;
560
                        this.firstTimeUsed = new Date();
561
                        this.lastTimeUsed = new Date();
562

    
563
                        if (result == 0)
564
                        {
565
                                this.blob = blobInString[0].getBytes();
566
                                this.retCode = result;
567
                                updateTokenObject();
568
                        }
569
                        else
570
                        {
571
                                try
572
                                {
573
                                        this.errorCount++;
574
                                        this.retCode = result;
575
                                        updateTokenObject();
576
                                        return errorCodeConversion(result);
577
                                } catch (Exception e)
578
                                {
579
                                        e.printStackTrace();
580
                                }
581
                        }
582

    
583
                }
584

    
585
                return Constants.ERR_SUCCESS;
586
        }
587

    
588
        /**
589
         * This will reset the token back to the initial state
590
         * The blob will be regenerated with the backup blob which is initially generated when it is imported from the pskc
591
         * file.
592
         * 
593
         */
594
        public int resetToken()
595
        {
596
                this.retCode = 0;
597
                this.blob = tb.getVbkCipherText();
598
                this.useCount = 0;
599
                this.errorCount = 0;
600
                this.lastTimeUsed = null;
601
                this.firstTimeUsed = null;
602
                this.lastAuthentication = null;
603
                this.tokenExpectedDateTime = null;
604
                updateTokenObject();
605

    
606
                return Constants.ERR_SUCCESS;
607
        }
608

    
609
        public HashMap<String, String> getTokenBlobInfo()
610
        {
611
                HashMap<String, String> map = new HashMap<String, String>();
612

    
613
                map.put("TOKEN_MODEL", tb.getVdpModel());
614
                map.put("USE_COUNT", Integer.toString(tb.getVuseCount()));
615
                map.put("ERROR_COUNT", Integer.toString(tb.getVerrorCount()));
616
                map.put("LAST_TIME_USED", String.valueOf(tb.getVdateLastUsed()));
617
                map.put("TIME_STEP_USED", Integer.toString(Constants.TIMESTEPUSED));
618

    
619
                return map;
620
        }
621

    
622
        /**
623
         * display gemalto token information
624
         * In comparion with vasco, only limited information will be displayed.
625
         * 
626
         */
627
        public void displayTokenInfo()
628
        {
629
                System.out.println("--Info----------------------------------------------");
630
                System.out.println("TOKEN_MODEL......." + tb.getVdpModel());
631
                System.out.println("USE_COUNT........." + tb.getVuseCount());
632
                System.out.println("ERR_COUNT........." + tb.getVerrorCount());
633
                System.out.println("LAST_TIME_USED...." + tb.getVdateLastUsed());
634
                System.out.println("TIME_STEP_USED...." + Constants.TIMESTEPUSED);
635
                System.out.println("----------------------------------------------------");
636
        }
637

    
638
        /**
639
         * This will override the existing tokenBean object
640
         * 
641
         */
642
        private void updateTokenObject()
643
        {
644
                tb.setVuseCount(this.useCount);
645
                tb.setVerrorCount(this.errorCount);
646
                tb.setVdpCipherText(this.blob);
647
                tb.setVdateFirstUsed(this.firstTimeUsed);
648
                tb.setVdateLastUsed(this.lastTimeUsed);
649
        }
650

    
651
        /*
652
         * Code the gemalto returned error code to match with vasco's
653
         */
654
        private int errorCodeConversion(int errorCode) throws Exception
655
        {
656
                switch (errorCode)
657
                {
658
                case 0:
659
                        return Constants.ERR_SUCCESS;
660
                case 1:
661
                        return Constants.ERR_INVALID_CREDENTIAL;
662
                case 2:
663
                        return Constants.ERR_BLOBINVALID;
664
                case 3:
665
                        return Constants.ERR_BUFFER;
666
                case 4:
667
                        return Constants.ERR_PARAM;
668
                case 5:
669
                        return Constants.ERR_SNOINVALID;
670
                case 6:
671
                        return Constants.ERR_OTPINVALID;
672
                case 7:
673
                        return Constants.ERR_REUSED_PASSWD;
674
                case 8:
675
                        return Constants.ERR_BLOBOTINIT;
676
                case 9:
677
                        return Constants.ERR_FAILED;
678
                case 10:
679
                        return Constants.ERR_REQINVALID;
680
                case 11:
681
                        return Constants.ERR_AUTH_MODE;
682
                default:
683
                        throw new Exception("Invalid error code.");
684
                }
685
        }
686

    
687
        public int syncToken(String userAlias, String otp1, String otp2) {
688
                // TODO Auto-generated method stub
689
                return 0;
690
        }
691
}