Statistics
| Branch: | Revision:

m2u-upass-core / src / my / com / upass / gemalto / GemaltoTokenControllerImpl.java @ 0:02300db8682b

History | View | Annotate | Download (16.1 KB)

1 0:02300db8682b hadi
/*
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
14
import java.util.Date;
15
import java.util.HashMap;
16
import ocra.Ocra;
17
import my.com.upass.Constants;
18
import my.com.upass.TokenBean;
19
import my.com.upass.vasco.TokenController;
20
21
/*
22
 * <pre>
23
 * PROGRAMMER: Enson Yeoh
24
 * CHANGE-NO:
25
 * TASK-NO:
26
 * DATE CREATED: Oct 5, 2012
27
 * TAG AS:
28
 * REASON(S):
29
 * MODIFICATION:
30
 * </pre>
31
 *
32
 *
33
 * Requirements:
34
 * 1) Retrieve the tokenBean and override the existing tokenBean object.
35
 * 2) Override the existing serial number with the given tokenBean.
36
 * 3) Override the existing authentication mode with the given tokenBean.
37
 * 4) Override the existing blob with the given tokenBean.
38
 * 5) Update useCount (total number of usage of the given token)
39
 * 6) Update errorCount (total number of errors attempted by the given token)
40
 * 7) Update last first time (the first usage date of the given token)
41
 * 8) Update last used time (the last usage date of the given token)
42
 * 9) Update the tokenBean object whenever there is changes.
43
 * 10) Verify token with the given password (OTP)
44
 * 11) Blob synchronization.
45
 * 12) Check last authentication
46
 *
47
 *
48
 */
