Statistics
| Branch: | Revision:

m2u-upass-core / src / my / com / upass / gemalto / GemaltoTokenControllerImpl.java @ 5:f608e6319b70

History | View | Annotate | Download (16 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
        public void setObject(TokenBean tokenBean) 
125
        {
126
                this.tb = tokenBean;
127
        }
128
        
129
        /**
130
         * this will return the updated object (tokenBean)
131
         * 
132
         */
133
        public TokenBean getUpdatedObject() 
134
        {
135
                return tb;
136
        }
137
        
138
        /**
139
         * this will override the existing serial number
140
         * 
141
         */
142
        private void setSerialNumber() 
143
        {
144
                this.serialNumber = tb.getVserialNumber();
145
        }
146
        
147
        /**
148
         * this will override the existing authentication mode
149
         * 
150
         */
151
        private void setAuthMode() 
152
        {
153
                this.authMode = tb.getVdpAuthMode();
154
        }
155
        
156
        /**
157
         * this will override the existing blob
158
         * 
159
         */
160
        private void setBlob() 
161
        {
162
                this.blob = tb.getVdpCipherText();
163
        }
164
        
165
        /**
166
         * this will return the updated blob
167
         * 
168
         */
169
        public byte[] getUpdatedBlob() 
170
        {
171
                return this.blob;
172
        }
173
        
174
        /**
175
         * this will override the existing useCount
176
         * 
177
         */
178
        public void setUseCount()
179
        {
180
                this.useCount = tb.getVuseCount();
181
        }
182
        
183
        /**
184
         * this will increase the existing useCount by 1 whenever it is invoked.
185
         * 
186
         */
187
        public void increaseUseCount()
188
        {
189
                this.useCount++;
190
        }
191
        
192
        /**
193
         * this will return the updated useCount
194
         * 
195
         */
196
        public int getUseCount() 
197
        {
198
                return this.useCount;
199
        }
200
        
201
        /**
202
         * this will override the existing errorCount
203
         * 
204
         */
205
        public void setErrorCount()
206
        {
207
                this.errorCount = tb.getVerrorCount();
208
        }
209
        
210
        /**
211
         * this will increase the existing errorCount by 1 whenever it is invoked.
212
         * 
213
         */
214
        public void increaseErrorCount()
215
        {
216
                this.errorCount++;
217
        }
218
        
219
        /**
220
         * this will return the updated errorCount
221
         * 
222
         */
223
        public int getErrorCount() 
224
        {
225
                return this.errorCount;
226
        }
227
        
228
        /**
229
         * this will override the existing first used date
230
         * 
231
         */
232
        public void setFirstTimeUsed()
233
        {
234
                this.firstTimeUsed = tb.getVdateFirstUsed();
235
        }
236
        
237
        /**
238
         * case 1: if first used date is null, then first used date will be override by current date.
239
         * case 2: throw exception if first used date is after last used date.
240
         * 
241
         * @param currentDate
242
         * @throws Exception
243
         */
244
        public void setFirstTimeUsed(Date currentDate) throws Exception
245
        {
246
                if(this.firstTimeUsed == null)
247
                {
248
                        this.firstTimeUsed = currentDate;
249
                }
250
                else if(this.firstTimeUsed.compareTo(this.lastTimeUsed) > 0)
251
                {                
252
                        throw new Exception("Invalid date. First used date cannot be after last used date.");
253
                }
254
        }
255
        
256
        /**
257
         * this will return the updated first used date
258
         * 
259
         */
260
        public Date getFirstTimeUsed()
261
        {
262
                return firstTimeUsed;
263
        }
264
        
265
        /**
266
         * this will override the existing last used date.
267
         * 
268
         */
269
        public void setLastTimeUsed()
270
        {
271
                this.lastTimeUsed = tb.getVdateFirstUsed();
272
        }
273
        
274
        /**
275
         * case 1: if last used date is null, then last used date will be override by current date.
276
         * case 2: if last used date is before the current date, then last used date will be override by current date.
277
         * case 3: throw exception if last used date is after the current date.
278
         * case 4: throw exception if last used date is before first used date.
279
         * 
280
         * @param currentDate
281
         * @throws Exception
282
         */
283
        public void setLastTimeUsed(Date currentDate) throws Exception
284
        {
285
                if(this.lastTimeUsed == null)
286
                {
287
                        this.lastTimeUsed = currentDate;
288
                }                
289
                else if(this.lastTimeUsed.compareTo(currentDate) < 0)
290
                {
291
                        this.lastTimeUsed = currentDate;
292
                }
293
                else if(this.lastTimeUsed.compareTo(currentDate) > 0)
294
                {
295
                        throw new Exception("Invalid date. Last used date cannot be after current date.");
296
                }
297
                else if(this.lastTimeUsed.compareTo(this.firstTimeUsed) < 0)
298
                {
299
                        throw new Exception("Invalid date. Last used date cannot be before first used date.");
300
                }
301
        }
302
        
303
        /**
304
         * this will return the updated last used date
305
         * 
306
         */
307
        public Date getLastTimeUsed()
308
        {
309
                return lastTimeUsed;
310
        }
311

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

    
322
        /**
323
         * this will return the updated error text based on the error code
324
         * 
325
         */
326
        public String getLastError() 
327
        {
328
                String code = null;
329
                
330
                switch(this.retCode)
331
                {
332
                        case 0: code = "0";
333
                        case 1: code = "1";
334
                        case 2: code = "18";
335
                        case 3: code = "19";
336
                        case 4: code = "20";
337
                        case 5: code = "21";
338
                        case 6: code = "22";
339
                        case 7: code = "3";
340
                        case 8: code = "23";
341
                        case 9: code = "24";
342
                        case 10: code = "25";
343
                        case 11: code = "26";
344
                        default: 
345
                                try 
346
                                {
347
                                        throw new Exception("Invalid error code.");
348
                                }
349
                                catch (Exception e) 
350
                                {
351
                                        e.printStackTrace();
352
                                }
353
                }
354
                
355
                return Constants.getErrText(code).get(code);
356
        }
357

    
358
        /**
359
         * Verify the entered On Time Password (OTP/password) for the given token
360
         * 
361
         */
362
        public int verifyToken(String otp, String userAlias, String pin) throws Exception
363
        {
364
                return verifyToken(otp);
365
        }
366
        /**
367
         * Verify the entered On Time Password (OTP/password) for the given token
368
         * 
369
         */
370
        
371
        public int verifyToken(String password) 
372
        {
373
                int[] blobLen = new int[1];
374
                blobLen[0]=500;
375
                
376
                String[] blobInString = new String[1];
377
                blobInString[0] = new String(this.blob);
378
                
379
                //Time based OTP verification
380
                //Authentication window need to be bigger for first OTP verification.
381
                int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode), 20, 1, 100, 
382
                                                        new byte[0], 0, 
383
                                                        new byte[0], 0,        
384
                                                        new byte[0], 0, 
385
                                                        6, password, 
386
                                                        blobInString, blobLen);
