├── .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 |
--------------------------------------------------------------------------------