49
50
public class GemaltoTokenControllerImpl implements TokenController
51
{
52
        private Ocra myocra = new Ocra();
53
54
        private TokenBean tb;
55
        private int retCode;
56
        private String serialNumber;
57
        private String authMode;
58
        private byte[] blob;
59
        private int useCount;
60
        private int errorCount;
61
        private Date lastTimeUsed;
62
        private Date firstTimeUsed;
63
        private Date lastAuthentication;
64
        private Date tokenExpectedDateTime;
65
66
        /**
67
         * this will override the existing tokenBean object
68
         * this will override the existing serial number, authentication mode and blob
69
         *
70
         * @param tokenBean
71
         */
72
        public GemaltoTokenControllerImpl(TokenBean tokenBean)
73
        {
74
                this.tb = tokenBean;
75
                setSerialNumber();
76
                setAuthMode();
77
                setBlob();
78
        }
79
80
        /**
81
         * this will override the existing last authentication date
82
         *
83
         * @param LastAuthentication
84
         */
85
        public void setLastAuthentication(Date lastAuthentication)
86
        {
87
                this.lastAuthentication = lastAuthentication;
88
        }
89
90
        /**
91
         * this will return updated last authentication date
92
         *
93
         * @return
94
         */
95
        public Date getLastAuthentication()
96
        {
97
                return lastAuthentication;
98
        }
99
100
        /**
101
         * this will override the existing token expected date and time
102
         *
103
         * @param LastAuthentication
104
         */
105
        public void setTokenExpectedDateTime(Date tokenExpectedDateTime)
106
        {
107
                this.tokenExpectedDateTime = tokenExpectedDateTime;
108
        }
109
110
        /**
111
         * this will return updated token expected date and time
112
         *
113
         * @return
114
         */
115
        public Date getTokenExpectedDateTime()
116
        {
117
                return tokenExpectedDateTime;
118
        }
119
120
        /**
121
         * this will override the existing tokenBean
122
         *
123
         */
124
        @Override
125
        public void setObject(TokenBean tokenBean)
126
        {
127
                this.tb = tokenBean;
128
        }
129
130
        /**
131
         * this will return the updated object (tokenBean)
132
         *
133
         */
134
        @Override
135
        public TokenBean getUpdatedObject()
136
        {
137
                return tb;
138
        }
139
140
        /**
141
         * this will override the existing serial number
142
         *
143
         */
144
        private void setSerialNumber()
145
        {
146
                this.serialNumber = tb.getVserialNumber();
147
        }
148
149
        /**
150
         * this will override the existing authentication mode
151
         *
152
         */
153
        private void setAuthMode()
154
        {
155
                this.authMode = tb.getVdpAuthMode();
156
        }
157
158
        /**
159
         * this will override the existing blob
160
         *
161
         */
162
        private void setBlob()
163
        {
164
                this.blob = tb.getVdpCipherText();
165
        }
166
167
        /**
168
         * this will return the updated blob
169
         *
170
         */
171
        public byte[] getUpdatedBlob()
172
        {
173
                return this.blob;
174
        }
175
176
        /**
177
         * this will override the existing useCount
178
         *
179
         */
180
        public void setUseCount()
181
        {
182
                this.useCount = tb.getVuseCount();
183
        }
184
185
        /**
186
         * this will increase the existing useCount by 1 whenever it is invoked.
187
         *
188
         */
189
        public void increaseUseCount()
190
        {
191
                this.useCount++;
192
        }
193
194
        /**
195
         * this will return the updated useCount
196
         *
197
         */
198
        public int getUseCount()
199
        {
200
                return this.useCount;
201
        }
202
203
        /**
204
         * this will override the existing errorCount
205
         *
206
         */
207
        public void setErrorCount()
208
        {
209
                this.errorCount = tb.getVerrorCount();
210
        }
211
212
        /**
213
         * this will increase the existing errorCount by 1 whenever it is invoked.
214
         *
215
         */
216
        public void increaseErrorCount()
217
        {
218
                this.errorCount++;
219
        }
220
221
        /**
222
         * this will return the updated errorCount
223
         *
224
         */
225
        public int getErrorCount()
226
        {
227
                return this.errorCount;
228
        }
229
230
        /**
231
         * this will override the existing first used date
232
         *
233
         */
234
        public void setFirstTimeUsed()
235
        {
236
                this.firstTimeUsed = tb.getVdateFirstUsed();
237
        }
238
239
        /**
240
         * case 1: if first used date is null, then first used date will be override by current date.
241
         * case 2: throw exception if first used date is after last used date.
242
         *
243
         * @param currentDate
244
         * @throws Exception
245
         */
246
        public void setFirstTimeUsed(Date currentDate) throws Exception
247
        {
248
                if(this.firstTimeUsed == null)
249
                {
250
                        this.firstTimeUsed = currentDate;
251
                }
252
                else if(this.firstTimeUsed.compareTo(this.lastTimeUsed) > 0)
253
                {
254
                        throw new Exception("Invalid date. First used date cannot be after last used date.");
255
                }
256
        }
257
258
        /**
259
         * this will return the updated first used date
260
         *
261
         */
262
        public Date getFirstTimeUsed()
263
        {
264
                return firstTimeUsed;
265
        }
266
267
        /**
268
         * this will override the existing last used date.
269
         *
270
         */
271
        public void setLastTimeUsed()
272
        {
273
                this.lastTimeUsed = tb.getVdateFirstUsed();
274
        }
275
276
        /**
277
         * case 1: if last used date is null, then last used date will be override by current date.
278
         * case 2: if last used date is before the current date, then last used date will be override by current date.
279
         * case 3: throw exception if last used date is after the current date.
280
         * case 4: throw exception if last used date is before first used date.
281
         *
282
         * @param currentDate
283
         * @throws Exception
284
         */
285
        public void setLastTimeUsed(Date currentDate) throws Exception
286
        {
287
                if(this.lastTimeUsed == null)
288
                {
289
                        this.lastTimeUsed = currentDate;
290
                }
291
                else if(this.lastTimeUsed.compareTo(currentDate) < 0)
292
                {
293
                        this.lastTimeUsed = currentDate;
294
                }
295
                else if(this.lastTimeUsed.compareTo(currentDate) > 0)
296
                {
297
                        throw new Exception("Invalid date. Last used date cannot be after current date.");
298
                }
299
                else if(this.lastTimeUsed.compareTo(this.firstTimeUsed) < 0)
300
                {
301
                        throw new Exception("Invalid date. Last used date cannot be before first used date.");
302
                }
303
        }
304
305
        /**
306
         * this will return the updated last used date
307
         *
308
         */
309
        public Date getLastTimeUsed()
310
        {
311
                return lastTimeUsed;
312
        }
313
314
        /**
315
         * this will return the updated returned code by each invoked method
316
         * it also acts as last returned error code.
317
         *
318
         */
319
        @Override
320
        public int getRetCode()
321
        {
322
                return retCode;
323
        }
324
325
        /**
326
         * this will return the updated error text based on the error code
327
         *
328
         */
329
        @Override
330
        public String getLastError()
331
        {
332
                String code = null;
333
334
                switch(this.retCode)
335
                {
336
                        case 0: code = "0";
337
                        case 1: code = "1";
338
                        case 2: code = "18";
339
                        case 3: code = "19";
340
                        case 4: code = "20";
341
                        case 5: code = "21";
342
                        case 6: code = "22";
343
                        case 7: code = "3";
344
                        case 8: code = "23";
345
                        case 9: code = "24";
346
                        case 10: code = "25";
347
                        case 11: code = "26";
348
                        default:
349
                                try
350
                                {
351
                                        throw new Exception("Invalid error code.");
352
                                }
353
                                catch (Exception e)
354
                                {
355
                                        e.printStackTrace();
356
                                }
357
                }
358
359
                return Constants.getErrText(code).get(code);
360
        }
361
362
        /**
363
         * Verify the entered On Time Password (OTP/password) for the given token
364
         *
365
         */
366
        @Override
367
        public int verifyToken(String otp, String userAlias, String pin) throws Exception
368
        {
369
                return verifyToken(otp);
370
        }
371
        /**
372
         * Verify the entered On Time Password (OTP/password) for the given token
373
         *
374
         */
375
376
        public int verifyToken(String password)
377
        {
378
                int[] blobLen = new int[1];
379
                blobLen[0]=500;
380
381
                String[] blobInString = new String[1];
382
                blobInString[0] = new String(this.blob);
383
384
                //Time based OTP verification
385
                //Authentication window need to be bigger for first OTP verification.
386
                int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode), 20, 1, 100,
387
                                                        new byte[0], 0,
388
                                                        new byte[0], 0,
389
                                                        new byte[0], 0,
390
                                                        6, password,
391
                                                        blobInString, blobLen);