387
                
388
                this.useCount++;
389
                this.firstTimeUsed = new Date();
390
                this.lastTimeUsed = new Date();
391
                
392
                if(result == 0)
393
                {
394
                        this.blob = blobInString[0].getBytes();
395
                        this.retCode = result;
396
                        updateTokenObject();
397
                }
398
                else
399
                {
400
                        try 
401
                        {
402
                                this.errorCount++;
403
                                this.retCode = result;
404
                                updateTokenObject();
405
                                return errorCodeConversion(result);        
406
                        } 
407
                        catch (Exception e) 
408
                        {
409
                                e.printStackTrace();
410
                        }
411
                }
412

    
413
                return Constants.ERR_SUCCESS;
414
        }
415
        
416
        /**
417
         * Check last successful authentication
418
         * 
419
         * @return
420
         */
421
        public int checkLastAuthentication()
422
        {
423
                String[] blobInString = new String[1];
424
                blobInString[0] = new String(this.blob);
425
                int [] LastAuthTime = new int[1];
426
        int [] TokenExpectedTime = new int[1];
427
                                
428
                int result = myocra.comGetInfo(0, 0, serialNumber, Constants.getAuthenticationMode("AUTH_OCRA"), blobInString, blobInString[0].length(), LastAuthTime, TokenExpectedTime);
429
                
430
                if(result == 0)
431
                {
432
                        //For first use of blob, LastAuthTimeDate returns a value of 0 or in Date format, Thu Jan 01 07:30:00 SGT 1970.
433
                        if(LastAuthTime[0] == 0)
434
                        {
435
                                System.out.println("No Last authentication.");
436
                        }
437
                        else
438
                        {
439
                                this.blob = blobInString[0].getBytes();
440
                                this.lastAuthentication = new Date(Long.parseLong(""+LastAuthTime[0])* 1000);
441
                    this.tokenExpectedDateTime = new Date(Long.parseLong(""+TokenExpectedTime[0])* 1000);
442
                    this.retCode = result;
443
                        }
444
                }
445
                else
446
                {
447
                        try 
448
                        {
449
                                this.errorCount++;
450
                                this.retCode = result;
451
                                updateTokenObject();
452
                                return errorCodeConversion(result);
453
                        } 
454
                        catch (Exception e) 
455
                        {
456
                                e.printStackTrace();
457
                        }
458
                }
459
                
460
                return Constants.ERR_SUCCESS;
461
        }
