001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package  org.jpos.security;
020
021import org.javatuples.Pair;
022import org.jpos.core.Configurable;
023import org.jpos.core.Configuration;
024import org.jpos.core.ConfigurationException;
025import org.jpos.iso.ISOUtil;
026import org.jpos.util.LogEvent;
027import org.jpos.util.LogSource;
028import org.jpos.util.Loggeable;
029import org.jpos.util.Logger;
030import org.jpos.util.NameRegistrar;
031import org.jpos.util.NameRegistrar.NotFoundException;
032import org.jpos.util.SimpleMsg;
033
034import java.security.MessageDigest;
035import java.security.PublicKey;
036import java.security.spec.AlgorithmParameterSpec;
037import java.util.ArrayList;
038import java.util.Date;
039import java.util.List;
040import java.util.Map;
041
042/**
043 * <p>
044 * Provides base functionality for the actual Security Module Adapter.
045 * </p>
046 * <p>
047 * You adapter needs to override the methods that end with "Impl"
048 * </p>
049 * @author Hani S. Kirollos
050 * @version $Revision$ $Date$
051
052 * @param <T> the SecureKey implementation type
053 */
054public class BaseSMAdapter<T>
055        implements SMAdapter<T>, Configurable, LogSource {
056    /** Logger for this security module adapter. */
057    protected Logger logger = null;
058    /** Log realm for this security module adapter. */
059    protected String realm = null;
060    /** Configuration for this adapter. */
061    protected Configuration cfg;
062    private String name;
063    private boolean debug;
064
065    /** Default constructor. */
066    public BaseSMAdapter () {
067        super();
068    }
069
070    /**
071     * Creates a BaseSMAdapter with the given configuration, logger and realm.
072     * @param cfg configuration
073     * @param logger the logger
074     * @param realm log realm
075     * @throws ConfigurationException on invalid configuration
076     */
077    public BaseSMAdapter (Configuration cfg, Logger logger, String realm) throws ConfigurationException
078    {
079        super();
080        setLogger(logger, realm);
081        setConfiguration(cfg);
082    }
083
084    @Override
085    public void setConfiguration (Configuration cfg) throws ConfigurationException {
086        this.cfg = cfg;
087        debug = cfg.getBoolean("debug", false);
088    }
089
090    @Override
091    public void setLogger (Logger logger, String realm) {
092        this.logger = logger;
093        this.realm = realm;
094    }
095
096    @Override
097    public Logger getLogger () {
098        return  logger;
099    }
100
101    @Override
102    public String getRealm () {
103        return  realm;
104    }
105
106    /**
107     * associates this SMAdapter with a name using NameRegistrar
108     * @param name name to register
109     * @see NameRegistrar
110     */
111    public void setName (String name) {
112        this.name = name;
113        NameRegistrar.register("s-m-adapter." + name, this);
114    }
115
116    /**
117     * Returns the registered name of this SMAdapter.
118     * @return this SMAdapter's name ("" if no name was set)
119     */
120    public String getName () {
121        return  this.name;
122    }
123
124    /**
125     * Looks up a registered SMAdapter by name from the NameRegistrar.
126     * @param name the registered adapter name
127     * @return SMAdapter instance with given name.
128     * @throws NotFoundException if name is not found in the registry
129     * @see NameRegistrar
130     */
131    public static SMAdapter getSMAdapter (String name) throws NameRegistrar.NotFoundException {
132        return  (SMAdapter)NameRegistrar.get("s-m-adapter." + name);
133    }
134
135    @Override
136    public SecureDESKey generateKey (short keyLength, String keyType) throws SMException {
137        List<Loggeable> cmdParameters = new ArrayList<>();
138        cmdParameters.add(new SimpleMsg("parameter", "Key Length", keyLength));
139        cmdParameters.add(new SimpleMsg("parameter", "Key Type", keyType));
140        LogEvent evt = new LogEvent(this, "s-m-operation");
141        evt.addMessage(new SimpleMsg("command", "Generate Key", cmdParameters));
142        SecureDESKey result = null;
143        try {
144            result = generateKeyImpl(keyLength, keyType);
145            evt.addMessage(new SimpleMsg("result", "Generated Key", result));
146        } catch (Exception e) {
147            evt.addMessage(e);
148            throw  e instanceof SMException ? (SMException) e : new SMException(e);
149        } finally {
150            logEvent(evt);
151        }
152        return  result;
153    }
154
155    @Override
156    public SecureKey generateKey(SecureKeySpec keySpec) throws SMException {
157        List<Loggeable> cmdParameters = new ArrayList<>();
158        cmdParameters.add(new SimpleMsg("parameter", "Key Specification", keySpec));
159        LogEvent evt = new LogEvent(this, "s-m-operation");
160        evt.addMessage(new SimpleMsg("command", "Generate Key", cmdParameters));
161        SecureKey result = null;
162        try {
163            result = generateKeyImpl(keySpec);
164            evt.addMessage(new SimpleMsg("result", "Generated Key", result));
165        } catch (Exception e) {
166            evt.addMessage(e);
167            throw e instanceof SMException ? (SMException) e : new SMException(e);
168        } finally {
169            logEvent(evt);
170        }
171        return  result;
172    }
173
174    @Override
175    public byte[] generateKeyCheckValue(T kd) throws SMException {
176        List<Loggeable> cmdParameters = new ArrayList<>();
177        cmdParameters.add(new SimpleMsg("parameter", "Key with untrusted check value", kd));
178        LogEvent evt = new LogEvent(this, "s-m-operation");
179        evt.addMessage(new SimpleMsg("command", "Generate Key Check Value", cmdParameters));
180        byte[] result = null;
181        try {
182            result = generateKeyCheckValueImpl(kd);
183            evt.addMessage(new SimpleMsg("result", "Generated Key Check Value", ISOUtil.hexString(result)));
184        } catch (Exception e) {
185            evt.addMessage(e);
186            throw  e instanceof SMException ? (SMException) e : new SMException(e);
187        } finally {
188            logEvent(evt);
189        }
190        return  result;
191    }
192
193    @Override
194    public SecureDESKey translateKeyScheme(SecureDESKey key, KeyScheme destKeyScheme)
195            throws SMException {
196        List<Loggeable> cmdParameters = new ArrayList<>();
197        cmdParameters.add(new SimpleMsg("parameter", "Key", key));
198        cmdParameters.add(new SimpleMsg("parameter", "Destination Key Scheme", destKeyScheme));
199        LogEvent evt = new LogEvent(this, "s-m-operation");
200        evt.addMessage(new SimpleMsg("command", "Translate Key Scheme", cmdParameters));
201        SecureDESKey result = null;
202        try {
203            result = translateKeySchemeImpl(key, destKeyScheme);
204            evt.addMessage(new SimpleMsg("result", "Translate Key Scheme", result));
205        } catch (Exception e) {
206            evt.addMessage(e);
207            throw  e instanceof SMException ? (SMException) e : new SMException(e);
208        } finally {
209            logEvent(evt);
210        }
211        return  result;
212    }
213
214    @Override
215    public SecureDESKey importKey (short keyLength, String keyType, byte[] encryptedKey,
216            SecureDESKey kek, boolean checkParity) throws SMException {
217        List<Loggeable> cmdParameters = new ArrayList<>();
218        cmdParameters.add(new SimpleMsg("parameter", "Key Length", keyLength));
219        cmdParameters.add(new SimpleMsg("parameter", "Key Type", keyType));
220        cmdParameters.add(new SimpleMsg("parameter", "Encrypted Key", encryptedKey));
221        cmdParameters.add(new SimpleMsg("parameter", "Key-Encrypting Key", kek));
222        cmdParameters.add(new SimpleMsg("parameter", "Check Parity", checkParity));
223        LogEvent evt = new LogEvent(this, "s-m-operation");
224        evt.addMessage(new SimpleMsg("command", "Import Key", cmdParameters));
225        SecureDESKey result = null;
226        try {
227            result = importKeyImpl(keyLength, keyType, encryptedKey, kek, checkParity);
228            evt.addMessage(new SimpleMsg("result", "Imported Key", result));
229        } catch (Exception e) {
230            evt.addMessage(e);
231            throw  e instanceof SMException ? (SMException) e : new SMException(e);
232        } finally {
233            logEvent(evt);
234        }
235        return  result;
236    }
237
238    @Override
239    public SecureKey importKey(SecureKey kek, SecureKey key, SecureKeySpec keySpec
240            , boolean checkParity) throws SMException {
241        List<Loggeable> cmdParameters = new ArrayList<>();
242        cmdParameters.add(new SimpleMsg("parameter", "Key-Encrypting Key", kek));
243        cmdParameters.add(new SimpleMsg("parameter", "Encrypted Key", key));
244        cmdParameters.add(new SimpleMsg("parameter", "Key Specification", keySpec));
245        cmdParameters.add(new SimpleMsg("parameter", "Check Parity", checkParity));
246        LogEvent evt = new LogEvent(this, "s-m-operation");
247        evt.addMessage(new SimpleMsg("command", "Import Key", cmdParameters));
248        SecureKey result = null;
249        try {
250            result = importKeyImpl(kek, key, keySpec, checkParity);
251            evt.addMessage(new SimpleMsg("result", "Imported Key", result));
252        } catch (Exception e) {
253            evt.addMessage(e);
254            throw  e instanceof SMException ? (SMException) e : new SMException(e);
255        } finally {
256            logEvent(evt);
257        }
258        return  result;
259    }
260
261    @Override
262    public byte[] exportKey (SecureDESKey key, SecureDESKey kek) throws SMException {
263        List<Loggeable> cmdParameters = new ArrayList<>();
264        cmdParameters.add(new SimpleMsg("parameter", "Key", key));
265        cmdParameters.add(new SimpleMsg("parameter", "Key-Encrypting Key", kek));
266        LogEvent evt = new LogEvent(this, "s-m-operation");
267        evt.addMessage(new SimpleMsg("command", "Export Key", cmdParameters));
268        byte[] result = null;
269        try {
270            result = exportKeyImpl(key, kek);
271            evt.addMessage(new SimpleMsg("result", "Exported Key", result));
272        } catch (Exception e) {
273            evt.addMessage(e);
274            throw  e instanceof SMException ? (SMException) e : new SMException(e);
275        } finally {
276            logEvent(evt);
277        }
278        return  result;
279    }
280
281    @Override
282    public SecureKey exportKey(SecureKey kek, SecureKey key, SecureKeySpec keySpec)
283            throws SMException {
284        List<Loggeable> cmdParameters = new ArrayList<>();
285        cmdParameters.add(new SimpleMsg("parameter", "Key-Encrypting Key", kek));
286        cmdParameters.add(new SimpleMsg("parameter", "Key", key));
287        cmdParameters.add(new SimpleMsg("parameter", "Key Specification", keySpec));
288        LogEvent evt = new LogEvent(this, "s-m-operation");
289        evt.addMessage(new SimpleMsg("command", "Export Key", cmdParameters));
290        SecureKey result = null;
291        try {
292            result = exportKeyImpl(kek, key, keySpec);
293            evt.addMessage(new SimpleMsg("result", "Exported Key", result));
294        } catch (Exception e) {
295            evt.addMessage(e);
296            throw  e instanceof SMException ? (SMException) e : new SMException(e);
297        } finally {
298            logEvent(evt);
299        }
300        return  result;
301    }
302
303    @Override
304    public EncryptedPIN encryptPIN (String pin, String accountNumber, boolean extract) throws SMException {
305        accountNumber = extract ? EncryptedPIN.extractAccountNumberPart(accountNumber) : accountNumber;
306        List<Loggeable> cmdParameters = new ArrayList<>();
307        cmdParameters.add(new SimpleMsg("parameter", "clear pin", pin));
308        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNumber));
309        LogEvent evt = new LogEvent(this, "s-m-operation");
310        evt.addMessage(new SimpleMsg("command", "Encrypt Clear PIN", cmdParameters));
311        EncryptedPIN result = null;
312        try {
313            result = encryptPINImpl(pin, accountNumber);
314            evt.addMessage(new SimpleMsg("result", "PIN under LMK", result));
315        } catch (Exception e) {
316            evt.addMessage(e);
317            throw  e instanceof SMException ? (SMException) e : new SMException(e);
318        } finally {
319            logEvent(evt);
320        }
321        return  result;
322    }
323    @Override
324    public EncryptedPIN encryptPIN (String pin, String accountNumber) throws SMException {
325        return encryptPIN(pin, accountNumber, true);
326    }
327
328    @Override
329    public EncryptedPIN encryptPIN(String pin, String accountNumber, T pek) throws SMException {
330        accountNumber = EncryptedPIN.extractAccountNumberPart(accountNumber);
331        List<Loggeable> cmdParameters = new ArrayList<>();
332        cmdParameters.add(new SimpleMsg("parameter", "clear pin", pin));
333        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNumber));
334        cmdParameters.add(new SimpleMsg("parameter", "pin encryption Key", pek));
335        LogEvent evt = new LogEvent(this, "s-m-operation");
336        evt.addMessage(new SimpleMsg("command", "Encrypt clear PIN under PEK", cmdParameters));
337        EncryptedPIN result = null;
338        try {
339            result = encryptPINImpl(pin, accountNumber, pek);
340            evt.addMessage(new SimpleMsg("result", "PIN under PEK", result));
341        } 
342        catch (Exception e) {
343            evt.addMessage(e);
344            throw e instanceof SMException ? (SMException) e : new SMException(e);
345        } 
346        finally {
347            logEvent(evt);
348        }
349        return result;
350    }
351
352    @Override
353    public String decryptPIN (EncryptedPIN pinUnderLmk) throws SMException {
354        List<Loggeable> cmdParameters = new ArrayList<>();
355        cmdParameters.add(new SimpleMsg("parameter", "PIN under LMK", pinUnderLmk));
356        LogEvent evt = new LogEvent(this, "s-m-operation");
357        evt.addMessage(new SimpleMsg("command", "Decrypt PIN", cmdParameters));
358        String result = null;
359        try {
360            result = decryptPINImpl(pinUnderLmk);
361            evt.addMessage(new SimpleMsg("result", "clear PIN", result));
362        } catch (Exception e) {
363            evt.addMessage(e);
364            throw  e instanceof SMException ? (SMException) e : new SMException(e);
365        } finally {
366            logEvent(evt);
367        }
368        return  result;
369    }
370
371    @Override
372    public EncryptedPIN importPIN(EncryptedPIN pinUnderKd1, T kd1) throws SMException {
373        List<Loggeable> cmdParameters = new ArrayList<>();
374        cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
375        cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
376        LogEvent evt = new LogEvent(this, "s-m-operation");
377        evt.addMessage(new SimpleMsg("command", "Import PIN", cmdParameters));
378        EncryptedPIN result = null;
379        try {
380            result = importPINImpl(pinUnderKd1, kd1);
381            evt.addMessage(new SimpleMsg("result", "PIN under LMK", result));
382        } catch (Exception e) {
383            evt.addMessage(e);
384            throw  e instanceof SMException ? (SMException) e : new SMException(e);
385        } finally {
386            logEvent(evt);
387        }
388        return  result;
389    }
390
391    @Override
392    public EncryptedPIN translatePIN(EncryptedPIN pinUnderKd1, T kd1,
393            T kd2, byte destinationPINBlockFormat) throws SMException {
394        List<Loggeable> cmdParameters = new ArrayList<>();
395        cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
396        cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
397        cmdParameters.add(new SimpleMsg("parameter", "Data Key 2", kd2));
398        cmdParameters.add(new SimpleMsg("parameter", "Destination PIN Block Format", destinationPINBlockFormat));
399        LogEvent evt = new LogEvent(this, "s-m-operation");
400        evt.addMessage(new SimpleMsg("command", "Translate PIN from Data Key 1 to Data Key 2",
401                cmdParameters));
402        EncryptedPIN result = null;
403        try {
404            result = translatePINImpl(pinUnderKd1, kd1, kd2, destinationPINBlockFormat);
405            evt.addMessage(new SimpleMsg("result", "PIN under Data Key 2", result));
406        } catch (Exception e) {
407            evt.addMessage(e);
408            throw  e instanceof SMException ? (SMException) e : new SMException(e);
409        } finally {
410            logEvent(evt);
411        }
412        return  result;
413    }
414
415    @Override
416    public EncryptedPIN importPIN(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
417            T bdk) throws SMException {
418        return importPIN(pinUnderDuk,ksn,bdk,false);
419    }
420
421    @Override
422    public EncryptedPIN importPIN(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
423            T bdk, boolean tdes) throws SMException {
424        List<Loggeable> cmdParameters = new ArrayList<>();
425        cmdParameters.add(new SimpleMsg("parameter", "PIN under Derived Unique Key", pinUnderDuk));
426        cmdParameters.add(new SimpleMsg("parameter", "Key Serial Number", ksn));
427        cmdParameters.add(new SimpleMsg("parameter", "Base Derivation Key", bdk));
428        LogEvent evt = new LogEvent(this, "s-m-operation");
429        evt.addMessage(new SimpleMsg("command", "Import PIN", cmdParameters));
430        EncryptedPIN result = null;
431        try {
432            result = importPINImpl(pinUnderDuk, ksn, bdk, tdes);
433            evt.addMessage(new SimpleMsg("result", "PIN under LMK", result));
434        } catch (Exception e) {
435            evt.addMessage(e);
436            throw  e instanceof SMException ? (SMException) e : new SMException(e);
437        } finally {
438            logEvent(evt);
439        }
440        return  result;
441    }
442
443    @Override
444    public EncryptedPIN translatePIN(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
445            T bdk, T kd2, byte destinationPINBlockFormat) throws SMException {
446        return translatePIN(pinUnderDuk,ksn,bdk,kd2,destinationPINBlockFormat,false);
447    }
448
449    @Override
450    public EncryptedPIN translatePIN(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
451            T bdk, T kd2, byte destinationPINBlockFormat, boolean tdes) throws SMException {
452        List<Loggeable> cmdParameters = new ArrayList<>();
453        cmdParameters.add(new SimpleMsg("parameter", "PIN under Derived Unique Key", pinUnderDuk));
454        cmdParameters.add(new SimpleMsg("parameter", "Key Serial Number", ksn));
455        cmdParameters.add(new SimpleMsg("parameter", "Base Derivation Key", bdk));
456        cmdParameters.add(new SimpleMsg("parameter", "Data Key 2", kd2));
457        cmdParameters.add(new SimpleMsg("parameter", "Destination PIN Block Format", destinationPINBlockFormat));
458        LogEvent evt = new LogEvent(this, "s-m-operation");
459        evt.addMessage(new SimpleMsg("command", "Translate PIN", cmdParameters));
460        EncryptedPIN result = null;
461        try {
462            result = translatePINImpl(pinUnderDuk, ksn, bdk, kd2, destinationPINBlockFormat,tdes);
463            evt.addMessage(new SimpleMsg("result", "PIN under Data Key 2", result));
464        } catch (Exception e) {
465            evt.addMessage(e);
466            throw  e instanceof SMException ? (SMException) e : new SMException(e);
467        } finally {
468            logEvent(evt);
469        }
470        return  result;
471    }
472
473    @Override
474    public EncryptedPIN exportPIN(EncryptedPIN pinUnderLmk, T kd2, byte destinationPINBlockFormat) throws SMException {
475        List<Loggeable> cmdParameters = new ArrayList<>();
476        cmdParameters.add(new SimpleMsg("parameter", "PIN under LMK", pinUnderLmk));
477        cmdParameters.add(new SimpleMsg("parameter", "Data Key 2", kd2));
478        cmdParameters.add(new SimpleMsg("parameter", "Destination PIN Block Format", destinationPINBlockFormat));
479        LogEvent evt = new LogEvent(this, "s-m-operation");
480        evt.addMessage(new SimpleMsg("command", "Export PIN", cmdParameters));
481        EncryptedPIN result = null;
482        try {
483            result = exportPINImpl(pinUnderLmk, kd2, destinationPINBlockFormat);
484            evt.addMessage(new SimpleMsg("result", "PIN under Data Key 2", result));
485        } catch (Exception e) {
486            evt.addMessage(e);
487            throw  e instanceof SMException ? (SMException) e : new SMException(e);
488        } finally {
489            logEvent(evt);
490        }
491        return  result;
492    }
493
494    @Override
495    public EncryptedPIN generatePIN(String accountNumber, int pinLen)
496            throws SMException {
497      return generatePIN(accountNumber, pinLen, null);
498    }
499
500    @Override
501    public EncryptedPIN generatePIN(String accountNumber, int pinLen, List<String> excludes)
502            throws SMException {
503      List<Loggeable> cmdParameters = new ArrayList<>();
504      cmdParameters.add(new SimpleMsg("parameter", "account number", accountNumber));
505      cmdParameters.add(new SimpleMsg("parameter", "PIN length", pinLen));
506      if(excludes != null && !excludes.isEmpty())
507        cmdParameters.add(new SimpleMsg("parameter", "Excluded PINs list", excludes));
508
509      LogEvent evt = new LogEvent(this, "s-m-operation");
510      evt.addMessage(new SimpleMsg("command", "Generate PIN", cmdParameters));
511      EncryptedPIN result = null;
512      try {
513        result = generatePINImpl(accountNumber, pinLen, excludes);
514        evt.addMessage(new SimpleMsg("result", "Generated PIN", result));
515      } catch (Exception e) {
516        evt.addMessage(e);
517        throw e instanceof SMException ? (SMException) e : new SMException(e);
518      } finally {
519        logEvent(evt);
520      }
521      return result;
522    }
523
524    @Override
525    public void printPIN(String accountNo, EncryptedPIN pinUnderKd1, T kd1
526                         ,String template, Map<String, String> fields) throws SMException {
527      List<Loggeable> cmdParameters = new ArrayList<>();
528      cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo == null ? "" : accountNo));
529      cmdParameters.add(new SimpleMsg("parameter", "PIN under Key data 1", pinUnderKd1 == null ? "" : pinUnderKd1));
530      if (kd1!=null)
531        cmdParameters.add(new SimpleMsg("parameter", "Key data 1", kd1));
532      cmdParameters.add(new SimpleMsg("parameter", "Template", template == null ? "" : template));
533      if (fields!=null)
534        cmdParameters.add(new SimpleMsg("parameter", "Fields", fields));
535
536      LogEvent evt = new LogEvent(this, "s-m-operation");
537      evt.addMessage(new SimpleMsg("command", "Print PIN", cmdParameters));
538      try {
539          printPINImpl(accountNo, pinUnderKd1, kd1, template, fields);
540      } catch (Exception e) {
541          evt.addMessage(e);
542          throw  e instanceof SMException ? (SMException) e : new SMException(e);
543      } finally {
544          logEvent(evt);
545      }
546    }
547
548    @Override
549    public String calculatePVV(EncryptedPIN pinUnderLMK, T pvkA,
550                               T pvkB, int pvkIdx) throws SMException {
551      return calculatePVV(pinUnderLMK, pvkA, pvkB, pvkIdx, null);
552    }
553
554    @Override
555    public String calculatePVV(EncryptedPIN pinUnderLMK, T pvkA,
556                               T pvkB, int pvkIdx, List<String> excludes)
557            throws SMException {
558      List<Loggeable> cmdParameters = new ArrayList<>();
559      cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderLMK.getAccountNumber()));
560      cmdParameters.add(new SimpleMsg("parameter", "PIN under LMK", pinUnderLMK));
561      cmdParameters.add(new SimpleMsg("parameter", "PVK-A", pvkA == null ? "" : pvkA));
562      cmdParameters.add(new SimpleMsg("parameter", "PVK-B", pvkB == null ? "" : pvkB));
563      cmdParameters.add(new SimpleMsg("parameter", "PVK index", pvkIdx));
564      if(excludes != null && !excludes.isEmpty())
565        cmdParameters.add(new SimpleMsg("parameter", "Excluded PINs list", excludes));
566      LogEvent evt = new LogEvent(this, "s-m-operation");
567      evt.addMessage(new SimpleMsg("command", "Calculate PVV", cmdParameters));
568      String result = null;
569      try {
570        result = calculatePVVImpl(pinUnderLMK, pvkA, pvkB, pvkIdx, excludes);
571        evt.addMessage(new SimpleMsg("result", "Calculated PVV", result));
572      } catch (Exception e) {
573        evt.addMessage(e);
574        throw e instanceof SMException ? (SMException) e : new SMException(e);
575      } finally {
576        logEvent(evt);
577      }
578      return result;
579    }
580
581    @Override
582    public String calculatePVV(EncryptedPIN pinUnderKd1, T kd1,
583                               T pvkA, T pvkB, int pvkIdx)
584            throws SMException {
585      return calculatePVV(pinUnderKd1, kd1, pvkA, pvkB, pvkIdx, null);
586    }
587
588    @Override
589    public String calculatePVV(EncryptedPIN pinUnderKd1, T kd1,
590                               T pvkA, T pvkB, int pvkIdx,
591                               List<String> excludes) throws SMException {
592      List<Loggeable> cmdParameters = new ArrayList<>();
593      cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderKd1.getAccountNumber()));
594      cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
595      cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
596      cmdParameters.add(new SimpleMsg("parameter", "PVK-A", pvkA == null ? "" : pvkA));
597      cmdParameters.add(new SimpleMsg("parameter", "PVK-B", pvkB == null ? "" : pvkB));
598      cmdParameters.add(new SimpleMsg("parameter", "PVK index", pvkIdx));
599      if(excludes != null && !excludes.isEmpty())
600        cmdParameters.add(new SimpleMsg("parameter", "Excluded PINs list", excludes));
601      LogEvent evt = new LogEvent(this, "s-m-operation");
602      evt.addMessage(new SimpleMsg("command", "Calculate PVV", cmdParameters));
603      String result = null;
604      try {
605        result = calculatePVVImpl(pinUnderKd1, kd1, pvkA, pvkB, pvkIdx, excludes);
606        evt.addMessage(new SimpleMsg("result", "Calculated PVV", result));
607      } catch (Exception e) {
608        evt.addMessage(e);
609        throw e instanceof SMException ? (SMException) e : new SMException(e);
610      } finally {
611        logEvent(evt);
612      }
613      return result;
614    }
615
616    @Override
617    public boolean verifyPVV(EncryptedPIN pinUnderKd1, T kd1, T pvkA,
618                          T pvkB, int pvki, String pvv) throws SMException {
619        List<Loggeable> cmdParameters = new ArrayList<>();
620        cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderKd1.getAccountNumber()));
621        cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
622        cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
623        cmdParameters.add(new SimpleMsg("parameter", "PVK-A", pvkA == null ? "" : pvkA));
624        cmdParameters.add(new SimpleMsg("parameter", "PVK-B", pvkB == null ? "" : pvkB));
625        cmdParameters.add(new SimpleMsg("parameter", "pvki", pvki));
626        cmdParameters.add(new SimpleMsg("parameter", "pvv", pvv));
627      LogEvent evt = new LogEvent(this, "s-m-operation");
628      evt.addMessage(new SimpleMsg("command", "Verify a PIN Using the VISA Method", cmdParameters));
629
630      try {
631        boolean r = verifyPVVImpl(pinUnderKd1, kd1, pvkA, pvkB, pvki, pvv);
632        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
633        return r;
634      } catch (Exception e) {
635        evt.addMessage(e);
636        throw e instanceof SMException ? (SMException) e : new SMException(e);
637      } finally {
638        logEvent(evt);
639      }
640    }
641
642    @Override
643    public String calculateIBMPINOffset(EncryptedPIN pinUnderLmk, T pvk,
644                           String decTab, String pinValData, int minPinLen)
645            throws SMException {
646      return calculateIBMPINOffset(pinUnderLmk, pvk, decTab, pinValData, minPinLen, null);
647    }
648
649    @Override
650    public String calculateIBMPINOffset(EncryptedPIN pinUnderLmk, T pvk,
651                           String decTab, String pinValData, int minPinLen,
652                           List<String> excludes) throws SMException {
653      List<Loggeable> cmdParameters = new ArrayList<>();
654      cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderLmk.getAccountNumber()));
655      cmdParameters.add(new SimpleMsg("parameter", "PIN under LMK", pinUnderLmk));
656      cmdParameters.add(new SimpleMsg("parameter", "PVK", pvk));
657      cmdParameters.add(new SimpleMsg("parameter", "decimalisation table", decTab));
658      cmdParameters.add(new SimpleMsg("parameter", "PIN validation data", pinValData));
659      cmdParameters.add(new SimpleMsg("parameter", "minimum PIN length", minPinLen));
660      if(excludes != null && !excludes.isEmpty())
661        cmdParameters.add(new SimpleMsg("parameter", "Excluded PINs list", excludes));
662      LogEvent evt = new LogEvent(this, "s-m-operation");
663      evt.addMessage(new SimpleMsg("command", "Calculate PIN offset", cmdParameters));
664      String result = null;
665      try {
666        result = calculateIBMPINOffsetImpl(pinUnderLmk, pvk,
667                decTab, pinValData, minPinLen, excludes);
668        evt.addMessage(new SimpleMsg("result", "Calculated PIN offset", result));
669      } catch (Exception e) {
670        evt.addMessage(e);
671        throw e instanceof SMException ? (SMException) e : new SMException(e);
672      } finally {
673        logEvent(evt);
674      }
675      return result;
676    }
677
678    @Override
679    public String calculateIBMPINOffset(EncryptedPIN pinUnderKd1, T kd1,
680                           T pvk, String decTab, String pinValData, int minPinLen)
681            throws SMException {
682      return calculateIBMPINOffset(pinUnderKd1, kd1, pvk, decTab,
683              pinValData, minPinLen, null);
684    }
685
686    @Override
687    public String calculateIBMPINOffset(EncryptedPIN pinUnderKd1, T kd1,
688                           T pvk, String decTab, String pinValData, int minPinLen,
689                           List<String> excludes) throws SMException {
690      List<Loggeable> cmdParameters = new ArrayList<>();
691      cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderKd1.getAccountNumber()));
692      cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
693      cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
694      cmdParameters.add(new SimpleMsg("parameter", "PVK", pvk));
695      cmdParameters.add(new SimpleMsg("parameter", "decimalisation table", decTab));
696      cmdParameters.add(new SimpleMsg("parameter", "PIN validation data", pinValData));
697      cmdParameters.add(new SimpleMsg("parameter", "minimum PIN length", minPinLen));
698      if(excludes != null && !excludes.isEmpty())
699        cmdParameters.add(new SimpleMsg("parameter", "Excluded PINs list", excludes));
700      LogEvent evt = new LogEvent(this, "s-m-operation");
701      evt.addMessage(new SimpleMsg("command", "Calculate PIN offset", cmdParameters));
702      String result = null;
703      try {
704        result = calculateIBMPINOffsetImpl(pinUnderKd1, kd1, pvk,
705                decTab, pinValData, minPinLen, excludes);
706        evt.addMessage(new SimpleMsg("result", "Calculated PIN offset", result));
707      } catch (Exception e) {
708        evt.addMessage(e);
709        throw e instanceof SMException ? (SMException) e : new SMException(e);
710      } finally {
711        logEvent(evt);
712      }
713      return result;
714    }
715
716    @Override
717    public boolean verifyIBMPINOffset(EncryptedPIN pinUnderKd1, T kd1, T pvk,
718                                      String offset, String decTab, String pinValData,
719                                      int minPinLen) throws SMException {
720        List<Loggeable> cmdParameters = new ArrayList<>();
721        cmdParameters.add(new SimpleMsg("parameter", "account number", pinUnderKd1.getAccountNumber()));
722        cmdParameters.add(new SimpleMsg("parameter", "PIN under Data Key 1", pinUnderKd1));
723        cmdParameters.add(new SimpleMsg("parameter", "Data Key 1", kd1));
724        cmdParameters.add(new SimpleMsg("parameter", "PVK", pvk));
725        cmdParameters.add(new SimpleMsg("parameter", "Pin block format", pinUnderKd1.getPINBlockFormat()));
726        cmdParameters.add(new SimpleMsg("parameter", "decimalisation table", decTab));
727        cmdParameters.add(new SimpleMsg("parameter", "PIN validation data", pinValData));
728        cmdParameters.add(new SimpleMsg("parameter", "minimum PIN length", minPinLen));
729        cmdParameters.add(new SimpleMsg("parameter", "offset", offset));
730      LogEvent evt = new LogEvent(this, "s-m-operation");
731      evt.addMessage(new SimpleMsg("command", "Verify PIN offset", cmdParameters));
732
733      try {
734        boolean r = verifyIBMPINOffsetImpl(pinUnderKd1, kd1, pvk, offset, decTab,
735                 pinValData, minPinLen);
736        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
737        return r;
738      } catch (Exception e) {
739        evt.addMessage(e);
740        throw e instanceof SMException ? (SMException) e : new SMException(e);
741      } finally {
742        logEvent(evt);
743      }
744    }
745
746    @Override
747    public EncryptedPIN deriveIBMPIN(String accountNo, T pvk,
748                                     String decTab, String pinValData,
749                                     int minPinLen, String offset) throws SMException {
750        List<Loggeable> cmdParameters = new ArrayList<>();
751        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
752        cmdParameters.add(new SimpleMsg("parameter", "Offset", offset));
753        cmdParameters.add(new SimpleMsg("parameter", "PVK", pvk));
754        cmdParameters.add(new SimpleMsg("parameter", "Decimalisation table", decTab));
755        cmdParameters.add(new SimpleMsg("parameter", "PIN validation data", pinValData));
756        cmdParameters.add(new SimpleMsg("parameter", "Minimum PIN length", minPinLen));
757      LogEvent evt = new LogEvent(this, "s-m-operation");
758      evt.addMessage(new SimpleMsg("command", "Derive a PIN Using the IBM Method", cmdParameters));
759      EncryptedPIN result = null;
760      try {
761        result = deriveIBMPINImpl(accountNo, pvk, decTab,  pinValData, minPinLen,  offset);
762        evt.addMessage(new SimpleMsg("result", "Derived PIN", result));
763      } catch (Exception e) {
764        evt.addMessage(e);
765        throw e instanceof SMException ? (SMException) e : new SMException(e);
766      } finally {
767        logEvent(evt);
768      }
769      return result;
770    }
771
772    @Override
773    public String calculateCVV(String accountNo, T cvkA, T cvkB,
774                               Date expDate, String serviceCode) throws SMException {
775
776        List<Loggeable> cmdParameters = new ArrayList<>();
777        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
778        cmdParameters.add(new SimpleMsg("parameter", "cvk-a", cvkA == null ? "" : cvkA));
779        cmdParameters.add(new SimpleMsg("parameter", "cvk-b", cvkB == null ? "" : cvkB));
780        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
781        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
782        LogEvent evt = new LogEvent(this, "s-m-operation");
783        evt.addMessage(new SimpleMsg("command", "Calculate CVV/CVC", cmdParameters));
784        String result = null;
785        try {
786            result = calculateCVVImpl(accountNo, cvkA, cvkB, expDate, serviceCode);
787            evt.addMessage(new SimpleMsg("result", "Calculated CVV/CVC", result));
788        } catch (Exception e) {
789            evt.addMessage(e);
790            throw e instanceof SMException ? (SMException) e : new SMException(e);
791        } finally {
792            logEvent(evt);
793        }
794        return result;
795    }
796
797    @Override
798    public String calculateCVD(String accountNo, T cvkA, T cvkB,
799                               String expDate, String serviceCode) throws SMException {
800
801        List<Loggeable> cmdParameters = new ArrayList<>();
802        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
803        cmdParameters.add(new SimpleMsg("parameter", "cvk-a", cvkA == null ? "" : cvkA));
804        cmdParameters.add(new SimpleMsg("parameter", "cvk-b", cvkB == null ? "" : cvkB));
805        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
806        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
807        LogEvent evt = new LogEvent(this, "s-m-operation");
808        evt.addMessage(new SimpleMsg("command", "Calculate CVV/CVC", cmdParameters));
809        String result = null;
810        try {
811            result = calculateCVDImpl(accountNo, cvkA, cvkB, expDate, serviceCode);
812            evt.addMessage(new SimpleMsg("result", "Calculated CVV/CVC", result));
813        } catch (Exception e) {
814            evt.addMessage(e);
815            throw e instanceof SMException ? (SMException) e : new SMException(e);
816        } finally {
817            logEvent(evt);
818        }
819        return result;
820    }
821
822    @Override
823    public String calculateCAVV(String accountNo, T cvk, String upn,
824                                String authrc, String sfarc) throws SMException {
825
826      List<Loggeable> cmdParameters = new ArrayList<>();
827      cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
828      cmdParameters.add(new SimpleMsg("parameter", "cvk", cvk == null ? "" : cvk));
829      cmdParameters.add(new SimpleMsg("parameter", "unpredictable number", upn));
830      cmdParameters.add(new SimpleMsg("parameter", "auth rc", authrc));
831      cmdParameters.add(new SimpleMsg("parameter", "second factor auth rc", sfarc));
832      LogEvent evt = new LogEvent(this, "s-m-operation");
833      evt.addMessage(new SimpleMsg("command", "Calculate CAVV/AAV", cmdParameters));
834      String result = null;
835      try {
836          result = calculateCAVVImpl(accountNo, cvk, upn, authrc, sfarc);
837          evt.addMessage(new SimpleMsg("result", "Calculated CAVV/AAV", result));
838      } catch (Exception e) {
839          evt.addMessage(e);
840          throw e instanceof SMException ? (SMException) e : new SMException(e);
841      } finally {
842          logEvent(evt);
843      }
844      return result;
845    }
846
847    @Override
848    public boolean verifyCVV(String accountNo , T cvkA, T cvkB,
849                            String cvv, Date expDate, String serviceCode) throws SMException {
850
851        List<Loggeable> cmdParameters = new ArrayList<>();
852        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
853        cmdParameters.add(new SimpleMsg("parameter", "cvk-a", cvkA == null ? "" : cvkA));
854        cmdParameters.add(new SimpleMsg("parameter", "cvk-b", cvkB == null ? "" : cvkB));
855        cmdParameters.add(new SimpleMsg("parameter", "CVV/CVC", cvv));
856        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
857        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
858      LogEvent evt = new LogEvent(this, "s-m-operation");
859      evt.addMessage(new SimpleMsg("command", "Verify CVV/CVC", cmdParameters));
860      try {
861        boolean r = verifyCVVImpl(accountNo, cvkA, cvkB, cvv, expDate, serviceCode);
862        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
863        return r;
864      } catch (Exception e) {
865        evt.addMessage(e);
866        throw e instanceof SMException ? (SMException) e : new SMException(e);
867      } finally {
868        logEvent(evt);
869      }
870    }
871
872    @Override
873    public boolean verifyCVD(String accountNo, T cvkA, T cvkB,
874                            String cvv, String expDate, String serviceCode) throws SMException {
875
876        List<Loggeable> cmdParameters = new ArrayList<>();
877        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
878        cmdParameters.add(new SimpleMsg("parameter", "cvk-a", cvkA == null ? "" : cvkA));
879        cmdParameters.add(new SimpleMsg("parameter", "cvk-b", cvkB == null ? "" : cvkB));
880        cmdParameters.add(new SimpleMsg("parameter", "CVV/CVC", cvv));
881        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
882        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
883        LogEvent evt = new LogEvent(this, "s-m-operation");
884        evt.addMessage(new SimpleMsg("command", "Verify CVV/CVC", cmdParameters));
885        try {
886            boolean r = verifyCVVImpl(accountNo, cvkA, cvkB, cvv, expDate, serviceCode);
887            evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
888            return r;
889        } catch (Exception e) {
890            evt.addMessage(e);
891            throw e instanceof SMException ? (SMException) e : new SMException(e);
892        } finally {
893            logEvent(evt);
894        }
895    }
896
897    @Override
898    public boolean verifyCAVV(String accountNo, T cvk, String cavv,
899                              String upn, String authrc, String sfarc) throws SMException {
900
901      List<Loggeable> cmdParameters = new ArrayList<>();
902      cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
903      cmdParameters.add(new SimpleMsg("parameter", "cvk", cvk == null ? "" : cvk));
904      cmdParameters.add(new SimpleMsg("parameter", "cavv", cavv == null ? "" : cavv));
905      cmdParameters.add(new SimpleMsg("parameter", "unpredictable number", upn));
906      cmdParameters.add(new SimpleMsg("parameter", "auth rc", authrc));
907      cmdParameters.add(new SimpleMsg("parameter", "second factor auth rc", sfarc));
908      LogEvent evt = new LogEvent(this, "s-m-operation");
909      evt.addMessage(new SimpleMsg("command", "Verify CAVV/AAV", cmdParameters));
910      boolean r = false;
911      try {
912          r = verifyCAVVImpl(accountNo, cvk, cavv, upn, authrc, sfarc);
913          evt.addMessage(new SimpleMsg("result", "Verification status", r));
914      } catch (Exception e) {
915          evt.addMessage(e);
916          throw e instanceof SMException ? (SMException) e : new SMException(e);
917      } finally {
918          logEvent(evt);
919      }
920      return r;
921    }
922
923    @Override
924    public boolean verifydCVV(String accountNo, T imkac, String dcvv,
925                     Date expDate, String serviceCode, byte[] atc, MKDMethod mkdm)
926                     throws SMException {
927
928        List<Loggeable> cmdParameters = new ArrayList<>();
929        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
930        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac == null ? "" : imkac));
931        cmdParameters.add(new SimpleMsg("parameter", "dCVV", dcvv));
932        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
933        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
934        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
935        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
936      LogEvent evt = new LogEvent(this, "s-m-operation");
937      evt.addMessage(new SimpleMsg("command", "Verify dCVV", cmdParameters));
938      try {
939        boolean r = verifydCVVImpl(accountNo, imkac, dcvv, expDate, serviceCode, atc, mkdm);
940        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
941        return r;
942      } catch (Exception e) {
943        evt.addMessage(e);
944        throw e instanceof SMException ? (SMException) e : new SMException(e);
945      } finally {
946        logEvent(evt);
947      }
948    }
949
950    @Override
951    public boolean verifydCVV(String accountNo, T imkac, String dcvv,
952                     String expDate, String serviceCode, byte[] atc, MKDMethod mkdm)
953                     throws SMException {
954
955        if (accountNo == null || accountNo.trim().length() == 0)
956            throw new IllegalArgumentException("Account number not set.");
957
958        List<Loggeable> cmdParameters = new ArrayList<>();
959        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
960        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac == null ? "" : imkac));
961        cmdParameters.add(new SimpleMsg("parameter", "dCVV", dcvv));
962        cmdParameters.add(new SimpleMsg("parameter", "Exp date", expDate));
963        cmdParameters.add(new SimpleMsg("parameter", "Service code", serviceCode));
964        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
965        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
966        LogEvent evt = new LogEvent(this, "s-m-operation");
967        evt.addMessage(new SimpleMsg("command", "Verify dCVV", cmdParameters));
968        try {
969            boolean r = verifydCVVImpl(accountNo, imkac, dcvv, expDate, serviceCode, atc, mkdm);
970            evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
971            return r;
972        } catch (Exception e) {
973            evt.addMessage(e);
974            throw e instanceof SMException ? (SMException) e : new SMException(e);
975        } finally {
976            logEvent(evt);
977        }
978    }
979
980    /**
981     * @param imkcvc3 the issuer master key for generating and verifying CVC3
982     * @param accountNo The account number including BIN and the check digit
983     * @param acctSeqNo account sequence number, 2 decimal digits
984     * @param atc application transactin counter. This is used for ICC Master
985     *        Key derivation. A 2 byte value must be supplied.
986     * @param upn  unpredictable number. This is used for Session Key Generation
987     *        A 4 byte value must be supplied.
988     * @param data track data
989     * @param mkdm ICC Master Key Derivation Method. If {@code null} specified
990     *        is assumed.
991     * @param cvc3 dynamic Card Verification Code 3
992     * @return true if cvc3 is valid false if not
993     * @throws SMException on security module error
994     */
995    @Override
996    public boolean verifyCVC3(T imkcvc3, String accountNo, String acctSeqNo,
997                     byte[] atc, byte[] upn, byte[] data, MKDMethod mkdm, String cvc3)
998                     throws SMException {
999
1000        List<Loggeable> cmdParameters = new ArrayList<>();
1001        cmdParameters.add(new SimpleMsg("parameter", "imk-cvc3", imkcvc3 == null ? "" : imkcvc3));
1002        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
1003        cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1004        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1005        cmdParameters.add(new SimpleMsg("parameter", "upn", upn == null ? "" : ISOUtil.hexString(upn)));
1006        cmdParameters.add(new SimpleMsg("parameter", "data", data == null ? "" : ISOUtil.hexString(data)));
1007        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1008        cmdParameters.add(new SimpleMsg("parameter", "cvc3", cvc3));
1009      LogEvent evt = new LogEvent(this, "s-m-operation");
1010      evt.addMessage(new SimpleMsg("command", "Verify CVC3", cmdParameters));
1011      try {
1012        boolean r = verifyCVC3Impl(imkcvc3, accountNo, acctSeqNo, atc, upn, data, mkdm, cvc3);
1013        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
1014        return r;
1015      } catch (Exception e) {
1016        evt.addMessage(e);
1017        throw e instanceof SMException ? (SMException) e : new SMException(e);
1018      } finally {
1019        logEvent(evt);
1020      }
1021    }
1022
1023    @Override
1024    public boolean verifyARQC(MKDMethod mkdm, SKDMethod skdm, T imkac
1025            ,String accoutNo, String acctSeqNo, byte[] arqc, byte[] atc
1026            ,byte[] upn, byte[] txnData) throws SMException {
1027
1028        List<Loggeable> cmdParameters = new ArrayList<>();
1029        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1030        cmdParameters.add(new SimpleMsg("parameter", "skd method", skdm));
1031        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac));
1032        cmdParameters.add(new SimpleMsg("parameter", "account number", accoutNo));
1033        cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1034        cmdParameters.add(new SimpleMsg("parameter", "arqc", arqc == null ? "" : ISOUtil.hexString(arqc)));
1035        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1036        cmdParameters.add(new SimpleMsg("parameter", "upn", upn == null ? "" : ISOUtil.hexString(upn)));
1037        cmdParameters.add(new SimpleMsg("parameter", "txn data", txnData == null ? "" : ISOUtil.hexString(txnData)));
1038      LogEvent evt = new LogEvent(this, "s-m-operation");
1039      evt.addMessage(new SimpleMsg("command", "Verify ARQC/TC/AAC", cmdParameters));
1040      try {
1041        boolean r = verifyARQCImpl(mkdm, skdm, imkac, accoutNo, acctSeqNo, arqc, atc, upn, txnData);
1042        evt.addMessage(new SimpleMsg("result", "Verification status", r ? "valid" : "invalid"));
1043        return r;
1044      } catch (Exception e) {
1045        evt.addMessage(e);
1046        throw e instanceof SMException ? (SMException) e : new SMException(e);
1047      } finally {
1048        logEvent(evt);
1049      }
1050    }
1051
1052    @Override
1053    public byte[] generateARPC(MKDMethod mkdm, SKDMethod skdm, T imkac
1054            ,String accoutNo, String acctSeqNo, byte[] arqc, byte[] atc, byte[] upn
1055            ,ARPCMethod arpcMethod, byte[] arc, byte[] propAuthData)
1056            throws SMException {
1057
1058        List<Loggeable> cmdParameters = new ArrayList<>();
1059        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1060        cmdParameters.add(new SimpleMsg("parameter", "skd method", skdm));
1061        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac));
1062        cmdParameters.add(new SimpleMsg("parameter", "account number", accoutNo));
1063        cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1064        cmdParameters.add(new SimpleMsg("parameter", "arqc", arqc == null ? "" : ISOUtil.hexString(arqc)));
1065        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1066        cmdParameters.add(new SimpleMsg("parameter", "upn", upn == null ? "" : ISOUtil.hexString(upn)));
1067        cmdParameters.add(new SimpleMsg("parameter", "arpc gen. method", arpcMethod));
1068        cmdParameters.add(new SimpleMsg("parameter", "auth. rc", arc == null ? "" : ISOUtil.hexString(arc)));
1069        cmdParameters.add(new SimpleMsg("parameter", "prop auth. data"
1070                , propAuthData == null ? "" : ISOUtil.hexString(propAuthData))
1071        );
1072      LogEvent evt = new LogEvent(this, "s-m-operation");
1073      evt.addMessage(new SimpleMsg("command", "Genarate ARPC", cmdParameters));
1074      try {
1075        byte[] result = generateARPCImpl(mkdm, skdm, imkac, accoutNo, acctSeqNo
1076            , arqc, atc, upn, arpcMethod, arc, propAuthData);
1077        evt.addMessage(new SimpleMsg("result", "Generated ARPC", result));
1078        return result;
1079      } catch (Exception e) {
1080        evt.addMessage(e);
1081        throw e instanceof SMException ? (SMException) e : new SMException(e);
1082      } finally {
1083        logEvent(evt);
1084      }
1085    }
1086
1087    @Override
1088    public byte[] verifyARQCGenerateARPC(MKDMethod mkdm, SKDMethod skdm, T imkac
1089            ,String accoutNo, String acctSeqNo, byte[] arqc, byte[] atc, byte[] upn
1090            ,byte[] txnData, ARPCMethod arpcMethod, byte[] arc, byte[] propAuthData)
1091            throws SMException {
1092
1093        List<Loggeable> cmdParameters = new ArrayList<>();
1094        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1095        cmdParameters.add(new SimpleMsg("parameter", "skd method", skdm));
1096        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac));
1097        cmdParameters.add(new SimpleMsg("parameter", "account number", accoutNo));
1098        cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1099        cmdParameters.add(new SimpleMsg("parameter", "arqc", arqc == null ? "" : ISOUtil.hexString(arqc)));
1100        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1101        cmdParameters.add(new SimpleMsg("parameter", "upn", upn == null ? "" : ISOUtil.hexString(upn)));
1102        cmdParameters.add(new SimpleMsg("parameter", "txn data", txnData == null ? "" : ISOUtil.hexString(txnData)));
1103        cmdParameters.add(new SimpleMsg("parameter", "arpc gen. method", arpcMethod));
1104        cmdParameters.add(new SimpleMsg("parameter", "auth. rc", arc == null ? "" : ISOUtil.hexString(arc)));
1105        cmdParameters.add(new SimpleMsg("parameter", "prop auth. data",
1106                propAuthData == null ? "" : ISOUtil.hexString(propAuthData))
1107        );
1108      LogEvent evt = new LogEvent(this, "s-m-operation");
1109      evt.addMessage(new SimpleMsg("command", "Genarate ARPC", cmdParameters));
1110      try {
1111            byte[] result = verifyARQCGenerateARPCImpl(
1112                      mkdm, skdm, imkac, accoutNo, acctSeqNo, arqc, atc, upn
1113                    , txnData, arpcMethod, arc, propAuthData
1114            );
1115        evt.addMessage(new SimpleMsg("result", "ARPC", result == null ? "" : ISOUtil.hexString(result)));
1116        return result;
1117      } catch (Exception e) {
1118        evt.addMessage(e);
1119        throw e instanceof SMException ? (SMException) e : new SMException(e);
1120      } finally {
1121        logEvent(evt);
1122      }
1123    }
1124
1125    @Override
1126    public byte[] generateSM_MAC(MKDMethod mkdm, SKDMethod skdm
1127            ,T imksmi, String accountNo, String acctSeqNo
1128            ,byte[] atc, byte[] arqc, byte[] data) throws SMException {
1129
1130        List<Loggeable> cmdParameters = new ArrayList<>();
1131        cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1132        cmdParameters.add(new SimpleMsg("parameter", "skd method", skdm));
1133        cmdParameters.add(new SimpleMsg("parameter", "imk-smi", imksmi));
1134        cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
1135        cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1136        cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1137        cmdParameters.add(new SimpleMsg("parameter", "arqc", arqc == null ? "" : ISOUtil.hexString(arqc)));
1138        cmdParameters.add(new SimpleMsg("parameter", "data", data == null ? "" : ISOUtil.hexString(data)));
1139      LogEvent evt = new LogEvent(this, "s-m-operation");
1140      evt.addMessage(new SimpleMsg("command", "Generate Secure Messaging MAC", cmdParameters));
1141      try {
1142        byte[] mac = generateSM_MACImpl(mkdm, skdm, imksmi, accountNo, acctSeqNo, atc, arqc, data);
1143        evt.addMessage(new SimpleMsg("result", "Generated MAC", mac!=null ? ISOUtil.hexString(mac) : ""));
1144        return mac;
1145      } catch (Exception e) {
1146        evt.addMessage(e);
1147        throw e instanceof SMException ? (SMException) e : new SMException(e);
1148      } finally {
1149        logEvent(evt);
1150      }
1151    }
1152
1153    @Override
1154    public Pair<EncryptedPIN,byte[]> translatePINGenerateSM_MAC(MKDMethod mkdm
1155           ,SKDMethod skdm, PaddingMethod padm, T imksmi
1156           ,String accountNo, String acctSeqNo, byte[] atc, byte[] arqc
1157           ,byte[] data, EncryptedPIN currentPIN, EncryptedPIN newPIN
1158           ,T kd1, T imksmc, T imkac
1159           ,byte destinationPINBlockFormat) throws SMException {
1160
1161      List<Loggeable> cmdParameters = new ArrayList<>();
1162      cmdParameters.add(new SimpleMsg("parameter", "mkd method", mkdm));
1163      cmdParameters.add(new SimpleMsg("parameter", "skd method", skdm));
1164      if (padm!=null)
1165        cmdParameters.add(new SimpleMsg("parameter", "padding method", padm));
1166      cmdParameters.add(new SimpleMsg("parameter", "imk-smi", imksmi));
1167      cmdParameters.add(new SimpleMsg("parameter", "account number", accountNo));
1168      cmdParameters.add(new SimpleMsg("parameter", "accnt seq no", acctSeqNo));
1169      cmdParameters.add(new SimpleMsg("parameter", "atc", atc == null ? "" : ISOUtil.hexString(atc)));
1170      cmdParameters.add(new SimpleMsg("parameter", "arqc", arqc == null ? "" : ISOUtil.hexString(arqc)));
1171      cmdParameters.add(new SimpleMsg("parameter", "data", data == null ? "" : ISOUtil.hexString(data)));
1172      cmdParameters.add(new SimpleMsg("parameter", "Current Encrypted PIN", currentPIN));
1173      cmdParameters.add(new SimpleMsg("parameter", "New Encrypted PIN", newPIN));
1174      cmdParameters.add(new SimpleMsg("parameter", "Source PIN Encryption Key", kd1));
1175      cmdParameters.add(new SimpleMsg("parameter", "imk-smc", imksmc));
1176      if (imkac!=null)
1177        cmdParameters.add(new SimpleMsg("parameter", "imk-ac", imkac));
1178      cmdParameters.add(new SimpleMsg("parameter", "Destination PIN Block Format", destinationPINBlockFormat));
1179      LogEvent evt = new LogEvent(this, "s-m-operation");
1180      evt.addMessage(new SimpleMsg("command", "Translate PIN block format and Generate Secure Messaging MAC"
1181                    ,cmdParameters)
1182      );
1183      try {
1184            Pair<EncryptedPIN,byte[]> r = translatePINGenerateSM_MACImpl(mkdm, skdm
1185                ,padm, imksmi, accountNo, acctSeqNo, atc, arqc, data, currentPIN
1186                ,newPIN, kd1, imksmc, imkac, destinationPINBlockFormat
1187            );
1188            List<Loggeable> cmdResults = new ArrayList<>();
1189            cmdResults.add(new SimpleMsg("result", "Translated PIN block", r.getValue0()));
1190            cmdResults.add(new SimpleMsg("result", "Generated MAC", r.getValue1() == null ? "" : ISOUtil.hexString(r.getValue1())));
1191            evt.addMessage(new SimpleMsg("results", "Complex results", cmdResults));
1192            return r;
1193      } catch (Exception e) {
1194        evt.addMessage(e);
1195        throw e instanceof SMException ? (SMException) e : new SMException(e);
1196      } finally {
1197        logEvent(evt);
1198      }
1199    }
1200
1201    /**
1202     * Encrypt Data Block.
1203     *
1204     * @param cipherMode block cipher mode
1205     * @param kd DEK or ZEK key used to encrypt data
1206     * @param data data to be encrypted
1207     * @param iv initial vector
1208     * @return encrypted data
1209     * @throws SMException on security module error
1210     */
1211    @Override
1212    public byte[] encryptData(CipherMode cipherMode, SecureDESKey kd
1213            ,byte[] data, byte[] iv) throws SMException {
1214
1215        List<Loggeable> cmdParameters = new ArrayList<>();
1216        cmdParameters.add(new SimpleMsg("parameter", "Block Cipher Mode", cipherMode));
1217        if(kd != null)
1218            cmdParameters.add(new SimpleMsg("parameter", "Data key", kd));
1219        if(data != null)
1220            cmdParameters.add(new SimpleMsg("parameter", "Data", ISOUtil.hexString(data)));
1221        if(iv != null)
1222            cmdParameters.add(new SimpleMsg("parameter", "Initialization Vector", ISOUtil.hexString(iv)));
1223
1224        LogEvent evt = new LogEvent(this, "s-m-operation");
1225        evt.addMessage(new SimpleMsg("command", "Encrypt Data", cmdParameters));
1226        byte[] encData = null;
1227        try {
1228            encData = encryptDataImpl(cipherMode, kd, data, iv);
1229            List<Loggeable> r = new ArrayList<>();
1230            r.add(new SimpleMsg("result", "Encrypted Data", encData));
1231            if(iv != null)
1232                r.add(new SimpleMsg("result", "Initialization Vector", iv));
1233            evt.addMessage(new SimpleMsg("results", r));
1234        } catch (Exception e) {
1235            evt.addMessage(e);
1236            throw e instanceof SMException ? (SMException) e : new SMException(e);
1237        } finally {
1238            logEvent(evt);
1239        }
1240        return encData;
1241    }
1242
1243    /**
1244     * Decrypt Data Block.
1245     *
1246     * @param cipherMode block cipher mode
1247     * @param kd DEK or ZEK key used to decrypt data
1248     * @param data data to be decrypted
1249     * @param iv initial vector
1250     * @return decrypted data
1251     * @throws SMException on security module error
1252     */
1253    @Override
1254    public byte[] decryptData(CipherMode cipherMode, SecureDESKey kd
1255            ,byte[] data, byte[] iv) throws SMException {
1256
1257        List<Loggeable> cmdParameters = new ArrayList<>();
1258        cmdParameters.add(new SimpleMsg("parameter", "Block Cipher Mode", cipherMode));
1259        if(kd != null)
1260            cmdParameters.add(new SimpleMsg("parameter", "Data key", kd));
1261        if(data != null)
1262            cmdParameters.add(new SimpleMsg("parameter", "Data", ISOUtil.hexString(data)));
1263        if(iv != null)
1264            cmdParameters.add(new SimpleMsg("parameter", "Initialization Vector", ISOUtil.hexString(iv)));
1265
1266        LogEvent evt = new LogEvent(this, "s-m-operation");
1267        evt.addMessage(new SimpleMsg("command", "Decrypt Data", cmdParameters));
1268        byte[] decData = null;
1269        try {
1270            decData = decryptDataImpl(cipherMode, kd, data, iv);
1271            List<Loggeable> r = new ArrayList<>();
1272            r.add(new SimpleMsg("result", "Decrypted Data", decData));
1273            if(iv != null)
1274                r.add(new SimpleMsg("result", "Initialization Vector", iv));
1275            evt.addMessage(new SimpleMsg("results", r));
1276        } catch (Exception e) {
1277            evt.addMessage(e);
1278            throw e instanceof SMException ? (SMException) e : new SMException(e);
1279        } finally {
1280            logEvent(evt);
1281        }
1282        return decData;
1283    }
1284
1285    @Override
1286    public byte[] generateCBC_MAC(byte[] data, T kd) throws SMException {
1287        List<Loggeable> cmdParameters = new ArrayList<>();
1288        cmdParameters.add(new SimpleMsg("parameter", "data", data));
1289        cmdParameters.add(new SimpleMsg("parameter", "data key", kd));
1290        LogEvent evt = new LogEvent(this, "s-m-operation");
1291        evt.addMessage(new SimpleMsg("command", "Generate CBC-MAC", cmdParameters));
1292        byte[] result = null;
1293        try {
1294            result = generateCBC_MACImpl(data, kd);
1295            evt.addMessage(new SimpleMsg("result", "CBC-MAC", result));
1296        } catch (Exception e) {
1297            evt.addMessage(e);
1298            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1299        } finally {
1300            logEvent(evt);
1301        }
1302        return  result;
1303    }
1304
1305    @Override
1306    public byte[] generateEDE_MAC(byte[] data, T kd) throws SMException {
1307        List<Loggeable> cmdParameters = new ArrayList<>();
1308        cmdParameters.add(new SimpleMsg("parameter", "data", data));
1309        cmdParameters.add(new SimpleMsg("parameter", "data key", kd));
1310        LogEvent evt = new LogEvent(this, "s-m-operation");
1311        evt.addMessage(new SimpleMsg("command", "Generate EDE-MAC", cmdParameters));
1312        byte[] result = null;
1313        try {
1314            result = generateEDE_MACImpl(data, kd);
1315            evt.addMessage(new SimpleMsg("result", "EDE-MAC", result));
1316        } catch (Exception e) {
1317            evt.addMessage(e);
1318            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1319        } finally {
1320            logEvent(evt);
1321        }
1322        return  result;
1323    }
1324
1325    @Override
1326    public SecureDESKey translateKeyFromOldLMK(SecureDESKey kd) throws SMException {
1327        List<Loggeable> cmdParameters = new ArrayList<>();
1328        cmdParameters.add(new SimpleMsg("parameter", "Key under old LMK", kd));
1329        LogEvent evt = new LogEvent(this, "s-m-operation");
1330        evt.addMessage(new SimpleMsg("command", "Translate Key from old to new LMK", cmdParameters));
1331        SecureDESKey result = null;
1332        try {
1333            result = translateKeyFromOldLMKImpl(kd);
1334            evt.addMessage(new SimpleMsg("result", "Translated Key under new LMK", result));
1335        } catch (Exception e) {
1336            evt.addMessage(e);
1337            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1338        } finally {
1339            logEvent(evt);
1340        }
1341        return  result;
1342    }
1343
1344    @Override
1345    public SecureKey translateKeyFromOldLMK(SecureKey key, SecureKeySpec keySpec) throws SMException {
1346        List<Loggeable> cmdParameters = new ArrayList<>();
1347        cmdParameters.add(new SimpleMsg("parameter", "Key under old LMK", key));
1348        cmdParameters.add(new SimpleMsg("parameter", "Key Specification", keySpec));
1349        LogEvent evt = new LogEvent(this, "s-m-operation");
1350        evt.addMessage(new SimpleMsg("command", "Translate Key from old to new LMK", cmdParameters));
1351        SecureKey result = null;
1352        try {
1353            result = translateKeyFromOldLMKImpl(key, keySpec);
1354            evt.addMessage(new SimpleMsg("result", "Translated Key under new LMK", result));
1355        } catch (Exception e) {
1356            evt.addMessage(e);
1357            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1358        } finally {
1359            logEvent(evt);
1360        }
1361        return  result;
1362    }
1363
1364    @Override
1365    public Pair<PublicKey, SecurePrivateKey> generateKeyPair(AlgorithmParameterSpec spec)
1366            throws SMException {
1367        List<Loggeable> cmdParameters = new ArrayList<>();
1368        cmdParameters.add(new SimpleMsg("parameter", "Algorithm Parameter Spec", spec.getClass().getName()));
1369
1370        LogEvent evt = new LogEvent(this, "s-m-operation");
1371        evt.addMessage(new SimpleMsg("command", "Generate public/private key pair", cmdParameters));
1372        Pair<PublicKey, SecurePrivateKey> result = null;
1373        try {
1374            result = generateKeyPairImpl(spec);
1375            List<Loggeable> cmdResults = new ArrayList<>();
1376            cmdResults.add(new SimpleMsg("result", "Public Key", result.getValue0().getEncoded()));
1377            cmdResults.add(new SimpleMsg("result", "Private Key", result.getValue1().getKeyBytes()));
1378            evt.addMessage(new SimpleMsg("results", "Complex results", cmdResults));
1379        } catch (Exception e) {
1380            evt.addMessage(e);
1381            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1382        } finally {
1383            logEvent(evt);
1384        }
1385        return result;
1386    }
1387
1388    @Override
1389    public Pair<PublicKey, SecureKey> generateKeyPair(SecureKeySpec keySpec)
1390            throws SMException {
1391        List<Loggeable> cmdParameters = new ArrayList<>();
1392        cmdParameters.add(new SimpleMsg("parameter", "Key Pair Specification", keySpec));
1393
1394        LogEvent evt = new LogEvent(this, "s-m-operation");
1395        evt.addMessage(new SimpleMsg("command", "Generate public/private key pair", cmdParameters));
1396        Pair<PublicKey, SecureKey> result = null;
1397        try {
1398            result = generateKeyPairImpl(keySpec);
1399            List<Loggeable> cmdResults = new ArrayList<>();
1400            cmdResults.add(new SimpleMsg("result", "Public Key", result.getValue0().getEncoded()));
1401            cmdResults.add(new SimpleMsg("result", "Private Key", result.getValue1().getKeyBytes()));
1402            evt.addMessage(new SimpleMsg("results", "Complex results", cmdResults));
1403        } catch (Exception e) {
1404            evt.addMessage(e);
1405            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1406        } finally {
1407            logEvent(evt);
1408        }
1409        return result;
1410    }
1411
1412    @Override
1413    public byte[] calculateSignature(MessageDigest hash, SecureKey privateKey
1414            ,byte[] data) throws SMException {
1415        List<Loggeable> cmdParameters = new ArrayList<>();
1416        cmdParameters.add(new SimpleMsg("parameter", "Hash Identifier", hash));
1417        cmdParameters.add(new SimpleMsg("parameter", "Private Key", privateKey));
1418        cmdParameters.add(new SimpleMsg("parameter", "data", data));
1419
1420        LogEvent evt = new LogEvent(this, "s-m-operation");
1421        evt.addMessage(new SimpleMsg("command", "Generate data signature", cmdParameters));
1422        byte[] result = null;
1423        try {
1424            result = calculateSignatureImpl(hash, privateKey, data);
1425            evt.addMessage(new SimpleMsg("result", "Data Signature", result));
1426        } catch (Exception e) {
1427            evt.addMessage(e);
1428            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1429        } finally {
1430            logEvent(evt);
1431        }
1432        return result;
1433    }
1434
1435    @Override
1436    public byte[] encryptData(SecureKey encKey, byte[] data
1437            , AlgorithmParameterSpec algspec, byte[] iv) throws SMException {
1438        List<Loggeable> cmdParameters = new ArrayList<>();
1439        cmdParameters.add(new SimpleMsg("parameter", "Encription Key", encKey));
1440        cmdParameters.add(new SimpleMsg("parameter", "Data", ISOUtil.hexString(data)));
1441        if (algspec != null)
1442            cmdParameters.add(new SimpleMsg("parameter", "Algorithm Spec", algspec));
1443        if (iv != null)
1444            cmdParameters.add(new SimpleMsg("parameter", "Initialization Vector", ISOUtil.hexString(iv)));
1445        LogEvent evt = new LogEvent(this, "s-m-operation");
1446        evt.addMessage(new SimpleMsg("command", "Encrypt Data", cmdParameters));
1447        byte[] result = null;
1448        try {
1449            result = encryptDataImpl(encKey, data, algspec, iv);
1450            List<Loggeable> r = new ArrayList<>();
1451            r.add(new SimpleMsg("result", "Encrypted Data", result));
1452            if (iv != null)
1453                r.add(new SimpleMsg("result", "Initialization Vector", iv));
1454            evt.addMessage(new SimpleMsg("results", r));
1455        } catch (SMException ex) {
1456            evt.addMessage(ex);
1457            throw ex;
1458        } catch (RuntimeException ex) {
1459            evt.addMessage(ex);
1460            throw new SMException(ex);
1461        } finally {
1462            logEvent(evt);
1463        }
1464        return result;
1465    }
1466
1467    @Override
1468    public byte[] decryptData(SecureKey privKey, byte[] data
1469            , AlgorithmParameterSpec algspec, byte[] iv) throws SMException {
1470        List<Loggeable> cmdParameters = new ArrayList<>();
1471        cmdParameters.add(new SimpleMsg("parameter", "Decription Key", privKey));
1472        cmdParameters.add(new SimpleMsg("parameter", "Encrypted Data", ISOUtil.hexString(data)));
1473        if (algspec != null)
1474            cmdParameters.add(new SimpleMsg("parameter", "Algorithm Spec", algspec));
1475        if (iv != null)
1476            cmdParameters.add(new SimpleMsg("parameter", "Initialization Vector", ISOUtil.hexString(iv)));
1477        LogEvent evt = new LogEvent(this, "s-m-operation");
1478        evt.addMessage(new SimpleMsg("command", "Decrypt Data", cmdParameters));
1479        byte[] result = null;
1480        try {
1481            result = decryptDataImpl(privKey, data, algspec, iv);
1482            List<Loggeable> r = new ArrayList<>();
1483            r.add(new SimpleMsg("result", "Decrypted Data", result));
1484            if (iv != null)
1485                r.add(new SimpleMsg("result", "Initialization Vector", iv));
1486            evt.addMessage(new SimpleMsg("results", r));
1487        } catch (SMException ex) {
1488            evt.addMessage(ex);
1489            throw ex;
1490        } catch (RuntimeException ex) {
1491            evt.addMessage(ex);
1492            throw new SMException(ex);
1493        } finally {
1494            logEvent(evt);
1495        }
1496        return result;
1497    }
1498
1499    @Override
1500    public void eraseOldLMK () throws SMException {
1501        List<Loggeable> cmdParameters = new ArrayList<>();
1502        LogEvent evt = new LogEvent(this, "s-m-operation");
1503        evt.addMessage(new SimpleMsg("command", "Erase the key change storage", cmdParameters));
1504        try {
1505            eraseOldLMKImpl();
1506        } catch (Exception e) {
1507            evt.addMessage(e);
1508            throw  e instanceof SMException ? (SMException) e : new SMException(e);
1509        } finally {
1510            logEvent(evt);
1511        }
1512    }
1513
1514    /**
1515     * Your SMAdapter should override this method if it has this functionality
1516     * @param keyLength requested key length
1517     * @param keyType requested key type
1518     * @return generated key
1519     * @throws SMException on security module error
1520     */
1521    protected SecureDESKey generateKeyImpl (short keyLength, String keyType) throws SMException {
1522        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1523    }
1524
1525    /**
1526     * Your SMAdapter should override this method if it has this functionality.
1527     *
1528     * @param keySpec key specification
1529     * @return generated key
1530     * @throws SMException on security module error
1531     */
1532    protected SecureKey generateKeyImpl(SecureKeySpec keySpec) throws SMException {
1533        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
1534    }
1535
1536    /**
1537     * Your SMAdapter should override this method if it has this functionality
1538     * @param kd secure key
1539     * @return generated Key Check Value
1540     * @throws SMException on security module error
1541     */
1542    protected byte[] generateKeyCheckValueImpl(T kd) throws SMException {
1543        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1544    }
1545
1546    /**
1547     * Your SMAdapter should override this method if it has this functionality
1548     * @param key secure key
1549     * @param destKeyScheme destination key scheme
1550     * @return translated key with {@code destKeyScheme} scheme
1551     * @throws SMException on security module error
1552     */
1553    protected SecureDESKey translateKeySchemeImpl(SecureDESKey key, KeyScheme destKeyScheme)
1554            throws SMException {
1555        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1556    }
1557
1558    /**
1559     * Your SMAdapter should override this method if it has this functionality
1560     * @param keyLength requested key length
1561     * @param keyType requested key type
1562     * @param encryptedKey encrypted key bytes
1563     * @param kek key-encrypting key
1564     * @param checkParity whether to check DES key parity
1565     * @return imported key
1566     * @throws SMException on security module error
1567     */
1568    protected SecureDESKey importKeyImpl(short keyLength, String keyType, byte[] encryptedKey,
1569            SecureDESKey kek, boolean checkParity) throws SMException {
1570        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1571    }
1572
1573    /**
1574     * Your SMAdapter should override this method if it has this functionality.
1575     *
1576     * @param kek key-encrypting key
1577     * @param key secure key
1578     * @param keySpec key specification
1579     * @param checkParity whether to check DES key parity
1580     * @return imported key
1581     * @throws SMException on security module error
1582     */
1583    protected SecureKey importKeyImpl(SecureKey kek, SecureKey key,
1584            SecureKeySpec keySpec, boolean checkParity) throws SMException {
1585        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
1586    }
1587
1588    /**
1589     * Your SMAdapter should override this method if it has this functionality
1590     * @param key secure key
1591     * @param kek key-encrypting key
1592     * @return exported key
1593     * @throws SMException on security module error
1594     */
1595    protected byte[] exportKeyImpl(SecureDESKey key, SecureDESKey kek) throws SMException {
1596        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1597    }
1598
1599    /**
1600     * Your SMAdapter should override this method if it has this functionality.
1601     *
1602     * @param kek key-encrypting key
1603     * @param key secure key
1604     * @param keySpec key specification
1605     * @return exported key
1606     * @throws SMException on security module error
1607     */
1608    protected SecureKey exportKeyImpl(SecureKey kek, SecureKey key
1609            , SecureKeySpec keySpec) throws SMException {
1610        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
1611    }
1612
1613    /**
1614     * Your SMAdapter should override this method if it has this functionality
1615     * @param pin clear PIN value
1616     * @param accountNumber account number associated with the PIN block
1617     * @return encrypted PIN under LMK
1618     * @throws SMException on security module error
1619     */
1620    protected EncryptedPIN encryptPINImpl (String pin, String accountNumber) throws SMException {
1621        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1622    }
1623
1624    /**
1625     * Your SMAdapter should override this method if it has this functionality.
1626     *
1627     * @param pin clear PIN value
1628     * @param accountNumber account number associated with the PIN block
1629     * @param pek PIN-encrypting key
1630     * @return encrypted PIN under PEK.
1631     * @throws SMException on security module error
1632     */
1633    protected EncryptedPIN encryptPINImpl(String pin, String accountNumber, T pek) throws SMException {
1634        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1635    }
1636
1637    /**
1638     * Your SMAdapter should override this method if it has this functionality
1639     * @param pinUnderLmk PIN block encrypted under the LMK
1640     * @return clear pin as entered by card holder
1641     * @throws SMException on security module error
1642     */
1643    protected String decryptPINImpl (EncryptedPIN pinUnderLmk) throws SMException {
1644        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1645    }
1646
1647    /**
1648     * Your SMAdapter should override this method if it has this functionality
1649     * @param pinUnderKd1 PIN block encrypted under the source key
1650     * @param kd1 source key
1651     * @return imported pin
1652     * @throws SMException on security module error
1653     */
1654    protected EncryptedPIN importPINImpl(EncryptedPIN pinUnderKd1, T kd1) throws SMException {
1655        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1656    }
1657
1658    /**
1659     * Your SMAdapter should override this method if it has this functionality
1660     * @param pinUnderKd1 PIN block encrypted under the source key
1661     * @param kd1 source key
1662     * @param kd2 destination key
1663     * @param destinationPINBlockFormat destination PIN block format
1664     * @return translated pin
1665     * @throws SMException on security module error
1666     */
1667    protected EncryptedPIN translatePINImpl(EncryptedPIN pinUnderKd1, T kd1,
1668            T kd2, byte destinationPINBlockFormat) throws SMException {
1669        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1670    }
1671
1672    /**
1673     * Your SMAdapter should override this method if it has this functionality
1674     * @deprecated
1675     * @param pinUnderDuk PIN block encrypted under a DUKPT-derived key
1676     * @param ksn key serial number
1677     * @param bdk base derivation key
1678     * @return imported pin
1679     * @throws SMException on security module error
1680     */
1681    @Deprecated
1682    protected EncryptedPIN importPINImpl(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
1683            T bdk) throws SMException {
1684        return importPINImpl(pinUnderDuk,ksn,bdk,false);
1685    }
1686
1687    /**
1688     * Your SMAdapter should override this method if it has this functionality
1689     * @param pinUnderDuk PIN block encrypted under a DUKPT-derived key
1690     * @param ksn key serial number
1691     * @param bdk base derivation key
1692     * @param tdes whether to use triple-DES DUKPT derivation
1693     * @return imported pin
1694     * @throws SMException on security module error
1695     */
1696    protected EncryptedPIN importPINImpl(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
1697            T bdk, boolean tdes) throws SMException {
1698        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1699    }
1700
1701    /**
1702     * Your SMAdapter should override this method if it has this functionality
1703     * @deprecated
1704     * @param pinUnderDuk PIN block encrypted under a DUKPT-derived key
1705     * @param ksn key serial number
1706     * @param bdk base derivation key
1707     * @param kd2 destination key
1708     * @param destinationPINBlockFormat destination PIN block format
1709     * @return translated pin
1710     * @throws SMException on security module error
1711     */
1712    @Deprecated
1713    protected EncryptedPIN translatePINImpl(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
1714            T bdk, T kd2, byte destinationPINBlockFormat) throws SMException {
1715        return translatePINImpl(pinUnderDuk,ksn,bdk,kd2,destinationPINBlockFormat,false);
1716    }
1717
1718    /**
1719     * Your SMAdapter should override this method if it has this functionality
1720     * @param pinUnderDuk PIN block encrypted under a DUKPT-derived key
1721     * @param ksn key serial number
1722     * @param bdk base derivation key
1723     * @param kd2 destination key
1724     * @param tdes whether to use triple-DES DUKPT derivation
1725     * @param destinationPINBlockFormat destination PIN block format
1726     * @return translated pin
1727     * @throws SMException on security module error
1728     */
1729    protected EncryptedPIN translatePINImpl(EncryptedPIN pinUnderDuk, KeySerialNumber ksn,
1730            T bdk, T kd2, byte destinationPINBlockFormat,
1731            boolean tdes) throws SMException {
1732        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1733    }
1734
1735    /**
1736     * Your SMAdapter should override this method if it has this functionality
1737     * @param pinUnderLmk PIN block encrypted under the LMK
1738     * @param kd2 destination key
1739     * @param destinationPINBlockFormat destination PIN block format
1740     * @return exported pin
1741     * @throws SMException on security module error
1742     */
1743    protected EncryptedPIN exportPINImpl(EncryptedPIN pinUnderLmk, T kd2,
1744            byte destinationPINBlockFormat) throws SMException {
1745        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1746    }
1747
1748    /**
1749     * Your SMAdapter should override this method if it has this functionality
1750     * @param accountNumber account number associated with the PIN block
1751     * @param pinLen requested PIN length
1752     * @param excludes PIN values to reject
1753     * @return generated PIN under LMK
1754     * @throws SMException on security module error
1755     */
1756    protected EncryptedPIN generatePINImpl(String accountNumber, int pinLen, List<String> excludes) throws
1757            SMException {
1758        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1759    }
1760
1761    /**
1762     * Your SMAdapter should override this method if it has this functionality
1763     * @param accountNo card account number
1764     * @param pinUnderKd1 PIN block encrypted under the source key
1765     * @param kd1 source key
1766     * @param template decimalisation table template
1767     * @param fields template fields
1768     * @throws SMException on security module error
1769     */
1770    protected void printPINImpl(String accountNo, EncryptedPIN pinUnderKd1, T kd1
1771                             ,String template, Map<String, String> fields) throws SMException {
1772        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1773    }
1774
1775    /**
1776     * Your SMAdapter should override this method if it has this functionality
1777     * @param pinUnderLMK PIN block encrypted under the LMK
1778     * @param pvkA first PIN verification key
1779     * @param pvkB second PIN verification key
1780     * @param pvkIdx PIN verification key index
1781     * @param excludes PIN values to reject
1782     * @return PVV (VISA PIN Verification Value)
1783     * @throws SMException on security module error
1784     */
1785    protected String calculatePVVImpl(EncryptedPIN pinUnderLMK,
1786                       T pvkA, T pvkB, int pvkIdx, List<String> excludes)
1787            throws SMException {
1788        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1789    }
1790
1791    /**
1792     * Your SMAdapter should override this method if it has this functionality
1793     * @param pinUnderKd1 PIN block encrypted under the source key
1794     * @param kd1 source key
1795     * @param pvkA first PIN verification key
1796     * @param pvkB second PIN verification key
1797     * @param pvkIdx PIN verification key index
1798     * @param excludes PIN values to reject
1799     * @return PVV (VISA PIN Verification Value)
1800     * @throws SMException on security module error
1801     */
1802    protected String calculatePVVImpl(EncryptedPIN pinUnderKd1, T kd1,
1803                       T pvkA, T pvkB, int pvkIdx,
1804                       List<String> excludes) throws SMException {
1805        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1806    }
1807
1808    /**
1809     * Your SMAdapter should override this method if it has this functionality
1810     * @param pinUnderKd PIN block encrypted under the key
1811     * @param kd secure key
1812     * @param pvkA first PIN verification key
1813     * @param pvkB second PIN verification key
1814     * @param pvki PIN verification key index
1815     * @param pvv PIN verification value
1816     * @return true if pin is valid false if not
1817     * @throws SMException on security module error
1818     */
1819    protected boolean verifyPVVImpl(EncryptedPIN pinUnderKd, T kd, T pvkA,
1820                        T pvkB, int pvki, String pvv) throws SMException {
1821        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1822    }
1823
1824    /**
1825     * Your SMAdapter should override this method if it has this functionality
1826     * @param pinUnderLmk PIN block encrypted under the LMK
1827     * @param pvk PIN verification key
1828     * @param decTab decimalisation table
1829     * @param pinValData PIN validation data
1830     * @param minPinLen minimum PIN length
1831     * @param excludes PIN values to reject
1832     * @return IBM PIN Offset
1833     * @throws SMException on security module error
1834     */
1835    protected String calculateIBMPINOffsetImpl(EncryptedPIN pinUnderLmk, T pvk,
1836                              String decTab, String pinValData, int minPinLen,
1837                              List<String> excludes) throws SMException {
1838        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1839    }
1840
1841    /**
1842     * Your SMAdapter should override this method if it has this functionality
1843     * @param pinUnderKd1 PIN block encrypted under the source key
1844     * @param kd1 source key
1845     * @param pvk PIN verification key
1846     * @param decTab decimalisation table
1847     * @param pinValData PIN validation data
1848     * @param minPinLen minimum PIN length
1849     * @param excludes PIN values to reject
1850     * @return IBM PIN Offset
1851     * @throws SMException on security module error
1852     */
1853    protected String calculateIBMPINOffsetImpl(EncryptedPIN pinUnderKd1, T kd1,
1854                              T pvk, String decTab, String pinValData,
1855                              int minPinLen, List<String> excludes)
1856            throws SMException {
1857        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1858    }
1859
1860    /**
1861     * Your SMAdapter should override this method if it has this functionality
1862     * @param pinUnderKd PIN block encrypted under the key
1863     * @param kd secure key
1864     * @param pvk PIN verification key
1865     * @param offset PIN offset
1866     * @param decTab decimalisation table
1867     * @param pinValData PIN validation data
1868     * @param minPinLen minimum PIN length
1869     * @return true if pin is valid false if not
1870     * @throws SMException on security module error
1871     */
1872    protected boolean verifyIBMPINOffsetImpl(EncryptedPIN pinUnderKd, T kd
1873                            ,T pvk, String offset, String decTab
1874                            ,String pinValData, int minPinLen) throws SMException {
1875        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1876    }
1877
1878    /**
1879     * Your SMAdapter should override this method if it has this functionality
1880     * @param accountNo card account number
1881     * @param pvk PIN verification key
1882     * @param decTab decimalisation table
1883     * @param pinValData PIN validation data
1884     * @param minPinLen minimum PIN length
1885     * @param offset PIN offset
1886     * @return derived PIN under LMK
1887     * @throws SMException on security module error
1888     */
1889    protected EncryptedPIN deriveIBMPINImpl(String accountNo, T pvk, String decTab
1890                                , String pinValData, int minPinLen, String offset)
1891            throws SMException {
1892        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1893    }
1894
1895    /**
1896     * Your SMAdapter should override this method if it has this functionality
1897     * @param accountNo card account number
1898     * @param cvkA first card verification key
1899     * @param cvkB second card verification key
1900     * @param expDate card expiration date
1901     * @param serviceCode card service code
1902     * @return Card Verification Code/Value
1903     * @throws SMException on security module error
1904     */
1905    protected String calculateCVVImpl(String accountNo, T cvkA, T cvkB,
1906                                   Date expDate, String serviceCode) throws SMException {
1907        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1908    }
1909
1910
1911    /**
1912     * Your SMAdapter should override this method if it has this functionality
1913     * @param accountNo card account number
1914     * @param cvkA first card verification key
1915     * @param cvkB second card verification key
1916     * @param expDate card expiration date
1917     * @param serviceCode card service code
1918     * @return Card Verification Digit (Code/Value)
1919     * @throws SMException on security module error
1920     */
1921    protected String calculateCVDImpl(String accountNo, T cvkA, T cvkB,
1922                                   String expDate, String serviceCode) throws SMException {
1923        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
1924    }
1925
1926
1927    /**
1928     * Your SMAdapter should override this method if it has this functionality
1929     * @param accountNo card account number
1930     * @param cvk card verification key
1931     * @param upn unpredictable number
1932     * @param authrc authorization response code
1933     * @param sfarc second-factor authorization response code
1934     * @return Cardholder Authentication Verification Value
1935     * @throws SMException on security module error
1936     */
1937    protected String calculateCAVVImpl(String accountNo, T cvk, String upn,
1938                                    String authrc, String sfarc) throws SMException {
1939        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1940    }
1941
1942    /**
1943     * Your SMAdapter should override this method if it has this functionality
1944     * @param accountNo card account number
1945     * @param cvkA first card verification key
1946     * @param cvkB second card verification key
1947     * @param cvv card verification value
1948     * @param expDate card expiration date
1949     * @param serviceCode card service code
1950     * @return true if CVV/CVC is falid or false if not
1951     * @throws SMException on security module error
1952     */
1953    protected boolean verifyCVVImpl(String accountNo, T cvkA, T cvkB,
1954                        String cvv, Date expDate, String serviceCode) throws SMException {
1955        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1956    }
1957
1958    /**
1959     * Your SMAdapter should override this method if it has this functionality
1960     * @param accountNo card account number
1961     * @param cvkA first card verification key
1962     * @param cvkB second card verification key
1963     * @param cvv card verification value
1964     * @param expDate card expiration date
1965     * @param serviceCode card service code
1966     * @return {@code true} if CVV/CVC is valid or {@code false} otherwise
1967     * @throws SMException on security module error
1968     */
1969    protected boolean verifyCVVImpl(String accountNo, T cvkA, T cvkB,
1970                        String cvv, String expDate, String serviceCode) throws SMException {
1971        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
1972    }
1973
1974    /**
1975     * Your SMAdapter should override this method if it has this functionality
1976     * @param accountNo card account number
1977     * @param cvk card verification key
1978     * @param cavv cardholder authentication verification value
1979     * @param upn unpredictable number
1980     * @param authrc authorization response code
1981     * @param sfarc second-factor authorization response code
1982     * @return Cardholder Authentication Verification Value
1983     * @throws SMException on security module error
1984     */
1985    protected boolean verifyCAVVImpl(String accountNo, T cvk, String cavv,
1986                                     String upn, String authrc, String sfarc) throws SMException {
1987        throw  new SMException("Operation not supported in: " + this.getClass().getName());
1988    }
1989
1990    /**
1991     * Your SMAdapter should override this method if it has this functionality
1992     * @param accountNo card account number
1993     * @param imkac issuer master key for application cryptograms
1994     * @param dcvv dynamic card verification value
1995     * @param expDate card expiration date
1996     * @param serviceCode card service code
1997     * @param atc application transaction counter
1998     * @param mkdm master-key derivation method
1999     * @return true if dcvv is valid false if not
2000     * @throws SMException on security module error
2001     */
2002    protected boolean verifydCVVImpl(String accountNo, T imkac, String dcvv,
2003                     Date expDate, String serviceCode, byte[] atc, MKDMethod mkdm)
2004                     throws SMException {
2005        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2006    }
2007
2008    /**
2009     * Your SMAdapter should override this method if it has this functionality
2010     * @param accountNo card account number
2011     * @param imkac issuer master key for application cryptograms
2012     * @param dcvv dynamic card verification value
2013     * @param expDate card expiration date
2014     * @param serviceCode card service code
2015     * @param atc application transaction counter
2016     * @param mkdm master-key derivation method
2017     * @return true if dcvv is valid false if not
2018     * @throws SMException on security module error
2019     */
2020    protected boolean verifydCVVImpl(String accountNo, T imkac, String dcvv,
2021                     String expDate, String serviceCode, byte[] atc, MKDMethod mkdm)
2022                     throws SMException {
2023        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2024    }
2025
2026    /**
2027     * Your SMAdapter should override this method if it has this functionality
2028     * @param imkcvc3 issuer master key for CVC3
2029     * @param accountNo card account number
2030     * @param acctSeqNo PAN sequence number
2031     * @param atc application transaction counter
2032     * @param upn unpredictable number
2033     * @param data input data
2034     * @param mkdm master-key derivation method
2035     * @param cvc3 card validation code 3
2036     * @return true if cvc3 is valid false if not
2037     * @throws SMException on security module error
2038     */
2039    protected boolean verifyCVC3Impl(T imkcvc3, String accountNo, String acctSeqNo,
2040                     byte[] atc, byte[] upn, byte[] data, MKDMethod mkdm, String cvc3)
2041                     throws SMException {
2042        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2043    }
2044
2045    /**
2046     * Your SMAdapter should override this method if it has this functionality
2047     * @param mkdm master-key derivation method
2048     * @param skdm session-key derivation method
2049     * @param imkac issuer master key for application cryptograms
2050     * @param accountNo card account number
2051     * @param acctSeqNo PAN sequence number
2052     * @param arqc application request cryptogram
2053     * @param atc application transaction counter
2054     * @param upn unpredictable number
2055     * @param txnData transaction data
2056     * @return true if ARQC/TC/AAC is valid or false if not
2057     * @throws SMException on security module error
2058     */
2059    protected boolean verifyARQCImpl(MKDMethod mkdm, SKDMethod skdm, T imkac
2060            ,String accountNo, String acctSeqNo, byte[] arqc, byte[] atc
2061            ,byte[] upn, byte[] txnData) throws SMException {
2062        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2063    }
2064
2065    /**
2066     * Your SMAdapter should override this method if it has this functionality
2067     * @param mkdm master-key derivation method
2068     * @param skdm session-key derivation method
2069     * @param imkac issuer master key for application cryptograms
2070     * @param accountNo card account number
2071     * @param acctSeqNo PAN sequence number
2072     * @param arqc application request cryptogram
2073     * @param atc application transaction counter
2074     * @param upn unpredictable number
2075     * @param arpcMethod ARPC generation method
2076     * @param arc authorization response code
2077     * @param propAuthData proprietary authentication data
2078     * @return calculated ARPC
2079     * @throws SMException on security module error
2080     */
2081    protected byte[] generateARPCImpl(MKDMethod mkdm, SKDMethod skdm, T imkac
2082            ,String accountNo, String acctSeqNo, byte[] arqc, byte[] atc
2083            ,byte[] upn, ARPCMethod arpcMethod, byte[] arc, byte[] propAuthData)
2084            throws SMException {
2085        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2086    }
2087
2088    /**
2089     * Your SMAdapter should override this method if it has this functionality
2090     * @param mkdm master-key derivation method
2091     * @param skdm session-key derivation method
2092     * @param imkac issuer master key for application cryptograms
2093     * @param accountNo card account number
2094     * @param acctSeqNo PAN sequence number
2095     * @param arqc application request cryptogram
2096     * @param atc application transaction counter
2097     * @param upn unpredictable number
2098     * @param transData transaction data
2099     * @param arpcMethod ARPC generation method
2100     * @param arc authorization response code
2101     * @param propAuthData proprietary authentication data
2102     * @return calculated ARPC
2103     * @throws SMException on security module error
2104     */
2105    protected byte[] verifyARQCGenerateARPCImpl(MKDMethod mkdm, SKDMethod skdm, T imkac
2106            ,String accountNo, String acctSeqNo, byte[] arqc, byte[] atc, byte[] upn
2107            ,byte[] transData, ARPCMethod arpcMethod, byte[] arc, byte[] propAuthData)
2108            throws SMException {
2109        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2110    }
2111
2112
2113
2114    /**
2115     * Your SMAdapter should override this method if it has this functionality
2116     * @param mkdm master-key derivation method
2117     * @param skdm session-key derivation method
2118     * @param imksmi issuer master key for secure messaging integrity
2119     * @param accountNo card account number
2120     * @param acctSeqNo PAN sequence number
2121     * @param atc application transaction counter
2122     * @param arqc application request cryptogram
2123     * @param data input data
2124     * @return generated 8 bytes MAC
2125     * @throws SMException on security module error
2126     */
2127    protected byte[] generateSM_MACImpl(MKDMethod mkdm, SKDMethod skdm
2128            ,T imksmi, String accountNo, String acctSeqNo
2129            ,byte[] atc, byte[] arqc, byte[] data) throws SMException {
2130        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2131    }
2132
2133    /**
2134     * Your SMAdapter should override this method if it has this functionality
2135     * @param mkdm master-key derivation method
2136     * @param skdm session-key derivation method
2137     * @param padm proprietary authentication data method
2138     * @param imksmi issuer master key for secure messaging integrity
2139     * @param accountNo card account number
2140     * @param acctSeqNo PAN sequence number
2141     * @param atc application transaction counter
2142     * @param arqc application request cryptogram
2143     * @param data input data
2144     * @param currentPIN current PIN value
2145     * @param newPIN replacement PIN value
2146     * @param kd1 source key
2147     * @param imksmc issuer master key for secure messaging confidentiality
2148     * @param imkac issuer master key for application cryptograms
2149     * @param destinationPINBlockFormat destination PIN block format
2150     * @return Pair of values, encrypted PIN and 8 bytes MAC
2151     * @throws SMException on security module error
2152     */
2153    protected Pair<EncryptedPIN,byte[]> translatePINGenerateSM_MACImpl(MKDMethod mkdm
2154           ,SKDMethod skdm, PaddingMethod padm, T imksmi
2155           ,String accountNo, String acctSeqNo, byte[] atc, byte[] arqc
2156           ,byte[] data, EncryptedPIN currentPIN, EncryptedPIN newPIN
2157           ,T kd1, T imksmc, T imkac
2158           ,byte destinationPINBlockFormat) throws SMException {
2159        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2160    }
2161
2162    /**
2163     * Your SMAdapter should override this method if it has this functionality
2164     * @param cipherMode cipher mode
2165     * @param kd secure key
2166     * @param data input data
2167     * @param iv initialization vector
2168     * @return encrypted data
2169     * @throws SMException on security module error
2170     */
2171    protected byte[] encryptDataImpl(CipherMode cipherMode, SecureDESKey kd
2172            ,byte[] data, byte[] iv) throws SMException {
2173        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2174    }
2175
2176    /**
2177     * Your SMAdapter should override this method if it has this functionality
2178     * @param cipherMode cipher mode
2179     * @param kd secure key
2180     * @param data input data
2181     * @param iv initialization vector
2182     * @return decrypted data
2183     * @throws SMException on security module error
2184     */
2185    protected byte[] decryptDataImpl(CipherMode cipherMode, SecureDESKey kd
2186            ,byte[] data, byte[] iv) throws SMException {
2187        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2188    }
2189
2190    /**
2191     * Your SMAdapter should override this method if it has this functionality
2192     * @param data input data
2193     * @param kd secure key
2194     * @return generated CBC-MAC
2195     * @throws SMException on security module error
2196     */
2197    protected byte[] generateCBC_MACImpl(byte[] data, T kd) throws SMException {
2198        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2199    }
2200
2201    /**
2202     * Your SMAdapter should override this method if it has this functionality
2203     * @param data input data
2204     * @param kd secure key
2205     * @return generated EDE-MAC
2206     * @throws SMException on security module error
2207     */
2208    protected byte[] generateEDE_MACImpl(byte[] data, T kd) throws SMException {
2209        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2210    }
2211
2212    /**
2213     * Translate key from encryption under the LMK held in key change storage
2214     * to encryption under a new LMK.
2215     *
2216     * @param kd the key encrypted under old LMK
2217     * @return key encrypted under the new LMK
2218     * @throws SMException if the parity of the imported key is not adjusted AND checkParity = true
2219     */
2220    protected SecureDESKey translateKeyFromOldLMKImpl(SecureDESKey kd) throws SMException {
2221        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2222    }
2223
2224    /**
2225     * Your SMAdapter should override this method if it has this functionality.
2226     *
2227     * @param key secure key
2228     * @param keySpec key specification
2229     * @return key encrypted under the new LMK
2230     * @throws SMException if the parity of the imported key is not adjusted AND checkParity = true
2231     */
2232    protected SecureKey translateKeyFromOldLMKImpl(SecureKey key, SecureKeySpec keySpec) throws SMException {
2233        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2234    }
2235
2236    /**
2237     * Your SMAdapter should override this method if it has this functionality
2238     * @param spec algorithm specific parameters (contains e.g. key size)
2239     * @return key pair generated according to passed parameters
2240     * @throws SMException on security module error
2241     */
2242    protected Pair<PublicKey, SecurePrivateKey> generateKeyPairImpl(AlgorithmParameterSpec spec)
2243            throws SMException {
2244        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2245    }
2246
2247    /**
2248     * Your SMAdapter should override this method if it has this functionality.
2249     *
2250     * @param keySpec key specification
2251     * @return key pair generated according to passed parameters
2252     * @throws SMException on security module error
2253     */
2254    protected Pair<PublicKey, SecureKey> generateKeyPairImpl(SecureKeySpec keySpec)
2255            throws SMException {
2256        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2257    }
2258
2259    /**
2260     * Your SMAdapter should override this method if it has this functionality
2261     * @param hash identifier of the hash algorithm used to hash passed data.
2262     * @param privateKey private key used to compute data signature.
2263     * @param data data to be sifned.
2264     * @return signature of passed data.
2265     * @throws SMException on security module error
2266     */
2267    protected byte[] calculateSignatureImpl(MessageDigest hash, SecureKey privateKey
2268            ,byte[] data) throws SMException {
2269        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2270    }
2271
2272    /**
2273     * Encrypts clear Data Block with specified cipher.
2274     *
2275     * @param encKey the data encryption key
2276     * @param data data block to encrypt
2277     * @param algspec algorithm specification
2278     * @param iv the inital vector
2279     * @return encrypted data block
2280     * @throws SMException on security module error
2281     */
2282    protected byte[] encryptDataImpl(SecureKey encKey, byte[] data
2283            , AlgorithmParameterSpec algspec, byte[] iv)
2284            throws SMException {
2285        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2286    }
2287
2288    /**
2289     * Decrypts Data Block encrypted with assymetric cipher.
2290     *
2291     * @param decKey the data decryption key
2292     * @param data data block to decrypt
2293     * @param algspec algorithm specification
2294     * @param iv the inital vector
2295     * @return decrypted data block
2296     * @throws SMException on security module error
2297     */
2298    protected byte[] decryptDataImpl(SecureKey decKey, byte[] data
2299            , AlgorithmParameterSpec algspec, byte[] iv)
2300            throws SMException {
2301        throw new UnsupportedOperationException("Operation not supported in: " + this.getClass().getName());
2302    }
2303
2304    /**
2305     * Erase the key change storage area of memory
2306     *
2307     * It is recommended that this command is used after keys stored
2308     * by the Host have been translated from old to new LMKs.
2309     *
2310     * @throws SMException on security module error
2311     */
2312    protected void eraseOldLMKImpl () throws SMException {
2313        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2314    }
2315
2316    @Override
2317    public byte[] dataEncrypt(T bdk, byte[] clearText) throws SMException {
2318        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2319    }
2320
2321    @Override
2322    public byte[] dataDecrypt(T bdk, byte[] clearText) throws SMException {
2323        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2324    }
2325
2326    @Override
2327    public SecureDESKey formKEYfromClearComponents(short keyLength, String keyType, String... clearComponents) throws SMException {
2328        throw  new SMException("Operation not supported in: " + this.getClass().getName());
2329    }
2330
2331    private void logEvent(LogEvent evt) {
2332        if (debug)
2333            Logger.log(evt);
2334    }
2335}