392
393
                this.useCount++;
394
                this.firstTimeUsed = new Date();
395
                this.lastTimeUsed = new Date();
396
397
                if(result == 0)
398
                {
399
                        this.blob = blobInString[0].getBytes();
400
                        this.retCode = result;
401
                        updateTokenObject();
402
                }
403
                else
404
                {
405
                        try
406
                        {
407
                                this.errorCount++;
408
                                this.retCode = result;
409
                                updateTokenObject();
410
                                return errorCodeConversion(result);
411
                        }
412
                        catch (Exception e)
413
                        {
414
                                e.printStackTrace();
415
                        }
416
                }
417
418
                return Constants.ERR_SUCCESS;
419
        }
420
421
        /**
422
         * Check last successful authentication
423
         *
424
         * @return
425
         */
426
        public int checkLastAuthentication()
427
        {
428
                String[] blobInString = new String[1];
429
                blobInString[0] = new String(this.blob);
430
                int [] LastAuthTime = new int[1];
431
        int [] TokenExpectedTime = new int[1];
432
433
                int result = myocra.comGetInfo(0, 0, serialNumber, Constants.getAuthenticationMode("AUTH_OCRA"), blobInString, blobInString[0].length(), LastAuthTime, TokenExpectedTime);
434
435
                if(result == 0)
436
                {
437
                        //For first use of blob, LastAuthTimeDate returns a value of 0 or in Date format, Thu Jan 01 07:30:00 SGT 1970.
438
                        if(LastAuthTime[0] == 0)
439
                        {
440
                                System.out.println("No Last authentication.");
441
                        }
442
                        else
443
                        {
444
                                this.blob = blobInString[0].getBytes();
445
                                this.lastAuthentication = new Date(Long.parseLong(""+LastAuthTime[0])* 1000);
446
                    this.tokenExpectedDateTime = new Date(Long.parseLong(""+TokenExpectedTime[0])* 1000);
447
                    this.retCode = result;
448
                        }
449
                }
450
                else
451
                {
452
                        try
453
                        {
454
                                this.errorCount++;
455
                                this.retCode = result;
456
                                updateTokenObject();
457
                                return errorCodeConversion(result);
458
                        }
459
                        catch (Exception e)
460
                        {
461
                                e.printStackTrace();
462
                        }
463
                }
464
465
                return Constants.ERR_SUCCESS;
466
        }