462
        
463
        /**
464
         * In order to perform blob synchronization, 2 token verifications shall be performed .
465
         * First token verification must have larger time drift windows then the second's.
466
         * First token verification must be executed first before execute the second.
467
         * Second token verification must use new password (OTP) and lesser time drift window.
468
         * If the returned result of first verification is successful or 0, then second verification will be executed.
469
         * If the returned results of both first and second verifications are successful or 0, then blobSynchronization is successful,
470
         * otherwise, it is failed.
471
         * 
472
         * 
473
         * @param timeDriftWindow
474
         * @param password
475
         * @return
476
         */
477
        public int blobSynchronization(int timeDriftWindow1, String password1, int timeDriftWindow2, String password2)
478
        {
479
                int result = blobSynchronizationTokenVerification(timeDriftWindow1, password1);
480
                                
481
                if(result == 0)
482
                {                        
483
                        result = blobSynchronizationTokenVerification(timeDriftWindow2, password2);
484
                        
485
                        if(result == 0)
486
                        {
487
                                this.retCode = result;
488
                                updateTokenObject();
489
                        }
490
                        else
491
                        {
492
                                try 
493
                                {
494
                                        this.errorCount++;
495
                                        this.retCode = result;
496
                                        updateTokenObject();
497
                                        return errorCodeConversion(result);        
498
                                } 
499
                                catch (Exception e) 
500
                                {
501
                                        e.printStackTrace();
502
                                }
503
                        }                
504
                }
505
                else
506
                {
507
                        try 
508
                        {
509
                                this.retCode = result;
510
                                return errorCodeConversion(result);        
511
                        } 
512
                        catch (Exception e) 
513
                        {
514
                                e.printStackTrace();
515
                        }
516
                }
517

    
518
                return Constants.ERR_SUCCESS;
519
        }
520
        
521
        /**
522
         * This method will be used in blobSynchronization to verify the token and blob synchronization
523
         * 
524
         * @param timeDriftWindow
525
         * @param password
526
         * @return
527
         */
528
        private int blobSynchronizationTokenVerification(int timeDriftWindow, String password)
529
        {
530
                if(this.retCode == 0)
531
                {
532
                        int[] blobLen = new int[1];
533
                        blobLen[0]=500;
534
                        
535
                        String[] blobInString = new String[1];
536
                        blobInString[0] = new String(this.blob);
537
                        
538
                        //Time based OTP verification
539
                        //Authentication window need to be bigger for first OTP verification.
540
                        int result = myocra.comAuthBlob(0, 0, this.serialNumber, Constants.getAuthenticationMode(this.authMode), timeDriftWindow, 1, 100, 
541
                                                                new byte[0], 0, 
542
                                                                new byte[0], 0,        
543
                                                                new byte[0], 0, 
544
                                                                6, password, 
545
                                                                blobInString, blobLen);
546
                        
547
                        this.useCount++;
548
                        this.firstTimeUsed = new Date();
549
                        this.lastTimeUsed = new Date();
550
                        
551
                        if(result == 0)
552
                        {
553
                                this.blob = blobInString[0].getBytes();
554
                                this.retCode = result;
555
                                updateTokenObject();
556
                        }
557
                        else
558
                        {
559
                                try 
560
                                {
561
                                        this.errorCount++;
562
                                        this.retCode = result;
563
                                        updateTokenObject();
564
                                        return errorCodeConversion(result);        
565
                                } 
566
                                catch (Exception e) 
567
                                {
568
                                        e.printStackTrace();
569
                                }
570
                        }
571

    
572
                }
573
                
574
                return Constants.ERR_SUCCESS;
575
        }
