├── .classpath ├── .gitignore ├── .project ├── .travis.yml ├── README.md ├── build.xml ├── src ├── javacard │ ├── framework │ │ ├── AID.java │ │ ├── APDU.java │ │ ├── APDUException.java │ │ ├── Applet.java │ │ ├── AppletEvent.java │ │ ├── CardException.java │ │ ├── CardRuntimeException.java │ │ ├── ISO7816.java │ │ ├── ISOException.java │ │ ├── JCSystem.java │ │ ├── MultiSelectable.java │ │ ├── OwnerPIN.java │ │ ├── PIN.java │ │ ├── PINException.java │ │ ├── Shareable.java │ │ ├── SystemException.java │ │ ├── TransactionException.java │ │ ├── UserException.java │ │ └── Util.java │ └── security │ │ ├── AESKey.java │ │ ├── Checksum.java │ │ ├── CryptoException.java │ │ ├── DESKey.java │ │ ├── DSAKey.java │ │ ├── DSAPrivateKey.java │ │ ├── DSAPublicKey.java │ │ ├── ECKey.java │ │ ├── ECPrivateKey.java │ │ ├── ECPublicKey.java │ │ ├── HMACKey.java │ │ ├── InitializedMessageDigest.java │ │ ├── Key.java │ │ ├── KeyAgreement.java │ │ ├── KeyBuilder.java │ │ ├── KeyPair.java │ │ ├── KoreanSEEDKey.java │ │ ├── MessageDigest.java │ │ ├── PrivateKey.java │ │ ├── PublicKey.java │ │ ├── RSAPrivateCrtKey.java │ │ ├── RSAPrivateKey.java │ │ ├── RSAPublicKey.java │ │ ├── RandomData.java │ │ ├── SecretKey.java │ │ ├── Signature.java │ │ └── SignatureMessageRecovery.java ├── javacardx │ ├── apdu │ │ └── ExtendedLength.java │ └── crypto │ │ ├── Cipher.java │ │ └── KeyEncryption.java ├── pro │ └── javacard │ │ └── vre │ │ ├── Misc.java │ │ ├── VJCREProvider.java │ │ ├── VRE.java │ │ ├── vAID.java │ │ ├── vAPDU.java │ │ ├── vChecksum.java │ │ ├── vCipher.java │ │ ├── vKey.java │ │ ├── vKeyAgreement.java │ │ ├── vKeyPair.java │ │ ├── vMessageDigest.java │ │ ├── vRSAPrivateCrtKey.java │ │ ├── vRSAPrivateKey.java │ │ ├── vRSAPublicKey.java │ │ ├── vRandomData.java │ │ └── vSignature.java └── visa │ └── openplatform │ ├── OPSystem.java │ └── ProviderSecurityDomain.java └── vjcre.pro /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /build 3 | /*.jar 4 | /lib/*.jar 5 | *~ 6 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | JavaCard VRE 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | jdk: 4 | - oraclejdk8 5 | script: ant 6 | env: 7 | global: 8 | - secure: VmFGgw9Ryj85nryhEriMapZXEakDpjcaTb1SHtEa+fXYfgsw/0fPPflkiET/wr1YJzWTpzpS1U/z91QaUyt75BJR+CXEcVAQCPN9xDoLXhAdLpIM9IJvui82VAp/xz1IU+9yS3zgc7H84yHlJfoCthHSlTL2nNxr9aYsBncXKo0= 9 | addons: 10 | coverity_scan: 11 | project: 12 | name: martinpaljak/vJCRE 13 | description: Virtual JCRE 14 | notification_email: martin@martinpaljak.net 15 | build_command_prepend: 16 | build_command: ant compile 17 | branch_pattern: coverity 18 | deploy: 19 | api-key: 20 | secure: B2I+zUghBVM2qFzGhj+vEaF5II2XvQwyOlth9DzC2wGQTpcWN7Vvu+Yr8b+a7T/VLodNREBvyFVDyTCh705Ta4iBQUjuAxYDt7qeVyQoMhpzVhBys46cMfsa6vSTHFmJsz/oikyZc/+WYpsQMyppPQyYGT+vd+F/qJDAwL3zgFs= 21 | provider: releases 22 | file: 23 | - vjcre.jar 24 | skip_cleanup: true 25 | on: 26 | tags: true 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # import pro.javacard.vre.*; 2 | > Focus on running **existing code** in a **modern container**, instead of emulating an old environment to the dumbest details. Fully **open source**! 3 | 4 | vJCRE is a vritual Java Card Runtime Environment that allows to run Java code targeting the smart card platform inside a standard desktop Java virtual machine. Ideal for fast development, testing or experimentation. 5 | 6 | #### Jump to ... 7 | * [Download](#get-it-now) 8 | * [Contact](#contact) 9 | 10 | # Features 11 | * Easy interfacing with any APDU-like interface: 12 | * `CommandAPDU` from [javax.smartcardio](http://docs.oracle.com/javase/7/docs/jre/api/security/smartcardio/spec/javax/smartcardio/package-summary.html) 13 | * Generic `byte[]` exchange, like [Android Host Card Emulation](http://developer.android.com/guide/topics/connectivity/nfc/hce.html) 14 | * JavaCard 2.2.2+, usage of Extended APDU encouraged 15 | * [HostApduService](https://developer.android.com/reference/android/nfc/cardemulation/HostApduService.html) proxy for Android 16 | * Includes all packages with essential interfaces and abstract classes up to JavaCard v3.0.4: 17 | * `javacard.framework.*` 18 | * `javacard.security.*` 19 | * `javacardx.apdu.*` 20 | * `javacardx.crypto.*` 21 | * Simple, thin and modular codebase to the finest extent possible. 22 | * Minimal one-liner pollution in `javacard*.*`. The only allowed import is from pro.javacard.vre.*; 23 | * No Javadoc or license for API specification. Go read the original API docs. *([hint](http://www.win.tue.nl/pinpasjc/docs/apis/jc222/overview-summary.html))* 24 | * Implements necessary JCSystem and APDU, cryptography provided either by standard JCE or [BouncyCastle](http://bouncycastle.org/java.html). 25 | * Applet management interface, not unlike [GlobalPlatform](https://github.com/martinpaljak/GlobalPlatform#globalplatform-from-openkms) 26 | * No support for: 27 | * Transactions 28 | * RMI 29 | * Services 30 | * Logical channels 31 | * Future versions 32 | * More algorithms, including JavaCard 3.0.X features 33 | * Multiple independent VJCRE instances in a single VM 34 | * Saving and loading VM instances (real "virtual cards") 35 | * Works great with the rest of the open source smart card stack. 36 | * Made in Estonia 37 | 38 | # Usage 39 | 40 | ```java 41 | import pro.javacard.*; 42 | 43 | VRE vre = VRE.getInstance(); 44 | AID aid = new AID(FakeEstEIDApplet.aid); 45 | vre.load(FakeEstEIDApplet.class, aid); // Load the applet with the specified AID 46 | vre.install(aid, default); // Make a default selected instance of the applet with same AID 47 | TerminalFactory tf = TerminalFactory.getInstance("PC/SC", vre, new VJCREProvider()); 48 | CardTerminals terms = tf.terminals(); 49 | // Now use javax.smartcardio as you would do when talking to a real smart card 50 | ``` 51 | 52 | # Get it now! 53 | Version 0.1 will be released early March 2014 together with [FakeEstEID](https://github.com/martinpaljak/AppletPlayground/wiki/FakeEstEID) [Android version](https://github.com/martinpaljak/mobiil-idkaart#mobile-id-as-esteid-over-nfc). Until that time feel free to look around in the repository. 54 | 55 | # Contact 56 | * martin@martinpaljak.net 57 | 58 | #### Similar projects 59 | * jCardSim - https://github.com/licel/jcardsim 60 | * JavaCard 2.2.1, T=0 only 61 | * Apache license (Also in JC API classes???) 62 | * Currently implements more algorithms 63 | * https://github.com/christianhujer/jcardmock 64 | #### Related projects 65 | * AlgTest - https://github.com/petrs/AlgTest 66 | 67 | ---- 68 | [javacard.pro](http://javacard.pro) 69 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ANT build file for vJCRE 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/javacard/framework/AID.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | 4 | public final class AID extends pro.javacard.vre.vAID { 5 | 6 | public AID(byte bArray[], short offset, byte length) throws SystemException, NullPointerException, ArrayIndexOutOfBoundsException, SecurityException { 7 | if (length < 5 || length > 16) { 8 | SystemException.throwIt(SystemException.ILLEGAL_VALUE); 9 | } 10 | aid = new byte[length]; 11 | Util.arrayCopy(bArray, offset, aid, (short) 0, length); 12 | } 13 | 14 | public final byte getBytes(byte dest[], short offset) throws NullPointerException, ArrayIndexOutOfBoundsException, SecurityException { 15 | Util.arrayCopy(aid, (short) 0, dest, offset, (short) aid.length); 16 | return (byte) aid.length; 17 | } 18 | 19 | public final boolean equals(byte bArray[], short offset, byte length) throws ArrayIndexOutOfBoundsException, SecurityException { 20 | if (length != aid.length) 21 | return false; 22 | return Util.arrayCompare(bArray, offset, aid, (short) 0, length) == 0; 23 | } 24 | 25 | public final boolean partialEquals(byte bArray[], short offset, byte length) throws ArrayIndexOutOfBoundsException, SecurityException { 26 | if (length > aid.length) { 27 | return false; 28 | } 29 | return Util.arrayCompare(bArray, offset, aid, (short) 0, length) == 0; 30 | } 31 | 32 | public final byte getPartialBytes(short aidOffset, byte dest[], short oOffset, byte oLength) throws NullPointerException, ArrayIndexOutOfBoundsException, SecurityException { 33 | byte len = oLength; 34 | if (oLength == 0) { 35 | len = (byte) (aid.length - aidOffset); 36 | } 37 | Util.arrayCopy(aid, aidOffset, dest, oOffset, len); 38 | return len; 39 | } 40 | 41 | public final boolean RIDEquals(AID otherAID) throws SecurityException { 42 | if (otherAID == null) { 43 | return false; 44 | } 45 | return Util.arrayCompare(aid, (short) 0, otherAID.aid, (short) 0, (short) 5) == 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/javacard/framework/APDU.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | 4 | public final class APDU extends pro.javacard.vre.vAPDU { 5 | 6 | public static final byte STATE_INITIAL = 0; 7 | public static final byte STATE_PARTIAL_INCOMING = 1; 8 | public static final byte STATE_FULL_INCOMING = 2; 9 | public static final byte STATE_OUTGOING = 3; 10 | public static final byte STATE_OUTGOING_LENGTH_KNOWN = 4; 11 | public static final byte STATE_PARTIAL_OUTGOING = 5; 12 | public static final byte STATE_FULL_OUTGOING = 6; 13 | public static final byte STATE_ERROR_NO_T0_GETRESPONSE = -1; 14 | public static final byte STATE_ERROR_T1_IFD_ABORT = -2; 15 | public static final byte STATE_ERROR_IO = -3; 16 | public static final byte STATE_ERROR_NO_T0_REISSUE = -4; 17 | public static final byte PROTOCOL_MEDIA_MASK = (byte) 0xF0; 18 | public static final byte PROTOCOL_TYPE_MASK = (byte) 0x0F; 19 | public static final byte PROTOCOL_T0 = 0; 20 | public static final byte PROTOCOL_T1 = 1; 21 | public static final byte PROTOCOL_MEDIA_DEFAULT = 0; 22 | public static final byte PROTOCOL_MEDIA_CONTACTLESS_TYPE_A = (byte) 0x80; 23 | public static final byte PROTOCOL_MEDIA_CONTACTLESS_TYPE_B = (byte) 0x90; 24 | public static final byte PROTOCOL_MEDIA_USB = (byte) 0xA0; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/javacard/framework/APDUException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class APDUException extends CardRuntimeException { 7 | 8 | public static final short ILLEGAL_USE = 1; 9 | public static final short BUFFER_BOUNDS = 2; 10 | public static final short BAD_LENGTH = 3; 11 | public static final short IO_ERROR = 4; 12 | public static final short NO_T0_GETRESPONSE = 170; 13 | public static final short T1_IFD_ABORT = 171; 14 | public static final short NO_T0_REISSUE = 172; 15 | 16 | public APDUException(short reason) { 17 | super(reason); 18 | } 19 | 20 | public static void throwIt(short reason) throws APDUException { 21 | if (VRE.debugMode) 22 | throw new APDUException(reason); 23 | VRE.vAPDUException.setReason(reason); 24 | throw VRE.vAPDUException; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/javacard/framework/Applet.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | public abstract class Applet { 6 | 7 | protected Applet() { 8 | } 9 | 10 | public static void install(byte bArray[], short bOffset, byte bLength) throws ISOException { 11 | ISOException.throwIt(ISO7816.SW_FUNC_NOT_SUPPORTED); 12 | } 13 | 14 | public abstract void process(APDU apdu) throws ISOException; 15 | 16 | public boolean select() { 17 | return true; 18 | } 19 | 20 | public void deselect() { 21 | } 22 | 23 | public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) { 24 | return null; 25 | } 26 | 27 | protected final void register() throws SystemException { 28 | VRE.getInstance().register(this); 29 | } 30 | 31 | protected final void register(byte bArray[], short bOffset, byte bLength) throws SystemException { 32 | VRE.getInstance().register(this, bArray, bOffset, bLength); 33 | } 34 | 35 | protected final boolean selectingApplet() { 36 | return false; // FIXME 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/javacard/framework/AppletEvent.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public interface AppletEvent { 4 | void uninstall(); 5 | } 6 | -------------------------------------------------------------------------------- /src/javacard/framework/CardException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class CardException extends Exception { 7 | 8 | private short reason; 9 | 10 | public CardException(short reason) { 11 | this.reason = reason; 12 | } 13 | 14 | public short getReason() { 15 | return reason; 16 | } 17 | 18 | public void setReason(short reason) { 19 | this.reason = reason; 20 | } 21 | 22 | public static void throwIt(short reason) throws CardException { 23 | if (VRE.debugMode) 24 | throw new CardException(reason); 25 | VRE.vCardException.setReason(reason); 26 | throw VRE.vCardException; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/javacard/framework/CardRuntimeException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class CardRuntimeException extends RuntimeException { 7 | 8 | private short reason; 9 | 10 | public CardRuntimeException(short reason) { 11 | this.reason = reason; 12 | } 13 | 14 | public short getReason() { 15 | return this.reason; 16 | } 17 | 18 | public void setReason(short reason) { 19 | this.reason = reason; 20 | } 21 | 22 | public static void throwIt(short reason) throws CardRuntimeException { 23 | if (VRE.debugMode) 24 | throw new CardRuntimeException(reason); 25 | VRE.vCardRuntimeException.setReason(reason); 26 | throw VRE.vCardRuntimeException; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/javacard/framework/ISO7816.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public interface ISO7816 { 4 | short SW_NO_ERROR = (short) 0x9000; 5 | short SW_BYTES_REMAINING_00 = (short) 0x6100; 6 | short SW_WRONG_LENGTH = (short) 0x6700; 7 | short SW_SECURITY_STATUS_NOT_SATISFIED = (short) 0x6982; 8 | short SW_FILE_INVALID = (short) 0x6983; 9 | short SW_DATA_INVALID = (short) 0x6984; 10 | short SW_CONDITIONS_NOT_SATISFIED = (short) 0x6985; 11 | short SW_COMMAND_NOT_ALLOWED = (short) 0x6986; 12 | short SW_APPLET_SELECT_FAILED = (short) 0x6999; 13 | short SW_WRONG_DATA = (short) 0x6700; 14 | short SW_FUNC_NOT_SUPPORTED = 0x6A81; 15 | short SW_FILE_NOT_FOUND = 0x6A82; 16 | short SW_RECORD_NOT_FOUND = 0x6A83; 17 | short SW_INCORRECT_P1P2 = 0x6A86; 18 | short SW_WRONG_P1P2 = 0x6B00; 19 | short SW_CORRECT_LENGTH_00 = 0x6C00; 20 | short SW_INS_NOT_SUPPORTED = 0x6D00; 21 | short SW_CLA_NOT_SUPPORTED = 0x6E00; 22 | short SW_UNKNOWN = 0x6F00; 23 | short SW_FILE_FULL = 0x6A84; 24 | short SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881; 25 | short SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882; 26 | short SW_WARNING_STATE_UNCHANGED = 0x6200; 27 | byte OFFSET_CLA = 0; 28 | byte OFFSET_INS = 1; 29 | byte OFFSET_P1 = 2; 30 | byte OFFSET_P2 = 3; 31 | byte OFFSET_LC = 4; 32 | byte OFFSET_CDATA = 5; 33 | byte OFFSET_EXT_CDATA = 7; 34 | byte CLA_ISO7816 = 0x00; 35 | byte INS_SELECT = (byte) 0xA4; 36 | byte INS_EXTERNAL_AUTHENTICATE = (byte) 0x82; 37 | } 38 | -------------------------------------------------------------------------------- /src/javacard/framework/ISOException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class ISOException extends CardRuntimeException { 7 | 8 | public ISOException(short sw) { 9 | super(sw); 10 | } 11 | 12 | public static void throwIt(short sw) throws ISOException { 13 | if (VRE.debugMode) 14 | throw new ISOException(sw); 15 | VRE.vISOException.setReason(sw); 16 | throw VRE.vISOException; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/javacard/framework/JCSystem.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | public final class JCSystem extends VRE { 6 | public static final byte MEMORY_TYPE_PERSISTENT = 0; 7 | public static final byte MEMORY_TYPE_TRANSIENT_RESET = 1; 8 | public static final byte MEMORY_TYPE_TRANSIENT_DESELECT = 2; 9 | public static final byte NOT_A_TRANSIENT_OBJECT = 0; 10 | public static final byte CLEAR_ON_RESET = 1; 11 | public static final byte CLEAR_ON_DESELECT = 2; 12 | } 13 | -------------------------------------------------------------------------------- /src/javacard/framework/MultiSelectable.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public interface MultiSelectable { 4 | boolean select(boolean appInstAlreadyActive); 5 | void deselect(boolean appInstStillActive); 6 | } 7 | -------------------------------------------------------------------------------- /src/javacard/framework/OwnerPIN.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public class OwnerPIN implements PIN { 4 | private byte remaining = 0; 5 | private byte limit = 0; 6 | private byte[] value; 7 | private transient boolean validated = false; 8 | 9 | public OwnerPIN(byte tryLimit, byte maxPINSize) { 10 | value = new byte[1+maxPINSize]; 11 | } 12 | public byte getTriesRemaining() { 13 | return remaining; 14 | } 15 | 16 | public boolean check(byte[] pin, short offset, byte length) throws ArrayIndexOutOfBoundsException, NullPointerException { 17 | if (remaining == 0) 18 | return false; 19 | remaining = (byte) (remaining - 1); 20 | setValidatedFlag(false); 21 | 22 | if (value[0] != length) 23 | return false; 24 | 25 | if (Util.arrayCompare(pin, (short) 0, value, (short) 1, length) == 0) { 26 | setValidatedFlag(true); 27 | remaining = (byte) (remaining + 1); // Restore 28 | return true; 29 | } 30 | return false; 31 | } 32 | 33 | public boolean isValidated() { 34 | return validated; 35 | } 36 | 37 | protected boolean getValidatedFlag() { 38 | return validated; 39 | } 40 | 41 | protected void setValidatedFlag(boolean value) { 42 | validated = false; 43 | } 44 | 45 | public void reset() { 46 | if (getValidatedFlag()) { 47 | setValidatedFlag(false); 48 | remaining = limit; 49 | } 50 | } 51 | public void update(byte[] pin, short offset, byte length) throws PINException { 52 | if (length > value.length + 1) 53 | PINException.throwIt(PINException.ILLEGAL_VALUE); 54 | value[0] = length; 55 | Util.arrayCopy(pin, (short)0, value, (short)1, length); 56 | setValidatedFlag(false); 57 | } 58 | 59 | public void resetAndUnblock() { 60 | setValidatedFlag(false); 61 | remaining = limit; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/javacard/framework/PIN.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public interface PIN { 4 | byte getTriesRemaining(); 5 | boolean check(byte pin[], short offset, byte length) throws ArrayIndexOutOfBoundsException, NullPointerException; 6 | boolean isValidated(); 7 | void reset(); 8 | } 9 | -------------------------------------------------------------------------------- /src/javacard/framework/PINException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class PINException extends CardRuntimeException { 7 | 8 | public static final short ILLEGAL_VALUE = 1; 9 | 10 | public PINException(short reason) { 11 | super(reason); 12 | } 13 | 14 | public static void throwIt(short reason) throws PINException { 15 | if (VRE.debugMode) 16 | throw new PINException(reason); 17 | VRE.vPINException.setReason(reason); 18 | throw VRE.vPINException; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/javacard/framework/Shareable.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | public interface Shareable { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/javacard/framework/SystemException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class SystemException extends CardRuntimeException { 7 | 8 | public static final short ILLEGAL_VALUE = 1; 9 | public static final short NO_TRANSIENT_SPACE = 2; 10 | public static final short ILLEGAL_TRANSIENT = 3; 11 | public static final short ILLEGAL_AID = 4; 12 | public static final short NO_RESOURCE = 5; 13 | public static final short ILLEGAL_USE = 6; 14 | 15 | public SystemException(short reason) { 16 | super(reason); 17 | } 18 | 19 | public static void throwIt(short reason) throws SystemException { 20 | if (VRE.debugMode) 21 | throw new SystemException(reason); 22 | VRE.vSystemException.setReason(reason); 23 | throw VRE.vSystemException; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/javacard/framework/TransactionException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class TransactionException extends CardRuntimeException { 7 | public static final short IN_PROGRESS = 1; 8 | public static final short NOT_IN_PROGRESS = 2; 9 | public static final short BUFFER_FULL = 3; 10 | public static final short INTERNAL_FAILURE = 4; 11 | 12 | public TransactionException(short reason) { 13 | super(reason); 14 | } 15 | 16 | public static void throwIt(short reason) throws TransactionException { 17 | if (VRE.debugMode) 18 | throw new TransactionException(reason); 19 | VRE.vTransactionException.setReason(reason); 20 | throw VRE.vTransactionException; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/javacard/framework/UserException.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.VRE; 4 | 5 | @SuppressWarnings("serial") 6 | public class UserException extends CardException { 7 | 8 | public UserException(short reason) { 9 | super(reason); 10 | } 11 | 12 | public static void throwIt(short reason) throws UserException { 13 | if (VRE.debugMode) 14 | throw new UserException(reason); 15 | VRE.vUserException.setReason(reason); 16 | throw VRE.vUserException; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/javacard/framework/Util.java: -------------------------------------------------------------------------------- 1 | package javacard.framework; 2 | 3 | import pro.javacard.vre.Misc; 4 | 5 | public class Util { 6 | 7 | public static final short arrayCopy(byte src[], short srcOff, byte dest[], short destOff, short length) throws ArrayIndexOutOfBoundsException, NullPointerException, TransactionException { 8 | return arrayCopyNonAtomic(src, srcOff, dest, destOff, length); 9 | } 10 | 11 | public static final short arrayCopyNonAtomic(byte src[], short srcOff, byte dest[], short destOff, short length) throws ArrayIndexOutOfBoundsException, NullPointerException { 12 | System.arraycopy(src, srcOff, dest, destOff, length); 13 | return (short) (destOff + length); 14 | } 15 | 16 | public static final short arrayFillNonAtomic(byte bArray[], short bOff, short bLen, byte bValue) throws ArrayIndexOutOfBoundsException, NullPointerException { 17 | for (short i=0; i (short) (dest[destOff + i] & 0x00ff) ? 1 : -1); 34 | } 35 | } 36 | return 0; 37 | } 38 | 39 | public static final short makeShort(byte b1, byte b2) { 40 | return (short) (((short) b1 << 8) + ((short) b2 & 0xff)); 41 | } 42 | 43 | public static final short getShort(byte bArray[], short bOff) throws ArrayIndexOutOfBoundsException, NullPointerException { 44 | return (short) (((short) bArray[bOff] << 8) + ((short) bArray[bOff + 1] & 0xff)); 45 | } 46 | 47 | public static final short setShort(byte bArray[], short bOff, short sValue) throws TransactionException, ArrayIndexOutOfBoundsException, NullPointerException { 48 | bArray[bOff] = (byte) (sValue >> 8); 49 | bArray[bOff + 1] = (byte) sValue; 50 | return (short) (bOff + 2); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/javacard/security/AESKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface AESKey extends SecretKey { 4 | void setKey(byte[] keyData, short kOff) throws CryptoException, NullPointerException, ArrayIndexOutOfBoundsException; 5 | byte getKey(byte[] keyData, short kOff) throws CryptoException; 6 | } -------------------------------------------------------------------------------- /src/javacard/security/Checksum.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vChecksum; 4 | 5 | public abstract class Checksum { 6 | public static final byte ALG_ISO3309_CRC16 = 1; 7 | public static final byte ALG_ISO3309_CRC32 = 2; 8 | 9 | protected Checksum() {} 10 | public abstract byte getAlgorithm(); 11 | public abstract void init(byte bArray[], short bOff, short bLen) throws CryptoException; 12 | public abstract short doFinal(byte inBuff[], short inOffset, short inLength, byte outBuff[], short outOffset); 13 | public abstract void update(byte inBuff[], short inOffset, short inLength); 14 | 15 | public static final Checksum getInstance(byte algorithm, boolean externalAccess) throws CryptoException { 16 | if (externalAccess) { 17 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 18 | } 19 | return new vChecksum(algorithm); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/javacard/security/CryptoException.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import javacard.framework.CardRuntimeException; 4 | import pro.javacard.vre.VRE; 5 | 6 | @SuppressWarnings("serial") 7 | public class CryptoException extends CardRuntimeException { 8 | 9 | public static final short ILLEGAL_VALUE = 1; 10 | public static final short UNINITIALIZED_KEY = 2; 11 | public static final short NO_SUCH_ALGORITHM = 3; 12 | public static final short INVALID_INIT = 4; 13 | public static final short ILLEGAL_USE = 5; 14 | 15 | public CryptoException(short reason) { 16 | super(reason); 17 | } 18 | 19 | public static void throwIt(short reason) { 20 | if (VRE.debugMode) 21 | throw new CryptoException(reason); 22 | VRE.vCryptoException.setReason(reason); 23 | throw VRE.vCryptoException; 24 | } 25 | } -------------------------------------------------------------------------------- /src/javacard/security/DESKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface DESKey extends SecretKey { 4 | void setKey(byte[] keyData, short kOff) throws CryptoException, NullPointerException, ArrayIndexOutOfBoundsException; 5 | byte getKey(byte[] keyData, short kOff) throws CryptoException; 6 | } -------------------------------------------------------------------------------- /src/javacard/security/DSAKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface DSAKey { 4 | void setP(byte[] buffer, short offset, short length) throws CryptoException; 5 | void setQ(byte[] buffer, short offset, short length) throws CryptoException; 6 | void setG(byte[] buffer, short offset, short length) throws CryptoException; 7 | short getP(byte[] buffer, short offset) throws CryptoException; 8 | short getQ(byte[] buffer, short offset) throws CryptoException; 9 | short getG(byte[] buffer, short offset) throws CryptoException; 10 | } -------------------------------------------------------------------------------- /src/javacard/security/DSAPrivateKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface DSAPrivateKey extends PrivateKey, DSAKey { 4 | void setX(byte[] buffer, short offset, short length) throws CryptoException; 5 | short getX(byte[] buffer, short offset) throws CryptoException; 6 | } -------------------------------------------------------------------------------- /src/javacard/security/DSAPublicKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface DSAPublicKey extends PublicKey, DSAKey { 4 | void setY(byte[] buffer, short offset, short length) throws CryptoException; 5 | short getY(byte[] buffer, short offset) throws CryptoException; 6 | } -------------------------------------------------------------------------------- /src/javacard/security/ECKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface ECKey { 4 | void setFieldFP(byte[] buffer, short offset, short length) throws CryptoException; 5 | void setFieldF2M(short e) throws CryptoException; 6 | void setFieldF2M(short e1, short e2, short e3) throws CryptoException; 7 | void setA(byte[] buffer, short offset, short length) throws CryptoException; 8 | void setB(byte[] buffer, short offset, short length) throws CryptoException; 9 | void setG(byte[] buffer, short offset, short length) throws CryptoException; 10 | void setR(byte[] buffer, short offset, short length) throws CryptoException; 11 | void setK(short K); 12 | short getField(byte[] buffer, short offset) throws CryptoException; 13 | short getA(byte[] buffer, short offset) throws CryptoException; 14 | short getB(byte[] buffer, short offset) throws CryptoException; 15 | short getG(byte[] buffer, short offset) throws CryptoException; 16 | short getR(byte[] buffer, short offset) throws CryptoException; 17 | short getK() throws CryptoException; 18 | } 19 | -------------------------------------------------------------------------------- /src/javacard/security/ECPrivateKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface ECPrivateKey extends PrivateKey, ECKey { 4 | void setS(byte[] buffer, short offset, short length) throws CryptoException; 5 | short getS(byte[] buffer, short offset) throws CryptoException; 6 | } 7 | -------------------------------------------------------------------------------- /src/javacard/security/ECPublicKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface ECPublicKey extends PublicKey, ECKey { 4 | void setW(byte[] buffer, short offset, short length) throws CryptoException; 5 | short getW(byte[] buffer, short offset) throws CryptoException; 6 | } -------------------------------------------------------------------------------- /src/javacard/security/HMACKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface HMACKey extends SecretKey { 4 | byte getKey(byte[] keyData, short kOff); 5 | void setKey(byte[] keyData, short kOff, short kLen) throws CryptoException, NullPointerException, ArrayIndexOutOfBoundsException; 6 | } 7 | -------------------------------------------------------------------------------- /src/javacard/security/InitializedMessageDigest.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public abstract class InitializedMessageDigest extends MessageDigest { 4 | abstract void setInitialDigest(byte[] initialDigestBuf, short initialDigestOffset, short initialDigestLength, byte[] digestedMsgLenBuf, short digestedMsgLenOffset, short digestedMsgLenLength) throws CryptoException; 5 | } 6 | -------------------------------------------------------------------------------- /src/javacard/security/Key.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface Key { 4 | void clearKey(); 5 | short getSize(); 6 | byte getType(); 7 | boolean isInitialized(); 8 | } 9 | -------------------------------------------------------------------------------- /src/javacard/security/KeyAgreement.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vKeyAgreement; 4 | 5 | public abstract class KeyAgreement { 6 | public static final byte ALG_EC_SVDP_DH = 1; 7 | public static final byte ALG_EC_SVDP_DHC = 2; 8 | // 3.0.1 9 | public static final byte ALG_EC_SVDP_DH_KDF = 1; 10 | public static final byte ALG_EC_SVDP_DH_PLAIN = 3; 11 | public static final byte ALG_EC_SVDP_DHC_KDF = 2; 12 | public static final byte ALG_EC_SVDP_DHC_PLAIN = 4; 13 | 14 | protected KeyAgreement() {} 15 | public abstract void init(PrivateKey privateKey) throws CryptoException; 16 | public abstract byte getAlgorithm(); 17 | public abstract short generateSecret(byte[] publicData, short publicOffset, short publicLength, byte[] secret, short secretOffset) throws CryptoException; 18 | public static final KeyAgreement getInstance(byte algorithm, boolean externalAccess) throws CryptoException { 19 | if (externalAccess) 20 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 21 | return new vKeyAgreement(algorithm); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/javacard/security/KeyBuilder.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vKey; 4 | 5 | public final class KeyBuilder { 6 | 7 | public static final byte TYPE_DES_TRANSIENT_RESET = 1; 8 | public static final byte TYPE_DES_TRANSIENT_DESELECT = 2; 9 | public static final byte TYPE_DES = 3; 10 | public static final byte TYPE_RSA_PUBLIC = 4; 11 | public static final byte TYPE_RSA_PRIVATE = 5; 12 | public static final byte TYPE_RSA_CRT_PRIVATE = 6; 13 | public static final byte TYPE_DSA_PUBLIC = 7; 14 | public static final byte TYPE_DSA_PRIVATE = 8; 15 | public static final byte TYPE_EC_F2M_PUBLIC = 9; 16 | public static final byte TYPE_EC_F2M_PRIVATE = 10; 17 | public static final byte TYPE_EC_FP_PUBLIC = 11; 18 | public static final byte TYPE_EC_FP_PRIVATE = 12; 19 | public static final byte TYPE_AES_TRANSIENT_RESET = 13; 20 | public static final byte TYPE_AES_TRANSIENT_DESELECT = 14; 21 | public static final byte TYPE_AES = 15; 22 | public static final byte TYPE_KOREAN_SEED_TRANSIENT_RESET = 16; 23 | public static final byte TYPE_KOREAN_SEED_TRANSIENT_DESELECT = 17; 24 | public static final byte TYPE_KOREAN_SEED = 18; 25 | public static final byte TYPE_HMAC_TRANSIENT_RESET = 19; 26 | public static final byte TYPE_HMAC_TRANSIENT_DESELECT = 20; 27 | public static final byte TYPE_HMAC = 21; 28 | // 3.0.1 29 | public static final byte TYPE_RSA_PRIVATE_TRANSIENT_RESET = 22; 30 | public static final byte TYPE_RSA_PRIVATE_TRANSIENT_DESELECT = 23; 31 | public static final byte TYPE_RSA_CRT_PRIVATE_TRANSIENT_RESET = 24; 32 | public static final byte TYPE_RSA_CRT_PRIVATE_TRANSIENT_DESELECT = 25; 33 | public static final byte TYPE_DSA_PRIVATE_TRANSIENT_RESET = 26; 34 | public static final byte TYPE_DSA_PRIVATE_TRANSIENT_DESELECT = 27; 35 | public static final byte TYPE_EC_F2M_PRIVATE_TRANSIENT_RESET = 28; 36 | public static final byte TYPE_EC_F2M_PRIVATE_TRANSIENT_DESELECT = 29; 37 | public static final byte TYPE_EC_FP_PRIVATE_TRANSIENT_RESET = 30; 38 | public static final byte TYPE_EC_FP_PRIVATE_TRANSIENT_DESELECT = 31; 39 | 40 | public static final short LENGTH_DES = 64; 41 | public static final short LENGTH_DES3_2KEY = 128; 42 | public static final short LENGTH_DES3_3KEY = 192; 43 | public static final short LENGTH_RSA_512 = 512; 44 | public static final short LENGTH_RSA_736 = 736; 45 | public static final short LENGTH_RSA_768 = 768; 46 | public static final short LENGTH_RSA_896 = 896; 47 | public static final short LENGTH_RSA_1024 = 1024; 48 | public static final short LENGTH_RSA_1280 = 1280; 49 | public static final short LENGTH_RSA_1536 = 1536; 50 | public static final short LENGTH_RSA_1984 = 1984; 51 | public static final short LENGTH_RSA_2048 = 2048; 52 | public static final short LENGTH_DSA_512 = 512; 53 | public static final short LENGTH_DSA_768 = 768; 54 | public static final short LENGTH_DSA_1024 = 1024; 55 | public static final short LENGTH_EC_FP_112 = 112; 56 | public static final short LENGTH_EC_F2M_113 = 113; 57 | public static final short LENGTH_EC_FP_128 = 128; 58 | public static final short LENGTH_EC_F2M_131 = 131; 59 | public static final short LENGTH_EC_FP_160 = 160; 60 | public static final short LENGTH_EC_F2M_163 = 163; 61 | public static final short LENGTH_EC_FP_192 = 192; 62 | public static final short LENGTH_EC_F2M_193 = 193; 63 | public static final short LENGTH_AES_128 = 128; 64 | public static final short LENGTH_AES_192 = 192; 65 | public static final short LENGTH_AES_256 = 256; 66 | public static final short LENGTH_HMAC_SHA_1_BLOCK_64 = 64; 67 | public static final short LENGTH_HMAC_SHA_256_BLOCK_64 = 64; 68 | public static final short LENGTH_HMAC_SHA_384_BLOCK_128 = 128; 69 | public static final short LENGTH_HMAC_SHA_512_BLOCK_128 = 128; 70 | public static final short LENGTH_KOREAN_SEED_128 = 128; 71 | // 3.0.1 72 | public static final short LENGTH_EC_FP_224 = 224; 73 | public static final short LENGTH_EC_FP_256 = 256; 74 | public static final short LENGTH_EC_FP_384 = 384; 75 | public static final short LENGTH_RSA_3072 = 3072; 76 | public static final short LENGTH_RSA_4096 = 4096; 77 | // 3.0.4 78 | public static final short LENGTH_EC_FP_521 = 521; 79 | 80 | // 3.0.4 81 | public static final byte ALG_TYPE_DES = 1; 82 | public static final byte ALG_TYPE_AES = 2; 83 | public static final byte ALG_TYPE_DSA_PUBLIC = 3; 84 | public static final byte ALG_TYPE_DSA_PRIVATE = 4; 85 | public static final byte ALG_TYPE_EC_F2M_PUBLIC = 5; 86 | public static final byte ALG_TYPE_EC_F2M_PRIVATE = 6; 87 | public static final byte ALG_TYPE_EC_FP_PUBLIC = 7; 88 | public static final byte ALG_TYPE_EC_FP_PRIVATE = 8; 89 | public static final byte ALG_TYPE_HMAC = 9; 90 | public static final byte ALG_TYPE_KOREAN_SEED = 10; 91 | public static final byte ALG_TYPE_RSA_PUBLIC = 11; 92 | public static final byte ALG_TYPE_RSA_PRIVATE = 12; 93 | public static final byte ALG_TYPE_RSA_CRT_PRIVATE = 13; 94 | 95 | public static Key buildKey(byte keyType, short keyLength, boolean keyEncryption) throws CryptoException { 96 | if (keyEncryption) 97 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 98 | return vKey.buildKey(keyType, keyLength); 99 | } 100 | // 3.0.4 101 | public static Key buildKey(byte algorithmicKeyType, byte keyMemoryType, short keyLength, boolean keyEncryption) throws CryptoException { 102 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 103 | return null; 104 | } 105 | } -------------------------------------------------------------------------------- /src/javacard/security/KeyPair.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vKeyPair; 4 | 5 | public final class KeyPair extends vKeyPair { 6 | public static final byte ALG_RSA = 1; 7 | public static final byte ALG_RSA_CRT = 2; 8 | public static final byte ALG_DSA = 3; 9 | public static final byte ALG_EC_F2M = 4; 10 | public static final byte ALG_EC_FP = 5; 11 | 12 | public KeyPair(byte algorithm, short keyLength) { 13 | super(algorithm, keyLength); 14 | } 15 | 16 | public KeyPair(PublicKey publicKey, PrivateKey privateKey) { 17 | super(publicKey, privateKey); 18 | } 19 | } -------------------------------------------------------------------------------- /src/javacard/security/KoreanSEEDKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface KoreanSEEDKey extends SecretKey { 4 | byte getKey(byte[] keyData, short kOff); 5 | void setKey(byte[] keyData, short kOff); 6 | } 7 | -------------------------------------------------------------------------------- /src/javacard/security/MessageDigest.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vMessageDigest; 4 | 5 | public abstract class MessageDigest { 6 | public static final byte ALG_NULL = 0; // 3.0.1 7 | public static final byte ALG_SHA = 1; 8 | public static final byte ALG_MD5 = 2; 9 | public static final byte ALG_RIPEMD160 = 3; 10 | public static final byte ALG_SHA_256 = 4; 11 | public static final byte ALG_SHA_384 = 5; 12 | public static final byte ALG_SHA_512 = 6; 13 | public static final byte ALG_SHA_224 = 7; // 3.0.1 14 | public static final byte LENGTH_MD5 = 16; 15 | public static final byte LENGTH_RIPEMD160 = 20; 16 | public static final byte LENGTH_SHA = 20; 17 | public static final byte LENGTH_SHA_256 = 32; 18 | public static final byte LENGTH_SHA_384 = 48; 19 | public static final byte LENGTH_SHA_512 = 64; 20 | public static final byte LENGTH_SHA_224 = 28; // 3.0.1 21 | 22 | 23 | protected MessageDigest() {} 24 | public abstract byte getAlgorithm(); 25 | public abstract byte getLength(); 26 | public abstract short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset); 27 | public abstract void update(byte[] inBuff, short inOffset, short inLength); 28 | public abstract void reset(); 29 | 30 | public static final InitializedMessageDigest getInitializedMessageDigestInstance(byte algorithm, boolean externalAccess) throws CryptoException { 31 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 32 | return null; 33 | } 34 | 35 | public static final MessageDigest getInstance(byte algorithm, boolean externalAccess) throws CryptoException { 36 | if (externalAccess) { 37 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 38 | } 39 | return new vMessageDigest(algorithm); 40 | } 41 | } -------------------------------------------------------------------------------- /src/javacard/security/PrivateKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface PrivateKey extends Key { 4 | } -------------------------------------------------------------------------------- /src/javacard/security/PublicKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface PublicKey extends Key { 4 | } -------------------------------------------------------------------------------- /src/javacard/security/RSAPrivateCrtKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface RSAPrivateCrtKey extends PrivateKey { 4 | void setP(byte[] buffer, short offset, short length) throws CryptoException; 5 | void setQ(byte[] buffer, short offset, short length) throws CryptoException; 6 | void setDP1(byte[] buffer, short offset, short length) throws CryptoException; 7 | void setDQ1(byte[] buffer, short offset, short length) throws CryptoException; 8 | void setPQ(byte[] buffer, short offset, short length) throws CryptoException; 9 | short getP(byte[] buffer, short offset) throws CryptoException; 10 | short getQ(byte[] buffer, short offset) throws CryptoException; 11 | short getDP1(byte[] buffer, short offset) throws CryptoException; 12 | short getDQ1(byte[] buffer, short offset) throws CryptoException; 13 | short getPQ(byte[] buffer, short offset) throws CryptoException; 14 | } -------------------------------------------------------------------------------- /src/javacard/security/RSAPrivateKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface RSAPrivateKey extends PrivateKey { 4 | short getExponent(byte[] buffer, short offset) throws CryptoException; 5 | short getModulus(byte[] buffer, short offset) throws CryptoException; 6 | void setExponent(byte[] buffer, short offset, short length) throws CryptoException; 7 | void setModulus(byte[] buffer, short offset, short length) throws CryptoException; 8 | } 9 | -------------------------------------------------------------------------------- /src/javacard/security/RSAPublicKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface RSAPublicKey extends PublicKey { 4 | short getExponent(byte[] buffer, short offset) throws CryptoException; 5 | short getModulus(byte[] buffer, short offset) throws CryptoException; 6 | void setExponent(byte[] buffer, short offset, short length) throws CryptoException; 7 | void setModulus(byte[] buffer, short offset, short length) throws CryptoException; 8 | } -------------------------------------------------------------------------------- /src/javacard/security/RandomData.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vRandomData; 4 | 5 | public abstract class RandomData { 6 | public static final byte ALG_PSEUDO_RANDOM = 1; 7 | public static final byte ALG_SECURE_RANDOM = 2; 8 | 9 | protected RandomData() {} 10 | public abstract void generateData(byte[] buffer, short offset, short length) throws CryptoException; 11 | public abstract void setSeed(byte[] buffer, short offset, short length); 12 | 13 | public static final RandomData getInstance(byte algorithm) throws CryptoException { 14 | return new vRandomData(algorithm); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/javacard/security/SecretKey.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface SecretKey extends Key { 4 | } -------------------------------------------------------------------------------- /src/javacard/security/Signature.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | import pro.javacard.vre.vSignature; 4 | 5 | public abstract class Signature { 6 | 7 | public static final byte ALG_DES_MAC4_NOPAD = 1; 8 | public static final byte ALG_DES_MAC8_NOPAD = 2; 9 | public static final byte ALG_DES_MAC4_ISO9797_M1 = 3; 10 | public static final byte ALG_DES_MAC8_ISO9797_M1 = 4; 11 | public static final byte ALG_DES_MAC4_ISO9797_M2 = 5; 12 | public static final byte ALG_DES_MAC8_ISO9797_M2 = 6; 13 | public static final byte ALG_DES_MAC4_PKCS5 = 7; 14 | public static final byte ALG_DES_MAC8_PKCS5 = 8; 15 | public static final byte ALG_RSA_SHA_ISO9796 = 9; 16 | public static final byte ALG_RSA_SHA_PKCS1 = 10; 17 | public static final byte ALG_RSA_MD5_PKCS1 = 11; 18 | public static final byte ALG_RSA_RIPEMD160_ISO9796 = 12; 19 | public static final byte ALG_RSA_RIPEMD160_PKCS1 = 13; 20 | public static final byte ALG_DSA_SHA = 14; 21 | public static final byte ALG_RSA_SHA_RFC2409 = 15; 22 | public static final byte ALG_RSA_MD5_RFC2409 = 16; 23 | public static final byte ALG_ECDSA_SHA = 17; 24 | public static final byte ALG_AES_MAC_128_NOPAD = 18; 25 | public static final byte ALG_DES_MAC4_ISO9797_1_M2_ALG3 = 19; 26 | public static final byte ALG_DES_MAC8_ISO9797_1_M2_ALG3 = 20; 27 | public static final byte ALG_RSA_SHA_PKCS1_PSS = 21; 28 | public static final byte ALG_RSA_MD5_PKCS1_PSS = 22; 29 | public static final byte ALG_RSA_RIPEMD160_PKCS1_PSS = 23; 30 | public static final byte ALG_HMAC_SHA1 = 24; 31 | public static final byte ALG_HMAC_SHA_256 = 25; 32 | public static final byte ALG_HMAC_SHA_384 = 26; 33 | public static final byte ALG_HMAC_SHA_512 = 27; 34 | public static final byte ALG_HMAC_MD5 = 28; 35 | public static final byte ALG_HMAC_RIPEMD160 = 29; 36 | public static final byte ALG_RSA_SHA_ISO9796_MR = 30; 37 | public static final byte ALG_RSA_RIPEMD160_ISO9796_MR = 31; 38 | public static final byte ALG_KOREAN_SEED_MAC_NOPAD = 32; 39 | 40 | // 3.0.1 41 | public static final byte ALG_ECDSA_SHA_256 = 33; 42 | public static final byte ALG_ECDSA_SHA_384 = 34; 43 | public static final byte ALG_AES_MAC_192_NOPAD = 35; 44 | public static final byte ALG_AES_MAC_256_NOPAD = 36; 45 | public static final byte ALG_ECDSA_SHA_224 = 37; 46 | public static final byte ALG_ECDSA_SHA_512 = 38; 47 | public static final byte ALG_RSA_SHA_224_PKCS1 = 39; 48 | public static final byte ALG_RSA_SHA_256_PKCS1 = 40; 49 | public static final byte ALG_RSA_SHA_384_PKCS1 = 41; 50 | public static final byte ALG_RSA_SHA_512_PKCS1 = 42; 51 | public static final byte ALG_RSA_SHA_224_PKCS1_PSS = 43; 52 | public static final byte ALG_RSA_SHA_256_PKCS1_PSS = 44; 53 | public static final byte ALG_RSA_SHA_384_PKCS1_PSS = 45; 54 | public static final byte ALG_RSA_SHA_512_PKCS1_PSS = 46; 55 | 56 | // 3.0.4 57 | public static final byte ALG_DES_MAC4_ISO9797_1_M1_ALG3 = 47; 58 | public static final byte ALG_DES_MAC8_ISO9797_1_M1_ALG3 = 48; 59 | 60 | // 3.0.4 61 | public static final byte SIG_CIPHER_DES_MAC4 = 1; 62 | public static final byte SIG_CIPHER_DES_MAC8 = 2; 63 | public static final byte SIG_CIPHER_RSA = 3; 64 | public static final byte SIG_CIPHER_DSA = 4; 65 | public static final byte SIG_CIPHER_ECDSA = 5; 66 | public static final byte SIG_CIPHER_AES_MAC128 = 6; 67 | public static final byte SIG_CIPHER_HMAC = 7; 68 | public static final byte SIG_CIPHER_KOREAN_SEED_MAC = 8; 69 | 70 | public static final byte MODE_SIGN = 1; 71 | public static final byte MODE_VERIFY = 2; 72 | 73 | protected Signature() { } 74 | 75 | public abstract void init(Key theKey, byte theMode) throws CryptoException; 76 | public abstract void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException; 77 | public abstract short getLength() throws CryptoException; 78 | public abstract byte getAlgorithm(); 79 | public abstract void update(byte[] inBuff, short inOffset, short inLength) throws CryptoException; 80 | public abstract short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset) throws CryptoException; 81 | public abstract boolean verify(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset, short sigLength) throws CryptoException; 82 | public static final Signature getInstance(byte algorithm, boolean externalAccess) throws CryptoException { 83 | if (externalAccess) { 84 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 85 | } 86 | return new vSignature(algorithm); 87 | } 88 | // 3.0.4 89 | public static final Signature getInstance(byte messageDigestAlgorithm, byte cipherAlgorithm, byte paddingAlgorithm, boolean externalAccess) throws CryptoException { 90 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 91 | return null; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/javacard/security/SignatureMessageRecovery.java: -------------------------------------------------------------------------------- 1 | package javacard.security; 2 | 3 | public interface SignatureMessageRecovery { 4 | short beginVerify(byte[] sigAndRecDataBuff, short buffOffset, short sigLength) throws CryptoException; 5 | byte getAlgorithm(); 6 | short getLength() throws CryptoException; 7 | void init(Key theKey, byte theMode) throws CryptoException; 8 | short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset, short[] recMsgLen, short recMsgLenOffset) throws CryptoException; 9 | void update(byte[] inBuff, short inOffset, short inLength) throws CryptoException; 10 | boolean verify(byte[] inBuff, short inOffset, short inLength) throws CryptoException; 11 | } 12 | -------------------------------------------------------------------------------- /src/javacardx/apdu/ExtendedLength.java: -------------------------------------------------------------------------------- 1 | package javacardx.apdu; 2 | 3 | public interface ExtendedLength { 4 | } 5 | -------------------------------------------------------------------------------- /src/javacardx/crypto/Cipher.java: -------------------------------------------------------------------------------- 1 | package javacardx.crypto; 2 | 3 | import javacard.security.CryptoException; 4 | import javacard.security.Key; 5 | import pro.javacard.vre.vCipher; 6 | 7 | public abstract class Cipher { 8 | public static final byte ALG_DES_CBC_NOPAD = 1; 9 | public static final byte ALG_DES_CBC_ISO9797_M1 = 2; 10 | public static final byte ALG_DES_CBC_ISO9797_M2 = 3; 11 | public static final byte ALG_DES_CBC_PKCS5 = 4; 12 | public static final byte ALG_DES_ECB_NOPAD = 5; 13 | public static final byte ALG_DES_ECB_ISO9797_M1 = 6; 14 | public static final byte ALG_DES_ECB_ISO9797_M2 = 7; 15 | public static final byte ALG_DES_ECB_PKCS5 = 8; 16 | public static final byte ALG_RSA_ISO14888 = 9; 17 | public static final byte ALG_RSA_PKCS1 = 10; 18 | @Deprecated 19 | public static final byte ALG_RSA_ISO9796 = 11; 20 | public static final byte ALG_RSA_NOPAD = 12; 21 | public static final byte ALG_AES_BLOCK_128_CBC_NOPAD = 13; 22 | public static final byte ALG_AES_BLOCK_128_ECB_NOPAD = 14; 23 | public static final byte ALG_RSA_PKCS1_OAEP = 15; 24 | public static final byte ALG_KOREAN_SEED_ECB_NOPAD = 16; 25 | public static final byte ALG_KOREAN_SEED_CBC_NOPAD = 17; 26 | // 3.0.1 27 | public static final byte ALG_AES_BLOCK_192_CBC_NOPAD = 18; 28 | public static final byte ALG_AES_BLOCK_192_ECB_NOPAD = 19; 29 | public static final byte ALG_AES_BLOCK_256_CBC_NOPAD = 20; 30 | public static final byte ALG_AES_BLOCK_256_ECB_NOPAD = 21; 31 | public static final byte ALG_AES_CBC_ISO9797_M1 = 22; 32 | public static final byte ALG_AES_CBC_ISO9797_M2 = 23; 33 | public static final byte ALG_AES_CBC_PKCS5 = 24; 34 | public static final byte ALG_AES_ECB_ISO9797_M1 = 25; 35 | public static final byte ALG_AES_ECB_ISO9797_M2 = 26; 36 | public static final byte ALG_AES_ECB_PKCS5 = 27; 37 | public static final byte MODE_DECRYPT = 1; 38 | public static final byte MODE_ENCRYPT = 2; 39 | // 3.0.4 40 | public static final byte PAD_NULL = 0; 41 | public static final byte PAD_NOPAD = 1; 42 | public static final byte PAD_ISO9797_M1 = 2; 43 | public static final byte PAD_ISO9797_M2 = 3; 44 | public static final byte PAD_ISO9797_1_M1_ALG3 = 4; 45 | public static final byte PAD_ISO9797_1_M2_ALG3 = 5; 46 | public static final byte PAD_PKCS5 = 6; 47 | public static final byte PAD_PKCS1 = 7; 48 | public static final byte PAD_PKCS1_PSS = 8; 49 | public static final byte PAD_PKCS1_OAEP = 9; 50 | public static final byte PAD_ISO9796 = 10; 51 | public static final byte PAD_ISO9796_MR = 11; 52 | public static final byte PAD_RFC2409 = 12; 53 | 54 | 55 | protected Cipher() {} 56 | public abstract void init(Key theKey, byte theMode) throws CryptoException; 57 | public abstract void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException; 58 | public abstract byte getAlgorithm(); 59 | public abstract short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException; 60 | public abstract short update(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException; 61 | 62 | public static final Cipher getInstance(byte algorithm, boolean externalAccess) throws CryptoException { 63 | if (externalAccess) { 64 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 65 | } 66 | return new vCipher(algorithm); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/javacardx/crypto/KeyEncryption.java: -------------------------------------------------------------------------------- 1 | package javacardx.crypto; 2 | 3 | public interface KeyEncryption { 4 | void setKeyCipher(Cipher keyCipher); 5 | Cipher getKeyCipher(); 6 | } 7 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/Misc.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | public class Misc { 4 | private static final char[] LOWER_HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 5 | public static String encodeHexString(final byte[] data) { 6 | 7 | final int l = data.length; 8 | final char[] out = new char[l << 1]; 9 | // two characters form the hex value. 10 | for (int i = 0, j = 0; i < l; i++) { 11 | out[j++] = LOWER_HEX[(0xF0 & data[i]) >>> 4]; 12 | out[j++] = LOWER_HEX[0x0F & data[i]]; 13 | } 14 | return new String(out); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/VJCREProvider.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.security.Provider; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import javacard.framework.APDU; 9 | 10 | import javax.smartcardio.ATR; 11 | import javax.smartcardio.Card; 12 | import javax.smartcardio.CardChannel; 13 | import javax.smartcardio.CardException; 14 | import javax.smartcardio.CardTerminal; 15 | import javax.smartcardio.CardTerminals; 16 | import javax.smartcardio.CommandAPDU; 17 | import javax.smartcardio.ResponseAPDU; 18 | import javax.smartcardio.TerminalFactorySpi; 19 | 20 | @SuppressWarnings("serial") 21 | public class VJCREProvider extends Provider { 22 | public static final String PROVIDER_NAME = "VJCRE"; 23 | public static final String TERMINAL_NAME = "VirtualJavaCard"; 24 | 25 | public VJCREProvider() { 26 | super(PROVIDER_NAME, 0.0d, "Virtual JCRE from javacard.pro"); 27 | put("TerminalFactory.PC/SC", VJCREProviderSpi.class.getName()); 28 | } 29 | 30 | public static class VJCREProviderSpi extends TerminalFactorySpi { 31 | VRE vre = null; 32 | 33 | public VJCREProviderSpi(Object parameter) { 34 | if (parameter != null && (parameter instanceof VRE)) { 35 | vre = (VRE) parameter; 36 | } 37 | } 38 | 39 | @Override 40 | public CardTerminals engineTerminals() { 41 | return new JCTerminals(vre != null ? vre : VRE.getInstance()); 42 | } 43 | 44 | 45 | private static class JCTerminals extends CardTerminals { 46 | final VRE vre ; 47 | protected JCTerminals(VRE vre) { 48 | this.vre = vre; 49 | } 50 | 51 | @Override 52 | public List list(State state) throws CardException { 53 | ArrayList terminals = new ArrayList(); 54 | if (state == State.ALL || state == State.CARD_PRESENT) { 55 | terminals.add(new JCTerminal()); 56 | } 57 | return terminals; 58 | } 59 | 60 | @Override 61 | public boolean waitForChange(long arg0) throws CardException { 62 | return false; 63 | } 64 | 65 | private class JCTerminal extends CardTerminal { 66 | @Override 67 | public Card connect(String protocol) throws CardException { 68 | if (protocol.equals("*") || protocol.equalsIgnoreCase("T=1")) { 69 | vre.connect(APDU.PROTOCOL_T1); 70 | } else if (protocol.equalsIgnoreCase("T=0")) { 71 | vre.connect(APDU.PROTOCOL_T0); 72 | } else { 73 | throw new IllegalArgumentException("Unknown protocol: " + protocol); 74 | } 75 | // FIXME: must re-use card objects 76 | return new JCCard(); 77 | } 78 | 79 | @Override 80 | public String getName() { 81 | return TERMINAL_NAME; 82 | } 83 | 84 | @Override 85 | public boolean isCardPresent() throws CardException { 86 | return true; 87 | } 88 | 89 | @Override 90 | public boolean waitForCardAbsent(long arg0) throws CardException { 91 | return false; 92 | } 93 | 94 | @Override 95 | public boolean waitForCardPresent(long arg0) throws CardException { 96 | return true; 97 | } 98 | 99 | public class JCCard extends Card { 100 | private final CardChannel basicChannel; 101 | protected JCCard() { 102 | basicChannel = new JCCardChannel(); 103 | } 104 | 105 | @Override 106 | public void beginExclusive() throws CardException { 107 | // TODO Auto-generated method stub 108 | // This makes no sense as there is just this JVM instance 109 | // Maybe synchronize on transmit? 110 | } 111 | 112 | @Override 113 | public void disconnect(boolean reset) throws CardException { 114 | // TODO: invalidate card? 115 | if (reset) 116 | vre.reset(); 117 | } 118 | 119 | @Override 120 | public void endExclusive() throws CardException { 121 | // TODO Auto-generated method stub 122 | } 123 | 124 | @Override 125 | public ATR getATR() { 126 | // for OPSystem.setATRHistBytes() 127 | return new ATR(vre.getATR()); 128 | } 129 | 130 | @Override 131 | public CardChannel getBasicChannel() { 132 | return basicChannel; 133 | } 134 | 135 | @Override 136 | public String getProtocol() { 137 | if (vre.getProtocol() == APDU.PROTOCOL_T0) 138 | return "T=0"; 139 | if (vre.getProtocol() == APDU.PROTOCOL_T1) 140 | return "T=1"; 141 | throw new RuntimeException("vJCRE connection has unknown protocol!"); 142 | } 143 | 144 | @Override 145 | public CardChannel openLogicalChannel() throws CardException { 146 | throw new CardException("Logical channels not supported"); 147 | } 148 | 149 | @Override 150 | public byte[] transmitControlCommand(int arg0, byte[] arg1) throws CardException { 151 | throw new RuntimeException("Control commands don't make sense"); 152 | } 153 | 154 | 155 | public class JCCardChannel extends CardChannel { 156 | 157 | @Override 158 | public void close() throws CardException { 159 | // As only basic logical channel is supported 160 | throw new IllegalStateException("Can't close basic channel"); 161 | } 162 | 163 | @Override 164 | public Card getCard() { 165 | return JCCard.this; 166 | } 167 | 168 | @Override 169 | public int getChannelNumber() { 170 | return 0; 171 | } 172 | 173 | @Override 174 | public ResponseAPDU transmit(CommandAPDU apdu) throws CardException { 175 | return new ResponseAPDU(vre.transmit(apdu.getBytes())); 176 | } 177 | 178 | @Override 179 | public int transmit(ByteBuffer arg0, ByteBuffer arg1) throws CardException { 180 | byte[] cmd = new byte[arg0.remaining()]; 181 | arg0.get(cmd); 182 | byte[] resp = vre.transmit(cmd); 183 | arg1.put(resp); 184 | return resp.length; 185 | } 186 | } 187 | } 188 | } 189 | } 190 | } 191 | } 192 | 193 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/VRE.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Method; 9 | import java.security.Security; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import javacard.framework.AID; 16 | import javacard.framework.APDU; 17 | import javacard.framework.APDUException; 18 | import javacard.framework.Applet; 19 | import javacard.framework.CardException; 20 | import javacard.framework.CardRuntimeException; 21 | import javacard.framework.ISO7816; 22 | import javacard.framework.ISOException; 23 | import javacard.framework.JCSystem; 24 | import javacard.framework.PINException; 25 | import javacard.framework.Shareable; 26 | import javacard.framework.SystemException; 27 | import javacard.framework.TransactionException; 28 | import javacard.framework.UserException; 29 | import javacard.security.CryptoException; 30 | import javacardx.apdu.ExtendedLength; 31 | 32 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 33 | 34 | public class VRE { 35 | public static final int API_LEVEL_222 = 222; 36 | public static final int API_LEVEL_301 = 301; 37 | public static final int API_LEVEL_304 = 304; 38 | 39 | // Disabling this makes it more JCRE-conforming but less easy to debug 40 | public static final boolean debugMode = true; 41 | public static final boolean verbose = true; 42 | public static final String provider = BouncyCastleProvider.PROVIDER_NAME; 43 | public static final void log(String msg) { 44 | System.out.println(msg); 45 | } 46 | protected static byte[] default_atr_bytes = new byte[] { (byte) 0x3b, (byte) 0x80, (byte) 0x80, (byte) 0x01, (byte) 0x01 }; 47 | 48 | // This is the singleton 49 | private transient static VRE instance = null; 50 | 51 | // AID-s of important applets. 52 | private AID currentApplet = null; 53 | private AID previousApplet = null; 54 | private AID defaultApplet = null; 55 | 56 | // JCRE technical details 57 | @SuppressWarnings("rawtypes") 58 | // Loaded applets 59 | private Map loaded = new HashMap(); 60 | // installed (registered) applets 61 | private Map installed = new HashMap(); 62 | 63 | // Memory slices. TODO: add DESELECT is applet-specific? 64 | private List resetSlices = new ArrayList(); 65 | private List deselectSlices = new ArrayList(); 66 | 67 | // JCRE-owned exception instances 68 | public static final SystemException vSystemException = new SystemException((short) 0);; 69 | public static final APDUException vAPDUException = new APDUException((short) 0); 70 | public static final CardException vCardException = new CardException((short) 0); 71 | public static final CardRuntimeException vCardRuntimeException = new CardRuntimeException((short) 0); 72 | public static final ISOException vISOException = new ISOException((short) 0); 73 | public static final PINException vPINException = new PINException((short) 0); 74 | public static final UserException vUserException = new UserException((short) 0); 75 | public static final TransactionException vTransactionException = new TransactionException((short) 0); 76 | public static final CryptoException vCryptoException = new CryptoException((short) 0); 77 | 78 | // Technical parameters of the card connection 79 | private byte protocol = APDU.PROTOCOL_T0; 80 | private byte[] atr = default_atr_bytes; 81 | 82 | private final transient APDU apdu = new APDU(); 83 | public VRE() { 84 | if (Security.getProvider(provider) == null) 85 | Security.addProvider(new BouncyCastleProvider()); 86 | 87 | instance = this; 88 | atr = default_atr_bytes; 89 | reset(); 90 | } 91 | 92 | public static VRE getInstance() { 93 | if (instance == null) 94 | instance = new VRE(); 95 | return instance; 96 | } 97 | 98 | // Only supposed to be called on loading? TODO 99 | public static void setInstance(VRE instance) { 100 | VRE.instance = instance; 101 | } 102 | 103 | public void setATR(byte[] atr) { 104 | this.atr = atr; // TODO: maybe copy ? 105 | } 106 | public byte[] getATR() { 107 | return atr; 108 | } 109 | 110 | public byte getProtocol() { 111 | return protocol; 112 | } 113 | 114 | public void connect(byte protocol) { 115 | this.protocol = protocol; 116 | 117 | if (defaultApplet != null) 118 | select(defaultApplet); 119 | log("CONNECT " + (defaultApplet != null ? defaultApplet : "nothing")); 120 | } 121 | 122 | // Actually invoke Applet.install() method 123 | @SuppressWarnings("rawtypes") 124 | private void install(Class applet, byte [] buff, short offset, byte len) throws SecurityException { 125 | try { 126 | Method install = applet.getMethod("install", new Class[]{byte[].class, short.class, byte.class}); 127 | install.invoke(null, new Object[]{buff, new Short(offset), new Byte(len)}); 128 | } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException | NoSuchMethodException e) { 129 | e.printStackTrace(); 130 | throw new RuntimeException("This is no applet!"); 131 | } 132 | } 133 | 134 | 135 | public void install(vAID applet, vAID instance) { 136 | @SuppressWarnings("rawtypes") 137 | Class app = loaded.get(applet); 138 | log("INSTALL " + app.getCanonicalName() + " with AID " + applet.toString()); 139 | 140 | byte [] instdata = new byte[ 3 + instance.getBytes().length]; 141 | instdata[0] = (byte) instance.getBytes().length; 142 | System.arraycopy(instance.getBytes(), 0, instdata, 1, instance.getBytes().length); 143 | install(app, instdata, (short)0, (byte) instdata.length); 144 | } 145 | 146 | public void install(AID applet, boolean isDefault) { 147 | if (isDefault) { 148 | defaultApplet = applet; 149 | } 150 | log("INSTALL instance of " + applet.toString() + " AS DEFAULT"); 151 | install(applet, applet); 152 | } 153 | 154 | @SuppressWarnings("rawtypes") 155 | public void load(Class applet, AID defaultAID) { 156 | log("LOAD " + applet.getName() + " with AID " + defaultAID); 157 | loaded.put(defaultAID, applet); 158 | } 159 | 160 | // Callback from Applet.register(byte[] buffer, short offset, byte length) 161 | public void register(Applet applet, byte[] buffer, short offset, byte length) { 162 | if (length < 5 || length > 16) { 163 | SystemException.throwIt(SystemException.ILLEGAL_VALUE); 164 | } 165 | AID instanceAID = new AID(buffer, offset, length); 166 | log("REGISTER " + applet.getClass().getName() + " with AID " + instanceAID); 167 | 168 | installed.put(instanceAID, applet); 169 | } 170 | 171 | // Callback from Applet.register() 172 | public void register(Applet applet) { 173 | log("REGISTER " + applet.getClass().getName() + " with AID " + currentApplet); 174 | installed.put(currentApplet, applet); 175 | } 176 | 177 | 178 | // Select applet 179 | public boolean select(AID aid) { 180 | if (!installed.containsKey(aid)) { 181 | return false; 182 | } 183 | if (currentApplet != null && installed.containsKey(currentApplet)) { 184 | Applet current = installed.get(currentApplet); 185 | current.deselect(); 186 | } 187 | Applet app = installed.get(aid); 188 | boolean selected = app.select(); 189 | if (selected) { 190 | if (currentApplet != null) 191 | previousApplet = currentApplet; 192 | currentApplet = aid; 193 | } 194 | log(aid + (selected?" SELECTED" : "NOT SELECTED")); 195 | return selected; 196 | } 197 | 198 | public byte[] transmit(byte[] apdu) { 199 | APDU ref = getInstance().apdu; 200 | 201 | Applet app = installed.get(currentApplet); 202 | ref.bb.rewind(); 203 | ref.bb.put(apdu); 204 | ref.bbin = ref.bb.duplicate(); 205 | // So that any output would go back to the real buffer 206 | ref.bb.rewind(); 207 | 208 | // Refuse to work with extended APDU-s unless... 209 | if (!currentIsExtended() && ref.isExtendedAPDU()) { 210 | throw new RuntimeException("Applet does not do extended APDU!"); 211 | } 212 | System.out.println(app); 213 | try { 214 | app.process(ref); 215 | ref.bb.putShort(ISO7816.SW_NO_ERROR); 216 | } catch (ISOException iso) { 217 | // If anything was already returned, set the SW at the end. 218 | // Set SW and return the thing. 219 | ref.bb.putShort(iso.getReason()); 220 | } catch (Exception e) { 221 | if (e instanceof CardRuntimeException) { 222 | CardRuntimeException cre = (CardRuntimeException) e; 223 | System.out.println(e.getClass().getName() + ": " + cre.getReason()); 224 | e.printStackTrace(); 225 | } 226 | e.printStackTrace(); 227 | // 228 | ref.bb.putShort(ISO7816.SW_UNKNOWN); 229 | } 230 | 231 | byte[] copy = new byte[ref.bb.position()]; 232 | ref.bb.rewind(); 233 | ref.bb.get(copy); 234 | return copy; 235 | } 236 | 237 | public boolean currentIsExtended() { 238 | Applet app = installed.get(currentApplet); 239 | return (app instanceof ExtendedLength); 240 | } 241 | 242 | public void reset() { 243 | previousApplet = null; 244 | if (defaultApplet != null) { 245 | currentApplet = defaultApplet; 246 | } else { 247 | currentApplet = null; 248 | } 249 | 250 | vSystemException.setReason((short) 0); 251 | vAPDUException.setReason((short) 0); 252 | vCardException.setReason((short) 0); 253 | vCardRuntimeException.setReason((short) 0); 254 | vISOException.setReason((short) 0); 255 | vPINException.setReason((short) 0); 256 | vUserException.setReason((short) 0); 257 | vTransactionException.setReason((short) 0); 258 | vCryptoException.setReason((short) 0); 259 | 260 | for (Object o: resetSlices) { 261 | resetTransient(o); 262 | } 263 | for (Object o: deselectSlices) { 264 | resetTransient(o); 265 | } 266 | } 267 | 268 | private void resetTransient(Object o) { 269 | if (o instanceof byte[]) { 270 | byte[] b = (byte[]) o; 271 | for (int i = 0; i < b.length; i++) { 272 | b[i] = 0x00; 273 | } 274 | } else if (o instanceof boolean[]) { 275 | boolean[] b = (boolean[]) o; 276 | for (int i = 0; i < b.length; i++) { 277 | b[i] = false; 278 | } 279 | } else if (o instanceof short[]) { 280 | short[] b = (short[]) o; 281 | for (int i = 0; i < b.length; i++) { 282 | b[i] = 0x00; 283 | } 284 | } else if (o instanceof Object[]) { 285 | Object[] b = (Object[]) o; 286 | for (int i = 0; i < b.length; i++) { 287 | b[i] = null; 288 | } 289 | } else { 290 | throw new RuntimeException("Unknown transient type: " + o.getClass().getCanonicalName()); 291 | } 292 | } 293 | 294 | // Helpers for memory management 295 | private byte whichMemoryType(Object theObj) { 296 | if (!theObj.getClass().isArray()) { 297 | return JCSystem.NOT_A_TRANSIENT_OBJECT; 298 | } 299 | if (deselectSlices.contains(theObj)) { 300 | return JCSystem.CLEAR_ON_DESELECT; 301 | } 302 | if (resetSlices.contains(theObj)) { 303 | return JCSystem.CLEAR_ON_RESET; 304 | } 305 | return JCSystem.NOT_A_TRANSIENT_OBJECT; 306 | } 307 | 308 | @SuppressWarnings("unchecked") 309 | private void setMemoryReference(Object ref, byte event) { 310 | switch (event) { 311 | case JCSystem.CLEAR_ON_DESELECT: 312 | deselectSlices.add(ref); 313 | break; 314 | case JCSystem.CLEAR_ON_RESET: 315 | resetSlices.add(ref); 316 | break; 317 | default: 318 | SystemException.throwIt(SystemException.ILLEGAL_VALUE); 319 | } 320 | } 321 | 322 | // javacard.framework.JCSystem methods 323 | public static byte isTransient(Object theObj) {return getInstance().whichMemoryType(theObj);} 324 | public static boolean[] makeTransientBooleanArray(short length, byte event) { 325 | boolean[] array = new boolean[length]; 326 | getInstance().setMemoryReference(array, event); 327 | return array; 328 | } 329 | public static byte[] makeTransientByteArray(short length, byte event) { 330 | byte[] array = new byte[length]; 331 | getInstance().setMemoryReference(array, event); 332 | return array; 333 | } 334 | public static short[] makeTransientShortArray(short length, byte event) { 335 | short[] array = new short[length]; 336 | getInstance().setMemoryReference(array, event); 337 | return array; 338 | } 339 | public static Object[] makeTransientObjectArray(short length, byte event) { 340 | Object[] array = new Object[length]; 341 | getInstance().setMemoryReference(array, event); 342 | return array; 343 | } 344 | public static short getVersion() {return 0x0202;} 345 | public static AID getAID() {return getInstance().currentApplet;} 346 | public static AID lookupAID(byte[] buffer, short offset, byte length) { 347 | AID q = new AID(buffer, offset, length); 348 | // get the VRE-owned instance 349 | for (AID a: getInstance().installed.keySet()) { 350 | if (q.equals(a)) 351 | return a; 352 | } 353 | return null; 354 | } 355 | public static void beginTransaction() throws TransactionException {} 356 | public static void abortTransaction() throws TransactionException {} 357 | public static void commitTransaction() throws TransactionException {} 358 | public static byte getTransactionDepth() {return 0;} 359 | public static short getUnusedCommitCapacity() {return Short.MAX_VALUE;} 360 | public static AID getPreviousContextAID() {return getInstance().previousApplet;} 361 | public static short getAvailableMemory(byte memoryType) throws SystemException {return Short.MAX_VALUE;} 362 | 363 | // FIXME: contexts 364 | public static Shareable getAppletShareableInterfaceObject(vAID serverAID, byte parameter) { 365 | Applet app = getInstance().installed.get(serverAID); 366 | return app.getShareableInterfaceObject(getInstance().currentApplet, parameter); 367 | }; 368 | public static boolean isObjectDeletionSupported() {return true;} 369 | public static void requestObjectDeletion() throws SystemException {} 370 | public static byte getAssignedChannel() {return 0;} 371 | } 372 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vAID.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Arrays; 5 | 6 | import javacard.framework.AID; 7 | 8 | public class vAID { 9 | protected byte aid []; 10 | 11 | // These are for internal use. 12 | public final byte[] getBytes() { 13 | return aid; 14 | } 15 | 16 | public static AID fromBytes(byte[] aid) { 17 | return new AID(aid, (short) 0, (byte) aid.length); 18 | } 19 | 20 | public final int hashCode() { 21 | return new BigInteger(aid).hashCode(); 22 | } 23 | 24 | public final boolean equals(Object anObject) throws SecurityException { 25 | if (anObject == null) { 26 | return false; 27 | } 28 | if (!(anObject instanceof vAID)) { 29 | return false; 30 | } 31 | vAID other = (vAID) anObject; 32 | 33 | if (other.aid.length != aid.length) { 34 | return false; 35 | } 36 | return Arrays.equals(aid, other.aid); 37 | } 38 | 39 | public String toString() { 40 | return Misc.encodeHexString(aid); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vAPDU.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.util.Arrays; 5 | 6 | import javacard.framework.APDU; 7 | import javacard.framework.APDUException; 8 | import javacard.framework.ISO7816; 9 | 10 | // translated CommandAPDU/ResponseAPDU and byte arrays into VRE objects 11 | // Instance of this class is fed to Applet.process() 12 | // This class needs seom spec-love. 13 | 14 | public class vAPDU { 15 | protected transient byte [] buffer; 16 | protected transient ByteBuffer bb; 17 | protected transient ByteBuffer bbin; 18 | private transient byte state; 19 | 20 | // the singleton 21 | private static vAPDU currentAPDU; 22 | 23 | protected vAPDU() { 24 | currentAPDU = this; 25 | buffer = new byte[Short.MAX_VALUE]; 26 | bb = ByteBuffer.wrap(buffer); 27 | bbin = bb.duplicate(); 28 | } 29 | 30 | public byte[] getBuffer() { 31 | return buffer; 32 | } 33 | 34 | public static byte getProtocol() { 35 | return VRE.getInstance().getProtocol(); 36 | } 37 | 38 | public byte getNAD() { 39 | return 0; 40 | } 41 | 42 | public static short getOutBlockSize() { 43 | if (getProtocol() == APDU.PROTOCOL_T0) { 44 | return 258; 45 | } 46 | return Short.MAX_VALUE; 47 | } 48 | 49 | // FIXME: get actual Le if exists. 50 | public short setOutgoing() throws APDUException { 51 | state = APDU.STATE_OUTGOING; 52 | short ret = 256; 53 | if (VRE.getInstance().currentIsExtended()) 54 | ret = Short.MAX_VALUE; 55 | return ret; 56 | } 57 | 58 | public short setOutgoingNoChaining() throws APDUException { 59 | state = APDU.STATE_OUTGOING; 60 | return 256; 61 | } 62 | 63 | // Ignore this, as all data is concatenated into the "endless" buffer 64 | public void setOutgoingLength(short len) throws APDUException { 65 | state = APDU.STATE_OUTGOING_LENGTH_KNOWN; 66 | } 67 | 68 | public short receiveBytes(short bOff) throws APDUException { 69 | state = APDU.STATE_FULL_INCOMING; 70 | // FIXME return "incoming minus offset in parameter" 71 | return (short) (bbin.position() - ISO7816.OFFSET_CDATA); 72 | } 73 | 74 | public short setIncomingAndReceive() throws APDUException { 75 | state = APDU.STATE_FULL_INCOMING; 76 | // Virtually call receiveBytes 77 | // FIXME: logic is wrong. 78 | if (VRE.getInstance().currentIsExtended() && isExtendedAPDU()) { 79 | return getExtendedLc(); 80 | } 81 | // Use Lc for short APDU-s 82 | if (bbin.position() > ISO7816.OFFSET_LC) 83 | return (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); 84 | 85 | return 0; 86 | } 87 | 88 | public void sendBytes(short bOff, short len) throws APDUException { 89 | bb.position(bOff + len); 90 | } 91 | 92 | public void sendBytesLong(byte outData[], short bOff, short len) throws APDUException, SecurityException { 93 | byte[] data = Arrays.copyOfRange(outData, bOff, bOff + len); 94 | bb.put(data); 95 | } 96 | 97 | public void setOutgoingAndSend(short bOff, short len) throws APDUException { 98 | setOutgoing(); 99 | setOutgoingLength(len); 100 | sendBytes(bOff, len); 101 | } 102 | 103 | public byte getCurrentState() { 104 | return state; 105 | } 106 | 107 | public static APDU getCurrentAPDU() throws SecurityException { 108 | return (APDU) currentAPDU; 109 | } 110 | 111 | public static byte[] getCurrentAPDUBuffer() throws SecurityException { 112 | return getCurrentAPDU().getBuffer(); 113 | } 114 | 115 | public static byte getCLAChannel() { 116 | // TODO set on incoming, but always 0 ATM 117 | return 0; 118 | } 119 | 120 | public static void waitExtension() throws APDUException { 121 | // Do nothing. Maybe APDUException.ILLEGAL_USE ? 122 | } 123 | public boolean isCommandChainingCLA() { 124 | return (buffer[ISO7816.OFFSET_CLA] & 0x10) != 0; 125 | } 126 | public boolean isSecureMessagingCLA() { 127 | return (buffer[ISO7816.OFFSET_CLA] & 0x2C) != 0; 128 | } 129 | public boolean isISOInterindustryCLA() { 130 | return (buffer[ISO7816.OFFSET_CLA] & 0x80) == 0; 131 | } 132 | public short getIncomingLength() { 133 | if (isExtendedAPDU()) 134 | return getExtendedLc(); 135 | return (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF); 136 | } 137 | public short getOffsetCdata() { 138 | if (isExtendedAPDU()) 139 | return 7; 140 | return 5; 141 | } 142 | 143 | // Internal helpers 144 | protected boolean isExtendedAPDU() { 145 | if (bbin.position() > 6 && buffer[ISO7816.OFFSET_LC] == 0x00) 146 | return true; 147 | return false; 148 | } 149 | 150 | protected short getExtendedLc() { 151 | return (short) ((buffer[ISO7816.OFFSET_LC +1] & 0xff << 8) | buffer[ISO7816.OFFSET_LC+2] & 0xff); 152 | } 153 | 154 | protected short getExtendedLe() { 155 | return (short) ((buffer[bbin.position()-2] & 0xff << 8) | buffer[bbin.position()-1] & 0xff); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vChecksum.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import javacard.security.Checksum; 4 | import javacard.security.CryptoException; 5 | 6 | public class vChecksum extends Checksum { 7 | private byte algorithm; 8 | 9 | public vChecksum(byte algorithm) { 10 | this.algorithm = algorithm; 11 | } 12 | 13 | @Override 14 | public byte getAlgorithm() { 15 | return algorithm; 16 | } 17 | 18 | @Override 19 | public void init(byte[] bArray, short bOff, short bLen) throws CryptoException { 20 | // TODO Auto-generated method stub 21 | 22 | } 23 | 24 | @Override 25 | public short doFinal(byte[] inBuff, short inOffset, short inLength, 26 | byte[] outBuff, short outOffset) { 27 | // TODO Auto-generated method stub 28 | return 0; 29 | } 30 | 31 | @Override 32 | public void update(byte[] inBuff, short inOffset, short inLength) { 33 | // TODO Auto-generated method stub 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vCipher.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.security.InvalidKeyException; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.NoSuchProviderException; 6 | 7 | import javacard.security.CryptoException; 8 | import javacard.security.Key; 9 | 10 | import javax.crypto.BadPaddingException; 11 | import javax.crypto.Cipher; 12 | import javax.crypto.IllegalBlockSizeException; 13 | import javax.crypto.NoSuchPaddingException; 14 | import javax.crypto.ShortBufferException; 15 | 16 | public final class vCipher extends javacardx.crypto.Cipher { 17 | 18 | byte algorithm = 0; 19 | boolean isInitialized = false; 20 | Cipher cipher = null; 21 | 22 | public vCipher(byte algorithm) { 23 | this.algorithm = algorithm; 24 | try { 25 | switch (algorithm) { 26 | case ALG_RSA_NOPAD: 27 | cipher = javax.crypto.Cipher.getInstance("RSA/ECB/NoPadding", VRE.provider); 28 | break; 29 | case ALG_RSA_PKCS1: 30 | cipher = javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding", VRE.provider); 31 | break; 32 | case ALG_RSA_PKCS1_OAEP: 33 | cipher = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPPadding", VRE.provider); 34 | break; 35 | default: 36 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 37 | break; 38 | } 39 | } catch (NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) { 40 | e.printStackTrace(); 41 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 42 | } 43 | } 44 | 45 | public void init(Key theKey, byte theMode) throws CryptoException { 46 | if (theKey == null) { 47 | CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY); 48 | } 49 | if (!theKey.isInitialized()) { 50 | CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY); 51 | } 52 | 53 | try { 54 | int jce_mode = 0; 55 | if (theMode == MODE_ENCRYPT) 56 | jce_mode = Cipher.ENCRYPT_MODE; 57 | else if (theMode == MODE_DECRYPT) 58 | jce_mode = Cipher.DECRYPT_MODE; 59 | else 60 | CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); 61 | cipher.init(jce_mode, ((vKey) theKey).jce()); 62 | } catch (InvalidKeyException e) { 63 | if (VRE.debugMode) { 64 | e.printStackTrace(); 65 | } 66 | CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); 67 | } 68 | isInitialized = true; 69 | } 70 | 71 | public void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException { 72 | CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); 73 | } 74 | 75 | public byte getAlgorithm() { 76 | return algorithm; 77 | } 78 | 79 | public short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException { 80 | if (!isInitialized) { 81 | CryptoException.throwIt(CryptoException.INVALID_INIT); 82 | } 83 | short result = 0; 84 | try { 85 | result = (short) cipher.doFinal(inBuff, inOffset, inLength, outBuff, outOffset); 86 | } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { 87 | e.printStackTrace(); 88 | CryptoException.throwIt(CryptoException.ILLEGAL_USE); 89 | } 90 | return result; 91 | } 92 | 93 | public short update(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException { 94 | if (!isInitialized) { 95 | CryptoException.throwIt(CryptoException.INVALID_INIT); 96 | } 97 | short result = 0; 98 | try { 99 | result = (short) cipher.update(inBuff, inOffset, inLength, outBuff, outOffset); 100 | } catch (ShortBufferException e) { 101 | e.printStackTrace(); 102 | CryptoException.throwIt(CryptoException.ILLEGAL_USE); 103 | } 104 | return result; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vKey.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Arrays; 5 | 6 | import javacard.security.CryptoException; 7 | import javacard.security.Key; 8 | import javacard.security.KeyBuilder; 9 | 10 | public abstract class vKey implements Key { 11 | protected byte type; 12 | protected short length; 13 | 14 | @Override 15 | public short getSize() { 16 | return length; 17 | } 18 | 19 | @Override 20 | public byte getType() { 21 | return type; 22 | } 23 | 24 | public static Key buildKey(byte keyType, short keyLength) { 25 | Key k = null; 26 | switch (keyType) { 27 | case KeyBuilder.TYPE_RSA_PUBLIC: 28 | k = new vRSAPublicKey(); 29 | break; 30 | case KeyBuilder.TYPE_RSA_PRIVATE: 31 | k = new vRSAPrivateKey(); 32 | break; 33 | case KeyBuilder.TYPE_RSA_CRT_PRIVATE: 34 | k = new vRSAPrivateCrtKey(); 35 | break; 36 | default: 37 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 38 | } 39 | ((vKey) k).type = keyType; 40 | ((vKey) k).length = keyLength; 41 | return k; 42 | } 43 | 44 | // Get the JCE-compatible key 45 | protected abstract java.security.Key jce(); 46 | 47 | // Copy BigInteger value to buffer 48 | protected static short send_positive_bigint(byte[] buffer, short offset, BigInteger i) { 49 | byte[] bytes = i.toByteArray(); 50 | System.arraycopy(bytes, 0, buffer, offset, bytes.length); 51 | return (short) bytes.length; 52 | } 53 | 54 | // Get BigInteger value from buffer 55 | protected static BigInteger get_positive_bigint(byte[] buffer, short offset, short length) { 56 | return new BigInteger(1, Arrays.copyOfRange(buffer, offset, offset + length)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vKeyAgreement.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import javacard.security.CryptoException; 4 | import javacard.security.KeyAgreement; 5 | import javacard.security.PrivateKey; 6 | 7 | public class vKeyAgreement extends KeyAgreement { 8 | public vKeyAgreement(byte algorithm) { 9 | // nada 10 | } 11 | 12 | @Override 13 | public void init(PrivateKey privateKey) throws CryptoException { 14 | // TODO Auto-generated method stub 15 | 16 | } 17 | 18 | @Override 19 | public byte getAlgorithm() { 20 | // TODO Auto-generated method stub 21 | return 0; 22 | } 23 | 24 | @Override 25 | public short generateSecret(byte[] publicData, short publicOffset, 26 | short publicLength, byte[] secret, short secretOffset) 27 | throws CryptoException { 28 | // TODO Auto-generated method stub 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vKeyPair.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.security.InvalidAlgorithmParameterException; 5 | import java.security.KeyPairGenerator; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.security.NoSuchProviderException; 8 | import java.security.interfaces.RSAPrivateCrtKey; 9 | import java.security.interfaces.RSAPrivateKey; 10 | import java.security.interfaces.RSAPublicKey; 11 | import java.security.spec.RSAKeyGenParameterSpec; 12 | 13 | import javacard.security.CryptoException; 14 | import javacard.security.KeyBuilder; 15 | import javacard.security.KeyPair; 16 | import javacard.security.PrivateKey; 17 | import javacard.security.PublicKey; 18 | 19 | public class vKeyPair { 20 | PrivateKey priv; 21 | PublicKey pub; 22 | 23 | protected vKeyPair() {} 24 | 25 | public final void genKeyPair() throws CryptoException { 26 | try { 27 | // Generate a key and copy over the material. 28 | if (pub.getType() == KeyBuilder.TYPE_RSA_PUBLIC) { 29 | KeyPairGenerator keyGen; 30 | keyGen = KeyPairGenerator.getInstance("RSA", VRE.provider); 31 | vRSAPublicKey vpubk = (vRSAPublicKey) pub; 32 | if (vpubk.publicExponent != BigInteger.ZERO) { 33 | keyGen.initialize(new RSAKeyGenParameterSpec(vpubk.getSize(), vpubk.publicExponent)); 34 | } else { 35 | keyGen.initialize(vpubk.getSize()); 36 | } 37 | java.security.KeyPair kp = keyGen.generateKeyPair(); 38 | RSAPublicKey pubk = (RSAPublicKey)kp.getPublic(); 39 | vpubk.publicExponent = pubk.getPublicExponent(); 40 | vpubk.modulus = pubk.getModulus(); 41 | if (priv.getType() == KeyBuilder.TYPE_RSA_CRT_PRIVATE) { 42 | vRSAPrivateCrtKey vprivk = (vRSAPrivateCrtKey) priv; 43 | RSAPrivateCrtKey privk = (RSAPrivateCrtKey)kp.getPrivate(); 44 | vprivk.p = privk.getPrimeP(); 45 | vprivk.q = privk.getPrimeQ(); 46 | vprivk.dp1 = privk.getPrimeExponentP(); 47 | vprivk.dq1 = privk.getPrimeExponentQ(); 48 | vprivk.pq = privk.getCrtCoefficient(); 49 | } else if (priv.getType() == KeyBuilder.TYPE_RSA_PRIVATE) { 50 | vRSAPrivateKey vprivk = (vRSAPrivateKey) priv; 51 | RSAPrivateKey privk = (RSAPrivateKey)kp.getPrivate(); 52 | vprivk.privateExponent = privk.getPrivateExponent(); 53 | vprivk.modulus = privk.getModulus(); 54 | } else { 55 | throw new CryptoException(CryptoException.NO_SUCH_ALGORITHM); 56 | } 57 | } 58 | } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { 59 | throw new CryptoException(CryptoException.NO_SUCH_ALGORITHM); 60 | } 61 | } 62 | 63 | public vKeyPair(byte algorithm, short keyLength) throws CryptoException { 64 | if (algorithm == KeyPair.ALG_RSA) { 65 | priv = (PrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, keyLength, false); 66 | pub = (PublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, keyLength, false); 67 | } else if (algorithm == KeyPair.ALG_RSA_CRT) { 68 | priv = (PrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_CRT_PRIVATE, keyLength, false); 69 | pub = (PublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, keyLength, false); 70 | } else { 71 | throw new CryptoException(CryptoException.NO_SUCH_ALGORITHM); 72 | } 73 | } 74 | 75 | 76 | public vKeyPair(PublicKey publicKey, PrivateKey privateKey) throws CryptoException { 77 | if (publicKey == null || privateKey == null) { 78 | CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); 79 | } 80 | if ((publicKey.getType() != privateKey.getType()) || (publicKey.getSize() != privateKey.getSize())) { 81 | CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); 82 | } 83 | priv = privateKey; 84 | pub = publicKey; 85 | } 86 | 87 | 88 | public PublicKey getPublic() { 89 | return pub; 90 | } 91 | 92 | public PrivateKey getPrivate() { 93 | return priv; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vMessageDigest.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | import java.security.NoSuchProviderException; 6 | import java.util.Arrays; 7 | 8 | import javacard.security.CryptoException; 9 | 10 | public class vMessageDigest extends javacard.security.MessageDigest { 11 | private byte algorithm = 0; 12 | private MessageDigest digest; 13 | public vMessageDigest(byte algorithm) { 14 | try { 15 | switch (algorithm) { 16 | case ALG_MD5: 17 | digest = MessageDigest.getInstance("MD5", VRE.provider); 18 | break; 19 | case ALG_SHA: 20 | digest = MessageDigest.getInstance("SHA-1", VRE.provider); 21 | break; 22 | case ALG_SHA_256: 23 | digest = MessageDigest.getInstance("SHA-256", VRE.provider); 24 | break; 25 | case ALG_SHA_384: 26 | digest = MessageDigest.getInstance("SHA-384", VRE.provider); 27 | break; 28 | case ALG_SHA_512: 29 | digest = MessageDigest.getInstance("SHA-512", VRE.provider); 30 | break; 31 | case ALG_SHA_224: 32 | digest = MessageDigest.getInstance("SHA-224", VRE.provider); 33 | break; 34 | default: 35 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 36 | break; 37 | } 38 | } catch (NoSuchAlgorithmException | NoSuchProviderException e) { 39 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 40 | } 41 | } 42 | 43 | public byte getAlgorithm() { 44 | return algorithm; 45 | } 46 | 47 | public byte getLength() { 48 | switch (algorithm) { 49 | case ALG_MD5: 50 | return LENGTH_MD5; 51 | case ALG_RIPEMD160: 52 | return LENGTH_RIPEMD160; 53 | case ALG_SHA: 54 | return LENGTH_SHA; 55 | case ALG_SHA_256: 56 | return LENGTH_SHA_256; 57 | case ALG_SHA_384: 58 | return LENGTH_SHA_384; 59 | case ALG_SHA_512: 60 | return LENGTH_SHA_512; 61 | case ALG_SHA_224: 62 | return LENGTH_SHA_224; 63 | default: 64 | return 0; 65 | } 66 | } 67 | 68 | public short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) { 69 | byte [] result = digest.digest(Arrays.copyOfRange(inBuff, inOffset, inOffset +inLength)); 70 | System.arraycopy(result, 0, outBuff, outOffset, result.length); 71 | return (short) result.length; 72 | } 73 | 74 | public void update(byte[] inBuff, short inOffset, short inLength) { 75 | digest.update(inBuff, inOffset, inLength); 76 | } 77 | 78 | public void reset() { 79 | digest.reset(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vRSAPrivateCrtKey.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.security.KeyFactory; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.NoSuchProviderException; 7 | import java.security.interfaces.RSAPrivateCrtKey; 8 | import java.security.spec.InvalidKeySpecException; 9 | import java.security.spec.RSAPrivateCrtKeySpec; 10 | 11 | import javacard.security.CryptoException; 12 | 13 | public class vRSAPrivateCrtKey extends vRSAPrivateKey implements javacard.security.RSAPrivateCrtKey { 14 | 15 | protected BigInteger p; 16 | protected BigInteger q; 17 | protected BigInteger dp1; 18 | protected BigInteger dq1; 19 | protected BigInteger pq; 20 | 21 | public void clearKey() { 22 | super.clearKey(); 23 | p = BigInteger.ZERO; 24 | q = BigInteger.ZERO; 25 | dp1 = BigInteger.ZERO; 26 | dq1 = BigInteger.ZERO; 27 | pq = BigInteger.ZERO; 28 | } 29 | 30 | public boolean isInitialized() { 31 | if (!p.equals(BigInteger.ZERO) && !q.equals(BigInteger.ZERO) && !dp1.equals(BigInteger.ZERO) && !dq1.equals(BigInteger.ZERO) && !pq.equals(BigInteger.ZERO)) 32 | return true; 33 | return false; 34 | } 35 | 36 | public void setP(byte[] buffer, short offset, short length) throws CryptoException { 37 | p = get_positive_bigint(buffer, offset, length); 38 | } 39 | 40 | public void setQ(byte[] buffer, short offset, short length) throws CryptoException { 41 | q = get_positive_bigint(buffer, offset, length); 42 | } 43 | 44 | public void setDP1(byte[] buffer, short offset, short length) throws CryptoException { 45 | dp1 = get_positive_bigint(buffer, offset, length); 46 | } 47 | 48 | public void setDQ1(byte[] buffer, short offset, short length) throws CryptoException { 49 | dq1 = get_positive_bigint(buffer, offset, length); 50 | } 51 | 52 | public void setPQ(byte[] buffer, short offset, short length) throws CryptoException { 53 | pq = get_positive_bigint(buffer, offset, length); 54 | } 55 | 56 | public short getP(byte[] buffer, short offset) throws CryptoException { 57 | return send_positive_bigint(buffer, offset, p); 58 | } 59 | 60 | public short getQ(byte[] buffer, short offset) throws CryptoException { 61 | return send_positive_bigint(buffer, offset, q); 62 | } 63 | 64 | public short getDP1(byte[] buffer, short offset) throws CryptoException { 65 | return send_positive_bigint(buffer, offset, dp1); 66 | } 67 | 68 | public short getDQ1(byte[] buffer, short offset) throws CryptoException { 69 | return send_positive_bigint(buffer, offset, dq1); 70 | } 71 | 72 | public short getPQ(byte[] buffer, short offset) throws CryptoException { 73 | return send_positive_bigint(buffer, offset, pq); 74 | } 75 | 76 | protected RSAPrivateCrtKey jce() { 77 | try { 78 | RSAPrivateCrtKeySpec spec = new RSAPrivateCrtKeySpec(p.multiply(q), null, null, p, q, dp1, dq1, pq); 79 | KeyFactory kf = KeyFactory.getInstance("RSA", VRE.provider); 80 | RSAPrivateCrtKey k = (RSAPrivateCrtKey) kf.generatePrivate(spec); 81 | System.out.println(k.getClass().getCanonicalName()); 82 | return k; 83 | } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { 84 | throw new RuntimeException(e); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vRSAPrivateKey.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.security.KeyFactory; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.NoSuchProviderException; 7 | import java.security.interfaces.RSAPrivateKey; 8 | import java.security.spec.InvalidKeySpecException; 9 | import java.security.spec.RSAPrivateKeySpec; 10 | 11 | import javacard.security.CryptoException; 12 | 13 | public class vRSAPrivateKey extends vKey implements javacard.security.RSAPrivateKey { 14 | protected BigInteger privateExponent; 15 | protected BigInteger modulus; 16 | 17 | public void clearKey() { 18 | modulus = BigInteger.ZERO; 19 | privateExponent = BigInteger.ZERO; 20 | } 21 | 22 | public boolean isInitialized() { 23 | return (!modulus.equals(BigInteger.ZERO) && !privateExponent.equals(BigInteger.ZERO)); 24 | } 25 | 26 | public short getExponent(byte[] buffer, short offset) throws CryptoException { 27 | return send_positive_bigint(buffer, offset, privateExponent); 28 | } 29 | 30 | public short getModulus(byte[] buffer, short offset) throws CryptoException { 31 | return send_positive_bigint(buffer, offset, modulus); 32 | } 33 | 34 | public void setExponent(byte[] buffer, short offset, short length) throws CryptoException { 35 | privateExponent = get_positive_bigint(buffer, offset, length); 36 | } 37 | 38 | public void setModulus(byte[] buffer, short offset, short length) throws CryptoException { 39 | modulus = get_positive_bigint(buffer, offset, length); 40 | } 41 | 42 | protected java.security.interfaces.RSAPrivateKey jce() { 43 | try { 44 | RSAPrivateKeySpec spec = new RSAPrivateKeySpec(modulus, privateExponent); 45 | KeyFactory kf = KeyFactory.getInstance("RSA", VRE.provider); 46 | RSAPrivateKey k = (RSAPrivateKey) kf.generatePrivate(spec); 47 | System.out.println(k.getClass().getCanonicalName()); 48 | return k; 49 | } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vRSAPublicKey.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.math.BigInteger; 4 | import java.security.KeyFactory; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.NoSuchProviderException; 7 | import java.security.interfaces.RSAPublicKey; 8 | import java.security.spec.InvalidKeySpecException; 9 | import java.security.spec.RSAPublicKeySpec; 10 | 11 | import javacard.security.CryptoException; 12 | 13 | public class vRSAPublicKey extends vKey implements javacard.security.RSAPublicKey { 14 | 15 | protected BigInteger publicExponent; 16 | protected BigInteger modulus; 17 | 18 | public void clearKey() { 19 | publicExponent = BigInteger.ZERO; 20 | modulus = BigInteger.ZERO; 21 | } 22 | 23 | public boolean isInitialized() { 24 | return (!modulus.equals(BigInteger.ZERO) && !publicExponent.equals(BigInteger.ZERO)); 25 | } 26 | 27 | public short getExponent(byte[] buffer, short offset) throws CryptoException { 28 | return send_positive_bigint(buffer, offset, publicExponent); 29 | } 30 | 31 | public short getModulus(byte[] buffer, short offset) throws CryptoException { 32 | return send_positive_bigint(buffer, offset, modulus); 33 | } 34 | 35 | public void setExponent(byte[] buffer, short offset, short length) throws CryptoException { 36 | publicExponent = get_positive_bigint(buffer, offset, length); 37 | } 38 | 39 | public void setModulus(byte[] buffer, short offset, short length) throws CryptoException { 40 | modulus = get_positive_bigint(buffer, offset, length); 41 | } 42 | 43 | protected RSAPublicKey jce() { 44 | try { 45 | RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent); 46 | KeyFactory kf = KeyFactory.getInstance("RSA", VRE.provider); 47 | RSAPublicKey k = (RSAPublicKey) kf.generatePublic(spec); 48 | return k; 49 | } catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vRandomData.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import java.security.NoSuchAlgorithmException; 4 | import java.security.NoSuchProviderException; 5 | import java.security.SecureRandom; 6 | import java.util.Arrays; 7 | 8 | import javacard.security.CryptoException; 9 | 10 | public class vRandomData extends javacard.security.RandomData { 11 | private SecureRandom rnd = null; 12 | 13 | public vRandomData(byte algorithm) { 14 | if (algorithm != ALG_PSEUDO_RANDOM && algorithm != ALG_SECURE_RANDOM) { 15 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 16 | } 17 | try { 18 | rnd = SecureRandom.getInstance("SHA1PRNG", VRE.provider); 19 | } catch (NoSuchAlgorithmException | NoSuchProviderException e) { 20 | CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); 21 | } 22 | } 23 | 24 | public void generateData(byte[] buffer, short offset, short length) throws CryptoException { 25 | byte[] d = new byte[length]; 26 | rnd.nextBytes(d); 27 | System.arraycopy(d, 0, buffer, offset, length); 28 | } 29 | 30 | public void setSeed(byte[] buffer, short offset, short length) { 31 | rnd.setSeed(Arrays.copyOfRange(buffer, offset, offset+length)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/pro/javacard/vre/vSignature.java: -------------------------------------------------------------------------------- 1 | package pro.javacard.vre; 2 | 3 | import javacard.security.CryptoException; 4 | import javacard.security.Key; 5 | 6 | 7 | public class vSignature extends javacard.security.Signature { 8 | 9 | public vSignature(byte algorithm) { 10 | // TODO Auto-generated constructor stub 11 | 12 | } 13 | 14 | @Override 15 | public void init(Key theKey, byte theMode) throws CryptoException { 16 | // TODO Auto-generated method stub 17 | 18 | 19 | } 20 | 21 | @Override 22 | public void init(Key theKey, byte theMode, byte[] bArray, short bOff, 23 | short bLen) throws CryptoException { 24 | // TODO Auto-generated method stub 25 | 26 | } 27 | 28 | @Override 29 | public short getLength() throws CryptoException { 30 | // TODO Auto-generated method stub 31 | return 0; 32 | } 33 | 34 | @Override 35 | public byte getAlgorithm() { 36 | // TODO Auto-generated method stub 37 | return 0; 38 | } 39 | 40 | @Override 41 | public void update(byte[] inBuff, short inOffset, short inLength) 42 | throws CryptoException { 43 | // TODO Auto-generated method stub 44 | 45 | } 46 | 47 | @Override 48 | public short sign(byte[] inBuff, short inOffset, short inLength, 49 | byte[] sigBuff, short sigOffset) throws CryptoException { 50 | // TODO Auto-generated method stub 51 | return 0; 52 | } 53 | 54 | @Override 55 | public boolean verify(byte[] inBuff, short inOffset, short inLength, 56 | byte[] sigBuff, short sigOffset, short sigLength) 57 | throws CryptoException { 58 | // TODO Auto-generated method stub 59 | return false; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/visa/openplatform/OPSystem.java: -------------------------------------------------------------------------------- 1 | package visa.openplatform; 2 | 3 | import javacard.framework.APDU; 4 | 5 | // TODO 6 | public class OPSystem { 7 | public static final byte APPLET_BLOCKED = 127; 8 | public static final byte APPLET_INSTALLED = 3; 9 | public static final byte APPLET_LOCKED = -127; 10 | public static final byte APPLET_PERSONALIZED = 15; 11 | public static final byte APPLET_SELECTABLE = 7; 12 | public static final byte CARD_INITIALIZED = 7; 13 | public static final byte CARD_LOCKED = 127; 14 | public static final byte CARD_OP_READY = 1; 15 | public static final byte CARD_SECURED = 15; 16 | public static final byte INITIALIZED = 7; 17 | public static final byte PACKAGE_LOADED = 1; 18 | 19 | public static byte getCardContentState() { 20 | return APPLET_SELECTABLE; 21 | } 22 | 23 | public static boolean setATRHistBytes(byte[] buffer, short bOffset, byte bLength) { 24 | return false; 25 | } 26 | 27 | public static byte getCardManagerState() { 28 | return CARD_OP_READY; 29 | } 30 | 31 | public static void getCPLCData(APDU apdu, short apdu_offset, short cplc_offset, short length) { 32 | } 33 | 34 | public static ProviderSecurityDomain getSecurityDomain() { 35 | return null; 36 | } 37 | 38 | static byte getTriesRemaining() { 39 | return 0; 40 | } 41 | 42 | public static boolean lockCardManager() { 43 | return false; 44 | } 45 | 46 | public static boolean setCardContentState(byte state) { 47 | return false; 48 | } 49 | 50 | public static boolean setPin(APDU apdu, short offset) { 51 | return false; 52 | } 53 | 54 | public static boolean terminateCardManager() { 55 | return false; 56 | } 57 | 58 | public static boolean verifyPin(APDU apdu, short offset) { 59 | return false; 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/visa/openplatform/ProviderSecurityDomain.java: -------------------------------------------------------------------------------- 1 | package visa.openplatform; 2 | 3 | import javacard.framework.APDU; 4 | 5 | public interface ProviderSecurityDomain { 6 | void closeSecureChannel(byte channel); 7 | boolean decryptVerifyKey(byte channel, APDU apdu, short offset); 8 | byte openSecureChannel(APDU apdu); 9 | void unwrap(byte channel, APDU apdu); 10 | void verifyExternalAuthenticate(byte channel, APDU apdu); 11 | } 12 | -------------------------------------------------------------------------------- /vjcre.pro: -------------------------------------------------------------------------------- 1 | -injars build 2 | -injars lib/bcpkix-jdk15on-154.jar(!META-INF/*) 3 | -libraryjars lib/bcprov-jdk15on-154.jar 4 | -libraryjars /lib/rt.jar:/lib/jce.jar 5 | 6 | -outjars optimized-vjcre.jar 7 | -dontobfuscate 8 | -dontoptimize 9 | -keep public class pro.javacard.** { public ; public ; } 10 | -keep public class javacard.** { public ; public ; } 11 | -keep public class javacardx.** { public ; public ; } 12 | -keep public class visa.** { public ; public ; } 13 | -printseeds 14 | -dontnote 15 | -ignorewarnings 16 | --------------------------------------------------------------------------------