467
468
        /**
469
         * In order to perform blob synchronization, 2 token verifications shall be performed .
470
         * First token verification must have larger time drift windows then the second's.
471
         * First token verification must be executed first before execute the second.
472
         * Second token verification must use new password (OTP) and lesser time drift window.
473
         * If the returned result of first verification is successful or 0, then second verification will be executed.
474
         * If the returned results of both first and second verifications are successful or 0, then blobSynchronization is successful,
475
         * otherwise, it is failed.
476
         *
477
         *
478
         * @param timeDriftWindow
479
         * @param password
480
         * @return
481
         */
482
        public int blobSynchronization(int timeDriftWindow1, String password1, int timeDriftWindow2, String password2)
483
        {
484
                int result = blobSynchronizationTokenVerification(timeDriftWindow1, password1);
485
486
                if(result == 0)
487
                {
488
                        result = blobSynchronizationTokenVerification(timeDriftWindow2, password2);
489
490
                        if(result == 0)
491
                        {
492
                                this.retCode = result;
493
                                updateTokenObject();
494
                        }
495
                        else
496
                        {
497
                                try
498
                                {
499
                                        this.errorCount++;
500
                                        this.retCode = result;
501
                                        updateTokenObject();
502
                                        return errorCodeConversion(result);
503
                                }
504
                                catch (Exception e)
505
                                {
506
                                        e.printStackTrace();
507
                                }
508
                        }
509
                }
510
                else
511
                {
512
                        try
513
                        {
514
                                this.retCode = result;
515
                                return errorCodeConversion(result);
516
                        }
517
                        catch (Exception e)
518
                        {
519
                                e.printStackTrace();
520
                        }
521
                }
522
523
                return Constants.ERR_SUCCESS;
524
        }
525
526
        /**
527
         * This method will be used in blobSynchronization to verify the token and blob synchronization
528
         *
529
         * @param timeDriftWindow
530
         * @param password
531
         * @return
532
         */
533
        private int blobSynchronizationTokenVerification(int timeDriftWindow, String password)
534
        {
535
                if(this.retCode == 0)
536
                {
537
                        int[] blobLen = new int[1];
538
                        blobLen[0]=500;
539
540
                        String[] blobInString = new String[1];
541
                        blobInString[0] = new String(this.blob);
542
543
                        //Time based OTP verification
544
                        //Authentication window need to be bigger for first OTP verification.
545
                        int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode), timeDriftWindow, 1, 100,
546
                                                                new byte[0], 0,
547
                                                                new byte[0], 0,
548
                                                                new byte[0], 0,
549
                                                                6, password,
550
                                                                blobInString, blobLen);
551
552
                        this.useCount++;
553
                        this.firstTimeUsed = new Date();
554
                        this.lastTimeUsed = new Date();
555
556
                        if(result == 0)
557
                        {
558
                                this.blob = blobInString[0].getBytes();
559
                                this.retCode = result;
560
                                updateTokenObject();
561
                        }
562
                        else
563
                        {
564
                                try
565
                                {
566
                                        this.errorCount++;
567
                                        this.retCode = result;
568
                                        updateTokenObject();
569
                                        return errorCodeConversion(result);
570
                                }
571
                                catch (Exception e)
572
                                {
573
                                        e.printStackTrace();
574
                                }
575
                        }