576

    
577
        /**
578
         * This will reset the token back to the initial state
579
         * The blob will be regenerated with the backup blob which is initially generated when it is imported from the pskc file.
580
         * 
581
         */
582
        public int resetToken() 
583
        {
584
                this.retCode = 0;
585
                this.blob = tb.getVbkCipherText();        
586
                this.useCount = 0;
587
                this.errorCount = 0;
588
                this.lastTimeUsed = null;
589
                this.firstTimeUsed = null;
590
                this.lastAuthentication = null;
591
                this.tokenExpectedDateTime = null;                
592
                updateTokenObject();
593
                
594
                return Constants.ERR_SUCCESS;
595
        }
596

    
597
        public HashMap<String, String> getTokenBlobInfo() 
598
        {
599
                HashMap<String,String>  map = new HashMap<String,String>();
600
                
601
                map.put("TOKEN_MODEL", tb.getVdpModel());
602
                map.put("USE_COUNT",  Integer.toString(tb.getVuseCount()));
603
                map.put("ERROR_COUNT",  Integer.toString(tb.getVerrorCount()));
604
                map.put("LAST_TIME_USED", String.valueOf (tb.getVdateLastUsed()));
605
                map.put("TIME_STEP_USED", Integer.toString(Constants.TIMESTEPUSED));
606
                
607
                return map;
608
        }
609
        
610
        /**
611
         * display gemalto token information
612
         * In comparion with vasco, only limited information will be displayed.
613
         * 
614
         */
615
        public void displayTokenInfo() 
616
        {                
617
                System.out.println("--Info----------------------------------------------");
618
                System.out.println("TOKEN_MODEL......." + tb.getVdpModel());
619
                System.out.println("USE_COUNT........." + tb.getVuseCount());
620
                System.out.println("ERR_COUNT........." + tb.getVerrorCount());
621
                System.out.println("LAST_TIME_USED...." + tb.getVdateLastUsed());
622
                System.out.println("TIME_STEP_USED...." + Constants.TIMESTEPUSED);
623
                System.out.println("----------------------------------------------------");
624
        }
625
        
626
        /**
627
         * This will override the existing tokenBean object
628
         * 
629
         */
630
        private void updateTokenObject() 
631
        {
632
                tb.setVuseCount(this.useCount );
633
                tb.setVerrorCount(this.errorCount );
634
                tb.setVdpCipherText(this.blob);
635
                tb.setVdateFirstUsed(this.firstTimeUsed);
636
                tb.setVdateLastUsed(this.lastTimeUsed);
637
        }
638
        
639

    
640
        
641
        /*
642
         * Code the gemalto returned error code to match with vasco's
643
         * 
644
         */
645
        private int errorCodeConversion(int errorCode) throws Exception
646
        {                
647
                switch(errorCode)
648
                {
649
                        case 0: return Constants.ERR_SUCCESS;
650
                        case 1: return Constants.ERR_INVALID_CREDENTIAL;
651
                        case 2: return Constants.ERR_BLOBINVALID;
652
                        case 3: return Constants.ERR_BUFFER;
653
                        case 4: return Constants.ERR_PARAM;
654
                        case 5: return Constants.ERR_SNOINVALID;
655
                        case 6: return Constants.ERR_OTPINVALID;
656
                        case 7: return Constants.ERR_REUSED_PASSWD;
657
                        case 8: return Constants.ERR_BLOBOTINIT;
658
                        case 9: return Constants.ERR_FAILED;
659
                        case 10: return Constants.ERR_REQINVALID;
660
                        case 11: return Constants.ERR_AUTH_MODE;
661
                        default: throw new Exception("Invalid error code.");
662
                }
663
        }
664

    
665
        public int syncToken(String userAlias, String otp1, String otp2) {
666
                // TODO Auto-generated method stub
667
                return 0;
668
        }
669
}