Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (16.1 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

    
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
}