576
577
                }
578
579
                return Constants.ERR_SUCCESS;
580
        }
581
582
        /**
583
         * This will reset the token back to the initial state
584
         * The blob will be regenerated with the backup blob which is initially generated when it is imported from the pskc file.
585
         *
586
         */
587
        @Override
588
        public int resetToken()
589
        {
590
                this.retCode = 0;
591
                this.blob = tb.getVbkCipherText();
592
                this.useCount = 0;
593
                this.errorCount = 0;
594
                this.lastTimeUsed = null;
595
                this.firstTimeUsed = null;
596
                this.lastAuthentication = null;
597
                this.tokenExpectedDateTime = null;
598
                updateTokenObject();
599
600
                return Constants.ERR_SUCCESS;
601
        }
602
603
        @Override
604
        public HashMap<String, String> getTokenBlobInfo()
605
        {
606
                HashMap<String,String>  map = new HashMap<String,String>();
607
608
                map.put("TOKEN_MODEL", tb.getVdpModel());
609
                map.put("USE_COUNT",  Integer.toString(tb.getVuseCount()));
610
                map.put("ERROR_COUNT",  Integer.toString(tb.getVerrorCount()));
611
                map.put("LAST_TIME_USED", String.valueOf (tb.getVdateLastUsed()));
612
                map.put("TIME_STEP_USED", Integer.toString(Constants.TIMESTEPUSED));
613
614
                return map;
615
        }
616
617
        /**
618
         * display gemalto token information
619
         * In comparion with vasco, only limited information will be displayed.
620
         *
621
         */
622
        public void displayTokenInfo()
623
        {
624
                System.out.println("--Info----------------------------------------------");
625
                System.out.println("TOKEN_MODEL......." + tb.getVdpModel());
626
                System.out.println("USE_COUNT........." + tb.getVuseCount());
627
                System.out.println("ERR_COUNT........." + tb.getVerrorCount());
628
                System.out.println("LAST_TIME_USED...." + tb.getVdateLastUsed());
629
                System.out.println("TIME_STEP_USED...." + Constants.TIMESTEPUSED);
630
                System.out.println("----------------------------------------------------");
631
        }
632
633
        /**
634
         * This will override the existing tokenBean object
635
         *
636
         */
637
        private void updateTokenObject()
638
        {
639
                tb.setVuseCount(this.useCount );
640
                tb.setVerrorCount(this.errorCount );
641
                tb.setVdpCipherText(this.blob);
642
                tb.setVdateFirstUsed(this.firstTimeUsed);
643
                tb.setVdateLastUsed(this.lastTimeUsed);
644
        }
645
646
647
648
        /*
649
         * Code the gemalto returned error code to match with vasco's
650
         *
651
         */
652
        private int errorCodeConversion(int errorCode) throws Exception
653
        {
654
                switch(errorCode)
655
                {
656
                        case 0: return Constants.ERR_SUCCESS;
657
                        case 1: return Constants.ERR_INVALID_CREDENTIAL;
658
                        case 2: return Constants.ERR_BLOBINVALID;
659
                        case 3: return Constants.ERR_BUFFER;
660
                        case 4: return Constants.ERR_PARAM;
661
                        case 5: return Constants.ERR_SNOINVALID;
662
                        case 6: return Constants.ERR_OTPINVALID;
663
                        case 7: return Constants.ERR_REUSED_PASSWD;
664
                        case 8: return Constants.ERR_BLOBOTINIT;
665
                        case 9: return Constants.ERR_FAILED;
666
                        case 10: return Constants.ERR_REQINVALID;
667
                        case 11: return Constants.ERR_AUTH_MODE;
668
                        default: throw new Exception("Invalid error code.");
669
                }
670
        }
671
672
        @Override
673
        public int syncToken(String userAlias, String otp1, String otp2) {
674
                // TODO Auto-generated method stub
675
                return 0;
676
        }
677
}