diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..6d9ff20d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+/target/
+# IDEA
+.idea/
+/*.iml
+# Netbeans
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+nbactions.xml
+nb-configuration.xml
+# Eclipse
+.metadata
+.settings/
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..4232215f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,94 @@
+jCardSim (Official repo of the [jCardSim](http://jcardsim.org) project)
+========
+
+### Congratulations! jCardSim has won [Duke's Choice 2013 Award](https://www.java.net//dukeschoice)!
+
+
+
+**Please note** that we moved our code repository from Google Code to GitHub.
+
+jCardSim is an open source simulator for Java Card, v.2.2.1/2:
+
+* `javacard.framework.*`
+* `javacard.framework.security.*`
+* `javacardx.crypto.*`
+
+Key Features:
+
+* Rapid application prototyping
+* Simplifies unit testing (5 lines of code)
+
+```java
+// 1. create simulator
+CardSimulator simulator = new CardSimulator();
+
+// 2. install applet
+AID appletAID = AIDUtil.create("F000000001");
+simulator.installApplet(appletAID, HelloWorldApplet.class);
+
+// 3. select applet
+simulator.selectApplet(appletAID);
+
+// 4. send APDU
+CommandAPDU commandAPDU = new CommandAPDU(0x00, 0x01, 0x00, 0x00);
+ResponseAPDU response = simulator.transmitCommand(commandAPDU);
+
+// 5. check response
+assertEquals(0x9000, response.getSW());
+```
+
+* Emulation of Java Card Terminal, ability to use `javax.smartcardio`
+* APDU scripting (scripts are compatible with `apdutool` from Java Card Development Kit)
+* Simplifies verification tests creation (Common Criteria)
+
+*JavaDoc*: https://jcardsim.googlecode.com/svn/trunk/javadoc/index.html
+
+*Latest stable release 2.2.1*: https://github.com/licel/jcardsim/raw/master/jcardsim-2.2.1-all.jar
+
+*Latest stable release 2.2.2*: https://github.com/licel/jcardsim/raw/master/jcardsim-2.2.2-all.jar
+
+*Maven Central Repository*
+```xml
+
com.licel.jcardsim.base.Simulator
+public class Simulator
public class Simulator
@@ -122,7 +128,7 @@
Simulator()
Simulator object and init base systemsApplet instance in Simulator
+ Create
+ Applet instance in Simulator
+
+ byte[]getATR()
+
+Applet into Simulator without installing dataApplet into Simulator without installing data
Applet into Simulator.Applet into Simulator.
+ AIDinstallApplet(AID aid,
+ String appletClassName,
+ byte[] appletContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
+Applet into Simulator. AIDinstallApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
+Applet into Simulator.Applet into SimulatorApplet into Simulator
+ AIDloadApplet(AID aid,
+ String appletClassName)
+
+Applet into Simulator AIDloadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
+Applet into Simulatorreset()
selectApplet(AID aid)
javax.smartcardio.ResponseAPDUtransmitCommand(javax.smartcardio.CommandAPDU commandAPDU)
+ byte[]transmitCommand(byte[] command)
public Simulator()
Simulator object and init base systems
+
+public AID loadApplet(AID aid, + String appletClassName, + byte[] appletJarContents) + throws SystemException+
JavaCardInterfaceApplet into Simulator
++
loadApplet in interface JavaCardInterfaceaid - applet aidappletClassName - fully qualified applet class name StrinappletJarContents - contains a byte array containing a jar file with an applet and its dependent classes
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID loadApplet(AID aid, + String appletClassName) + throws SystemException+
JavaCardInterfaceApplet into Simulator
++
loadApplet in interface JavaCardInterfaceaid - applet aid
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet@@ -257,13 +372,17 @@Class appletClass) throws SystemException
Applet into Simulator
+Applet into Simulator
aid - applet aidappletClass - applet class
AID
SystemException - if appletClass not instanceof
+SystemException - if appletClass not instanceof
javacard.framework.AppletApplet instance in Simulator
+JavaCardInterfaceApplet instance in Simulator
createApplet in interface JavaCardInterfaceaid - applet aidbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
AID
Applet into Simulator without installing data
+Applet into Simulator without installing data
aid - applet aid or nullappletClass - applet class
AID
SystemException - if appletClass not instanceof
+SystemException - if appletClass not instanceof
javacard.framework.AppletApplet into Simulator.
- This method is equal to:
+Applet into Simulator. This method is equal to:
loadApplet(...);
createApplet(...);
aid - applet aid or nullappletClass - applet classbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
AID
SystemException - if appletClass not instanceof
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID installApplet(AID aid, + String appletClassName, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
JavaCardInterfaceApplet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
installApplet in interface JavaCardInterfaceaid - applet aid or nullappletClassName - fully qualified applet class name StrinbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID installApplet(AID aid, + String appletClassName, + byte[] appletContents, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
JavaCardInterfaceApplet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
installApplet in interface JavaCardInterfaceaid - applet aid or nullappletClassName - fully qualified applet class name StrinappletContents - Contains a byte array containing a jar file with an applet and its dependent classesbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
javacard.framework.AppletJavaCardInterface
selectApplet in interface JavaCardInterfaceaid - appletId
-public javax.smartcardio.ResponseAPDU transmitCommand(javax.smartcardio.CommandAPDU commandAPDU) - throws SystemException+public byte[] transmitCommand(byte[] command) + throws SystemException
CardInterface
commandAPDU - command apdu
+transmitCommand in interface CardInterfaceSystemException.ILLEGAL_USE - if appplet not selected before
SystemExceptionCommandAPDU,
ResponseAPDUpublic void reset()
CardInterface
reset in interface CardInterface-public void resetRuntime()+public final void resetRuntime()
+public byte[] getATR()+
CardInterface+
getATR in interface CardInterfacestatic shortreceiveAPDU(byte[] buffer,
- short bOff)
-
-static voidregisterApplet(Applet applet)
@@ -1016,18 +1007,6 @@ -public static short receiveAPDU(byte[] buffer, - short bOff)-
diff --git a/javadoc/com/licel/jcardsim/base/TransientMemory.html b/javadoc/com/licel/jcardsim/base/TransientMemory.html index 21a70a93..ae80caeb 100644 --- a/javadoc/com/licel/jcardsim/base/TransientMemory.html +++ b/javadoc/com/licel/jcardsim/base/TransientMemory.html @@ -2,13 +2,13 @@ - +TransientMemory (Java Card Runime Environment Simulator 2.2.1-SNAPSHOT API) - + diff --git a/javadoc/com/licel/jcardsim/base/class-use/Simulator.html b/javadoc/com/licel/jcardsim/base/class-use/Simulator.html index 8053b766..552ec0a3 100644 --- a/javadoc/com/licel/jcardsim/base/class-use/Simulator.html +++ b/javadoc/com/licel/jcardsim/base/class-use/Simulator.html @@ -2,13 +2,13 @@ - +Uses of Class com.licel.jcardsim.base.Simulator (Java Card Runime Environment Simulator 2.2.1-SNAPSHOT API) - + @@ -84,7 +84,43 @@Uses of Class
-No usage of com.licel.jcardsim.base.Simulator + +
com.licel.jcardsim.base.Simulator
| +Packages that use Simulator | +|
|---|---|
| com.licel.jcardsim.io | ++ |
| +Uses of Simulator in com.licel.jcardsim.io | +
|---|
+ +
| Subclasses of Simulator in com.licel.jcardsim.io | +|
|---|---|
+ class |
+JavaxSmartCardInterface
+
++ Class with javacardx.smartcardio Command/Response support |
+
| +Packages that use com.licel.jcardsim.base | +|
|---|---|
| com.licel.jcardsim.io | ++ |
| +Classes in com.licel.jcardsim.base used by com.licel.jcardsim.io | +|
|---|---|
| Simulator
+
+ + Main class for deal with Applets |
+|
com.licel.jcardsim.crypto.DSAKeyImpl
org.bouncycastle.crypto.KeyGenerationParametersgetKeyGenerationParameters(SecureRandom rnd)
+
+DSAKeyGenerationParameters shortgetP(byte[] buffer,
short offset)
@@ -614,13 +623,31 @@ DSAKeyParameters
getParameters in interface KeyWithParameters
DSAKeyParameters+public org.bouncycastle.crypto.KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd)+
DSAKeyGenerationParameters
++
getKeyGenerationParameters in interface KeyWithParametersrnd - Secure Random Generator
+public class DSAPrivateKeyImpl
public class DSAPrivateKeyImpl
@@ -234,7 +234,7 @@
getG, getP, getQ, setG, setP, setQgetG, getKeyGenerationParameters, getP, getQ, setG, setP, setQpublic class DSAPublicKeyImpl
public class DSAPublicKeyImpl
@@ -234,7 +234,7 @@
getG, getP, getQ, setG, setP, setQgetG, getKeyGenerationParameters, getP, getQ, setG, setP, setQ
com.licel.jcardsim.crypto.ECKeyImpl
-Base class for ECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPI
+Base class for
+ ECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPI
@@ -281,7 +281,8 @@
getDomainParameters()
ECDomainParametersECDomainParameters
org.bouncycastle.crypto.KeyGenerationParametersgetKeyGenerationParameters(SecureRandom rnd)
+
+ECKeyGenerationParameters shortgetR(byte[] buffer,
short offset)
@@ -428,6 +438,15 @@ clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait| Methods inherited from interface com.licel.jcardsim.crypto.KeyWithParameters | +
|---|
getParameters |
+
@@ -559,7 +578,7 @@
keyType - - key typekeySize - - key size in bitsKeyPair,
+keyType - - key typekeySize - - key size in bitsKeyPair,
KeyBuilderpublic ECKeyImpl(org.bouncycastle.crypto.params.ECKeyParameters parameters)
KeyPair,
+KeyPair,
ECKeyParameterspublic org.bouncycastle.crypto.params.ECDomainParameters getDomainParameters()
ECDomainParameters
+ECDomainParameters
ECDomainParameters+public org.bouncycastle.crypto.KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd)+
ECKeyGenerationParameters
++
getKeyGenerationParameters in interface KeyWithParametersrnd - Secure Random Generator
+public class ECPrivateKeyImpl
public class ECPrivateKeyImpl
@@ -235,7 +235,7 @@
getA, getB, getDomainParameters, getField, getG, getK, getR, setA, setB, setFieldF2M, setFieldF2M, setFieldFP, setG, setK, setRgetA, getB, getDomainParameters, getField, getG, getK, getKeyGenerationParameters, getR, setA, setB, setFieldF2M, setFieldF2M, setFieldFP, setG, setK, setRpublic class ECPublicKeyImpl
public class ECPublicKeyImpl
@@ -235,7 +235,7 @@
getA, getB, getDomainParameters, getField, getG, getK, getR, setA, setB, setFieldF2M, setFieldF2M, setFieldFP, setG, setK, setRgetA, getB, getDomainParameters, getField, getG, getK, getKeyGenerationParameters, getR, setA, setB, setFieldF2M, setFieldF2M, setFieldFP, setG, setK, setR
com.licel.jcardsim.crypto.KeyImpl
public abstract class KeyImpl
public abstract class KeyImpl
@@ -202,6 +202,15 @@
clearKey, isInitialized| Methods inherited from interface com.licel.jcardsim.crypto.KeyWithParameters | +
|---|
getKeyGenerationParameters, getParameters |
+
diff --git a/javadoc/com/licel/jcardsim/crypto/KeyPairImpl.html b/javadoc/com/licel/jcardsim/crypto/KeyPairImpl.html index 05174678..f7e7eda2 100644 --- a/javadoc/com/licel/jcardsim/crypto/KeyPairImpl.html +++ b/javadoc/com/licel/jcardsim/crypto/KeyPairImpl.html @@ -2,13 +2,13 @@
- +
-Implementation KeyPair based
- on BouncyCastle CryptoAPI
+Implementation
+ KeyPair based on BouncyCastle CryptoAPI
@@ -129,7 +129,8 @@
KeyPair instance for the specified algorithm and keylength;
+ Constructs a
+ KeyPair instance for the specified algorithm and keylength;
the encapsulated keys are uninitialized.
KeyPair object containing the specified
- public key and private key.
+ Constructs a new
+ KeyPair object containing the specified public key and
+ private key.
genKeyPair()
KeyPair instance
- with new key values.KeyPair instance with new key values.
getPrivate()
KeyPair object.KeyPair object.getPublic()
KeyPair object.KeyPair object.KeyPair instance for the specified algorithm and keylength;
- the encapsulated keys are uninitialized.
- To initialize the KeyPair instance use the genKeyPair() method.
- The encapsulated key objects are of the specified keyLength size and
- implement the appropriate Key interface associated with the specified algorithm
- (example - RSAPublicKey interface for the public key and RSAPrivateKey
- interface for the private key within an ALG_RSA key pair).
-
Notes:
KeyPair object
- need not support the KeyEncryption interface.
- KeyPair instance for the specified algorithm and keylength;
+ the encapsulated keys are uninitialized. To initialize the
+ KeyPair instance use the
+ genKeyPair() method. The encapsulated key objects are of
+ the specified
+ keyLength size and implement the appropriate
+ Key interface associated with the specified algorithm
+ (example -
+ RSAPublicKey interface for the public key and
+ RSAPrivateKey interface for the private key within an
+ ALG_RSA key pair).
Notes:
KeyPair object need
+ not support the KeyEncryption interface.
algorithm - the type of algorithm whose key pair needs to be generated.
- Valid codes listed in ALG_.. constants above. KeyPairkeyLength - the key size in bits. The valid key bit lengths are key type dependent.
- See the KeyBuilder class.
+algorithm - the type of algorithm whose key pair needs to be
+ generated. Valid codes listed in ALG_.. constants above.
+ KeyPairkeyLength - the key size in bits. The valid key bit lengths are key
+ type dependent. See the KeyBuilder class.
CryptoException - with the following reason codes:CryptoException.NO_SUCH_ALGORITHM if the requested algorithm
- associated with the specified type, size of key is not supported.KeyBuilder,
+ CryptoException.NO_SUCH_ALGORITHM if the requested
+ algorithm associated with the specified type, size of key is not
+ supported.KeyBuilder,
KeyBuilder,
Signature,
KeyEncryption,
@@ -239,21 +248,21 @@ KeyPair object containing the specified
- public key and private key.
- Note that this constructor only stores references to the public
- and private key components in the generated KeyPair object. It
- does not throw an exception if the key parameter objects are uninitialized.
+
KeyPair object containing the specified public key and
+ private key. Note that this constructor only stores references to the
+ public and private key components in the generated
+ KeyPair object. It does not throw an exception if the key
+ parameter objects are uninitialized.
publicKey - the public key.privateKey - the private key.
CryptoException - with the following reason codes:CryptoException.ILLEGAL_VALUE if the input parameter key
- objects are inconsistent with each other - i.e mismatched algorithm, size etc.
- CryptoException.NO_SUCH_ALGORITHM if the algorithm
- associated with the specified type, size of key is not supported.
- CryptoException.NO_SUCH_ALGORITHM if the algorithm
+ associated with the specified type, size of key is not supported. KeyPair instance
- with new key values. The initialized public and private key objects
- encapsulated in this instance will then be suitable for use with the
- Signature, Cipher and KeyAgreement objects.
- An internal secure random number generator is used during new key pair generation.
- Notes:
KeyPair instance with new key values. The initialized public
+ and private key objects encapsulated in this instance will then be
+ suitable for use with the
+ Signature,
+ Cipher and
+ KeyAgreement objects. An internal secure random number
+ generator is used during new key pair generation. Notes:
CryptoException - with the following reason codes:CryptoException.ILLEGAL_VALUE if the exponent
- value parameter in RSA or the p, q, g parameter set in DSA or
- the Field, A, B, G and R parameter set in EC is invalid.
- APDU,
+ CryptoException.ILLEGAL_VALUE if the exponent value
+ parameter in RSA or the p, q, g parameter set in DSA or the Field, A, B,
+ G and R parameter set in EC is invalid. APDU,
Signature,
Cipher,
RSAPublicKey,
@@ -315,7 +326,8 @@ public PublicKey getPublic()
KeyPair object.
+KeyPair object.
public PrivateKey getPrivate()
KeyPair object.
+KeyPair object.
org.bouncycastle.crypto.KeyGenerationParametersgetKeyGenerationParameters(SecureRandom rnd)
+
+ org.bouncycastle.crypto.CipherParametersgetParameters()
org.bouncycastle.crypto.CipherParameters getParameters()
+
+org.bouncycastle.crypto.KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd)+
public class RSAKeyImpl
public class RSAKeyImpl
-Implementation RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPI
+Implementation
+ RSAPublic/RSAPrivate based on BouncyCastle CryptoAPI
@@ -214,6 +214,15 @@
org.bouncycastle.crypto.KeyGenerationParametersgetKeyGenerationParameters(SecureRandom rnd)
+
+RSAKeyGenerationParameters shortgetModulus(byte[] buffer,
short offset)
@@ -227,7 +236,8 @@ getParameters()
RSAKeyParametersRSAKeyParameterspublic RSAKeyImpl(org.bouncycastle.crypto.params.RSAKeyParameters params)
params - key params from BouncyCastle APIKeyPair,
@@ -530,7 +540,8 @@ public org.bouncycastle.crypto.CipherParameters getParameters()
RSAKeyParameters
+RSAKeyParameters
getParameters in interface KeyWithParametersRSAKeyParameters+public org.bouncycastle.crypto.KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd)+
RSAKeyGenerationParameters
++
getKeyGenerationParameters in interface KeyWithParametersrnd - Secure Random Generator
+getParameters()
RSAKeyParametersRSAKeyParametersgetExponent, getModulus, setExponent, setModulusgetExponent, getKeyGenerationParameters, getModulus, setExponent, setModulusRSAKeyImplRSAKeyParameters
+RSAKeyParameters
getParameters in interface KeyWithParametersgetParameters in class RSAKeyImplpublic class SymmetricKeyImpl
public class SymmetricKeyImpl
@@ -195,6 +195,14 @@
org.bouncycastle.crypto.KeyGenerationParametersgetKeyGenerationParameters(SecureRandom rnd)
+
+ org.bouncycastle.crypto.CipherParametersgetParameters()
@@ -424,6 +432,24 @@ true if the key has been initialized
+public org.bouncycastle.crypto.KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd)+
KeyWithParameters+
getKeyGenerationParameters in interface KeyWithParametersECKeyImpl
ECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPIRSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPI classDSAKeyImpl
+
+DSAPublicKeyImpl/DSAPrivateKeyImpl
+ on BouncyCastle CryptoAPI classDSAPrivateKeyImpl
classECKeyImpl
+
+ECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPI classECPrivateKeyImpl
classKeyImpl
+
+Key instances classRSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPI
ECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPIKeyPair based
- on BouncyCastle CryptoAPIKeyPair based on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPI
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+java.lang.Object ++com.licel.jcardsim.io.CAD +
public class CAD
+Card Acceptance Device (CAD) +
+ +
+
| +Field Summary | +|
|---|---|
+static byte |
+INTERNAL
+
++ |
+
+static byte |
+JAVAX_SMARTCARDIO
+
++ |
+
+static byte |
+RMI
+
++ |
+
| +Constructor Summary | +|
|---|---|
CAD(Properties params)
+
++ |
+|
| +Method Summary | +|
|---|---|
+ CardInterface |
+getCardInterface()
+
++ |
+
| Methods inherited from class java.lang.Object | +
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
+
| +Field Detail | +
|---|
+public static final byte INTERNAL+
+public static final byte RMI+
+public static final byte JAVAX_SMARTCARDIO+
| +Constructor Detail | +
|---|
+public CAD(Properties params)+
| +Method Detail | +
|---|
+public CardInterface getCardInterface()+
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
public interface CardInterface
+Basic SmartCard Interface +
+ +
+
| +Method Summary | +|
|---|---|
+ byte[] |
+getATR()
+
++ Returns ATR |
+
+ void |
+reset()
+
++ Powerdown/Powerup |
+
+ byte[] |
+transmitCommand(byte[] data)
+
++ Transmit APDU to previous selected applet |
+
| +Method Detail | +
|---|
+void reset()+
+
+byte[] getATR()+
+
+byte[] transmitCommand(byte[] data)+
+
commandAPDU - command apdu
+SystemException.ILLEGAL_USE - if appplet not selected beforeCommandAPDU,
+ResponseAPDU
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
public interface JavaCardInterface
+Interface with JavaCard-specific functions +
+ +
+
| +Method Summary | +|
|---|---|
+ AID |
+createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Create + Applet instance in Simulator |
+
+ AID |
+installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+loadApplet(AID aid,
+ String appletClass)
+
++ Load + Applet into Simulator |
+
+ AID |
+loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Load + Applet into Simulator |
+
+ boolean |
+selectApplet(AID aid)
+
++ Select applet by it's AID + It's method must be called before start working with applet instance |
+
| Methods inherited from interface com.licel.jcardsim.io.CardInterface | +
|---|
getATR, reset, transmitCommand |
+
| +Method Detail | +
|---|
+AID loadApplet(AID aid, + String appletClassName, + byte[] appletJarContents) + throws SystemException+
Applet into Simulator
++
aid - applet aidappletClassName - fully qualified applet class name StrinappletJarContents - contains a byte array containing a jar file with an applet and its dependent classes
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+AID loadApplet(AID aid, + String appletClass)+
Applet into Simulator
++
aid - applet aidappletClassName - fully qualified applet class name Strin
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+AID createApplet(AID aid, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
Applet instance in Simulator
++
aid - applet aidbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if exception in Applet.install(..)
+ method occurs.+AID installApplet(AID aid, + String appletClassName, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
Applet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
aid - applet aid or nullappletClassName - fully qualified applet class name StrinbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+AID installApplet(AID aid, + String appletClassName, + byte[] appletJarContents, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
Applet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
aid - applet aid or nullappletClassName - fully qualified applet class name StrinappletJarContents - Contains a byte array containing a jar file with an applet and its dependent classesbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+boolean selectApplet(AID aid)+
+
aid - appletId
+
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+java.lang.Object ++com.licel.jcardsim.base.Simulator +
com.licel.jcardsim.io.JavaxSmartCardInterface +
public class JavaxSmartCardInterface
+Class with javacardx.smartcardio Command/Response support +
+ +
+
| +Constructor Summary | +|
|---|---|
JavaxSmartCardInterface()
+
++ |
+|
| +Method Summary | +|
|---|---|
+ javax.smartcardio.ResponseAPDU |
+transmitCommand(javax.smartcardio.CommandAPDU commandApdu)
+
++ Wraper for the transmitCommand(byte[]) |
+
| Methods inherited from class com.licel.jcardsim.base.Simulator | +
|---|
createApplet, getATR, installApplet, installApplet, installApplet, installApplet, loadApplet, loadApplet, loadApplet, reset, resetRuntime, selectApplet, transmitCommand |
+
| Methods inherited from class java.lang.Object | +
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
+
| +Constructor Detail | +
|---|
+public JavaxSmartCardInterface()+
| +Method Detail | +
|---|
+public javax.smartcardio.ResponseAPDU transmitCommand(javax.smartcardio.CommandAPDU commandApdu)+
+
commandApdu - CommandAPDU
+
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use CardInterface | +|
|---|---|
| com.licel.jcardsim.base | ++ |
| com.licel.jcardsim.io | ++ |
| com.licel.jcardsim.remote | ++ |
| +Uses of CardInterface in com.licel.jcardsim.base | +
|---|
+ +
| Classes in com.licel.jcardsim.base that implement CardInterface | +|
|---|---|
+ class |
+Simulator
+
++ Main class for deal with Applets |
+
| +Uses of CardInterface in com.licel.jcardsim.io | +
|---|
+ +
| Subinterfaces of CardInterface in com.licel.jcardsim.io | +|
|---|---|
+ interface |
+JavaCardInterface
+
++ Interface with JavaCard-specific functions |
+
+ +
| Classes in com.licel.jcardsim.io that implement CardInterface | +|
|---|---|
+ class |
+JavaxSmartCardInterface
+
++ Class with javacardx.smartcardio Command/Response support |
+
+ +
| Methods in com.licel.jcardsim.io that return CardInterface | +|
|---|---|
+ CardInterface |
+CAD.getCardInterface()
+
++ |
+
| +Uses of CardInterface in com.licel.jcardsim.remote | +
|---|
+ +
| Classes in com.licel.jcardsim.remote that implement CardInterface | +|
|---|---|
+ class |
+JavaCardRemoteClient
+
++ RMI client |
+
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use JavaCardInterface | +|
|---|---|
| com.licel.jcardsim.base | ++ |
| com.licel.jcardsim.io | ++ |
| com.licel.jcardsim.remote | ++ |
| com.licel.jcardsim.smartcardio | ++ |
| +Uses of JavaCardInterface in com.licel.jcardsim.base | +
|---|
+ +
| Classes in com.licel.jcardsim.base that implement JavaCardInterface | +|
|---|---|
+ class |
+Simulator
+
++ Main class for deal with Applets |
+
| +Uses of JavaCardInterface in com.licel.jcardsim.io | +
|---|
+ +
| Classes in com.licel.jcardsim.io that implement JavaCardInterface | +|
|---|---|
+ class |
+JavaxSmartCardInterface
+
++ Class with javacardx.smartcardio Command/Response support |
+
| +Uses of JavaCardInterface in com.licel.jcardsim.remote | +
|---|
+ +
| Classes in com.licel.jcardsim.remote that implement JavaCardInterface | +|
|---|---|
+ class |
+JavaCardRemoteClient
+
++ RMI client |
+
| +Uses of JavaCardInterface in com.licel.jcardsim.smartcardio | +
|---|
+ +
| Constructors in com.licel.jcardsim.smartcardio with parameters of type JavaCardInterface | +|
|---|---|
JCSCard(JavaCardInterface cardInterface)
+
++ |
+|
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
|
+Interfaces
+
+ +CardInterface + +JavaCardInterface |
+
|
+Classes
+
+ +CAD + +JavaxSmartCardInterface |
+
+
+
|
++ + | +|||||||||
| + PREV PACKAGE + NEXT PACKAGE | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Interface Summary | +|
|---|---|
| CardInterface | +Basic SmartCard Interface | +
| JavaCardInterface | +Interface with JavaCard-specific functions | +
+ +
| +Class Summary | +|
|---|---|
| CAD | +Card Acceptance Device (CAD) | +
| JavaxSmartCardInterface | +Class with javacardx.smartcardio Command/Response support | +
+
+
+
|
++Â + | +|||||||||
| + PREV PACKAGE + NEXT PACKAGE | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use com.licel.jcardsim.io | +|
|---|---|
| com.licel.jcardsim.base | ++ |
| com.licel.jcardsim.io | ++ |
| com.licel.jcardsim.remote | ++ |
| com.licel.jcardsim.smartcardio | ++ |
| +Classes in com.licel.jcardsim.io used by com.licel.jcardsim.base | +|
|---|---|
| CardInterface
+
+ + Basic SmartCard Interface |
+|
| JavaCardInterface
+
+ + Interface with JavaCard-specific functions |
+|
| +Classes in com.licel.jcardsim.io used by com.licel.jcardsim.io | +|
|---|---|
| CardInterface
+
+ + Basic SmartCard Interface |
+|
| JavaCardInterface
+
+ + Interface with JavaCard-specific functions |
+|
| +Classes in com.licel.jcardsim.io used by com.licel.jcardsim.remote | +|
|---|---|
| CardInterface
+
+ + Basic SmartCard Interface |
+|
| JavaCardInterface
+
+ + Interface with JavaCard-specific functions |
+|
| +Classes in com.licel.jcardsim.io used by com.licel.jcardsim.smartcardio | +|
|---|---|
| JavaCardInterface
+
+ + Interface with JavaCard-specific functions |
+|
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+java.lang.Object ++com.licel.jcardsim.remote.JavaCardRemoteClient +
public class JavaCardRemoteClient
+RMI client +
+ +
+
| +Constructor Summary | +|
|---|---|
JavaCardRemoteClient(String serverHost,
+ int serverIp)
+
++ |
+|
| +Method Summary | +|
|---|---|
+ AID |
+createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Create + Applet instance in Simulator |
+
+ byte[] |
+getATR()
+
++ Returns ATR |
+
+ AID |
+installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+loadApplet(AID aid,
+ String appletClassName)
+
++ Load + Applet into Simulator |
+
+ AID |
+loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Load + Applet into Simulator |
+
+ void |
+reset()
+
++ Powerdown/Powerup |
+
+ boolean |
+selectApplet(AID aid)
+
++ Select applet by it's AID + It's method must be called before start working with applet instance |
+
+ byte[] |
+transmitCommand(byte[] data)
+
++ Transmit APDU to previous selected applet |
+
| Methods inherited from class java.lang.Object | +
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
+
| +Constructor Detail | +
|---|
+public JavaCardRemoteClient(String serverHost, + int serverIp) + throws RemoteException, + NotBoundException+
RemoteException
+NotBoundException| +Method Detail | +
|---|
+public AID loadApplet(AID aid, + String appletClassName) + throws SystemException+
JavaCardInterfaceApplet into Simulator
++
loadApplet in interface JavaCardInterfaceaid - applet aid
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID loadApplet(AID aid, + String appletClassName, + byte[] appletJarContents) + throws SystemException+
JavaCardInterfaceApplet into Simulator
++
loadApplet in interface JavaCardInterfaceaid - applet aidappletClassName - fully qualified applet class name StrinappletJarContents - contains a byte array containing a jar file with an applet and its dependent classes
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID createApplet(AID aid, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
JavaCardInterfaceApplet instance in Simulator
++
createApplet in interface JavaCardInterfaceaid - applet aidbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if exception in Applet.install(..)
+ method occurs.+public AID installApplet(AID aid, + String appletClassName, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
JavaCardInterfaceApplet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
installApplet in interface JavaCardInterfaceaid - applet aid or nullappletClassName - fully qualified applet class name StrinbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public AID installApplet(AID aid, + String appletClassName, + byte[] appletJarContents, + byte[] bArray, + short bOffset, + byte bLength) + throws SystemException+
JavaCardInterfaceApplet into Simulator.
+ This method is equal to:
+
+ loadApplet(...);
+ createApplet(...);
+
++
installApplet in interface JavaCardInterfaceaid - applet aid or nullappletClassName - fully qualified applet class name StrinappletJarContents - Contains a byte array containing a jar file with an applet and its dependent classesbArray - the array containing installation parametersbOffset - the starting offset in bArraybLength - the length in bytes of the parameter data in bArray
+AID
+SystemException - if appletClass not instanceof
+ javacard.framework.Applet+public boolean selectApplet(AID aid)+
JavaCardInterface+
selectApplet in interface JavaCardInterfaceaid - appletId
++public byte[] getATR()+
CardInterface+
getATR in interface CardInterface+public byte[] transmitCommand(byte[] data)+
CardInterface+
transmitCommand in interface CardInterfaceCommandAPDU,
+ResponseAPDU+public void reset()+
CardInterface+
reset in interface CardInterface
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
public interface JavaCardRemoteInterface
+RMI Wrapper for the JavaCardInterface
+
+ +
+
| +Field Summary | +|
|---|---|
+static String |
+RMI_SERVER_ID
+
++ |
+
| +Method Summary | +|
|---|---|
+ SerializableAID |
+createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ byte[] |
+getATR()
+
++ |
+
+ SerializableAID |
+loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ |
+
+ SerializableAID |
+loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
+
+ void |
+reset()
+
++ |
+
+ boolean |
+selectApplet(SerializableAID aid)
+
++ |
+
+ byte[] |
+transmitCommand(byte[] data)
+
++ |
+
| +Field Detail | +
|---|
+static final String RMI_SERVER_ID+
| +Method Detail | +
|---|
+SerializableAID loadApplet(SerializableAID aid, + String appletClassName) + throws RemoteException+
RemoteException+SerializableAID loadApplet(SerializableAID aid, + String appletClassName, + byte[] appletJarContents) + throws RemoteException+
RemoteException+SerializableAID createApplet(SerializableAID aid, + byte[] bArray, + short bOffset, + byte bLength) + throws RemoteException+
RemoteException+byte[] transmitCommand(byte[] data) + throws RemoteException+
RemoteException+boolean selectApplet(SerializableAID aid) + throws RemoteException+
RemoteException+void reset() + throws RemoteException+
RemoteException+byte[] getATR() + throws RemoteException+
RemoteException
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+java.lang.Object ++java.rmi.server.RemoteObject +
java.rmi.server.RemoteServer +
java.rmi.server.UnicastRemoteObject +
com.licel.jcardsim.remote.JavaCardRemoteServer +
public class JavaCardRemoteServer
+RMI Server +
+ +
+
| +Field Summary | +
|---|
| Fields inherited from class java.rmi.server.RemoteObject | +
|---|
ref |
+
| Fields inherited from interface com.licel.jcardsim.remote.JavaCardRemoteInterface | +
|---|
RMI_SERVER_ID |
+
| +Constructor Summary | +|
|---|---|
JavaCardRemoteServer(String host,
+ int port)
+
++ |
+|
| +Method Summary | +|
|---|---|
+ SerializableAID |
+createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Imlementation |
+
+ byte[] |
+getATR()
+
++ Imlementation |
+
+ SerializableAID |
+loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ Imlementation |
+
+ SerializableAID |
+loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Imlementation |
+
+static void |
+main(String[] args)
+
++ |
+
+ void |
+reset()
+
++ Imlementation |
+
+ boolean |
+selectApplet(SerializableAID aid)
+
++ Imlementation |
+
+ byte[] |
+transmitCommand(byte[] data)
+
++ Imlementation |
+
| Methods inherited from class java.rmi.server.UnicastRemoteObject | +
|---|
clone, exportObject, exportObject, exportObject, unexportObject |
+
| Methods inherited from class java.rmi.server.RemoteServer | +
|---|
getClientHost, getLog, setLog |
+
| Methods inherited from class java.rmi.server.RemoteObject | +
|---|
equals, getRef, hashCode, toString, toStub |
+
| Methods inherited from class java.lang.Object | +
|---|
finalize, getClass, notify, notifyAll, wait, wait, wait |
+
| +Constructor Detail | +
|---|
+public JavaCardRemoteServer(String host, + int port) + throws RemoteException+
RemoteException| +Method Detail | +
|---|
+public static void main(String[] args) + throws Exception+
Exception+public SerializableAID loadApplet(SerializableAID aid, + String appletClassName) + throws RemoteException+
+
loadApplet in interface JavaCardRemoteInterfaceRemoteException+public SerializableAID loadApplet(SerializableAID aid, + String appletClassName, + byte[] appletJarContents) + throws RemoteException+
+
loadApplet in interface JavaCardRemoteInterfaceRemoteException+public SerializableAID createApplet(SerializableAID aid, + byte[] bArray, + short bOffset, + byte bLength) + throws RemoteException+
+
createApplet in interface JavaCardRemoteInterfaceRemoteException+public byte[] transmitCommand(byte[] data) + throws RemoteException+
+
transmitCommand in interface JavaCardRemoteInterfaceRemoteException+public boolean selectApplet(SerializableAID aid) + throws RemoteException+
+
selectApplet in interface JavaCardRemoteInterfaceRemoteException+public void reset() + throws RemoteException+
+
reset in interface JavaCardRemoteInterfaceRemoteException+public byte[] getATR() + throws RemoteException+
+
getATR in interface JavaCardRemoteInterfaceRemoteException
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+java.lang.Object ++com.licel.jcardsim.remote.SerializableAID +
public class SerializableAID
+Serializable AID container for the RMI calls +
+ +
+
| +Constructor Summary | +|
|---|---|
SerializableAID()
+
++ |
+|
SerializableAID(AID aid)
+
++ |
+|
| +Method Summary | +|
|---|---|
+ AID |
+getAID()
+
++ |
+
| Methods inherited from class java.lang.Object | +
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
+
| +Constructor Detail | +
|---|
+public SerializableAID()+
+public SerializableAID(AID aid)+
| +Method Detail | +
|---|
+public AID getAID()+
+
+
|
++Â + | +|||||||||
| + PREV CLASS + NEXT CLASS | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| + SUMMARY: NESTED | FIELD | CONSTR | METHOD | ++DETAIL: FIELD | CONSTR | METHOD | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use JavaCardRemoteInterface | +|
|---|---|
| com.licel.jcardsim.remote | ++ |
| +Uses of JavaCardRemoteInterface in com.licel.jcardsim.remote | +
|---|
+ +
| Classes in com.licel.jcardsim.remote that implement JavaCardRemoteInterface | +|
|---|---|
+ class |
+JavaCardRemoteServer
+
++ RMI Server |
+
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use SerializableAID | +|
|---|---|
| com.licel.jcardsim.remote | ++ |
| +Uses of SerializableAID in com.licel.jcardsim.remote | +
|---|
+ +
| Methods in com.licel.jcardsim.remote that return SerializableAID | +|
|---|---|
+ SerializableAID |
+JavaCardRemoteServer.createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ SerializableAID |
+JavaCardRemoteServer.loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ |
+
+ SerializableAID |
+JavaCardRemoteServer.loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
+
+ +
| Methods in com.licel.jcardsim.remote with parameters of type SerializableAID | +|
|---|---|
+ SerializableAID |
+JavaCardRemoteServer.createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.createApplet(SerializableAID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ SerializableAID |
+JavaCardRemoteServer.loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.loadApplet(SerializableAID aid,
+ String appletClassName)
+
++ |
+
+ SerializableAID |
+JavaCardRemoteServer.loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Imlementation |
+
+ SerializableAID |
+JavaCardRemoteInterface.loadApplet(SerializableAID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
+
+ boolean |
+JavaCardRemoteServer.selectApplet(SerializableAID aid)
+
++ Imlementation |
+
+ boolean |
+JavaCardRemoteInterface.selectApplet(SerializableAID aid)
+
++ |
+
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
|
+Interfaces
+
+ +JavaCardRemoteInterface |
+
|
+Classes
+
+ +JavaCardRemoteClient + +JavaCardRemoteServer + +SerializableAID |
+
+
+
|
++ + | +|||||||||
| + PREV PACKAGE + NEXT PACKAGE | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Interface Summary | +|
|---|---|
| JavaCardRemoteInterface | +RMI Wrapper for the JavaCardInterface |
+
+ +
| +Class Summary | +|
|---|---|
| JavaCardRemoteClient | +RMI client | +
| JavaCardRemoteServer | +RMI Server | +
| SerializableAID | +Serializable AID container for the RMI calls | +
+
+
+
|
++Â + | +|||||||||
| + PREV PACKAGE + NEXT PACKAGE | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
+
+
|
++ + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
| +Packages that use com.licel.jcardsim.remote | +|
|---|---|
| com.licel.jcardsim.remote | ++ |
| +Classes in com.licel.jcardsim.remote used by com.licel.jcardsim.remote | +|
|---|---|
| JavaCardRemoteInterface
+
+ + RMI Wrapper for the JavaCardInterface |
+|
| SerializableAID
+
+ + Serializable AID container for the RMI calls |
+|
+
+
+
|
++Â + | +|||||||||
| + PREV + NEXT | ++ FRAMES + NO FRAMES + + + + + | +|||||||||
JCSCard()
+JCSCard(JavaCardInterface cardInterface)
getATR()
-public JCSCard()+public JCSCard(JavaCardInterface cardInterface)
public javax.smartcardio.ATR getATR()
getATR in class javax.smartcardio.Card| com.licel.jcardsim.samples.odSample.packageA.A | +com.licel.jcardsim.io.CAD | ||||
|---|---|---|---|---|---|
| + |
public static final byte |
-A_CLA |
--64 |
-||
- -
- -
| com.licel.jcardsim.samples.photocard.PhotoCard | -||
|---|---|---|
-public static final short |
-INVALID_ARGUMENT |
-24579 |
-
-public static final short |
-INVALID_PHOTO_ID |
-24578 |
-
-public static final short |
-MAX_BUFFER_BYTES |
-96 |
-
-public static final short |
-MAX_PHOTO_COUNT |
-4 |
-
-public static final short |
-MAX_SIZE |
-32767 |
-
-public static final short |
-NO_PHOTO_STORED |
-24577 |
-
-public static final short |
-NO_SPACE_AVAILABLE |
-24576 |
-
- -
- -
| com.licel.jcardsim.samples.RMIDemo.Purse | -|||||
|---|---|---|---|---|---|
-public static final short |
-BAD_ARGUMENT |
-24578 |
-|||
-public static final short |
-MAX_AMOUNT |
-400 |
+INTERNAL |
+0 |
|
-public static final short |
-OVERFLOW |
-24577 |
+
+public static final byte |
+JAVAX_SMARTCARDIO |
+2 |
-public static final short |
-UNDERFLOW |
-24576 |
+
+public static final byte |
+RMI |
+1 |
| com.licel.jcardsim.samples.SecureRMIDemo.Purse | -|||||
|---|---|---|---|---|---|
-public static final short |
-BAD_ARGUMENT |
-24578 |
-|||
-public static final short |
-CORRUPTED_DATA |
-24580 |
-|||
-public static final short |
-MAX_AMOUNT |
-400 |
-|||
-public static final short |
-OVERFLOW |
-24577 |
+com.licel.jcardsim.remote.JavaCardRemoteInterface | ||
-public static final short |
-REQUEST_DENIED |
-24579 |
-|||
-public static final short |
-UNDERFLOW |
-24576 |
+
+public static final String |
+RMI_SERVER_ID |
+"jCardSim.rmiServer" |
| com.licel.jcardsim.samples.JavaLoyalty | +com.licel.jcardsim.io | ||||
| com.licel.jcardsim.samples.odSample.packageB | +com.licel.jcardsim.remote | ||||
@@ -177,7 +177,8 @@
Class appletClass)
|
+ Install
+ |||||
@@ -189,7 +190,33 @@
byte bLength)
|
+ Install
+ |||||
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+||||
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
||||
@@ -198,7 +225,27 @@
Class appletClass)
|
+ Load
+ |||||
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+||||
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
||||
@@ -248,7 +295,7 @@
byte bLength)
|
+
|||||
@@ -283,7 +330,8 @@
Class appletClass)
|
+ Install
+ |||||
@@ -295,7 +343,33 @@
byte bLength)
|
+ Install
+ |||||
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+||||
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
||||
@@ -322,7 +396,27 @@
Class appletClass)
|
+ Load
+ |||||
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+||||
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
||||
@@ -347,17 +441,16 @@
Simulator.selectApplet(AID aid)
- Select applet by it's AID - It's method must be called before start working with applet instance |
|||||
| -Uses of AID in com.licel.jcardsim.samples.JavaLoyalty | +Uses of AID in com.licel.jcardsim.io
|---|
| Methods in com.licel.jcardsim.samples.JavaLoyalty with parameters of type AID | +Methods in com.licel.jcardsim.io that return AID | ||
|---|---|---|---|
- Shareable |
-JavaLoyalty.getShareableInterfaceObject(AID clientAID,
- byte parameter)
+ AID |
+JavaCardInterface.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Create + Applet instance in Simulator |
+|
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+||
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+||
+ AID |
+JavaCardInterface.loadApplet(AID aid,
+ String appletClass)
+
++ Load + Applet into Simulator |
+||
+ AID |
+JavaCardInterface.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Load + Applet into Simulator |
+||
+ +
| Methods in com.licel.jcardsim.io with parameters of type AID | +|
|---|---|
+ AID |
+JavaCardInterface.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Create + Applet instance in Simulator |
+
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+JavaCardInterface.loadApplet(AID aid,
+ String appletClass)
- Implements getShareableInterfaceObject method of Applet class. |
+ Load
+
+ AID |
+JavaCardInterface.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Load + Applet into Simulator |
+
+ boolean |
+JavaCardInterface.selectApplet(AID aid)
+
++ Select applet by it's AID + It's method must be called before start working with applet instance |
| -Uses of AID in com.licel.jcardsim.samples.odSample.packageB | +Uses of AID in com.licel.jcardsim.remote
|---|
| Methods in com.licel.jcardsim.samples.odSample.packageB with parameters of type AID | +Methods in com.licel.jcardsim.remote that return AID | ||
|---|---|---|---|
- Shareable |
-B.getShareableInterfaceObject(AID client_aid,
- byte param)
+ AID |
+JavaCardRemoteClient.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+|
+ AID |
+SerializableAID.getAID()
+
++ |
+||
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
- method returns pointer to this instance, ignores the param |
+
+||
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+||
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+||
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
+||
+ +
| Methods in com.licel.jcardsim.remote with parameters of type AID | +|
|---|---|
+ AID |
+JavaCardRemoteClient.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
+
+ boolean |
+JavaCardRemoteClient.selectApplet(AID aid)
+
++ |
+
+ +
| Constructors in com.licel.jcardsim.remote with parameters of type AID | +|
|---|---|
SerializableAID(AID aid)
+
++ |
|
| -Uses of APDU in com.licel.jcardsim.samples.ChannelsDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.ChannelsDemo with parameters of type APDU | -|
|---|---|
- void |
-ConnectionManager.process(APDU apdu)
-
-- |
-
- void |
-AccountAccessor.process(APDU apdu)
-
-- |
-
| -Uses of APDU in com.licel.jcardsim.samples.JavaLoyalty | -
|---|
- -
| Methods in com.licel.jcardsim.samples.JavaLoyalty with parameters of type APDU | -|
|---|---|
- void |
-JavaLoyalty.process(APDU apdu)
-
-- Dispatches APDU commands. |
-
| -Uses of APDU in com.licel.jcardsim.samples.JavaPurse | -
|---|
- -
| Methods in com.licel.jcardsim.samples.JavaPurse with parameters of type APDU | -|
|---|---|
- void |
-JavaPurse.process(APDU apdu)
-
-- Dispatches APDU commands. |
-
| -Uses of APDU in com.licel.jcardsim.samples.NullApp | -
|---|
- -
| Methods in com.licel.jcardsim.samples.NullApp with parameters of type APDU | -|
|---|---|
- void |
-NullApp.process(APDU apdu)
-
-- Returns <0x6D,INS> response status always. |
-
- -
| Constructors in com.licel.jcardsim.samples.NullApp with parameters of type APDU | -|
|---|---|
NullApp(APDU apdu)
-
-- Only this class's install method should create the applet object. |
-|
| -Uses of APDU in com.licel.jcardsim.samples.odSample.packageA | -
|---|
- -
| Methods in com.licel.jcardsim.samples.odSample.packageA with parameters of type APDU | -|
|---|---|
- void |
-A.process(APDU apdu)
-
-- method processes the APDU commands passed to this applet instance. |
-
| -Uses of APDU in com.licel.jcardsim.samples.odSample.packageB | -
|---|
- -
| Methods in com.licel.jcardsim.samples.odSample.packageB with parameters of type APDU | -|
|---|---|
- void |
-B.process(APDU apdu)
-
-- method processes the APDU commands passed to this applet instance. |
-
| -Uses of APDU in com.licel.jcardsim.samples.photocard | -
|---|
- -
| Methods in com.licel.jcardsim.samples.photocard with parameters of type APDU | -|
|---|---|
- void |
-PhotoCardApplet.process(APDU apdu)
-
-- |
-
| -Uses of APDU in com.licel.jcardsim.samples.RMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.RMIDemo with parameters of type APDU | -|
|---|---|
- void |
-PurseApplet.process(APDU apdu)
-
-- |
-
| -Uses of APDU in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.SecureRMIDemo with parameters of type APDU | -|
|---|---|
- void |
-SecurePurseApplet.process(APDU apdu)
-
-- |
-
- boolean |
-MySecurityService.processCommand(APDU apdu)
-
-- |
-
- boolean |
-MySecurityService.processDataIn(APDU apdu)
-
-- Pre-processes the input data for the command in the APDU object. |
-
- boolean |
-MySecurityService.processDataOut(APDU apdu)
-
-- |
-
| -Uses of APDU in com.licel.jcardsim.samples.ServiceDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.ServiceDemo with parameters of type APDU | -|
|---|---|
- void |
-Main.process(APDU apdu)
-
-- |
-
- boolean |
-TestService.processCommand(APDU command)
-
-- |
-
| -Uses of APDU in com.licel.jcardsim.samples.wallet | -
|---|
- -
| Methods in com.licel.jcardsim.samples.wallet with parameters of type APDU | -|
|---|---|
- void |
-Wallet.process(APDU apdu)
-
-- |
-
| com.licel.jcardsim.samples | |
| com.licel.jcardsim.samples.ChannelsDemo | -- |
| com.licel.jcardsim.samples.JavaLoyalty | -- |
| com.licel.jcardsim.samples.JavaPurse | -- |
| com.licel.jcardsim.samples.NullApp | -- |
| com.licel.jcardsim.samples.odSample.packageA | -- |
| com.licel.jcardsim.samples.odSample.packageB | -- |
| com.licel.jcardsim.samples.photocard | -- |
| com.licel.jcardsim.samples.RMIDemo | -- |
| com.licel.jcardsim.samples.SecureRMIDemo | -- |
| com.licel.jcardsim.samples.ServiceDemo | -- |
| com.licel.jcardsim.samples.wallet | -- |
@@ -242,301 +198,6 @@
| -Uses of Applet in com.licel.jcardsim.samples.ChannelsDemo | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.ChannelsDemo | -|
|---|---|
- class |
-AccountAccessor
-
-- This applet keeps track of the account information for a - fictional wireless device connecting to a network service. |
-
- class |
-ConnectionManager
-
-- This applet keeps track of the network connection for a - fictional wireless device. |
-
| -Uses of Applet in com.licel.jcardsim.samples.JavaLoyalty | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.JavaLoyalty | -|
|---|---|
- class |
-JavaLoyalty
-
-- Minimalistic loyalty applet. |
-
| -Uses of Applet in com.licel.jcardsim.samples.JavaPurse | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.JavaPurse | -|
|---|---|
- class |
-JavaPurse
-
-- This class is intended to demonstrate how an electronic cash application - might be developed using Java Card - See Java Card(TM) Development Kit User's Guide - for details. |
-
| -Uses of Applet in com.licel.jcardsim.samples.NullApp | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.NullApp | -|
|---|---|
- class |
-NullApp
-
-- |
-
| -Uses of Applet in com.licel.jcardsim.samples.odSample.packageA | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.odSample.packageA | -|
|---|---|
- class |
-A
-
-- package AID 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x01 - applet AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x01 0x01 - - This applet used to demonstrate object deletion mechanism and also to - monitor memory usage as other packages/applets get added/deleted |
-
| -Uses of Applet in com.licel.jcardsim.samples.odSample.packageB | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.odSample.packageB | -|
|---|---|
- class |
-B
-
-- package AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 - applet AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 0x01 - - Applet used to demonstrate applet deletion and package deletion. |
-
| -Uses of Applet in com.licel.jcardsim.samples.photocard | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.photocard | -|
|---|---|
- class |
-PhotoCardApplet
-
-- |
-
| -Uses of Applet in com.licel.jcardsim.samples.RMIDemo | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.RMIDemo | -|
|---|---|
- class |
-PurseApplet
-
-- |
-
| -Uses of Applet in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.SecureRMIDemo | -|
|---|---|
- class |
-SecurePurseApplet
-
-- |
-
| -Uses of Applet in com.licel.jcardsim.samples.ServiceDemo | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.ServiceDemo | -|
|---|---|
- class |
-Main
-
-- |
-
| -Uses of Applet in com.licel.jcardsim.samples.wallet | -
|---|
- -
| Subclasses of Applet in com.licel.jcardsim.samples.wallet | -|
|---|---|
- class |
-Wallet
-
-- |
-
| -Packages that use AppletEvent | -|
|---|---|
| com.licel.jcardsim.samples.odSample.packageB | -- |
| -Uses of AppletEvent in com.licel.jcardsim.samples.odSample.packageB | -
|---|
- -
| Classes in com.licel.jcardsim.samples.odSample.packageB that implement AppletEvent | -|
|---|---|
- class |
-B
-
-- package AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 - applet AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 0x01 - - Applet used to demonstrate applet deletion and package deletion. |
-
| -Uses of ISOException in com.licel.jcardsim.samples.JavaPurseCrypto | -
|---|
- -
| Methods in com.licel.jcardsim.samples.JavaPurseCrypto that throw ISOException | -|
|---|---|
- void |
-ParametersFile.addRecord(byte[] record)
-
-- Add (append) a new record to the file. |
-
| -Uses of ISOException in com.licel.jcardsim.samples.NullApp | -
|---|
- -
| Methods in com.licel.jcardsim.samples.NullApp that throw ISOException | -|
|---|---|
- void |
-NullApp.process(APDU apdu)
-
-- Returns <0x6D,INS> response status always. |
-
| -Uses of ISOException in com.licel.jcardsim.samples.odSample.packageA | -
|---|
- -
| Methods in com.licel.jcardsim.samples.odSample.packageA that throw ISOException | -|
|---|---|
- void |
-A.process(APDU apdu)
-
-- method processes the APDU commands passed to this applet instance. |
-
| -Uses of ISOException in com.licel.jcardsim.samples.odSample.packageB | -
|---|
- -
| Methods in com.licel.jcardsim.samples.odSample.packageB that throw ISOException | -|
|---|---|
- void |
-B.process(APDU apdu)
-
-- method processes the APDU commands passed to this applet instance. |
-
| -Uses of ISOException in com.licel.jcardsim.samples.photocard | -
|---|
- -
| Methods in com.licel.jcardsim.samples.photocard that throw ISOException | -|
|---|---|
- void |
-PhotoCardApplet.process(APDU apdu)
-
-- |
-
| -Uses of ISOException in com.licel.jcardsim.samples.RMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.RMIDemo that throw ISOException | -|
|---|---|
- void |
-PurseApplet.process(APDU apdu)
-
-- |
-
| -Uses of ISOException in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.SecureRMIDemo that throw ISOException | -|
|---|---|
- void |
-SecurePurseApplet.process(APDU apdu)
-
-- |
-
| -Uses of ISOException in com.licel.jcardsim.samples.ServiceDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.ServiceDemo that throw ISOException | -|
|---|---|
- void |
-Main.process(APDU apdu)
-
-- |
-
| -Packages that use MultiSelectable | -|
|---|---|
| com.licel.jcardsim.samples.ChannelsDemo | -- |
| -Uses of MultiSelectable in com.licel.jcardsim.samples.ChannelsDemo | -
|---|
- -
| Classes in com.licel.jcardsim.samples.ChannelsDemo that implement MultiSelectable | -|
|---|---|
- class |
-AccountAccessor
-
-- This applet keeps track of the account information for a - fictional wireless device connecting to a network service. |
-
- class |
-ConnectionManager
-
-- This applet keeps track of the network connection for a - fictional wireless device. |
-
| -Uses of Shareable in com.licel.jcardsim.samples.JavaLoyalty | -
|---|
- -
| Classes in com.licel.jcardsim.samples.JavaLoyalty that implement Shareable | -|
|---|---|
- class |
-JavaLoyalty
-
-- Minimalistic loyalty applet. |
-
- -
| Methods in com.licel.jcardsim.samples.JavaLoyalty that return Shareable | -|
|---|---|
- Shareable |
-JavaLoyalty.getShareableInterfaceObject(AID clientAID,
- byte parameter)
-
-- Implements getShareableInterfaceObject method of Applet class. |
-
| -Uses of Shareable in com.licel.jcardsim.samples.odSample.packageB | -
|---|
- -
| Classes in com.licel.jcardsim.samples.odSample.packageB that implement Shareable | -|
|---|---|
- class |
-B
-
-- package AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 - applet AID - 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x07 0x02 0x01 - - Applet used to demonstrate applet deletion and package deletion. |
-
- -
| Methods in com.licel.jcardsim.samples.odSample.packageB that return Shareable | -|
|---|---|
- Shareable |
-B.getShareableInterfaceObject(AID client_aid,
- byte param)
-
-- method returns pointer to this instance, ignores the param |
-
| -Uses of Shareable in com.licel.jcardsim.samples.SampleLibrary | -
|---|
- -
| Subinterfaces of Shareable in com.licel.jcardsim.samples.SampleLibrary | -|
|---|---|
- interface |
-JavaLoyaltyInterface
-
-- Shareable Loyalty Interface |
-
| com.licel.jcardsim.io | ++ |
| com.licel.jcardsim.remote | ++ |
| javacard.framework | |
@@ -133,7 +141,8 @@
Class appletClass)
|
+ Install
+ |
@@ -145,7 +154,33 @@
byte bLength)
|
+ Install
+ |
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ AID |
+Simulator.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
@@ -154,7 +189,27 @@
Class appletClass)
|
+ Load
+ |
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+
+ AID |
+Simulator.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ |
@@ -184,16 +239,154 @@
Simulator.selectApplet(AID aid)
- Select applet by it's AID - It's method must be called before start working with applet instance |
+|
+ byte[] |
+Simulator.transmitCommand(byte[] command)
+
++ |
+
| +Uses of SystemException in com.licel.jcardsim.io | +
|---|
+ +
| Methods in com.licel.jcardsim.io that throw SystemException | +|
|---|---|
+ AID |
+JavaCardInterface.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Create + Applet instance in Simulator |
+
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+JavaCardInterface.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ Install + Applet into Simulator. |
+
+ AID |
+JavaCardInterface.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
+
++ Load + Applet into Simulator |
+
| +Uses of SystemException in com.licel.jcardsim.remote | +
|---|
+ +
| Methods in com.licel.jcardsim.remote that throw SystemException | +||
|---|---|---|
+ AID |
+JavaCardRemoteClient.createApplet(AID aid,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+|
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
|
- javax.smartcardio.ResponseAPDU |
-Simulator.transmitCommand(javax.smartcardio.CommandAPDU commandAPDU)
+ AID |
+JavaCardRemoteClient.installApplet(AID aid,
+ String appletClassName,
+ byte[] bArray,
+ short bOffset,
+ byte bLength)
+
++ |
+
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName)
+
++ |
+|
+ AID |
+JavaCardRemoteClient.loadApplet(AID aid,
+ String appletClassName,
+ byte[] appletJarContents)
- Transmit APDU to previous selected applet |
+
|
| -Uses of UserException in com.licel.jcardsim.samples.photocard | -
|---|
- -
| Methods in com.licel.jcardsim.samples.photocard that throw UserException | -|
|---|---|
- void |
-PhotoCardImpl.deletePhoto(short photoID)
-
-- |
-
- void |
-PhotoCard.deletePhoto(short photoID)
-
-- This method deletes the photo whose ID is specified in the card. |
-
- byte[] |
-PhotoCardImpl.getPhoto(short photoID,
- short offset,
- short size)
-
-- |
-
- byte[] |
-PhotoCard.getPhoto(short photoID,
- short offset,
- short size)
-
-- This method retrueves a series of bytes belonging to the photo - from the smart card at the position specified. |
-
- short |
-PhotoCardImpl.getPhotoSize(short photoID)
-
-- |
-
- short |
-PhotoCard.getPhotoSize(short photoID)
-
-- This method retrieves the photo size whose ID is specified. |
-
- void |
-PhotoCardImpl.loadPhoto(short photoID,
- byte[] data,
- short size,
- short offset,
- boolean more)
-
-- |
-
- void |
-PhotoCard.loadPhoto(short photoID,
- byte[] data,
- short size,
- short offset,
- boolean more)
-
-- This method loads a series of bytes belonging to the photo - into the smart card at the position specified. |
-
- short |
-PhotoCardImpl.requestPhotoStorage(short size)
-
-- |
-
- short |
-PhotoCard.requestPhotoStorage(short size)
-
-- This method requests the smart card to allocate space to store - a photo image of the specified size. |
-
| -Uses of UserException in com.licel.jcardsim.samples.RMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.RMIDemo that throw UserException | -|
|---|---|
- void |
-PurseImpl.credit(short m)
-
-- |
-
- void |
-Purse.credit(short m)
-
-- |
-
- void |
-PurseImpl.debit(short m)
-
-- |
-
- void |
-Purse.debit(short m)
-
-- |
-
- void |
-PurseImpl.setAccountNumber(byte[] number)
-
-- |
-
- void |
-Purse.setAccountNumber(byte[] number)
-
-- |
-
| -Uses of UserException in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.SecureRMIDemo that throw UserException | -|
|---|---|
- void |
-SecurePurseImpl.credit(short m)
-
-- |
-
- void |
-Purse.credit(short m)
-
-- |
-
- void |
-SecurePurseImpl.debit(short m)
-
-- |
-
- void |
-Purse.debit(short m)
-
-- |
-
- byte[] |
-SecurePurseImpl.getAccountNumber()
-
-- |
-
- byte[] |
-Purse.getAccountNumber()
-
-- |
-
- short |
-SecurePurseImpl.getBalance()
-
-- |
-
- short |
-Purse.getBalance()
-
-- |
-
- void |
-SecurePurseImpl.setAccountNumber(byte[] number)
-
-- |
-
- void |
-Purse.setAccountNumber(byte[] number)
-
-- |
-
| - PREV PACKAGE + PREV PACKAGE NEXT PACKAGE |
FRAMES
@@ -234,7 +234,7 @@
- PREV PACKAGE
+ PREV PACKAGE
NEXT PACKAGE |
FRAMES
diff --git a/javadoc/javacard/framework/package-tree.html b/javadoc/javacard/framework/package-tree.html
index 0bf24e56..804b9811 100644
--- a/javadoc/javacard/framework/package-tree.html
+++ b/javadoc/javacard/framework/package-tree.html
@@ -2,13 +2,13 @@
-
+
|
- PREV
+ PREV
NEXT |
FRAMES
@@ -142,7 +142,7 @@ |
- PREV
+ PREV
NEXT |
FRAMES
diff --git a/javadoc/javacard/framework/package-use.html b/javadoc/javacard/framework/package-use.html
index 364eb07b..74833e3a 100644
--- a/javadoc/javacard/framework/package-use.html
+++ b/javadoc/javacard/framework/package-use.html
@@ -2,13 +2,13 @@
-
+
| |
| -Classes in javacard.framework used by com.licel.jcardsim.samples | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.ChannelsDemo | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| MultiSelectable
-
- - The MultiSelectable interface identifies the implementing
- Applet subclass as being capable of concurrent selections. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.JavaLoyalty | +Classes in javacard.framework used by com.licel.jcardsim.io|
|---|---|
| AID + | AID
This class encapsulates the Application Identifier (AID) associated with an applet. |
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet + | SystemException
- This abstract class defines an Java Card technology-based applet. |
-
| Shareable
-
- - The Shareable interface serves to identify all shared objects. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.JavaPurse | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.JavaPurseCrypto | -|
|---|---|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.NullApp | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.RMIDemo | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| UserException
-
- - UserException represents a User exception. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.SampleLibrary | -|
|---|---|
| Shareable
-
- - The Shareable interface serves to identify all shared objects. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.SecureRMIDemo | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| UserException
-
- - UserException represents a User exception. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.ServiceDemo | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.odSample.packageA | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
+ |
| -Classes in javacard.framework used by com.licel.jcardsim.samples.odSample.packageB | +Classes in javacard.framework used by com.licel.jcardsim.remote|
|---|---|
| AID + | AID
This class encapsulates the Application Identifier (AID) associated with an applet. |
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
| AppletEvent + | SystemException
- The AppletEvent interface provides a callback interface for
- the Java Card runtime environment to inform the applet about life cycle events. |
-
| ISOException
-
- - ISOException class encapsulates an ISO 7816-4 response status word as
- its reason code. |
-|
| Shareable
-
- - The Shareable interface serves to identify all shared objects. |
+ |
| -Classes in javacard.framework used by com.licel.jcardsim.samples.photocard | +Classes in javacard.framework used by com.licel.jcardsim.samples|
|---|---|
| APDU + | APDU
Application Protocol Data Unit (APDU) is the communication format between the card and the off-card applications. |
| Applet + | Applet
This abstract class defines an Java Card technology-based applet. |
| ISOException + | ISOException
ISOException class encapsulates an ISO 7816-4 response status word as
its reason code. |
| UserException
-
- - UserException represents a User exception. |
-|
| -Classes in javacard.framework used by com.licel.jcardsim.samples.wallet | -|
|---|---|
| APDU
-
- - Application Protocol Data Unit (APDU) is - the communication format between the card and the off-card applications. |
-|
| Applet
-
- - This abstract class defines an Java Card technology-based applet. |
-|
diff --git a/javadoc/javacard/framework/service/BasicService.html b/javadoc/javacard/framework/service/BasicService.html index 6372ea8b..2c4ea3dd 100644 --- a/javadoc/javacard/framework/service/BasicService.html +++ b/javadoc/javacard/framework/service/BasicService.html @@ -2,13 +2,13 @@
- +
javacard.framework.service.CardRemoteObject
public class CardRemoteObject
@@ -139,7 +136,7 @@
static voidexport(Remote obj)
+export(Remote obj)
static voidunexport(Remote obj)
+unexport(Remote obj)
-public static void export(Remote obj) +public static void export(Remote obj) throws SecurityException
-public static void unexport(Remote obj) +public static void unexport(Remote obj) throws SecurityException
RMIService(Remote initialObject)
+RMIService(Remote initialObject)
-public RMIService(Remote initialObject) +public RMIService(Remote initialObject) throws NullPointerException
public interface SecurityService
| -Uses of BasicService in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Subclasses of BasicService in com.licel.jcardsim.samples.SecureRMIDemo | -|
|---|---|
- class |
-MySecurityService
-
-- |
-
| -Uses of BasicService in com.licel.jcardsim.samples.ServiceDemo | -
|---|
- -
| Subclasses of BasicService in com.licel.jcardsim.samples.ServiceDemo | -|
|---|---|
- class |
-TestService
-
-- |
-
| -Packages that use CardRemoteObject | -|
|---|---|
| com.licel.jcardsim.samples.photocard | -- |
| com.licel.jcardsim.samples.RMIDemo | -- |
| com.licel.jcardsim.samples.SecureRMIDemo | -- |
| -Uses of CardRemoteObject in com.licel.jcardsim.samples.photocard | -
|---|
- -
| Subclasses of CardRemoteObject in com.licel.jcardsim.samples.photocard | -|
|---|---|
- class |
-PhotoCardImpl
-
-- |
-
| -Uses of CardRemoteObject in com.licel.jcardsim.samples.RMIDemo | -
|---|
- -
| Subclasses of CardRemoteObject in com.licel.jcardsim.samples.RMIDemo | -|
|---|---|
- class |
-PurseImpl
-
-- |
-
| -Uses of CardRemoteObject in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Subclasses of CardRemoteObject in com.licel.jcardsim.samples.SecureRMIDemo | -|
|---|---|
- class |
-SecurePurseImpl
-
-- |
-
| -Packages that use SecurityService | -|
|---|---|
| com.licel.jcardsim.samples.SecureRMIDemo | -- |
| -Uses of SecurityService in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Classes in com.licel.jcardsim.samples.SecureRMIDemo that implement SecurityService | -|
|---|---|
- class |
-MySecurityService
-
-- |
-
- -
| Constructors in com.licel.jcardsim.samples.SecureRMIDemo with parameters of type SecurityService | -|
|---|---|
SecurePurseImpl(SecurityService security)
-
-- |
-|
| -Uses of Service in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Classes in com.licel.jcardsim.samples.SecureRMIDemo that implement Service | -|
|---|---|
- class |
-MySecurityService
-
-- |
-
| -Uses of Service in com.licel.jcardsim.samples.ServiceDemo | -
|---|
- -
| Classes in com.licel.jcardsim.samples.ServiceDemo that implement Service | -|
|---|---|
- class |
-TestService
-
-- |
-
| com.licel.jcardsim.samples.SecureRMIDemo | -- |
| javacard.framework.service |
| -Uses of ServiceException in com.licel.jcardsim.samples.SecureRMIDemo | -
|---|
- -
| Methods in com.licel.jcardsim.samples.SecureRMIDemo that throw ServiceException | -|
|---|---|
- boolean |
-MySecurityService.isAuthenticated(short principal)
-
-- Checks whether or not the specified principal is currently authenticated. |
-
- boolean |
-MySecurityService.isCommandSecure(byte properties)
-
-- Checks whether a secure channel is in use between the card and the host for - the ongoing command that guarantees the indicated properties. |
-
| com.licel.jcardsim.samples.RMIDemo | -- |
| com.licel.jcardsim.samples.SecureRMIDemo | -- |
| com.licel.jcardsim.samples.ServiceDemo | -- |
| com.licel.jcardsim.samples.photocard | -- |
| javacard.framework.service |
| -Classes in javacard.framework.service used by com.licel.jcardsim.samples.RMIDemo | -|
|---|---|
| CardRemoteObject
-
- - |
-|
| -Classes in javacard.framework.service used by com.licel.jcardsim.samples.SecureRMIDemo | -|
|---|---|
| BasicService
-
- - |
-|
| CardRemoteObject
-
- - |
-|
| SecurityService
-
- - |
-|
| Service
-
- - |
-|
| ServiceException
-
- - |
-|
| -Classes in javacard.framework.service used by com.licel.jcardsim.samples.ServiceDemo | -|
|---|---|
| BasicService
-
- - |
-|
| Service
-
- - |
-|
| -Classes in javacard.framework.service used by com.licel.jcardsim.samples.photocard | -|
|---|---|
| CardRemoteObject
-
- - |
-|
KeyPairImpl.genKeyPair()
- (Re)Initializes the key objects encapsulated in this KeyPair instance
- with new key values. |
+ (Re)Initializes the key objects encapsulated in this
+
@@ -723,7 +723,8 @@
short keyLength)
|
ECKeyImpl
ECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPI
ECKeyImpl
ECPublicKeyImpl/ECPrivateKeyImpl
- on BouncyCastle CryptoAPIECPublicKeyImpl/ECPrivateKeyImpl on BouncyCastle CryptoAPIRSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPIRSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPIKeyPairImpl.getPrivate()
KeyPair object.KeyPair object.KeyPair object containing the specified
- public key and private key.KeyPair object containing the specified public key and
+ private key.
RSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPIKeyPairImpl.getPublic()
KeyPair object.KeyPair object.KeyPair object containing the specified
- public key and private key.KeyPair object containing the specified public key and
+ private key.
RSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPIRSAKeyImpl
RSAPublic/RSAPrivate based
- on BouncyCastle CryptoAPIRSAPublic/RSAPrivate based on BouncyCastle CryptoAPI| -Package com.licel.jcardsim.samples.JavaPurseCrypto | +Package com.licel.jcardsim.remote
|---|
| -Class com.licel.jcardsim.samples.JavaPurseCrypto.JavaPurseCrypto extends Object implements Serializable | +Class com.licel.jcardsim.remote.JavaCardRemoteServer extends UnicastRemoteObject implements Serializable
|---|
-
| -Package com.licel.jcardsim.smartcardio | -
|---|
| -Class com.licel.jcardsim.smartcardio.JCardSimProvider extends Provider implements Serializable | -
|---|
-
| -Package java.rmi | -
|---|
| -Class java.rmi.AccessException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 6314925228044966088L - -
- -
| -Class java.rmi.AlreadyBoundException extends Exception implements Serializable | -
|---|
-serialVersionUID: 9218657361741657110L - -
- -
| -Class java.rmi.ConnectException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 4863550261346652506L - -
- -
| -Class java.rmi.ConnectIOException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: -8087809532704668744L - -
- -
| -Class java.rmi.MarshalException extends RemoteException implements Serializable | +|
|---|---|
| +Serialized Fields | |
-serialVersionUID: 6223554758134037936L - -
+
+Simulator sim+
| -Class java.rmi.MarshalledObject extends Object implements Serializable | +Class com.licel.jcardsim.remote.SerializableAID extends Object implements Serializable
|---|
-serialVersionUID: 8988374069173025854L -
-byte[] objBytes+byte[] aidBytes
-byte[] locBytes+byte aidLen
-int hash-
| -Class java.rmi.NoSuchObjectException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 6619395951570472985L - -
- -
| -Class java.rmi.NotBoundException extends Exception implements Serializable | -
|---|
-serialVersionUID: -1857741824849069317L - -
- -
| -Class java.rmi.RemoteException extends IOException implements Serializable | -
|---|
- -
| -Class java.rmi.RMISecurityException extends SecurityException implements Serializable | -
|---|
-serialVersionUID: -8433406075740433514L - -
- -
| -Class java.rmi.ServerError extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 8455284893909696482L - -
- -
| -Class java.rmi.ServerException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: -4775845313121906682L - -
- -
| -Class java.rmi.ServerRuntimeException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 7054464920481467219L - -
- -
| -Class java.rmi.StubNotFoundException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: -7088199405468872373L - -
+
| -Class java.rmi.UnexpectedException extends RemoteException implements Serializable | -
|---|
-serialVersionUID: 1800467484195073863L - -
- -
| -Class java.rmi.UnknownHostException extends RemoteException implements Serializable | ++Package com.licel.jcardsim.smartcardio | |
|---|---|---|
-serialVersionUID: -8152710247442114228L - -
- -
| -Class java.rmi.UnmarshalException extends RemoteException implements Serializable | +Class com.licel.jcardsim.smartcardio.JCardSimProvider extends Provider implements Serializable
|---|
-serialVersionUID: 594380845140740218L -
RSAPublicKey interface for the public key and
* RSAPrivateKey interface for the private key within an
- * ALG_RSA key pair).
Notes:
ALG_RSA key pair).
+ * Notes:
The key objects
* encapsulated in the generated KeyPair object need
- * not support the KeyEncryption interface.
KeyEncryption interface.
*
* @param algorithm the type of algorithm whose key pair needs to be
* generated. Valid codes listed in ALG_.. constants above.
@@ -153,14 +120,15 @@ public final void genKeyPair()
* algorithm associated with the specified type, size of key is not
* supported.MessageDigest based
- * on BouncyCastle CryptoAPI
+ * Implementation
+ * MessageDigest based
+ * on BouncyCastle CryptoAPI.
* @see MessageDigest
* @see MD5Digest
* @see RIPEMD160Digest
* @see SHA1Digest
*/
-public class MessageDigestImpl extends MessageDigest {
+public class MessageDigestImpl extends InitializedMessageDigest {
private Digest engine;
private byte algorithm;
+ private short blockSize;
+ // internals BouncyCastle
+ private String byteCountFieldName = "byteCount";
+ private Class digestClass;
+ private byte componentSize;
+ private byte componentCount;
+ private byte componentStartIdx;
public MessageDigestImpl(byte algorithm) {
this.algorithm = algorithm;
+ blockSize = 64;
+ componentStartIdx = 1;
switch (algorithm) {
case ALG_SHA:
engine = new SHA1Digest();
+ digestClass = engine.getClass();
break;
case ALG_MD5:
engine = new MD5Digest();
+ digestClass = engine.getClass();
break;
case ALG_RIPEMD160:
engine = new RIPEMD160Digest();
+ digestClass = engine.getClass();
+ componentStartIdx = 0;
+ break;
+ case ALG_SHA_256:
+ engine = new SHA256Digest();
+ digestClass = engine.getClass();
+ break;
+ case ALG_SHA_384:
+ engine = new SHA384Digest();
+ blockSize = 128;
+ byteCountFieldName = "byteCount1";
+ digestClass = engine.getClass().getSuperclass();
+ break;
+ case ALG_SHA_512:
+ engine = new SHA512Digest();
+ blockSize = 128;
+ byteCountFieldName = "byteCount1";
+ digestClass = engine.getClass().getSuperclass();
break;
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
break;
}
+ componentSize = (byte)(blockSize == 64 ? 4 : 8);
+ componentCount = (byte) (engine.getDigestSize() / componentSize);
}
public byte getAlgorithm() {
@@ -74,4 +112,67 @@ public void update(byte inBuff[], short inOffset, short inLength) {
public void reset() {
engine.reset();
}
+
+ public void setInitialDigest(byte[] initialDigestBuf, short initialDigestOffset,
+ short initialDigestLength, byte[] digestedMsgLenBuf, short digestedMsgLenOffset,
+ short digestedMsgLenLength) throws CryptoException {
+ // initialDigestLength must be == DIGEST_SIZE
+ if (engine.getDigestSize() != initialDigestLength) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
+ }
+ // digestedMsgLenLength must be > 0 and < long value, more formal 2^64-1 bits
+ // TODO support length more 2^128-1 bits (SHA-384, SHA-512)
+ if (digestedMsgLenLength == 0 || digestedMsgLenLength > 8) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
+ }
+ long byteCount = 0;
+ for (short i = 0; i < digestedMsgLenLength; i++) {
+ byteCount = (byteCount << 8) + (digestedMsgLenBuf[digestedMsgLenOffset + i] & 0xff);
+ }
+ // byte count % block size must be == 0
+ if (byteCount % blockSize != 0) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
+ }
+ // set hash state - BouncyCastle specific
+ try {
+ for (byte i = 0; i < componentCount; i++) {
+ // some reflection work
+ Field h = digestClass.getDeclaredField("H" + (i + componentStartIdx));
+ h.setAccessible(true);
+ if (componentSize == 4) {
+ h.setInt(engine, Pack.bigEndianToInt(initialDigestBuf, initialDigestOffset + i * componentSize));
+ } else {
+ h.setLong(engine, Pack.bigEndianToLong(initialDigestBuf, initialDigestOffset + i * componentSize));
+ }
+ }
+ // set byteCount
+ Field h = digestClass.getSuperclass().getDeclaredField(byteCountFieldName);
+ h.setAccessible(true);
+ h.setLong(engine, byteCount);
+ } catch (Exception e) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_USE);
+ }
+ }
+
+ void getIntermediateDigest(byte[] intermediateDigest, int off) {
+ // get hash state - BouncyCastle specific
+ try {
+ for (byte i = 0; i < componentCount; i++) {
+ // some reflection work
+ Field h = digestClass.getDeclaredField("H" + (i + componentStartIdx));
+ h.setAccessible(true);
+ if (componentSize == 4) {
+ Pack.intToBigEndian(h.getInt(engine), intermediateDigest, off + i * componentSize);
+ } else {
+ Pack.longToBigEndian(h.getLong(engine), intermediateDigest, off + i * componentSize);
+ }
+ }
+ } catch (Exception e) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_USE);
+ }
+ }
+
+ short getBlockSize(){
+ return blockSize;
+ }
}
diff --git a/src/main/java/com/licel/jcardsim/crypto/RSAKeyImpl.java b/src/main/java/com/licel/jcardsim/crypto/RSAKeyImpl.java
index 9921de6a..8eeb7ed7 100644
--- a/src/main/java/com/licel/jcardsim/crypto/RSAKeyImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/RSAKeyImpl.java
@@ -28,7 +28,7 @@
/**
* Implementation
- * RSAPublic/RSAPrivate based on BouncyCastle CryptoAPI
+ * RSAPublic/RSAPrivate based on BouncyCastle CryptoAPI.
*
* @see RSAPrivateKey
* @see RSAPublicKey
@@ -57,14 +57,18 @@ public RSAKeyImpl(boolean isPrivate, short size) {
* Construct and initialize rsa key with RSAKeyParameters. Use in
* KeyPairImpl
*
- * @see KeyPair
+ * @see javacard.security.KeyPair
* @see RSAKeyParameters
* @param params key params from BouncyCastle API
*/
public RSAKeyImpl(RSAKeyParameters params) {
this(params.isPrivate(), (short) params.getModulus().bitLength());
- modulus.setBigInteger(params.getModulus());
- exponent.setBigInteger(params.getExponent());
+ setParameters(params);
+ }
+
+ public void setParameters(CipherParameters params){
+ modulus.setBigInteger(((RSAKeyParameters)params).getModulus());
+ exponent.setBigInteger(((RSAKeyParameters)params).getExponent());
}
public short getExponent(byte[] buffer, short offset) {
diff --git a/src/main/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImpl.java b/src/main/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImpl.java
index ecfba0ff..fbc01af1 100644
--- a/src/main/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImpl.java
@@ -24,7 +24,7 @@
/**
* Implementation RSAPrivateCrtKey based
- * on BouncyCastle CryptoAPI
+ * on BouncyCastle CryptoAPI.
* @see RSAPrivateCrtKey
* @see RSAPrivateCrtKeyParameters
*/
@@ -35,11 +35,10 @@ public class RSAPrivateCrtKeyImpl extends RSAKeyImpl implements RSAPrivateCrtKey
protected ByteContainer dp1 = new ByteContainer();
protected ByteContainer dq1 = new ByteContainer();
protected ByteContainer pq = new ByteContainer();
- protected ByteContainer publicExponent = new ByteContainer();
/**
* Construct not-initialized rsa private crt key
- * @param size key size it bits (modulus size)
+ * @param keySize key size it bits (modulus size)
* @see KeyBuilder
*/
public RSAPrivateCrtKeyImpl(short keySize) {
@@ -50,25 +49,24 @@ public RSAPrivateCrtKeyImpl(short keySize) {
/**
* Construct and initialize rsa key with RSAPrivateCrtKeyParameters.
* Use in KeyPairImpl
- * @see KeyPair
+ * @see javacard.security.KeyPair
* @see RSAPrivateCrtKeyParameters
* @param params key params from BouncyCastle API
*/
public RSAPrivateCrtKeyImpl(RSAPrivateCrtKeyParameters params) {
super(new RSAKeyParameters(true, params.getModulus(), params.getExponent()));
type = KeyBuilder.TYPE_RSA_CRT_PRIVATE;
- publicExponent.setBigInteger(params.getPublicExponent());
- p.setBigInteger(params.getP());
- q.setBigInteger(params.getQ());
- dp1.setBigInteger(params.getDP());
- dq1.setBigInteger(params.getDQ());
- pq.setBigInteger(params.getQInv());
+ setParameters(params);
}
- public void setPublicExponent(byte[] buffer, short offset, short length) throws CryptoException {
- publicExponent.setBytes(buffer, offset, length);
+ public void setParameters(CipherParameters params){
+ p.setBigInteger(((RSAPrivateCrtKeyParameters)params).getP());
+ q.setBigInteger(((RSAPrivateCrtKeyParameters)params).getQ());
+ dp1.setBigInteger(((RSAPrivateCrtKeyParameters)params).getDP());
+ dq1.setBigInteger(((RSAPrivateCrtKeyParameters)params).getDQ());
+ pq.setBigInteger(((RSAPrivateCrtKeyParameters)params).getQInv());
}
-
+
public void setP(byte[] buffer, short offset, short length) throws CryptoException {
p.setBytes(buffer, offset, length);
}
@@ -111,7 +109,6 @@ public short getPQ(byte[] buffer, short offset) {
public void clearKey() {
super.clearKey();
- publicExponent.clear();
p.clear();
q.clear();
dp1.clear();
@@ -120,8 +117,8 @@ public void clearKey() {
}
public boolean isInitialized() {
- return (super.isInitialized() && p.isInitialized() && q.isInitialized()
- && publicExponent.isInitialized() && dp1.isInitialized() && dq1.isInitialized()
+ return (p.isInitialized() && q.isInitialized()
+ && dp1.isInitialized() && dq1.isInitialized()
&& pq.isInitialized());
}
@@ -129,8 +126,9 @@ public CipherParameters getParameters() {
if (!isInitialized()) {
CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
}
- return new RSAPrivateCrtKeyParameters(modulus.getBigInteger(), publicExponent.getBigInteger(),
- exponent.getBigInteger(), p.getBigInteger(), q.getBigInteger(),
+ // modulus = p * q;
+ return new RSAPrivateCrtKeyParameters(p.getBigInteger().multiply(q.getBigInteger()), null,
+ null, p.getBigInteger(), q.getBigInteger(),
dp1.getBigInteger(), dq1.getBigInteger(), pq.getBigInteger());
}
}
diff --git a/src/main/java/com/licel/jcardsim/crypto/RandomDataImpl.java b/src/main/java/com/licel/jcardsim/crypto/RandomDataImpl.java
index 5b778eb4..6d4bd96c 100644
--- a/src/main/java/com/licel/jcardsim/crypto/RandomDataImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/RandomDataImpl.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.RandomData;
@@ -25,7 +24,7 @@
/**
* Implementation RandomData based
- * on BouncyCastle CryptoAPI
+ * on BouncyCastle CryptoAPI.
* @see RandomData
*/
public class RandomDataImpl extends RandomData {
@@ -41,7 +40,7 @@ public void generateData(byte[] buffer, short offset, short length) throws Crypt
}
public void setSeed(byte[] buffer, short offset, short length) {
- byte[] seed = JCSystem.makeTransientByteArray(length, JCSystem.CLEAR_ON_RESET);
+ byte[] seed = new byte[length];
Util.arrayCopyNonAtomic(buffer, offset, seed, (short) 0, length);
engine.addSeedMaterial(seed);
}
diff --git a/src/main/java/com/licel/jcardsim/crypto/SymmetricCipherImpl.java b/src/main/java/com/licel/jcardsim/crypto/SymmetricCipherImpl.java
index 1ad2bcd3..f9a55c6c 100644
--- a/src/main/java/com/licel/jcardsim/crypto/SymmetricCipherImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/SymmetricCipherImpl.java
@@ -30,7 +30,7 @@
/**
* Implementation Cipher with symmetric keys based
- * on BouncyCastle CryptoAPI
+ * on BouncyCastle CryptoAPI.
* @see Cipher
*/
public class SymmetricCipherImpl extends Cipher {
diff --git a/src/main/java/com/licel/jcardsim/crypto/SymmetricKeyImpl.java b/src/main/java/com/licel/jcardsim/crypto/SymmetricKeyImpl.java
index 4cfa1177..67a35e7c 100644
--- a/src/main/java/com/licel/jcardsim/crypto/SymmetricKeyImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/SymmetricKeyImpl.java
@@ -20,6 +20,7 @@
import javacard.security.AESKey;
import javacard.security.CryptoException;
import javacard.security.DESKey;
+import javacard.security.HMACKey;
import javacard.security.KeyBuilder;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
@@ -30,11 +31,11 @@
import org.bouncycastle.crypto.params.KeyParameter;
/**
- * Implementation of secret key
+ * Implementation of secret key.
* @see DESKey
* @see AESKey
*/
-public class SymmetricKeyImpl extends KeyImpl implements DESKey, AESKey {
+public class SymmetricKeyImpl extends KeyImpl implements DESKey, AESKey, HMACKey {
protected ByteContainer key;
@@ -50,14 +51,17 @@ public SymmetricKeyImpl(byte keyType, short keySize) {
switch (keyType) {
case KeyBuilder.TYPE_DES_TRANSIENT_DESELECT:
case KeyBuilder.TYPE_AES_TRANSIENT_DESELECT:
+ case KeyBuilder.TYPE_HMAC_TRANSIENT_DESELECT:
key = new ByteContainer(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
break;
case KeyBuilder.TYPE_DES_TRANSIENT_RESET:
case KeyBuilder.TYPE_AES_TRANSIENT_RESET:
+ case KeyBuilder.TYPE_HMAC_TRANSIENT_RESET:
key = new ByteContainer(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
break;
case KeyBuilder.TYPE_DES:
case KeyBuilder.TYPE_AES:
+ case KeyBuilder.TYPE_HMAC:
key = new ByteContainer(JCSystem.MEMORY_TYPE_PERSISTENT);
break;
}
@@ -77,6 +81,12 @@ public void setKey(byte[] keyData, short kOff) throws CryptoException, NullPoint
key.setBytes(keyData, kOff, (short) (size / 8));
}
+ /**
+ * Sets the Key data.
+ */
+ public void setKey(byte[] keyData, short kOff, short kLen) throws CryptoException, NullPointerException, ArrayIndexOutOfBoundsException {
+ key.setBytes(keyData, kOff, kLen);
+ }
/**
* Returns the Key data in plain text.
*/
@@ -84,6 +94,10 @@ public byte getKey(byte[] keyData, short kOff) {
return (byte) key.getBytes(keyData, kOff);
}
+ public void setParameters(CipherParameters params){
+ key.setBytes(((KeyParameter)params).getKey());
+ }
+
/**
* Return the BouncyCastle KeyParameter of the key
* @return parameter of the key
@@ -99,7 +113,7 @@ public CipherParameters getParameters() throws CryptoException {
/**
* Return the BouncyCastle BlockCipher for using with this key
- * @return BlockCipher for this key
+ * @return BlockCipher for this key, or null for HMACKey
* @throws CryptoException if key not initialized
* @see BlockCipher
*/
@@ -135,4 +149,5 @@ public boolean isInitialized() {
public KeyGenerationParameters getKeyGenerationParameters(SecureRandom rnd) {
return null;
}
+
}
diff --git a/src/main/java/com/licel/jcardsim/crypto/SymmetricSignatureImpl.java b/src/main/java/com/licel/jcardsim/crypto/SymmetricSignatureImpl.java
index f418f575..e9b13a53 100644
--- a/src/main/java/com/licel/jcardsim/crypto/SymmetricSignatureImpl.java
+++ b/src/main/java/com/licel/jcardsim/crypto/SymmetricSignatureImpl.java
@@ -15,132 +15,149 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.Key;
import javacard.security.Signature;
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Mac;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.crypto.digests.RIPEMD160Digest;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.digests.SHA384Digest;
+import org.bouncycastle.crypto.digests.SHA512Digest;
+import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;
-import org.bouncycastle.crypto.paddings.BlockCipherPadding;
+import org.bouncycastle.crypto.macs.HMac;
+import org.bouncycastle.crypto.macs.ISO9797Alg3Mac;
import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.ParametersWithIV;
/**
- * Implementation Signature with symmetric keys based
- * on BouncyCastle CryptoAPI
+ * Implementation
+ * Signature with symmetric keys based
+ * on BouncyCastle CryptoAPI.
* @see Signature
*/
public class SymmetricSignatureImpl extends Signature {
-
+
Mac engine;
byte algorithm;
boolean isInitialized;
- BlockCipherPadding paddingEngine;
- short macSize;
-
+
public SymmetricSignatureImpl(byte algorithm) {
this.algorithm = algorithm;
+ }
+
+ public void init(Key theKey, byte theMode) throws CryptoException {
+ init(theKey, theMode, null, (short) 0, (short) 0);
+ }
+
+ public void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException {
+ if (theKey == null) {
+ CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
+ }
+ if (!theKey.isInitialized()) {
+ CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
+ }
+ if (!(theKey instanceof SymmetricKeyImpl)) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
+ }
+ CipherParameters cipherParams = null;
+ BlockCipher cipher = ((SymmetricKeyImpl) theKey).getCipher();
+ if (bArray == null) {
+ cipherParams = ((SymmetricKeyImpl) theKey).getParameters();
+ } else {
+ if (bLen != cipher.getBlockSize()) {
+ CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
+ }
+ cipherParams = new ParametersWithIV(((SymmetricKeyImpl) theKey).getParameters(), bArray, bOff, bLen);
+ }
switch (algorithm) {
case ALG_DES_MAC4_NOPAD:
- macSize = 32;
- paddingEngine = null;
+ engine = new CBCBlockCipherMac(cipher, 32, null);
break;
case ALG_DES_MAC8_NOPAD:
- macSize = 64;
- paddingEngine = null;
+ engine = new CBCBlockCipherMac(cipher, 64, null);
break;
case ALG_DES_MAC4_ISO9797_M1:
- macSize = 32;
- paddingEngine = new ZeroBytePadding();
+ engine = new CBCBlockCipherMac(cipher, 32, new ZeroBytePadding());
break;
case ALG_DES_MAC8_ISO9797_M1:
- macSize = 64;
- paddingEngine = new ZeroBytePadding();
+ engine = new CBCBlockCipherMac(cipher, 64, new ZeroBytePadding());
break;
case ALG_DES_MAC4_ISO9797_M2:
- macSize = 32;
- paddingEngine = new ISO7816d4Padding();
+ engine = new CBCBlockCipherMac(cipher, 32, new ISO7816d4Padding());
break;
case ALG_DES_MAC8_ISO9797_M2:
- macSize = 64;
- paddingEngine = new ISO7816d4Padding();
+ engine = new CBCBlockCipherMac(cipher, 64, new ISO7816d4Padding());
+ break;
+ case ALG_DES_MAC8_ISO9797_1_M2_ALG3:
+ engine = new ISO9797Alg3Mac(new DESEngine(), 64, new ISO7816d4Padding());
break;
case ALG_DES_MAC4_PKCS5:
- macSize = 32;
- paddingEngine = new PKCS7Padding();
+ engine = new CBCBlockCipherMac(cipher, 32, new PKCS7Padding());
break;
case ALG_DES_MAC8_PKCS5:
- macSize = 64;
- paddingEngine = new PKCS7Padding();
+ engine = new CBCBlockCipherMac(cipher, 64, new PKCS7Padding());
+ break;
+ case ALG_AES_MAC_128_NOPAD:
+ engine = new CBCBlockCipherMac(cipher, 128, null);
+ break;
+ case ALG_HMAC_SHA1:
+ engine = new HMac(new SHA1Digest());
+ break;
+ case ALG_HMAC_SHA_256:
+ engine = new HMac(new SHA256Digest());
+ break;
+ case ALG_HMAC_SHA_384:
+ engine = new HMac(new SHA384Digest());
+ break;
+ case ALG_HMAC_SHA_512:
+ engine = new HMac(new SHA512Digest());
+ break;
+ case ALG_HMAC_MD5:
+ engine = new HMac(new MD5Digest());
+ break;
+ case ALG_HMAC_RIPEMD160:
+ engine = new HMac(new RIPEMD160Digest());
break;
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
break;
}
- }
-
- public void init(Key theKey, byte theMode) throws CryptoException {
- if (theKey == null) {
- CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
- }
- if (!theKey.isInitialized()) {
- CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
- }
- if (!(theKey instanceof SymmetricKeyImpl)) {
- CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
- }
- SymmetricKeyImpl key = (SymmetricKeyImpl) theKey;
- engine = new CBCBlockCipherMac(key.getCipher(), macSize, paddingEngine);
- engine.init(key.getParameters());
- isInitialized = true;
- }
-
- public void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException {
- if (theKey == null) {
- CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
- }
- if (!theKey.isInitialized()) {
- CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
- }
- if (!(theKey instanceof SymmetricKeyImpl)) {
- CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
- }
- if (bLen != 8) {
- CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
- }
- SymmetricKeyImpl key = (SymmetricKeyImpl) theKey;
- engine = new CBCBlockCipherMac(key.getCipher(), macSize, paddingEngine);
- engine.init(new ParametersWithIV(key.getParameters(), bArray, bOff, bLen));
+ engine.init(cipherParams);
isInitialized = true;
}
-
+
public short getLength() throws CryptoException {
if (!isInitialized) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
}
return (short) engine.getMacSize();
}
-
+
public byte getAlgorithm() {
return algorithm;
}
-
+
public void update(byte[] inBuff, short inOffset, short inLength) throws CryptoException {
if (!isInitialized) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
}
engine.update(inBuff, inOffset, inLength);
}
-
+
public short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset) throws CryptoException {
if (!isInitialized) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
}
if ((algorithm == ALG_DES_MAC8_NOPAD || algorithm == ALG_DES_MAC4_NOPAD)
- && ((inLength % 8) != 0)) {
+ && ((inLength % 8) != 0)) {
CryptoException.throwIt(CryptoException.ILLEGAL_USE);
}
engine.update(inBuff, inOffset, inLength);
@@ -148,19 +165,19 @@ public short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff,
engine.reset();
return processedBytes;
}
-
+
public boolean verify(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset, short sigLength) throws CryptoException {
if (!isInitialized) {
CryptoException.throwIt(CryptoException.INVALID_INIT);
}
if ((algorithm == ALG_DES_MAC8_NOPAD || algorithm == ALG_DES_MAC4_NOPAD)
- && ((inLength % 8) != 0)) {
+ && ((inLength % 8) != 0)) {
CryptoException.throwIt(CryptoException.ILLEGAL_USE);
}
engine.update(inBuff, inOffset, inLength);
- byte[] sig = JCSystem.makeTransientByteArray((short) (macSize / 8), JCSystem.CLEAR_ON_RESET);
+ byte[] sig = new byte[getLength()];
engine.doFinal(sig, (short) 0);
engine.reset();
return Util.arrayCompare(sig, (short) 0, sigBuff, sigOffset, (short) sig.length) == 0;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/licel/jcardsim/crypto/package-info.java b/src/main/java/com/licel/jcardsim/crypto/package-info.java
new file mode 100644
index 00000000..8a4a69f7
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/crypto/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * jCardSim cryptography support classes.
+ */
+package com.licel.jcardsim.crypto;
diff --git a/src/main/java/com/licel/jcardsim/io/CAD.java b/src/main/java/com/licel/jcardsim/io/CAD.java
new file mode 100644
index 00000000..a1785f55
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/io/CAD.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.io;
+
+import com.licel.jcardsim.base.Simulator;
+import com.licel.jcardsim.remote.JavaCardRemoteClient;
+import java.util.Properties;
+
+/**
+ * Card Acceptance Device (CAD).
+ *
+ * @author LICEL LLC
+ */
+public class CAD {
+
+ public final static byte INTERNAL = 0;
+ public final static byte RMI = 1;
+ public final static byte JAVAX_SMARTCARDIO = 2;
+ byte interfaceType;
+ CardInterface cardInterface;
+
+ public CAD(Properties params) {
+ byte type = Byte.parseByte(params.getProperty("com.licel.jcardsim.terminal.type", Byte.toString(INTERNAL)));
+ switch (type) {
+ case INTERNAL:
+ cardInterface = new Simulator();
+ break;
+ case RMI:
+ try {
+ String host = params.getProperty("com.licel.jcardsim.terminal.host");
+ int port = Integer.parseInt(params.getProperty("com.licel.jcardsim.terminal.port"));
+ cardInterface = new JavaCardRemoteClient(host, port);
+ } catch (Exception e) {
+ throw new RuntimeException("RMI CardInterface init error", e);
+ }
+ break;
+ case JAVAX_SMARTCARDIO:
+ cardInterface = new JavaxSmartCardInterface();
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown CAD type: " + type);
+ }
+ this.interfaceType = type;
+
+ }
+
+ public CardInterface getCardInterface() {
+ return cardInterface;
+ }
+}
diff --git a/src/main/java/com/licel/jcardsim/io/CardInterface.java b/src/main/java/com/licel/jcardsim/io/CardInterface.java
new file mode 100644
index 00000000..eaf0cef7
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/io/CardInterface.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.io;
+
+/**
+ * Basic SmartCard Interface.
+ *
+ * @author LICEL LLC
+ */
+public interface CardInterface {
+
+ /**
+ * Powerdown/Powerup
+ */
+ public void reset();
+
+ /**
+ * Returns ATR
+ * @return ATR bytes
+ */
+ public byte[] getATR();
+
+ /**
+ * Transmit APDU to previous selected applet
+ *
+ * If no applet was selected returns byte[2]
+ * with status word 0x6986 (Command not allowed (no current EF))
+ *
+ * @param commandAPDU command apdu
+ * @return response APDU
+ * @see javax.smartcardio.CommandAPDU
+ * @see javax.smartcardio.ResponseAPDU
+ */
+ public byte[] transmitCommand(byte[] commandAPDU);
+}
diff --git a/src/main/java/com/licel/jcardsim/io/JavaCardInterface.java b/src/main/java/com/licel/jcardsim/io/JavaCardInterface.java
new file mode 100644
index 00000000..941dc66e
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/io/JavaCardInterface.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.io;
+
+import javacard.framework.AID;
+import javacard.framework.SystemException;
+
+/**
+ * Interface with JavaCard-specific functions.
+ * @author LICEL LLC
+ */
+public interface JavaCardInterface extends CardInterface {
+
+ /**
+ * Load
+ * Applet into Simulator
+ *
+ * @param aid applet aid
+ * @param appletClassName fully qualified applet class name Strin
+ * @param appletJarContents contains a byte array containing a jar file with an applet and its dependent classes
+ * @return applet AID
+ * @throws SystemException if appletClass not instanceof
+ * javacard.framework.Applet
+ */
+ public AID loadApplet(AID aid, String appletClassName, byte[] appletJarContents) throws SystemException;
+
+ /**
+ * Load
+ * Applet into Simulator
+ *
+ * @param aid applet aid
+ * @param appletClassName fully qualified applet class name String
+ * @return applet AID
+ * @throws SystemException if appletClass not instanceof
+ * javacard.framework.Applet
+ */
+ public AID loadApplet(AID aid, String appletClassName);
+
+ /**
+ * Create
+ * Applet instance in Simulator
+ * @param aid applet aid
+ * @param bArray the array containing installation parameters
+ * @param bOffset the starting offset in bArray
+ * @param bLength the length in bytes of the parameter data in bArray
+ * @return applet AID
+ * @throws SystemException if exception in Applet.install(..)
+ * method occurs.
+ */
+ public AID createApplet(AID aid, byte bArray[], short bOffset,
+ byte bLength) throws SystemException;
+
+ /**
+ * Install
+ * Applet into Simulator.
+ * This method is equal to:
+ *
+ * loadApplet(...);
+ * createApplet(...);
+ *
+ * @param aid applet aid or null
+ * @param appletClassName fully qualified applet class name Strin
+ * @param bArray the array containing installation parameters
+ * @param bOffset the starting offset in bArray
+ * @param bLength the length in bytes of the parameter data in bArray
+ * @return applet AID
+ * @throws SystemException if appletClass not instanceof
+ * javacard.framework.Applet
+ */
+ public AID installApplet(AID aid, String appletClassName, byte bArray[], short bOffset,
+ byte bLength) throws SystemException;
+
+ /**
+ * Install
+ * Applet into Simulator.
+ * This method is equal to:
+ *
+ * loadApplet(...);
+ * createApplet(...);
+ *
+ * @param aid applet aid or null
+ * @param appletClassName fully qualified applet class name Strin
+ * @param appletJarContents Contains a byte array containing a jar file with an applet and its dependent classes
+ * @param bArray the array containing installation parameters
+ * @param bOffset the starting offset in bArray
+ * @param bLength the length in bytes of the parameter data in bArray
+ * @return applet AID
+ * @throws SystemException if appletClass not instanceof
+ * javacard.framework.Applet
+ */
+ public AID installApplet(AID aid, String appletClassName, byte[] appletJarContents, byte bArray[], short bOffset,
+ byte bLength) throws SystemException;
+
+ /**
+ * Select applet by it's AID
+ * It's method must be called before start working with applet instance
+ * @param aid appletId
+ * @return true if applet selection success
+ */
+ public boolean selectApplet(AID aid);
+
+ /**
+ * Select applet by it's AID
+ * It's method must be called before start working with applet instance
+ * @param aid appletId
+ * @return byte array
+ */
+ public byte[] selectAppletWithResult(AID aid);
+
+ /**
+ * Switch protocol
+ *
+ * Supported protocols are:
+ * T=0 (alias: *)T=1T=CL, TYPE_A, T0 (alias: T=CL)T=CL, TYPE_A, T1T=CL, TYPE_B, T0T=CL, TYPE_B, T1JavaxSmartCardInterface instances share one SimulatorRuntime.JavaxSmartCardInterface(SimulatorRuntime)runtime is null
+ */
+ public JavaxSmartCardInterface(SimulatorRuntime runtime) {
+ super(runtime);
+ }
+
+ /**
+ * Wrapper for transmitCommand(byte[])
+ * @param commandApdu CommandAPDU
+ * @return ResponseAPDU
+ */
+ public ResponseAPDU transmitCommand(CommandAPDU commandApdu) {
+ return new ResponseAPDU(transmitCommand(commandApdu.getBytes()));
+ }
+}
diff --git a/src/main/java/com/licel/jcardsim/io/package-info.java b/src/main/java/com/licel/jcardsim/io/package-info.java
new file mode 100644
index 00000000..36e9cd13
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/io/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * jCardSim I/O support classes.
+ */
+package com.licel.jcardsim.io;
diff --git a/src/main/java/com/licel/jcardsim/remote/BixVReaderCard.java b/src/main/java/com/licel/jcardsim/remote/BixVReaderCard.java
new file mode 100644
index 00000000..9dfe98f5
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/remote/BixVReaderCard.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.remote;
+
+import com.licel.jcardsim.base.CardManager;
+import com.licel.jcardsim.base.Simulator;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * BixVReader Card Implementation.
+ *
+ * @author LICEL LLC
+ */
+public class BixVReaderCard {
+
+ Simulator sim;
+
+ public BixVReaderCard(int idx) throws IOException {
+ sim = new Simulator();
+ BixVReaderIPCProtocol driverProtocol = new BixVReaderIPCProtocol();
+ driverProtocol.connect(idx);
+ final IOThread ioThread = new IOThread(sim, driverProtocol);
+ ShutDownHook hook = new ShutDownHook(ioThread);
+ Runtime.getRuntime().addShutdownHook(hook);
+ ioThread.start();
+ driverProtocol.writeEventCommand(BixVReaderIPCProtocol.CARD_INSERTED);
+ }
+
+ static public void main(String args[]) throws Exception {
+ if (args.length !=1) {
+ System.out.println("Usage: java com.licel.jcardsim.remote.BixVReaderCard JavaCardInterface.
+ *
+ * @author LICEL LLC
+ */
+public interface JavaCardRemoteInterface extends Remote {
+
+ public String RMI_SERVER_ID = "jCardSim.rmiServer";
+
+ public SerializableAID loadApplet(SerializableAID aid, String appletClassName) throws RemoteException;
+
+ public SerializableAID loadApplet(SerializableAID aid, String appletClassName, byte[] appletJarContents) throws RemoteException;
+
+ public SerializableAID createApplet(SerializableAID aid, byte[] bArray, short bOffset, byte bLength) throws RemoteException;
+
+ public byte[] transmitCommand(byte[] data) throws RemoteException;
+
+ public boolean selectApplet(SerializableAID aid) throws RemoteException;
+
+ public byte[] selectAppletWithResult(SerializableAID aid) throws RemoteException;
+
+ public void reset() throws RemoteException;
+
+ public byte[] getATR() throws RemoteException;
+
+ public void changeProtocol(String protocol) throws RemoteException;
+
+ public String getProtocol() throws RemoteException;
+}
diff --git a/src/main/java/com/licel/jcardsim/remote/JavaCardRemoteServer.java b/src/main/java/com/licel/jcardsim/remote/JavaCardRemoteServer.java
new file mode 100644
index 00000000..6c4962d0
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/remote/JavaCardRemoteServer.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.remote;
+
+import com.licel.jcardsim.base.Simulator;
+import com.licel.jcardsim.base.SimulatorRuntime;
+
+import java.io.FileInputStream;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * RMI Server.
+ * @author LICEL LLC
+ */
+public class JavaCardRemoteServer extends java.rmi.server.UnicastRemoteObject
+ implements JavaCardRemoteInterface {
+
+ protected final Simulator sim;
+
+ public JavaCardRemoteServer(String host, int port) throws RemoteException {
+ sim = new Simulator(new SimulatorRuntime());
+ System.setProperty("java.rmi.server.hostname", host);
+ Registry registry = LocateRegistry.createRegistry(port);
+ registry.rebind(RMI_SERVER_ID, this);
+ }
+
+ static public void main(String args[]) throws Exception {
+ if (args.length !=1) {
+ System.out.println("Usage: java com.licel.jcardsim.remote.JavaCardRemoteServer Supported APDUs:
+ * + *CLA=0x80 INS=0 read valueCLA=0x80 INS=2 store value from CData.
+ * Only works on contacted interface
+ * CLA=0x80 INS=4 get interface information (protocol byte)Returns FCI (file control information) on SELECT
Supported APDUs:
+ * + *CLA=0x80 INS=0 return AIDCLA=0x80 INS=2 return instance countCLA=0x80 INS=4 lock the appletSupported APDUs:
+ * + *CLA=0x80 INS=0 digest of CDataCLA=0x80 INS=2 echo inputCLA=0x80 INS=4 echo value of LeCLA=0x80 INS=8 return last digestruntime is null
+ */
+ public CardSimulator(SimulatorRuntime runtime) {
+ super(runtime);
+ }
+
+ /**
+ * Wrapper for {@link #transmitCommand(byte[])}
+ *
+ * @param commandApdu CommandAPDU
+ * @return ResponseAPDU
+ */
+ @Override
+ public ResponseAPDU transmitCommand(CommandAPDU commandApdu) {
+ return new ResponseAPDU(transmitCommand(commandApdu.getBytes()));
+ }
+
+ /**
+ * Assigns this simulated card to a CardTerminal.
+ *If the card is already assigned to another CardTerminal, it will be ejected
+ * and inserted into the CardTerminal terminal.
null
+ */
+ public synchronized void assignToTerminal(CardTerminal terminal) {
+ final CardTerminal oldCardTerminal = owningCardTerminalReference.getAndSet(terminal);
+
+ if (terminal == oldCardTerminal) {
+ return;
+ }
+
+ if (oldCardTerminal != null) {
+ // eject card from old Terminal
+ ((CardTerminalSimulator.CardTerminalImpl) oldCardTerminal).assignSimulator(null);
+ }
+
+ if (terminal != null) {
+ // reset card
+ card.disconnect();
+ // assign to new terminal
+ ((CardTerminalSimulator.CardTerminalImpl) terminal).assignSimulator(this);
+ }
+ }
+
+ /**
+ * @return the assigned CardTerminal or null if none is assigned
+ */
+ public CardTerminal getAssignedCardTerminal() {
+ return owningCardTerminalReference.get();
+ }
+
+ final Card internalConnect(String protocol) {
+ card.connect(protocol);
+ return card;
+ }
+
+ final void internalEject(CardTerminal oldTerminal) {
+ if (owningCardTerminalReference.compareAndSet(oldTerminal, null)) {
+ card.eject();
+ }
+ }
+
+ private enum CardState {
+ Connected, Disconnected, Ejected
+ }
+
+ private static final class CardChannelImpl extends CardChannel {
+ private final CardImpl card;
+ private final int channelNr;
+
+ public CardChannelImpl(CardImpl card, int channelNr) {
+ this.card = card;
+ this.channelNr = channelNr;
+ }
+
+ @Override
+ public Card getCard() {
+ return card;
+ }
+
+ @Override
+ public int getChannelNumber() {
+ card.ensureConnected();
+ return channelNr;
+ }
+
+ @Override
+ public ResponseAPDU transmit(CommandAPDU commandAPDU) throws CardException {
+ return new ResponseAPDU(card.transmitCommand(commandAPDU.getBytes()));
+ }
+
+ @Override
+ public int transmit(ByteBuffer byteBuffer, ByteBuffer byteBuffer2) throws CardException {
+ byte[] result = card.transmitCommand(new CommandAPDU(byteBuffer).getBytes());
+ byteBuffer2.put(result);
+ return result.length;
+ }
+
+ @Override
+ public void close() throws CardException {
+ throw new CardException("Can not close basic channel");
+ }
+ }
+
+ private final class CardImpl extends Card {
+ private final CardChannel basicChannel;
+ private volatile String protocol = "T=0";
+ private volatile byte protocolByte = 0;
+ private volatile CardState state = CardState.Connected;
+
+ CardImpl() {
+ this.basicChannel = new CardChannelImpl(this, 0);
+ }
+
+ void ensureConnected() {
+ CardState cardState = state;
+ if (cardState == CardState.Disconnected) {
+ throw new IllegalStateException("Card was disconnected");
+ } else if (cardState == CardState.Ejected) {
+ throw new IllegalStateException("Card was removed");
+ }
+ }
+
+ @Override
+ public ATR getATR() {
+ return new ATR(CardSimulator.this.getATR());
+ }
+
+ @Override
+ public String getProtocol() {
+ return protocol;
+ }
+
+ @Override
+ public CardChannel getBasicChannel() {
+ return basicChannel;
+ }
+
+ @Override
+ public CardChannel openLogicalChannel() throws CardException {
+ throw new CardException("Logical channel not supported");
+ }
+
+ @Override
+ public void beginExclusive() throws CardException {
+ synchronized (runtime) {
+ if (!threadReference.compareAndSet(null, Thread.currentThread())) {
+ throw new CardException("Card is held exclusively by Thread " + threadReference.get());
+ }
+ }
+ }
+
+ @Override
+ public void endExclusive() throws CardException {
+ synchronized (runtime) {
+ if (!threadReference.compareAndSet(Thread.currentThread(), null)) {
+ throw new CardException("Card is held exclusively by Thread " + threadReference.get());
+ }
+ }
+ }
+
+ @Override
+ public byte[] transmitControlCommand(int i, byte[] bytes) throws CardException {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ @Override
+ public void disconnect(boolean reset) throws CardException {
+ synchronized (runtime) {
+ if (reset) {
+ CardSimulator.this.reset();
+ }
+ state = CardState.Disconnected;
+ }
+ }
+
+ void connect(String protocol) {
+ synchronized (runtime) {
+ this.protocolByte = CardSimulator.this.getProtocolByte(protocol);
+ this.protocol = protocol;
+ this.state = CardState.Connected;
+ }
+ }
+
+ void eject() {
+ synchronized (runtime) {
+ CardSimulator.this.reset();
+ state = CardState.Ejected;
+ }
+ }
+
+ void disconnect() {
+ synchronized (runtime) {
+ CardSimulator.this.reset();
+ state = CardState.Disconnected;
+ }
+ }
+
+ byte[] transmitCommand(byte[] capdu) throws CardException {
+ synchronized (runtime) {
+ ensureConnected();
+ Thread thread = threadReference.get();
+ if (thread != null && thread != Thread.currentThread()) {
+ throw new CardException("Card is held exclusively by Thread " + thread.getName());
+ }
+
+ byte currentProtocol = getProtocolByte(CardSimulator.this.getProtocol());
+ try {
+ runtime.changeProtocol(protocolByte);
+ return CardManager.dispatchApdu(CardSimulator.this, capdu);
+ } finally {
+ runtime.changeProtocol(currentProtocol);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/licel/jcardsim/smartcardio/CardTerminalSimulator.java b/src/main/java/com/licel/jcardsim/smartcardio/CardTerminalSimulator.java
new file mode 100644
index 00000000..8d57e5b2
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/smartcardio/CardTerminalSimulator.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2015 Robert Bachmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.smartcardio;
+
+import com.licel.jcardsim.utils.AutoResetEvent;
+
+import javax.smartcardio.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A simulated {@link javax.smartcardio.TerminalFactory}.
+ *Example: Obtaining a Card
+ *
+ * // create card simulator
+ * CardSimulator cardSimulator = new CardSimulator();
+ *
+ * // connect to a card
+ * CardTerminal terminal =
+ * CardTerminalSimulator.terminal(cardSimulator);
+ * Card card = terminal.connect("*");
+ *
+ * Example: Inserting/ejecting a Card
+ *
+ * // create card simulator
+ * CardSimulator cardSimulator = new CardSimulator();
+ *
+ * // create CardTerminal
+ * CardTerminals terminals = CardTerminalSimulator.terminals("my terminal")
+ * CardTerminal terminal = terminals.getTerminal("my terminal");
+ *
+ * // insert Card
+ * cardSimulator.assignToTerminal(terminal);
+ *
+ * // eject Card
+ * cardSimulator.assignToTerminal(null);
+ *
+ *
+ * @see com.licel.jcardsim.smartcardio.CardSimulator
+ */
+public final class CardTerminalSimulator {
+ private CardTerminalSimulator() {
+ }
+
+ /**
+ * Create a single CardTerminal.
+ *
+ * @param cardSimulator card to insert
+ * @param name the terminal name
+ * @return a new CardTerminal instance
+ * @throws java.lang.NullPointerException if name or cardSimulator is null
+ */
+ public static CardTerminal terminal(CardSimulator cardSimulator, String name) {
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ if (cardSimulator == null) {
+ throw new NullPointerException("cardSimulator");
+ }
+ CardTerminal cardTerminal = terminals(name).getTerminal(name);
+ cardSimulator.assignToTerminal(cardTerminal);
+ return cardTerminal;
+ }
+
+ /**
+ * Create a CardTerminal with name "jCardSim.Terminal".
+ *
+ * @param cardSimulator card to insert
+ * @return a new CardTerminal instance
+ * @throws java.lang.NullPointerException if name or cardSimulator is null
+ */
+ public static CardTerminal terminal(CardSimulator cardSimulator) {
+ return terminal(cardSimulator, "jCardSim.Terminal");
+ }
+
+ /**
+ * Create CardTerminals.
+ *Example:
+ *
+ * CardTerminals terminals = CardTerminalSimulator.terminals("1","2");
+ * CardTerminal terminal = terminals.getTerminal("1");
+ *
+ * // assign simulator
+ * CardSimulator cardSimulator = new CardSimulator();
+ * cardSimulator.assignToTerminal(terminal);
+ *
+ *
+ * @param names the terminal names
+ * @return a new CardTerminals instance
+ * @throws java.lang.NullPointerException if names is null
+ * @throws java.lang.IllegalArgumentException if any name is null or duplicated
+ * @see javax.smartcardio.CardTerminals
+ */
+ public static CardTerminals terminals(String... names) {
+ if (names == null) {
+ throw new NullPointerException("names");
+ }
+ SetSecurity provider.
+ *Register the SecurityProvider with:
+ *
+ * if (Security.getProvider("CardTerminalSimulator") == null) {
+ * Security.addProvider(new CardTerminalSimulator.SecurityProvider());
+ * }
+ *
+ */
+ public static final class SecurityProvider extends Provider {
+ public SecurityProvider() {
+ super("CardTerminalSimulator", 1.0d, "jCardSim Virtual Terminal Provider");
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ put("TerminalFactory." + "CardTerminalSimulator", Factory.class.getCanonicalName()
+ .replace(".Factory", "$Factory"));
+ return null;
+ }
+ });
+ }
+ }
+
+ /**
+ * {@link javax.smartcardio.TerminalFactorySpi} implementation.
+ * Applications do not access this class directly, instead see {@link javax.smartcardio.TerminalFactory}.
+ */
+ @SuppressWarnings("unused")
+ public static final class Factory extends TerminalFactorySpi {
+ private final CardTerminals cardTerminals;
+
+ public Factory(Object params) {
+ String[] names;
+ if (params == null) {
+ names = new String[]{"jCardSim.Terminal"};
+ } else if (params instanceof String) {
+ names = new String[]{(String) params};
+ } else if (params instanceof String[]) {
+ names = (String[]) params;
+ } else {
+ throw new IllegalArgumentException("Illegal parameter: " + params);
+ }
+ cardTerminals = terminals(names);
+ }
+
+ @Override
+ protected CardTerminals engineTerminals() {
+ return cardTerminals;
+ }
+ }
+
+ static boolean waitForLatch(AutoResetEvent autoResetEvent, long timeoutMilliseconds) throws InterruptedException {
+ if (timeoutMilliseconds < 0) {
+ throw new IllegalArgumentException("timeout is negative");
+ }
+ if (timeoutMilliseconds == 0) { // wait forever
+ boolean success;
+ do {
+ success = autoResetEvent.await(1, TimeUnit.MINUTES);
+ } while (!success);
+ return true;
+ }
+ return autoResetEvent.await(timeoutMilliseconds, TimeUnit.MILLISECONDS);
+ }
+
+ static final class CardTerminalsImpl extends CardTerminals {
+ private final AtomicBoolean waitCalled = new AtomicBoolean(false);
+ private final AutoResetEvent terminalsChangeAutoResetEvent = new AutoResetEvent();
+ private final ArrayListjavax.smartcardio support.
+ */
+package com.licel.jcardsim.smartcardio;
diff --git a/src/main/java/com/licel/jcardsim/utils/AIDUtil.java b/src/main/java/com/licel/jcardsim/utils/AIDUtil.java
new file mode 100644
index 00000000..23392803
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/utils/AIDUtil.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014 Robert Bachmann
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.utils;
+
+import javacard.framework.AID;
+import javacard.framework.ISO7816;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.util.Comparator;
+
+/**
+ * Utility methods for dealing with AIDs.
+ */
+public final class AIDUtil {
+ private static final Comparatoraid
+ * @param aid AID to be selected
+ * @return SELECT APDU (CLA=0x00, INS=0xA4, P1=0x04, P2=0x00, Lc, AID, Le=0x00)
+ * @throws java.lang.NullPointerException if aid is null
+ */
+ public static byte[] select(AID aid) {
+ if (aid == null) {
+ throw new NullPointerException("aid");
+ }
+
+ byte[] aidBuffer = new byte[16];
+ byte length = aid.getBytes(aidBuffer, (short) 0);
+
+ byte[] selectCmd = new byte[length + ISO7816.OFFSET_CDATA + 1];
+ selectCmd[ISO7816.OFFSET_CLA] = ISO7816.CLA_ISO7816;
+ selectCmd[ISO7816.OFFSET_INS] = ISO7816.INS_SELECT;
+ selectCmd[ISO7816.OFFSET_P1] = 0x04;
+ selectCmd[ISO7816.OFFSET_P2] = 0x00;
+ selectCmd[ISO7816.OFFSET_LC] = length;
+ System.arraycopy(aidBuffer, 0, selectCmd, ISO7816.OFFSET_CDATA, length);
+ selectCmd[selectCmd.length - 1] = 0;
+
+ return selectCmd;
+ }
+
+ /**
+ * Generate a SELECT APDU for aid
+ * @param aid AID to be selected
+ * @return SELECT APDU (CLA=0x00, INS=0xA4, P1=0x04, P2=0x00, Lc, AID, Le=0x00)
+ * @throws java.lang.IllegalArgumentException if aid is invalid
+ * @throws java.lang.NullPointerException if aid is null
+ */
+ public static byte[] select(String aid) {
+ if (aid == null) {
+ throw new NullPointerException("aid");
+ }
+
+ byte[] aidBuffer = ByteUtil.byteArray(aid);
+ if (aidBuffer.length > 16) {
+ throw new IllegalArgumentException("AID must not be larger than 16 bytes: " + ByteUtil.hexString(aidBuffer));
+ }
+
+ byte[] selectCmd = new byte[aidBuffer.length + ISO7816.OFFSET_CDATA + 1];
+ selectCmd[ISO7816.OFFSET_CLA] = ISO7816.CLA_ISO7816;
+ selectCmd[ISO7816.OFFSET_INS] = ISO7816.INS_SELECT;
+ selectCmd[ISO7816.OFFSET_P1] = 0x04;
+ selectCmd[ISO7816.OFFSET_P2] = 0x00;
+ selectCmd[ISO7816.OFFSET_LC] = (byte) aidBuffer.length;
+ System.arraycopy(aidBuffer, 0, selectCmd, ISO7816.OFFSET_CDATA, aidBuffer.length);
+ selectCmd[selectCmd.length - 1] = 0;
+
+ return selectCmd;
+ }
+
+ /**
+ * Create an AID from a byte array
+ * @param aidBytes AID bytes
+ * @return aid
+ * @throws java.lang.NullPointerException if aidBytes is null
+ * @throws java.lang.IllegalArgumentException if aidBytes.length is incorrect
+ */
+ public static AID create(byte[] aidBytes) {
+ if (aidBytes == null) {
+ throw new NullPointerException("aidString");
+ }
+ if (aidBytes.length < 5 || aidBytes.length > 16) {
+ throw new IllegalArgumentException("AID size must be between 5 and 16 but was " + aidBytes.length);
+ }
+ return new AID(aidBytes, (short) 0, (byte) aidBytes.length);
+ }
+
+ /**
+ * Create an AID from a byte array
+ * @param aidString AID bytes as hex string
+ * @return aid
+ * @throws java.lang.NullPointerException if aidString is null
+ * @throws java.lang.IllegalArgumentException if length is incorrect
+ */
+ public static AID create(String aidString) {
+ if (aidString == null) {
+ throw new NullPointerException("aidString");
+ }
+ return create(Hex.decode(aidString));
+ }
+
+ /**
+ * Convert AID to hex-string
+ * @param aid AID to convert
+ * @return hex string
+ * @throws java.lang.NullPointerException if aid is null
+ */
+ public static String toString(AID aid) {
+ if (aid == null) {
+ throw new NullPointerException("aid");
+ }
+ byte[] buffer = new byte[16];
+ short len = aid.getBytes(buffer, (short) 0);
+ return ByteUtil.hexString(buffer, 0, len);
+ }
+
+ /**
+ * @return a Comparator for AIDs
+ */
+ public static ComparatorAutoResetEvent.
+ * See MSDN.
+ */ +public final class AutoResetEvent { + private final static int SIGNALED = 1; + private final static int NOT_SIGNALED = 0; + private final Sync sync = new Sync(); + + /** + * Wake up one thread that is waiting. + */ + public void signal() { + sync.releaseShared(SIGNALED); + } + + /** + * Reset. + */ + public void reset() { + sync.releaseShared(NOT_SIGNALED); + } + + /** + * Wait until thread is signaled or interrupted. + * @param time time to wait + * @param unit time unit oftime
+ * @return true if signaled
+ * @throws InterruptedException if the thread is interrupted
+ */
+ public boolean await(long time, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(time));
+ }
+
+ private static class Sync extends AbstractQueuedSynchronizer {
+ Sync() {
+ setState(NOT_SIGNALED);
+ }
+
+ protected int tryAcquireShared(int ignore) {
+ if (compareAndSetState(SIGNALED, NOT_SIGNALED)) {
+ return 1;
+ }
+ return -1;
+ }
+
+ protected boolean tryReleaseShared(int state) {
+ setState(state);
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/licel/jcardsim/utils/BiConsumer.java b/src/main/java/com/licel/jcardsim/utils/BiConsumer.java
new file mode 100644
index 00000000..075b3d3d
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/utils/BiConsumer.java
@@ -0,0 +1,8 @@
+package com.licel.jcardsim.utils;
+
+/**
+ * Back-port of Java 8 java.util.function.BiConsumer.
+ */
+public interface BiConsumerhexString is null
+ */
+ public static byte[] byteArray(String hexString) {
+ if (hexString == null) {
+ throw new NullPointerException("hexArray");
+ }
+ return Hex.decode(hexString);
+ }
+
+ /**
+ * Convert byte array into hex string
+ * @param bytes hex string
+ * @return hexString
+ * @throws java.lang.NullPointerException if bytes is null
+ */
+ public static String hexString(byte[] bytes) {
+ if (bytes == null) {
+ throw new NullPointerException("bytes");
+ }
+ return hexString(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Convert byte array into hex string
+ * @param bytes hex string
+ * @param offset offset
+ * @param length length
+ * @return hexString
+ * @throws java.lang.NullPointerException if bytes is null
+ */
+ public static String hexString(byte[] bytes, int offset, int length) {
+ // http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-java
+ if (bytes == null) {
+ throw new NullPointerException("bytes");
+ }
+ char[] hexChars = new char[length * 2];
+ for ( int j = offset; j < (offset + length); j++ ) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ /**
+ * Extract status word from APDU
+ * @param apduBuffer APDU bytes
+ * @return status word
+ * @throws java.lang.NullPointerException if apduBuffer is null
+ * @throws java.lang.IllegalArgumentException if apduBuffer.length is < 2
+ */
+ public static short getSW(byte[] apduBuffer) {
+ if (apduBuffer == null) {
+ throw new NullPointerException("bytes");
+ }
+ if (apduBuffer.length < 2) {
+ throw new IllegalArgumentException("bytes.length must be at least 2");
+ }
+ return getShort(apduBuffer, apduBuffer.length - 2);
+ }
+
+ /**
+ * Check status word from APDU
+ * @param apduBuffer APDU bytes
+ * @param expected expected status word
+ * @throws java.lang.NullPointerException if apduBuffer is null
+ * @throws java.lang.IllegalArgumentException if apduBuffer.length is < 2
+ * @throws java.lang.AssertionError if expected does not match the status word from apduBuffer
+ */
+ public static void requireSW(byte[] apduBuffer, int expected) {
+ int sw = getSW(apduBuffer) & 0xFFFF;
+ if (sw != expected) {
+ throw new AssertionError(String.format("Expected status word %x but got %x", expected, sw));
+ }
+ }
+
+ /**
+ * Check status word from APDU
+ * @param apduBuffer APDU bytes
+ * @param expected expected status word
+ * @throws java.lang.NullPointerException if apduBuffer is null
+ * @throws java.lang.IllegalArgumentException if apduBuffer.length is < 2
+ * @throws java.lang.AssertionError if expected does not match the status word from apduBuffer
+ */
+ public static void requireSW(byte[] apduBuffer, short expected) {
+ requireSW(apduBuffer, expected & 0xFFFF);
+ }
+
+ /**
+ * Read short from array
+ * @see javacard.framework.Util#getShort(byte[], short)
+ * @param bArray byte array
+ * @param offset offset
+ * @return short value
+ */
+ public static short getShort(byte[] bArray, int offset) {
+ return (short) (((short) bArray[offset] << 8) + ((short) bArray[offset + 1] & 0xff));
+ }
+
+ private ByteUtil() {}
+}
diff --git a/src/main/java/com/licel/jcardsim/utils/package-info.java b/src/main/java/com/licel/jcardsim/utils/package-info.java
new file mode 100644
index 00000000..bb4b69b9
--- /dev/null
+++ b/src/main/java/com/licel/jcardsim/utils/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Utility classes.
+ */
+package com.licel.jcardsim.utils;
diff --git a/src/main/java/java/rmi/RemoteException.java b/src/main/java/java/rmi/RemoteException.java
deleted file mode 100644
index 0a1f6a8a..00000000
--- a/src/main/java/java/rmi/RemoteException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2013 Licel LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.rmi;
-
-public class RemoteException extends java.io.IOException {
-
- public RemoteException() {
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/javacard/framework/AID.java b/src/main/java/javacard/framework/AID.java
index d8e0ad95..279b3c36 100644
--- a/src/main/java/javacard/framework/AID.java
+++ b/src/main/java/javacard/framework/AID.java
@@ -42,7 +42,6 @@
*
*/
public class AID {
-
byte aid[];
/**
@@ -97,7 +96,7 @@ public final byte getBytes(byte dest[], short offset)
* This method does not throw NullPointerException.
* @param anObject the object to compare this AID against
* @return true if the AID byte values are equal, false otherwise
- * @throws SecurityException anObject object is not accessible in the caller's context
*/
public final boolean equals(Object anObject)
throws SecurityException {
diff --git a/src/main/java/javacard/framework/APDU.java b/src/main/java/javacard/framework/APDU.java
index f882865c..852a8bf5 100644
--- a/src/main/java/javacard/framework/APDU.java
+++ b/src/main/java/javacard/framework/APDU.java
@@ -5,41 +5,47 @@
package javacard.framework;
import com.licel.jcardsim.base.SimulatorSystem;
+import com.licel.jcardsim.utils.ByteUtil;
+
+import java.util.Arrays;
/**
+ *
* Application Protocol Data Unit (APDU) is
* the communication format between the card and the off-card applications.
* The format of the APDU is defined in ISO specification 7816-4.- * + * * This class only supports messages which conform to the structure of * command and response defined in ISO 7816-4. The behavior of messages which - * use proprietary structure of messages ( for example with header CLA byte in range 0xD0-0xFE ) is - * undefined. This class does not support extended length fields.
- *
+ * use proprietary structure of messages is
+ * undefined. This class optionally supports extended length fields but only when
+ * the currently selected applet implements the javacardx.apdu.ExtendedLength interface.
+ *
* The APDU object is owned by the Java Card runtime environment. The APDU class maintains a byte array
* buffer which is used to transfer incoming APDU header and data bytes as well as outgoing data.
* The buffer length must be at least 133 bytes ( 5 bytes of header and 128 bytes of data ).
* The Java Card runtime environment must zero out the APDU buffer before each new message received from the CAD.
- *
+ *
* The Java Card runtime environment designates the The Java Card runtime environment similarly marks the APDU buffer as a global array
- * (See Runtime
+ * (See Runtime Environment
* Specification for the Java Card Platform, section 6.2.2 for details).
* A global array
* can be accessed from any applet context. References to global arrays
* cannot be stored in class variables or instance variables or array components.
*
- *
+ *
* The applet receives the
- *
+ * the first five header bytes [ CLA, INS, P1, P2, P3 ] are available
+ * in the APDU buffer. (The header format is the ISO7816-4 defined 7 byte extended APDU format
+ * with a 3 byte Lc field when the Lc field in the incoming APDU header is 3 bytes long).
+ *
* The
@@ -48,71 +54,84 @@
* outgoing response APDU data size may be bigger than the APDU buffer size and may
* need to be written in portions by the applet. The
- *
+ *
* For sending large byte arrays as response data,
* the
- *
+ * manages the APDU buffer.
+ *
*
* Note that the state number assignments are ordered as follows:
- * STATE_INITIAL < STATE_PARTIAL_INCOMING < STATE_FULL_INCOMING <
- * STATE_OUTGOING < STATE_OUTGOING_LENGTH_KNOWN < STATE_PARTIAL_OUTGOING <
+ * STATE_INITIAL < STATE_PARTIAL_INCOMING < STATE_FULL_INCOMING <
+ * STATE_OUTGOING < STATE_OUTGOING_LENGTH_KNOWN < STATE_PARTIAL_OUTGOING <
* STATE_FULL_OUTGOING.
*
* The following are processing error states and have negative state number
* assignments :
* STATE_ERROR_NO_T0_GETRESPONSE, STATE_ERROR_T1_IFD_ABORT, STATE_ERROR_IO and
* STATE_ERROR_NO_T0_REISSUE.
+ * Note: Note:APDU object as a temporary Java Card runtime environment Entry Point Object
- * (See Runtime
+ * (See Runtime Environment
* Specification for the Java Card Platform, section 6.2.1 for details).
* A temporary Java Card runtime environment Entry Point Object can be accessed from any applet context. References
* to these temporary objects cannot be stored in class variables or instance variables
* or array components.
* APDU instance to process from
* the Java Card runtime environment in the Applet.process(APDU) method, and
- * the first five bytes [ CLA, INS, P1, P2, P3 ] are available
- * in the APDU buffer.APDU class API is designed to be transport protocol independent.
* In other words, applets can use the same APDU methods regardless of whether
* the underlying protocol in use is T=0 or T=1 (as defined in ISO 7816-3).APDU class has methods
* to facilitate this.APDU class provides a special method sendBytesLong() which
- * manages the APDU buffer.
* // The purpose of this example is to show most of the methods
* // in use and not to depict any particular APDU processing
- *
+ *
+ * class MyApplet extends javacard.framework.Applet{
+ * // ...
* public void process(APDU apdu){
- * // ...
- * byte[] buffer = apdu.getBuffer();
- * byte cla = buffer[ISO7816.OFFSET_CLA];
- * byte ins = buffer[ISO7816.OFFSET_INS];
- * ...
- * // assume this command has incoming data
- * // Lc tells us the incoming apdu command length
- * short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
- * if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
- *
- * short readCount = apdu.setIncomingAndReceive();
- * while ( bytesLeft > 0){
- * // process bytes in buffer[5] to buffer[readCount+4];
- * bytesLeft -= readCount;
- * readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
- * }
- * //
- * //...
- * //
- * // Note that for a short response as in the case illustrated here
- * // the three APDU method calls shown : setOutgoing(),setOutgoingLength() & sendBytes()
- * // could be replaced by one APDU method call : setOutgoingAndSend().
- *
- * // construct the reply APDU
- * short le = apdu.setOutgoing();
- * if (le < (short)2) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
- * apdu.setOutgoingLength( (short)3 );
- *
- * // build response data in apdu.buffer[ 0.. outCount-1 ];
- * buffer[0] = (byte)1; buffer[1] = (byte)2; buffer[3] = (byte)3;
- * apdu.sendBytes ( (short)0 , (short)3 );
- * // return good complete status 90 00
- * }
+ * // ...
+ * byte[] buffer = apdu.getBuffer();
+ * byte cla = buffer[ISO7816.OFFSET_CLA];
+ * byte ins = buffer[ISO7816.OFFSET_INS];
+ * ...
+ * // assume this command has incoming data
+ * // Lc tells us the incoming apdu command length
+ * short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
+ * if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
+ *
+ * short readCount = apdu.setIncomingAndReceive();
+ * while ( bytesLeft > 0){
+ * // process bytes in buffer[5] to buffer[readCount+4];
+ * bytesLeft -= readCount;
+ * readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
+ * }
+ * //
+ * //...
+ * //
+ * // Note that for a short response as in the case illustrated here
+ * // the three APDU method calls shown : setOutgoing(),setOutgoingLength() & sendBytes()
+ * // could be replaced by one APDU method call : setOutgoingAndSend().
+ *
+ * // construct the reply APDU
+ * short le = apdu.setOutgoing();
+ * if (le < (short)2) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
+ * apdu.setOutgoingLength( (short)3 );
+ *
+ * // build response data in apdu.buffer[ 0.. outCount-1 ];
+ * buffer[0] = (byte)1; buffer[1] = (byte)2; buffer[3] = (byte)3;
+ * apdu.sendBytes ( (short)0 , (short)3 );
+ * // return good complete status 90 00
+ * }
+ * // ...
+ * }
*
- *
+ *
* The APDU class also defines a set of STATE_.. constants
- * which represent the various processing states of the APDUobject based
+ * which represent the various processing states of the APDU object based
* on the methods invoked and the state of the data transfers. The
* getCurrentState() method returns the current state.
*
+ *
* @see APDUException
* @see ISOException
- *
- */
-public final class APDU {
+ */
+public final class APDU {
/**
* This is the state of a new APDU object when only the command
* header is valid.
@@ -207,28 +226,34 @@ public final class APDU {
public static final byte PROTOCOL_MEDIA_USB = -96;
// buffer size
private static final short BUFFER_SIZE = 260;
+ // buffer size (extended APDU) + (CLA,INS,P1,P2,0,Lc_Hi,Lc_Low,CData,Le_Hi,Le_Lo)
+ private static final int BUFFER_EXTENDED_SIZE = Short.MAX_VALUE + 10;
// input block size, for T0 protocol = 1
private static final short T0_IBS = 1;
// output block size, for T0 protocol = 258
private static final short T0_OBS = 258;
+ // block size, for T1 protocol
+ private static final short T1_BLOCK_SIZE = 254;
// NAD, for T0 protocol = 9
private static final byte T0_NAD = 0;
// transient array to store variables
- private byte[] ramVars;
+ private short[] ramVars;
// LE variable offset in ramVars
private static final byte LE = 0;
// LR variable offset in ramVars
private static final byte LR = 1;
// LC variable offset in ramVars
- private static final byte LC = 2;
+ private static final byte LC = 3;
// PRE_READ_LENGTH variable offset in ramVars
- private static final byte PRE_READ_LENGTH = 3;
+ private static final byte PRE_READ_LENGTH = 4;
// CURRENT_STATE variable offset in ramVars
- private static final byte CURRENT_STATE = 4;
+ private static final byte CURRENT_STATE = 5;
// LOGICAL_CHN variable offset in ramVars
- private static final byte LOGICAL_CHN = 5;
+ private static final byte LOGICAL_CHN = 6;
+ // ACTIVE_PROTOCOL variable offset in ramVars
+ private static final byte ACTIVE_PROTOCOL = 7;
// total length ramVars
- private static final byte RAM_VARS_LENGTH = 6;
+ private static final byte RAM_VARS_LENGTH = 8;
// transient array to store boolean flags
private boolean[] flags;
// outgoingFlag;
@@ -241,27 +266,30 @@ public final class APDU {
private static final byte INCOMING_FLAG = 3;
// notGetResponseFlag;
private static final byte NO_GET_RESPONSE_FLAG = 4;
+ // accessAllowedFlag;
+ private static final byte ACCESS_ALLOWED_FLAG = 5;
// total length flags
- private static final byte FLAGS_LENGTH = 5;
- //
- private byte[] buffer;
- // reference to this
- private static APDU thisAPDU;
-
- APDU() {
- buffer = JCSystem.makeTransientByteArray(BUFFER_SIZE, JCSystem.CLEAR_ON_RESET);
- ramVars = JCSystem.makeTransientByteArray(RAM_VARS_LENGTH, JCSystem.CLEAR_ON_RESET);
- flags = JCSystem.makeTransientBooleanArray(FLAGS_LENGTH, JCSystem.CLEAR_ON_RESET);
- thisAPDU = this;
+ private static final byte FLAGS_LENGTH = 6;
+ // APDU input buffer
+ private final byte[] buffer;
+ // extended APDU flag
+ private final boolean extended;
+
+ APDU(boolean extended) {
+ this.extended = extended;
+ buffer = new byte[extended ? BUFFER_EXTENDED_SIZE : BUFFER_SIZE];
+ ramVars = new short[RAM_VARS_LENGTH];
+ flags = new boolean[FLAGS_LENGTH];
+ internalReset(PROTOCOL_T0, null);
}
/**
* Returns the APDU buffer byte array.
*
- *
, section 6.2.2 for details.
*
* @return byte array containing the APDU buffer
*/
@@ -283,10 +311,10 @@ public byte[] getBuffer() {
* should account for this potential blocksize.PROTOCOL_T0
*/
public static byte getProtocol() {
- return PROTOCOL_T0;
+ APDU apdu = SimulatorSystem.instance().getCurrentAPDU();
+ return (byte) apdu.ramVars[ACTIVE_PROTOCOL];
}
/**
@@ -331,17 +360,27 @@ public byte getNAD() {
/**
* This method is used to set the data transfer direction to
- * outbound and to obtain the expected length of response (Le).
- *
Notes. - *
Notes.
setIncomingAndReceive() must
+ * be invoked prior to calling this method. Otherwise, erroneous
+ * behavior may result in T=0 protocol.
* APDU object to
- * STATE_OUTGOING.
+ * javacardx.apdu.ExtendedLength interface.
+ * javacardx.apdu.ExtendedLength interface.
+ * APDU object to
+ * STATE_OUTGOING.
* APDUException.ILLEGAL_USE if this method, or setOutgoingNoChaining() method already invoked.
* APDUException.IO_ERROR on I/O error.
* setOutgoing() method by applets which need
+ * This method should be used in place of the
+ * setOutgoing() method by applets which need
* to be compatible with legacy CAD/terminals which do not support ISO 7816-3/4 defined block chaining.
- * See Runtime
+ * See Runtime Environment
* Specification for the Java Card Platform, section 9.4 for details.
- * Notes. - *
Notes.
setIncomingAndReceive() must
+ * be invoked prior to calling this method. Otherwise, erroneous
+ * behavior may result in T=0 protocol.
* javacardx.apdu.ExtendedLength interface.
* waitExtension() method cannot be used.
* (ISO7816.SW_BYTES_REMAINING_00+count) response status chaining.
+ * without using (ISO7816.SW_BYTES_REMAINING_00+count) response status chaining.
* APDU object to
- * STATE_OUTGOING.
+ * APDU object to
+ * STATE_OUTGOING.
* APDUException.ILLEGAL_USE if this method, or setOutgoing() method already invoked.
- * APDUException.IO_ERROR on I/O errorAPDUException.ILLEGAL_USE if this method, or setOutgoingNoChaining() method already invoked.
+ * APDUException.IO_ERROR on I/O error.
+ * 0 is specified, no data will be output.
+ * Sets the actual length of response data. If a length of
+ * 0 is specified, no data will be output.
* Note:
APDU object to
+ * APDU object to
* STATE_OUTGOING_LENGTH_KNOWN.
* + * * @param len the length of response data - * @throws APDUException with the following reason codes: - *
APDUException.ILLEGAL_USE if setOutgoing() not called or this method already invoked.
- * APDUException.BAD_LENGTH if len is greater than 256 or
- * if non BLOCK CHAINED data transfer is requested and len is greater than
- * (IFSD-2), where IFSD is the Outgoing Block Size. The -2 accounts for the status bytes in T=1.
- * * APDUException.NO_GETRESPONSE if T=0 protocol is in use and
- * the CAD does not respond to (ISO7816.SW_BYTES_REMAINING_00+count) response status
- * with GET RESPONSE command on the same origin logical channel number as that of the current
- * APDU command.
- * APDUException.NO_T0_REISSUE if T=0 protocol is in use and
- * the CAD does not respond to (ISO7816.SW_CORRECT_LENGTH_00+count) response status
- * by re-issuing same APDU command on the same origin logical channel number as that of the current
- * APDU command with the corrected length.
+ * @throws APDUException with the following reason codes:APDUException.ILLEGAL_USE if setOutgoing() or setOutgoingNoChaining() not called
+ * or if setOutgoingAndSend() already invoked, or this method already invoked.
+ * APDUException.BAD_LENGTH if any one of the following is true:len is negative.
+ * len is greater than 256 and the currently selected applet does not implement the javacardx.apdu.ExtendedLength interface.
+ * APDUException.NO_T0_GETRESPONSE if T=0 protocol is in use and the CAD does not respond to (ISO7816.SW_BYTES_REMAINING_00+count) response status
+ * with GET RESPONSE command on the same origin logical channel number as that of the current APDU command.
+ * APDUException.NO_T0_REISSUE if T=0 protocol
+ * is in use and the CAD does not respond to (ISO7816.SW_CORRECT_LENGTH_00+count) response status by re-issuing same APDU command on the same origin
+ * logical channel number as that of the current APDU command with the corrected length.
* APDUException.IO_ERROR on I/O error.
* + * This method should only be called on a case 3 or case 4 command, otherwise erroneous behavior may result. *
Notes: *
receiveBytes(5).
+ * and calls receiveBytes(5) for normal semantics or receiveBytes(7) for extended semantics.
* Applet.process() method.
* APDU object to
* STATE_PARTIAL_INCOMING if all incoming bytes are not received.
@@ -511,16 +562,19 @@ public short setIncomingAndReceive()
APDUException.throwIt(APDUException.ILLEGAL_USE);
}
flags[INCOMING_FLAG] = true;
- byte Lc = (byte) (buffer[ISO7816.OFFSET_LC]);
+ short Lc = (short) (0xFF & buffer[ISO7816.OFFSET_LC]);
+ if (extended) {
+ Lc = Util.getShort(buffer, (short) (ISO7816.OFFSET_LC + 1));
+ }
ramVars[LC] = Lc;
- ramVars[LE] = (byte) 0;
}
- return receiveBytes(ISO7816.OFFSET_CDATA);
+ return receiveBytes(getOffsetCdata());
}
public void sendBytes(short bOff, short len)
throws APDUException {
- if (bOff < 0 || len < 0 || (short) (bOff + len) > 255) {
+ final short max = extended ? Short.MAX_VALUE : T0_OBS;
+ if (bOff < 0 || len < 0 || (short) (bOff + len) > max) {
APDUException.throwIt(APDUException.BUFFER_BOUNDS);
}
if (!flags[OUTGOING_LEN_SET_FLAG] || flags[NO_GET_RESPONSE_FLAG]) {
@@ -529,24 +583,20 @@ public void sendBytes(short bOff, short len)
if (len == 0) {
return;
}
- short Lr = getLr();
+ short Lr = ramVars[LR];
if (len > Lr) {
APDUException.throwIt(APDUException.ILLEGAL_USE);
}
- short Le = getLe();
- SimulatorSystem.sendAPDU(buffer, bOff, len);
+ SimulatorSystem.instance().sendAPDU(buffer, bOff, len);
- bOff += len;
Lr -= len;
- Le = Lr;
-
if (Lr == 0) {
ramVars[CURRENT_STATE] = STATE_FULL_OUTGOING;
} else {
ramVars[CURRENT_STATE] = STATE_PARTIAL_OUTGOING;
}
- ramVars[LE] = (byte) Le;
- ramVars[LR] = (byte) Lr;
+
+ ramVars[LR] = Lr;
}
/**
@@ -651,13 +701,13 @@ public void setOutgoingAndSend(short bOff, short len)
* @return the current processing state of the APDU
*/
public byte getCurrentState() {
- return ramVars[CURRENT_STATE];
+ return (byte) ramVars[CURRENT_STATE];
}
/**
- * This method is called to obtain a reference to the current APDU object.
- * This method can only be called in the context of the currently
- * selected applet.
+ * This method is called during the Applet.process(APDU) method
+ * to obtain a reference to the current APDU object.
+ * This method can only be called in the context of the currently selected applet.
* Note: *
Applet.process(APDU) method
+ * to obtain a reference to the current APDU object.
+ * This method can only be called in the context of the currently selected applet.
* Note:
APDU command
- * based on the CLA byte. A number in the range 0-3 based on the least
- * significant two bits of the CLA byte is returned if the command contains
- * logical channel encoding. If the command does not contain logical channel
- * information, 0 is returned.
+ * based on the CLA byte. A number in the range 0-19 based on the CLA byte encoding
+ * is returned if the command contains logical channel encoding.
+ * If the command does not contain logical channel information, 0 is returned.
* See Runtime
* Specification for the Java Card Platform, section
* 4.3 for encoding details.
* @return logical channel number, if present, within the CLA byte, 0 otherwise
*/
public static byte getCLAChannel() {
- return thisAPDU.ramVars[LOGICAL_CHN];
+ APDU apdu = SimulatorSystem.instance().getCurrentAPDU();
+ return (byte) apdu.ramVars[LOGICAL_CHN];
}
/**
@@ -736,32 +789,152 @@ public static byte getCLAChannel() {
*/
public static void waitExtension()
throws APDUException {
- if (thisAPDU.flags[NO_CHAINING_FLAG]) {
- APDUException.throwIt((short) 1);
+ APDU apdu = SimulatorSystem.instance().getCurrentAPDU();
+ if (!apdu.flags[ACCESS_ALLOWED_FLAG] || apdu.flags[NO_CHAINING_FLAG]) {
+ APDUException.throwIt(APDUException.ILLEGAL_USE);
}
}
- // return Le variable
- private short getLe() {
- if (ramVars[LE] == 0) {
- return 256;
- } else {
- return (short) (ramVars[LE] & 0xff);
+ /**
+ * Returns whether the current
+ * APDU command is the first or
+ * part of a command chain. Bit b5 of the CLA byte if set, indicates
+ * that the
+ * APDU is the first or part of a chain of commands.
+ * See Runtime Environment Specification for the Java Card Platform, section 4.3 for encoding details.
+ * @return true if this APDU is not the last APDU of a command chain, false otherwise.
+ * @since 2.2.2
+ */
+ @SuppressWarnings("unused")
+ public boolean isCommandChainingCLA() {
+ return (buffer[ISO7816.OFFSET_CLA] & 0x10) == 0x10;
+ }
+
+ /**
+ * Returns
+ * true if the encoding of the current
+ * APDU
+ * command based on the
+ * CLA byte indicates secure messaging. The secure messaging information
+ * is in bits (b4,b3) for commands with origin channel numbers 0-3, and in bit
+ * b6 for origin channel numbers 4-19.
+ * See Runtime Environment Specification for the Java Card Platform, section 4.3 for encoding details.
+ * @return true if the secure messaging bit(s) is(are) nonzero, false otherwise
+ * @since 2.2.2
+ */
+ @SuppressWarnings("unused")
+ public boolean isSecureMessagingCLA() {
+ return (buffer[ISO7816.OFFSET_CLA] & 0x40) == 0x40 ? (buffer[ISO7816.OFFSET_CLA] & 0x20) == 0x20 : (buffer[ISO7816.OFFSET_CLA] & 0x0C) != 0;
+
+ }
+
+ /**
+ * Returns whether the current
+ * APDU command CLA byte corresponds
+ * to an interindustry command as defined in ISO 7816-4:2005 specification.
+ * Bit b8 of the CLA byte if
+ * 0, indicates that the
+ * APDU
+ * is an interindustry command.
+ * @return true if this APDU CLA byte corresponds to an interindustry command, false otherwise.
+ * @since 2.2.2
+ */
+ @SuppressWarnings("unused")
+ public boolean isISOInterindustryCLA() {
+ return (buffer[ISO7816.OFFSET_CLA]& 0x80) != 0x80;
+ }
+
+ /**
+ * Returns the incoming data length(Lc). This method can be invoked
+ * whenever inbound data processing methods can be invoked during case 1, 3 or 4
+ * processing. It is most useful for an extended length enabled applet to avoid
+ * parsing the variable length Lc format in the APDU header.
+ * @return the incoming byte length indicated by the Lc field in the APDU header. Return 0 if no incoming data (Case 1)
+ * @throws APDUException with the following reason codes:APDUException.ILLEGAL_USE if setIncomingAndReceive() not called
+ * or if setOutgoing() or setOutgoingNoChaining() previously invoked.
+ * setIncomingAndReceive() method. The value returned is either 5 (Lc is 1 byte), or 7 (when Lc is 3 bytes)
+ * @throws APDUException with the following reason codes:APDUException.ILLEGAL_USE if setIncomingAndReceive() not called
+ * or if setOutgoing() or setOutgoingNoChaining() previously invoked.
+ * Applet.process() method.
*/
@@ -65,7 +65,7 @@ public class APDUException extends CardRuntimeException {
public static final short T1_IFD_ABORT = 171;
/**
* This reason code indicates that during T=0 protocol, the CAD did not reissue the
- * same APDU command with the corrected length in response to a <6Cxx> response status
+ * same APDU command with the corrected length in response to a <6Cxx> response status
* to request command reissue with the specified length. The outgoing
* transfer has been aborted. No more data or status can be sent to the CAD
* in this Applet.process() method
diff --git a/src/main/java/javacard/framework/Applet.java b/src/main/java/javacard/framework/Applet.java
index e3c4cd21..ec54a65a 100644
--- a/src/main/java/javacard/framework/Applet.java
+++ b/src/main/java/javacard/framework/Applet.java
@@ -16,6 +16,7 @@
package javacard.framework;
import com.licel.jcardsim.base.SimulatorSystem;
+import com.licel.jcardsim.utils.BiConsumer;
/**
* This abstract class defines an Java Card technology-based applet.
@@ -23,7 +24,10 @@
* The Applet class must be extended by any applet that is intended to be
* loaded onto, installed into and executed on a Java Card technology-compliant
* smart card.
- *
+ * A compliant Java Card platform may optionally support the ISO7816-4 defined extended
+ * length APDU protocol. The applet subclass must implement the
+ * javacardx.apdu.ExtendedLength interface to access this extended length APDU
+ * protocol capability of the javacard.framework.APDU object.
*
* Example usage of Applet
*
@@ -63,7 +67,7 @@
* // send response data to select command
* short Le = apdu.setOutgoing();
* // assume data containing response bytes in replyData[] array.
- * if ( Le < ..) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH);
+ * if ( Le < ..) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH);
* apdu.setOutgoingLength( (short)replyData.length );
* apdu.sendBytesLong(replyData, (short) 0, (short)replyData.length);
* break;
@@ -78,6 +82,11 @@
* @see SystemException
*/
public abstract class Applet {
+ /**
+ * The current registration callback, set by SimulatorRuntime via reflection.
+ */
+ private static final ThreadLocal> registrationCallback
+ = new ThreadLocal>();
/**
* Only this class's install() method should create the applet object.
@@ -145,9 +154,9 @@ public static void install(byte bArray[], short bOffset, byte bLength)
* method the Java Card runtime environment sends the ISO 7816-4 defined success status (90 00) in APDU response.
* If this method throws an ISOException the Java Card runtime environment sends the associated reason code as the
* response status instead.
- * The Java Card runtime environment zeroes out the APDU buffer before receiving a new APDU command from the CAD.
- * The five header bytes of the APDU command are available in APDU buffer[0..4] at the time
- * this method is called.
+ * The Java Card runtime environment zeroes out the APDU buffer before receiving a new APDU command from the CAD.
+ * The five header bytes (or optionally the 7 extended header bytes) of the APDU command are available
+ * in APDU buffer at the time this method is called.
* The APDU object parameter is a temporary Java Card runtime environment Entry Point Object.
* A temporary Java Card runtime environment Entry Point Object can be accessed from any applet context. References
* to these temporary objects cannot be stored in class variables or instance variables
@@ -260,7 +269,13 @@ public Shareable getShareableInterfaceObject(AID clientAID, byte parameter) {
*/
protected final void register()
throws SystemException {
- SimulatorSystem.registerApplet(this);
+ BiConsumer callback = registrationCallback.get();
+ if (callback == null) { // not called from install()
+ SystemException.throwIt(SystemException.ILLEGAL_AID);
+ }
+ else {
+ callback.accept(this, null);
+ }
}
/**
@@ -287,9 +302,13 @@ protected final void register()
protected final void register(byte bArray[], short bOffset, byte bLength)
throws SystemException {
if (bLength < 5 || bLength > 16) {
- SystemException.throwIt(SystemException.ILLEGAL_VALUE);
+ throw new SystemException(SystemException.ILLEGAL_VALUE);
+ }
+ BiConsumer callback = registrationCallback.get();
+ if (callback == null) { // not called from install()
+ throw new SystemException(SystemException.ILLEGAL_AID);
}
- SimulatorSystem.registerApplet(this, bArray, bOffset, bLength);
+ callback.accept(this, new AID(bArray, bOffset, bLength));
}
/**
@@ -299,6 +318,6 @@ protected final void register(byte bArray[], short bOffset, byte bLength)
* @return true if this applet is being selected
*/
protected final boolean selectingApplet() {
- return SimulatorSystem.isAppletSelecting(this);
+ return SimulatorSystem.instance().isAppletSelecting(this);
}
}
diff --git a/src/main/java/javacard/framework/CardException.java b/src/main/java/javacard/framework/CardException.java
index b7e25a9b..36c46269 100644
--- a/src/main/java/javacard/framework/CardException.java
+++ b/src/main/java/javacard/framework/CardException.java
@@ -30,7 +30,7 @@
*/
public class CardException extends Exception {
- private byte theSw[];
+ private short reason;
/**
* Construct a CardException instance with the specified reason.
@@ -39,8 +39,7 @@ public class CardException extends Exception {
* @param reason the reason for the exception
*/
public CardException(short reason) {
- theSw = JCSystem.makeTransientByteArray((short) 2, JCSystem.CLEAR_ON_RESET);
- Util.setShort(theSw, (short) 0, reason);
+ this.reason = reason;
}
/**
@@ -48,7 +47,7 @@ public CardException(short reason) {
* @return the reason for the exception
*/
public short getReason() {
- return Util.getShort(theSw, (short) 0);
+ return reason;
}
/**
@@ -56,8 +55,7 @@ public short getReason() {
* @param reason the reason for the exception
*/
public void setReason(short reason) {
- Util.arrayFillNonAtomic(theSw, (short) 0, (short) 1, (byte) (reason >>> 8));
- Util.arrayFillNonAtomic(theSw, (short) 1, (short) 1, (byte) reason);
+ this.reason = reason;
}
/**
diff --git a/src/main/java/javacard/framework/CardRuntimeException.java b/src/main/java/javacard/framework/CardRuntimeException.java
index 351e67af..fff37922 100644
--- a/src/main/java/javacard/framework/CardRuntimeException.java
+++ b/src/main/java/javacard/framework/CardRuntimeException.java
@@ -29,7 +29,7 @@
*/
public class CardRuntimeException extends RuntimeException {
- private byte theSw[];
+ private short reason;
/**
* Constructs a CardRuntimeException instance with the specified reason.
@@ -38,8 +38,7 @@ public class CardRuntimeException extends RuntimeException {
* @param reason the reason for the exception
*/
public CardRuntimeException(short reason) {
- theSw = JCSystem.makeTransientByteArray((short) 2, JCSystem.CLEAR_ON_RESET);
- Util.setShort(theSw, (short) 0, reason);
+ this.reason = reason;
}
/**
@@ -47,7 +46,7 @@ public CardRuntimeException(short reason) {
* @return the reason for the exception
*/
public short getReason() {
- return Util.getShort(theSw, (short) 0);
+ return reason;
}
/**
@@ -55,8 +54,7 @@ public short getReason() {
* @param reason the reason for the exception
*/
public void setReason(short reason) {
- Util.arrayFillNonAtomic(theSw, (short) 0, (short) 1, (byte) (reason >>> 8));
- Util.arrayFillNonAtomic(theSw, (short) 1, (short) 1, (byte) reason);
+ this.reason = reason;
}
/**
diff --git a/src/main/java/javacard/framework/ISO7816.java b/src/main/java/javacard/framework/ISO7816.java
index 937df31b..27b95b32 100644
--- a/src/main/java/javacard/framework/ISO7816.java
+++ b/src/main/java/javacard/framework/ISO7816.java
@@ -21,7 +21,7 @@
* ISO7816 interface contains only static fields.
* The static fields with SW_ prefixes define constants for the ISO 7816-4 defined response
* status word. The fields which use the _00 suffix require the low order byte to be
- * customized appropriately e.g (ISO7816.SW_CORRECT_LENGTH_00 + (0x0025 & 0xFF)).
+ * customized appropriately e.g (ISO7816.SW_CORRECT_LENGTH_00 + (0x0025 & 0xFF)).
* The static fields with OFFSET_ prefixes define constants to be used to index into
* the APDU buffer byte array to access ISO 7816-4 defined header information.
*
@@ -37,7 +37,7 @@ public interface ISO7816
*/
public static final short SW_BYTES_REMAINING_00 = 24832;
/**
- * >Response status : Wrong length = 0x6700
+ * Response status : Wrong length = 0x6700
*/
public static final short SW_WRONG_LENGTH = 26368;
/**
@@ -100,6 +100,14 @@ public interface ISO7816
* Response status : CLA value not supported = 0x6E00
*/
public static final short SW_CLA_NOT_SUPPORTED = 28160;
+ /**
+ * Response status : Command chaining not supported = 0x6884
+ */
+ static final short SW_COMMAND_CHAINING_NOT_SUPPORTED=26756;
+ /**
+ * Response status : Last command in chain expected = 0x6883
+ */
+ static final short SW_LAST_COMMAND_EXPECTED=26755;
/**
* Response status : No precise diagnosis = 0x6F00
*/
@@ -109,7 +117,7 @@ public interface ISO7816
*/
public static final short SW_FILE_FULL = 27268;
/**
- * Response status : Card does not support logical channels = 0x6881
+ * Response status : Card does not support the operation on the specified logical channel = 0x6881
*/
public static final short SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 26753;
/**
diff --git a/src/main/java/javacard/framework/JCSystem.java b/src/main/java/javacard/framework/JCSystem.java
index 45236700..d19d22a2 100644
--- a/src/main/java/javacard/framework/JCSystem.java
+++ b/src/main/java/javacard/framework/JCSystem.java
@@ -41,7 +41,6 @@
* is written or nothing at all is written.
* The JCSystem includes methods to control an atomic transaction.
* See Runtime Environment Specification for the Java Card Platform for details.
- *
*
*/
public final class JCSystem {
@@ -80,21 +79,15 @@ public final class JCSystem {
*
Note: *
NOT_A_TRANSIENT_OBJECT if the specified object is
- * null or is not an array type.
+ * NOT_A_TRANSIENT_OBJECT if the specified object is
+ * null or is not an array type.NOT_A_TRANSIENT_OBJECT, CLEAR_ON_RESET, or CLEAR_ON_DESELECT
@@ -104,7 +97,7 @@ public final class JCSystem {
* @see #makeTransientShortArray(short, byte)
*/
public static byte isTransient(Object theObj) {
- return SimulatorSystem.isTransient(theObj);
+ return SimulatorSystem.instance().getTransientMemory().isTransient(theObj);
}
/**
@@ -123,7 +116,7 @@ public static byte isTransient(Object theObj) {
*/
public static boolean[] makeTransientBooleanArray(short length, byte event)
throws NegativeArraySizeException, SystemException {
- return SimulatorSystem.makeTransientBooleanArray(length, event);
+ return SimulatorSystem.instance().getTransientMemory().makeBooleanArray(length, event);
}
/**
@@ -142,7 +135,7 @@ public static boolean[] makeTransientBooleanArray(short length, byte event)
*/
public static byte[] makeTransientByteArray(short length, byte event)
throws NegativeArraySizeException, SystemException {
- return SimulatorSystem.makeTransientByteArray(length, event);
+ return SimulatorSystem.instance().getTransientMemory().makeByteArray(length, event);
}
/**
@@ -161,7 +154,7 @@ public static byte[] makeTransientByteArray(short length, byte event)
*/
public static short[] makeTransientShortArray(short length, byte event)
throws NegativeArraySizeException, SystemException {
- return SimulatorSystem.makeTransientShortArray(length, event);
+ return SimulatorSystem.instance().getTransientMemory().makeShortArray(length, event);
}
/**
@@ -180,7 +173,7 @@ public static short[] makeTransientShortArray(short length, byte event)
*/
public static Object[] makeTransientObjectArray(short length, byte event)
throws NegativeArraySizeException, SystemException {
- return SimulatorSystem.makeTransientObjectArray(length, event);
+ return SimulatorSystem.instance().getTransientMemory().makeObjectArray(length, event);
}
/**
@@ -203,7 +196,7 @@ public static short getVersion() {
* @return the AID object
*/
public static AID getAID() {
- return SimulatorSystem.getAID();
+ return SimulatorSystem.instance().getAID();
}
/**
@@ -223,7 +216,7 @@ public static AID getAID() {
* or if offset or length are out of range.
*/
public static AID lookupAID(byte buffer[], short offset, byte length) {
- return SimulatorSystem.lookupAID(buffer, offset, length);
+ return SimulatorSystem.instance().lookupAID(buffer, offset, length);
}
/**
@@ -245,7 +238,7 @@ public static AID lookupAID(byte buffer[], short offset, byte length) {
*/
public static void beginTransaction()
throws TransactionException {
- SimulatorSystem.beginTransaction();
+ SimulatorSystem.instance().beginTransaction();
}
/**
@@ -274,7 +267,7 @@ public static void beginTransaction()
*/
public static void abortTransaction()
throws TransactionException {
- SimulatorSystem.abortTransaction();
+ SimulatorSystem.instance().abortTransaction();
}
/**
@@ -297,7 +290,7 @@ public static void abortTransaction()
*/
public static void commitTransaction()
throws TransactionException {
- SimulatorSystem.commitTransaction();
+ SimulatorSystem.instance().commitTransaction();
}
/**
@@ -306,7 +299,7 @@ public static void commitTransaction()
* @return 1 if transaction in progress, 0 if not
*/
public static byte getTransactionDepth() {
- return SimulatorSystem.getTransactionDepth();
+ return SimulatorSystem.instance().getTransactionDepth();
}
/**
@@ -319,7 +312,7 @@ public static byte getTransactionDepth() {
* @see #getMaxCommitCapacity()
*/
public static short getUnusedCommitCapacity() {
- return SimulatorSystem.getUnusedCommitCapacity();
+ return SimulatorSystem.instance().getUnusedCommitCapacity();
}
/**
@@ -340,7 +333,7 @@ public static short getUnusedCommitCapacity() {
* @see #getUnusedCommitCapacity()
*/
public static short getMaxCommitCapacity() {
- return SimulatorSystem.getMaxCommitCapacity();
+ return SimulatorSystem.instance().getMaxCommitCapacity();
}
/**
@@ -355,7 +348,7 @@ public static short getMaxCommitCapacity() {
* @return the AID object of the previous context, or null if Java Card runtime environment
*/
public static AID getPreviousContextAID() {
- return SimulatorSystem.getPreviousContextAID();
+ return SimulatorSystem.instance().getPreviousContextAID();
}
/**
@@ -387,13 +380,13 @@ public static short getAvailableMemory(byte memoryType)
throws SystemException {
switch (memoryType) {
case MEMORY_TYPE_PERSISTENT:
- return SimulatorSystem.getAvailablePersistentMemory();
+ return SimulatorSystem.instance().getAvailablePersistentMemory();
case MEMORY_TYPE_TRANSIENT_RESET:
- return SimulatorSystem.getAvailableTransientResetMemory();
+ return SimulatorSystem.instance().getAvailableTransientResetMemory();
case MEMORY_TYPE_TRANSIENT_DESELECT:
- return SimulatorSystem.getAvailableTransientDeselectMemory();
+ return SimulatorSystem.instance().getAvailableTransientDeselectMemory();
}
SystemException.throwIt(SystemException.ILLEGAL_VALUE);
return 0;
@@ -411,10 +404,10 @@ public static short getAvailableMemory(byte memoryType)
* @param serverAID the AID of the server applet
* @param parameter optional parameter data
* @return the shareable interface object or null
- * @see Applet.getShareableInterfaceObject(AID, byte)
+ * @see Applet#getShareableInterfaceObject(AID, byte)
*/
public static Shareable getAppletShareableInterfaceObject(AID serverAID, byte parameter) {
- return SimulatorSystem.getSharedObject(serverAID, parameter);
+ return SimulatorSystem.instance().getSharedObject(serverAID, parameter);
}
/**
@@ -423,7 +416,7 @@ public static Shareable getAppletShareableInterfaceObject(AID serverAID, byte pa
* @return true if the object deletion mechanism is supported, false otherwise
*/
public static boolean isObjectDeletionSupported() {
- return SimulatorSystem.isObjectDeletionSupported();
+ return SimulatorSystem.instance().isObjectDeletionSupported();
}
/**
@@ -444,10 +437,11 @@ public static boolean isObjectDeletionSupported() {
* @throws SystemException with the following reason codes:SystemException.ILLEGAL_USE if the object deletion mechanism is
* not implemented.
+ * javacard.framework.Applet.select() method is not
* called if this method is invoked.true when the same applet
+ * @param appInstAlreadyActive boolean flag is true when the same applet
* instance is already active on another logical channel and false otherwise
+ * @return true to indicate success, false otherwise
*/
public abstract boolean select(boolean appInstAlreadyActive);
diff --git a/src/main/java/javacard/framework/OwnerPIN.java b/src/main/java/javacard/framework/OwnerPIN.java
index cbac40dd..0be57011 100644
--- a/src/main/java/javacard/framework/OwnerPIN.java
+++ b/src/main/java/javacard/framework/OwnerPIN.java
@@ -59,8 +59,8 @@ public class OwnerPIN implements PIN {
/**
* Constructor. Allocates a new PIN instance with validated flag
* set to false
- * @param tryLimit the maximum number of times an incorrect PIN can be presented. tryLimit must be >=1
- * @param maxPINSize the maximum allowed PIN size. maxPINSize must be >=1
+ * @param tryLimit the maximum number of times an incorrect PIN can be presented. tryLimit must be >=1
+ * @param maxPINSize the maximum allowed PIN size. maxPINSize must be >=1
* @throws PINException with the following reason codes:
* PINException.ILLEGAL_VALUE if tryLimit parameter is less than 1.
diff --git a/src/main/java/javacard/framework/Util.java b/src/main/java/javacard/framework/Util.java
index a09176f7..ed4039c4 100644
--- a/src/main/java/javacard/framework/Util.java
+++ b/src/main/java/javacard/framework/Util.java
@@ -47,7 +47,7 @@ public class Util {
* destOff+length is greater than dest.length, the length
* of the dest array an ArrayIndexOutOfBoundsException exception is thrown
* and no copy is performed.src or dest parameter is nullsrc or dest parameter is null
* a NullPointerException exception is thrown.src and dest arguments refer to the same array object,
* then the copying is performed as if the components at positions srcOff
@@ -68,7 +68,7 @@ public class Util {
* @throws ArrayIndexOutOfBoundsException if copying would cause access of data outside array bounds
* @throws NullPointerException if either src or dest is null
* @throws TransactionException f copying would cause the commit capacity to be exceeded
- * @see JCSystem.getUnusedCommitCapacity()
+ * @see JCSystem#getUnusedCommitCapacity()
*/
public static final short arrayCopy(byte src[], short srcOff, byte dest[], short destOff, short length)
throws ArrayIndexOutOfBoundsException, NullPointerException, TransactionException {
@@ -114,7 +114,7 @@ public static final short arrayCopy(byte src[], short srcOff, byte dest[], short
* @throws ArrayIndexOutOfBoundsException if copying would cause access of data outside array bounds
* @throws NullPointerException if either src or dest is null
* @throws TransactionException f copying would cause the commit capacity to be exceeded
- * @see JCSystem.getUnusedCommitCapacity()
+ * @see JCSystem#getUnusedCommitCapacity()
*/
public static final short arrayCopyNonAtomic(byte src[], short srcOff, byte dest[], short destOff, short length)
throws ArrayIndexOutOfBoundsException, NullPointerException {
@@ -147,7 +147,7 @@ public static final short arrayCopyNonAtomic(byte src[], short srcOff, byte dest
* @return bOff+bLen
* @throws ArrayIndexOutOfBoundsException if the fill operation would cause access of data outside array bounds
* @throws NullPointerException if bArray is null
- * @see JCSystem.getUnusedCommitCapacity()
+ * @see JCSystem#getUnusedCommitCapacity()
*/
public static final short arrayFillNonAtomic(byte bArray[], short bOff, short bLen, byte bValue)
throws ArrayIndexOutOfBoundsException, NullPointerException {
@@ -155,10 +155,12 @@ public static final short arrayFillNonAtomic(byte bArray[], short bOff, short bL
if (bLen < 0) {
throw new ArrayIndexOutOfBoundsException();
}
- while (bLen-- > 0) {
+ while (bLen > 0) {
bArray[bOff++] = bValue;
+ bLen--;
}
- return (short) (bOff + bLen);
+ // after loop bOff = bOff + bLen
+ return bOff;
}
/**
@@ -200,7 +202,9 @@ public static final byte arrayCompare(byte src[], short srcOff, byte dest[], sho
}
for (short i = 0; i < length; i++) {
if (src[srcOff + i] != dest[destOff + i]) {
- return ((byte) (src[srcOff + i] >= dest[destOff + i] ? 1 : -1));
+ short thisSrc = (short) (src[srcOff + i] & 0x00ff);
+ short thisDest = (short) (dest[destOff + i] & 0x00ff);
+ return (byte) (thisSrc >= thisDest ? 1 : -1);
}
}
@@ -222,7 +226,7 @@ public static final short makeShort(byte b1, byte b2) {
* @param bArray byte array
* @param bOff offset within byte array containing first byte (the high order byte)
* @return the short value the concatenated result
- * @throws ArrayIndexOutOfBoundsException if the bOff parameter is negative or if bOff+1 is greater than the length
+ * @throws ArrayIndexOutOfBoundsException if the bOff parameter is negative or if bOff+2 is greater than the length of bArray
* @throws NullPointerException if the bArray parameter is null
*/
public static final short getShort(byte bArray[], short bOff) throws ArrayIndexOutOfBoundsException, NullPointerException {
@@ -239,11 +243,11 @@ public static final short getShort(byte bArray[], short bOff) throws ArrayIndexO
* TransactionException
* exception is thrown.bOff parameter is negative or if bOff+1 is greater than the length
+ * @throws ArrayIndexOutOfBoundsException if the bOff parameter is negative or if bOff+2 is greater than the length of bArray
* of bArray
* @throws NullPointerException if the bArray parameter is null
* @throws TransactionException if the operation would cause the commit capacity to be exceeded
- * @see JCSystem.getUnusedCommitCapacity()
+ * @see JCSystem#getUnusedCommitCapacity()
*/
public static final short setShort(byte bArray[], short bOff, short sValue)
throws TransactionException, ArrayIndexOutOfBoundsException, NullPointerException {
@@ -251,4 +255,6 @@ public static final short setShort(byte bArray[], short bOff, short sValue)
bArray[bOff + 1] = (byte) sValue;
return (short) (bOff + 2);
}
+
+ private Util() {}
}
diff --git a/src/main/java/javacard/framework/package-info.java b/src/main/java/javacard/framework/package-info.java
new file mode 100644
index 00000000..df0bb1e6
--- /dev/null
+++ b/src/main/java/javacard/framework/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JavaCard API.
+ */
+package javacard.framework;
diff --git a/src/main/java/javacard/framework/service/CardRemoteObject.java b/src/main/java/javacard/framework/service/CardRemoteObject.java
index 543d543b..97fbfd07 100644
--- a/src/main/java/javacard/framework/service/CardRemoteObject.java
+++ b/src/main/java/javacard/framework/service/CardRemoteObject.java
@@ -17,6 +17,8 @@
package javacard.framework.service;
import java.rmi.Remote;
+
+import com.licel.jcardsim.base.SimulatorRuntime;
import com.licel.jcardsim.base.SimulatorSystem;
public class CardRemoteObject implements Remote {
@@ -26,16 +28,18 @@ public CardRemoteObject() {
}
public static void export(Remote obj) throws SecurityException {
- if (SimulatorSystem.getJavaContext(SimulatorSystem.getJavaOwner(obj)) != SimulatorSystem
- .getJavaContext(SimulatorSystem
- .getJavaOwner(SimulatorSystem.previousActiveObject)))
- throw SimulatorSystem.securityException;
+ SimulatorRuntime runtime = SimulatorSystem.instance();
+
+ if (runtime.getJavaContext(runtime.getJavaOwner(obj)) !=
+ runtime.getJavaContext(runtime.getJavaOwner(runtime.getPreviousActiveObject())))
+ throw new SecurityException();
}
public static void unexport(Remote obj) throws SecurityException {
- if (SimulatorSystem.getJavaContext(SimulatorSystem.getJavaOwner(obj)) != SimulatorSystem
- .getJavaContext(SimulatorSystem
- .getJavaOwner(SimulatorSystem.previousActiveObject)))
- throw SimulatorSystem.securityException;
+ SimulatorRuntime runtime = SimulatorSystem.instance();
+
+ if (runtime.getJavaContext(runtime.getJavaOwner(obj)) !=
+ runtime.getJavaContext(runtime.getJavaOwner(runtime.getPreviousActiveObject())))
+ throw new SecurityException();
}
}
diff --git a/src/main/java/javacard/framework/service/Dispatcher.java b/src/main/java/javacard/framework/service/Dispatcher.java
index e14981b2..6d799b52 100644
--- a/src/main/java/javacard/framework/service/Dispatcher.java
+++ b/src/main/java/javacard/framework/service/Dispatcher.java
@@ -39,9 +39,9 @@ public class Dispatcher {
public Dispatcher(short maxServices) throws ServiceException {
_services = new Service[maxServices];
- SimulatorSystem.setJavaOwner(_services, this);
+ SimulatorSystem.instance().setJavaOwner(_services, this);
_phases = new byte[maxServices];
- SimulatorSystem.setJavaOwner(_phases, this);
+ SimulatorSystem.instance().setJavaOwner(_phases, this);
_maxServices = maxServices;
}
diff --git a/src/main/java/javacard/framework/service/RMIService.java b/src/main/java/javacard/framework/service/RMIService.java
index 3b696c99..5f007a50 100644
--- a/src/main/java/javacard/framework/service/RMIService.java
+++ b/src/main/java/javacard/framework/service/RMIService.java
@@ -32,7 +32,7 @@ public class RMIService extends BasicService implements RemoteService {
public RMIService(Remote initialObject) throws NullPointerException {
if (initialObject == null)
- throw SimulatorSystem.nullPointerException;
+ throw new NullPointerException("initialObject");
_remoteObject = initialObject;
}
diff --git a/src/main/java/javacard/framework/service/package-info.java b/src/main/java/javacard/framework/service/package-info.java
new file mode 100644
index 00000000..96b7cbb9
--- /dev/null
+++ b/src/main/java/javacard/framework/service/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JavaCard API.
+ */
+package javacard.framework.service;
diff --git a/src/main/java/javacard/security/AESKey.java b/src/main/java/javacard/security/AESKey.java
index aa4ae0e4..f50bbce1 100644
--- a/src/main/java/javacard/security/AESKey.java
+++ b/src/main/java/javacard/security/AESKey.java
@@ -19,12 +19,11 @@
/**
* AESKey contains a 16/24/32 byte key for AES computations based
* on the Rijndael algorithm.
- * When the key data is set, the key is initialized and ready for use. - *
+ *
When the key data is set, the key is initialized and ready for use.
* @see KeyBuilder * @see Signature - * @see Cipher - * @see KeyEncryption + * @see javacardx.crypto.Cipher + * @see javacardx.crypto.KeyEncryption */ public interface AESKey extends SecretKey { diff --git a/src/main/java/javacard/security/Checksum.java b/src/main/java/javacard/security/Checksum.java index 52b83c1e..122ca9c2 100644 --- a/src/main/java/javacard/security/Checksum.java +++ b/src/main/java/javacard/security/Checksum.java @@ -138,7 +138,7 @@ public abstract void init(byte bArray[], short bOff, short bLen) *This method requires temporary storage of intermediate results.
* This may result in additional resource consumption and/or slow performance.
* This method should only be used if all the input data required for the checksum
- * is not available in one byte array. The {@link Checksum.html#doFinal(byte[], short, short, byte[], short)}
+ * is not available in one byte array. The {@link #doFinal(byte[], short, short, byte[], short)}
* doFinal(byte[], short, short, byte[], short) method is recommended whenever possible.
*
Note: *
When the key data is set, the key is initialized and ready for use.
* @see KeyBuilder
* @see Signature
- * @see Cipher
- * @see KeyEncryption
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
*
*/
public interface DESKey
diff --git a/src/main/java/javacard/security/DSAKey.java b/src/main/java/javacard/security/DSAKey.java
index e3b5c717..06098186 100644
--- a/src/main/java/javacard/security/DSAKey.java
+++ b/src/main/java/javacard/security/DSAKey.java
@@ -17,18 +17,18 @@
package javacard.security;
/**
- * The DSAKey interface is the base interface for the DSA algorithm's private and
+ * The DSAKey interface is the base interface for the DSA algorithm's private and
* public key implementations. A DSA private key implementation must also implement
* the DSAPrivateKey interface methods. A DSA public key implementation must also implement
* the DSAPublicKey interface methods.
*
When all four components of the key (X or Y,P,Q,G) are set, the key is - * initialized and ready for use. - *
+ * initialized and ready for use.
+ * * @see DSAPublicKey * @see DSAPrivateKey * @see KeyBuilder * @see Signature - * @see KeyEncryption + * @see javacardx.crypto.KeyEncryption */ public interface DSAKey { diff --git a/src/main/java/javacard/security/DSAPrivateKey.java b/src/main/java/javacard/security/DSAPrivateKey.java index 3d479930..9ca0a4f8 100644 --- a/src/main/java/javacard/security/DSAPrivateKey.java +++ b/src/main/java/javacard/security/DSAPrivateKey.java @@ -23,11 +23,11 @@ * theDSAKey interface methods.
* When all four components of the key (X,P,Q,G) are set, the key is * initialized and ready for use. - *
+ *
* @see DSAPublicKey
* @see KeyBuilder
* @see Signature
- * @see KeyEncryption
+ * @see javacardx.crypto.KeyEncryption
*/
public interface DSAPrivateKey
extends PrivateKey, DSAKey {
diff --git a/src/main/java/javacard/security/DSAPublicKey.java b/src/main/java/javacard/security/DSAPublicKey.java
index b9a54613..1c279c2b 100644
--- a/src/main/java/javacard/security/DSAPublicKey.java
+++ b/src/main/java/javacard/security/DSAPublicKey.java
@@ -26,7 +26,7 @@
* @see DSAPrivateKey
* @see KeyBuilder
* @see Signature
- * @see KeyEncryption
+ * @see javacardx.crypto.KeyEncryption
*/
public interface DSAPublicKey
extends PublicKey, DSAKey {
diff --git a/src/main/java/javacard/security/ECKey.java b/src/main/java/javacard/security/ECKey.java
index c24ab29f..b606e6a9 100644
--- a/src/main/java/javacard/security/ECKey.java
+++ b/src/main/java/javacard/security/ECKey.java
@@ -32,7 +32,7 @@
* @see ECPrivateKey
* @see KeyBuilder
* @see Signature
- * @see KeyEncryption
+ * @see javacardx.crypto.KeyEncryption
* @see KeyAgreement
*
*/
@@ -71,12 +71,12 @@ public abstract void setFieldFP(byte[] buffer, short offset, short length)
* of type TYPE_EC_F2M_PUBLIC or TYPE_EC_F2M_PRIVATE in
* the case where the polynomial is a trinomial, of the form
* x^n + x^e + 1 (where n is the bit length of the key).
- * It is required that n > e > 0.
+ * It is required that n > e > 0.
* @param e the value of the intermediate exponent of the trinomial
* @throws CryptoException with the following reason codes:
*
CryptoException.ILLEGAL_VALUE if the input parameter e
- * is not such that 0 < e < n.
+ * is not such that 0 < e < n.
* CryptoException.NO_SUCH_ALGORITHM if the key is neither
* of type TYPE_EC_F2M_PUBLIC nor TYPE_EC_F2M_PRIVATE. TYPE_EC_F2M_PUBLIC or TYPE_EC_F2M_PRIVATE in
* the case where the polynomial is a pentanomial, of the form
* x^n + x^e1 + x^e2 + x^e3 + 1 (where n is the bit length of the key).
- * It is required for all ei where ei = {e1, e2, e3} that n > ei > 0.
+ * It is required for all ei where ei = {e1, e2, e3} that n > ei > 0.
* @param e1 the value of the first of the intermediate exponents of the
* pentanomial
* @param e2 the value of the second of the intermediate exponent of the
@@ -98,7 +98,7 @@ public abstract void setFieldF2M(short e)
* CryptoException.ILLEGAL_VALUE if the input parameters
* ei where ei = {e1, e2, e3}
- * are not such that for all ei, n > ei > 0.
+ * are not such that for all ei, n > ei > 0.
* CryptoException.NO_SUCH_ALGORITHM if the key is neither
* of type TYPE_EC_F2M_PUBLIC nor TYPE_EC_F2M_PRIVATE.
* HMACKey contains a key for HMAC operations. This key can be of
+ * any length, but it is strongly recommended that the key is not shorter than the
+ * byte length of the hash output used in the HMAC implementation.
+ * Keys with length greater than the hash block length are first hashed with the
+ * hash algorithm used for the HMAC implementation.
+ * Implementations must support an HMAC key length equal to the length of + * the supported hash algorithm block size (e.g 64 bits for SHA-1) + *
When the key data is set, the key is initialized and ready for use.
+ *
+ * @see KeyBuilder
+ * @see Signature
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
+ * @since 2.2.2
+ */
+
+public interface HMACKey extends SecretKey {
+
+ /**
+ * Sets the
+ * Key data.
+ * The data format is big-endian and right-aligned (the least significant bit is the least significant
+ * bit of last byte). Input key data is copied into the internal representation.
+ *
Note:
javacardx.crypto.KeyEncryption
+ * interface and the Cipher object specified via setKeyCipher()
+ * is not null, keyData is decrypted using the Cipher object.
+ *
+ *
+ * @param keyData byte array containing key initialization data
+ * @param kOff offset within keyData to start
+ * @param kLen the byte length of the key initialization data
+ * @throws CryptoException - with the following reason code: CryptoException.ILLEGAL_VALUE if input data decryption is required and fails.
+ * @throws ArrayIndexOutOfBoundsException - if kOff is negative or the keyData array is too short
+ * @throws NullPointerException - if the keyData parameter is null
+ */
+ void setKey(byte[] keyData, short kOff, short kLen) throws CryptoException, NullPointerException, ArrayIndexOutOfBoundsException;
+
+ /**
+ * Returns the
+ * Key data in plain text. The key can be any length, but
+ * should be longer than the byte length of the hash algorithm output used. The data
+ * format is big-endian and right-aligned (the least significant bit is the least
+ * significant bit of last byte).
+ *
+ *
+ * @param keyData byte array to return key data
+ * @param kOff offset within keyData to start
+ * @return the byte length of the key data returned
+ * @throws CryptoException - with the following reason code: CryptoException.UNINITIALIZED_KEY if the key data has not been successfully initialized since the time the initialized state of the key was set to false.
+ * @see Key
+ */
+ byte getKey(byte[] keyData, short kOff);
+}
diff --git a/src/main/java/javacard/security/InitializedMessageDigest.java b/src/main/java/javacard/security/InitializedMessageDigest.java
new file mode 100644
index 00000000..c09222a6
--- /dev/null
+++ b/src/main/java/javacard/security/InitializedMessageDigest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javacard.security;
+
+/**
+ *
+ * The
+ * InitializedMessageDigest class is a subclass of the base
+ * class
+ * MessageDigest. This class is used to generate a hash representing
+ * a specified message but with the additional
+ * capability to initialize the starting hash value corresponding to a previously
+ * hashed part of the message.
+ * Implementations of
+ * InitializedMessageDigest
+ * algorithms must extend this class and implement all the abstract methods.
+ *
A tear or card reset event resets a
+ * InitializedMessageDigest object to the initial state (state upon construction).
+ *
Even if a transaction is in progress, update of intermediate result state in the implementation
+ * instance shall not participate in the transaction.
+ *
+ * @since 2.2.2
+ */
+public abstract class InitializedMessageDigest extends MessageDigest {
+
+ /**
+ * protected constructor
+ */
+ protected InitializedMessageDigest() {
+ }
+
+ /**
+ * This method initializes the starting hash value in place of the default
+ * value used by the
+ * MessageDigest superclass. The starting
+ * hash value represents the previously computed
+ * hash (using the same algorithm) of the first part of the message. The remaining
+ * bytes of the message must be presented to this
+ * InitializedMessageDigest
+ * object via the
+ * update and
+ * doFinal methods to
+ * generate the final message digest.
+ *
Note:
+ *
+ * @param initialDigestBuf input buffer containing the starting hash value representing the previously
+ * computed hash (using the same algorithm) of first part of the message
+ * @param initialDigestOffset offset into initialDigestBuf array where initial digest value data begins
+ * @param initialDigestLength the length of data in initialDigestBuf array.
+ * @param digestedMsgLenBuf the byte array containing the number of bytes in the first part of the message that
+ * has previously been hashed to obtain the specified initial digest value value
+ * @param digestedMsgLenOffset the offset within digestedMsgLenBuf where the digested length
+ * begins(the bytes starting at this offset for digestedMsgLenLength bytes are concatenated to form
+ * the actual digested message length value)
+ * @param digestedMsgLenLength byte length of the digested length
+ * @throws CryptoException with the following reason codes: CryptoException.ILLEGAL_VALUE
+ * if the parameter initialDigestLength is not equal to the length of message digest of the algorithm
+ * (see LENGTH_* constants {@link MessageDigest#LENGTH_SHA}) or if the number of bytes in the first part of the message that
+ * has previously been hashed is 0 or not a multiple of the algorithm's block size or greater than the maximum length
+ * supported by the algorithm (see ALG_* algorithm descriptions {@link MessageDigest#ALG_SHA}).
+ */
+ public abstract void setInitialDigest(byte[] initialDigestBuf, short initialDigestOffset,
+ short initialDigestLength, byte[] digestedMsgLenBuf, short digestedMsgLenOffset,
+ short digestedMsgLenLength) throws CryptoException;
+}
diff --git a/src/main/java/javacard/security/Key.java b/src/main/java/javacard/security/Key.java
index 1cf94310..081214af 100644
--- a/src/main/java/javacard/security/Key.java
+++ b/src/main/java/javacard/security/Key.java
@@ -18,7 +18,7 @@
/**
* The Key interface is the base interface for all keys.
- *
+ * *
A Key object sets its initialized state to true only when all the associated
* Key object parameters have been set at least once since the time the initialized state was set to false.
*
A newly created Key object sets its initialized state to false. Invocation of the
@@ -43,7 +43,6 @@ public interface Key {
* Returns the key interface type.
* @return the key interface type. Valid codes listed in TYPE.. constants
* See KeyBuilder.TYPE_DES_TRANSIENT_RESET
- *
* @see KeyBuilder
*/
public abstract byte getType();
diff --git a/src/main/java/javacard/security/KeyBuilder.java b/src/main/java/javacard/security/KeyBuilder.java
index 563f4c65..e0d169f6 100644
--- a/src/main/java/javacard/security/KeyBuilder.java
+++ b/src/main/java/javacard/security/KeyBuilder.java
@@ -203,6 +203,10 @@ public class KeyBuilder {
* EC Key Length LENGTH_EC_F2M_193 = 193.
*/
public static final short LENGTH_EC_F2M_193 = 193;
+ /**
+ * EC Key Length LENGTH_EC_FP_256 = 256.
+ */
+ public static final short LENGTH_EC_FP_256 = 256;
/**
* AES Key Length LENGTH_AES_128 = 128.
*/
@@ -216,6 +220,62 @@ public class KeyBuilder {
*/
public static final short LENGTH_AES_256 = 256;
+ /**
+ * Key object which implements interface type KoreanSEEDKey with
+ * CLEAR_ON_RESET transient key data. This Key object implicitly performs a
+ * clearKey() on power on or card reset.
+ */
+ public static final byte TYPE_KOREAN_SEED_TRANSIENT_RESET=16;
+ /**
+ * Key object which implements interface type KoreanSEEDKey with
+ * CLEAR_ON_DESELECT transient key data. This Key object implicitly performs
+ * a clearKey() on power on or card reset.
+ */
+ public static final byte TYPE_KOREAN_SEED_TRANSIENT_DESELECT = 17;
+ /**
+ * Key object which implements interface type KoreanSEEDKey with persistent
+ * key data.
+ */
+ public static final byte TYPE_KOREAN_SEED = 18;
+ /**
+ * Key object which implements interface type HMACKey with CLEAR_ON_RESET
+ * transient key data. This Key object implicitly performs a clearKey() on
+ * power on or card reset. Note, there is no length constant associated with
+ * HMAC, since the specification states that the key can have any length.
+ */
+ public static final byte TYPE_HMAC_TRANSIENT_RESET = 19;
+ /**
+ * Key object which implements interface type HMACKey with CLEAR_ON_DESELECT
+ * transient key data. This Key object implicitly performs a clearKey() on
+ * power on or card reset.
+ */
+ public static final byte TYPE_HMAC_TRANSIENT_DESELECT = 20;
+ /**
+ * Key object which implements interface type HMACKey with persistent key
+ * data.
+ */
+ public static final byte TYPE_HMAC = 21;
+ /**
+ * HMAC Key Length LENGTH_HMAC_SHA_1_BLOCK_64 = 64.
+ */
+ public static final short LENGTH_HMAC_SHA_1_BLOCK_64 = 64;
+ /**
+ * HMAC Key Length LENGTH_HMAC_SHA_256_BLOCK_64 = 64.
+ */
+ public static final short LENGTH_HMAC_SHA_256_BLOCK_64 = 64;
+ /**
+ * HMAC Key Length LENGTH_HMAC_SHA_384_BLOCK_128 = 64.
+ */
+ public static final short LENGTH_HMAC_SHA_384_BLOCK_128 = 128;
+ /**
+ * HMAC Key Length LENGTH_HMAC_SHA_512_BLOCK_128 = 64.
+ */
+ public static final short LENGTH_HMAC_SHA_512_BLOCK_128 = 128;
+ /**
+ * Korean Seed Key Length LENGTH_KOREAN_SEED_128 = 128.
+ */
+ public static final short LENGTH_KOREAN_SEED_128 = 128;
+
/**
* Creates uninitialized cryptographic keys for signature and cipher algorithms. Only instances created
* by this method may be the key objects used to initialize instances of
@@ -286,13 +346,13 @@ public static Key buildKey(byte keyType, short keyLength, boolean keyEncryption)
break;
case TYPE_EC_FP_PUBLIC:
- if (keyLength != 112 && keyLength != 128 && keyLength != 160 && keyLength != 192) {
+ if (keyLength != 112 && keyLength != 128 && keyLength != 160 && keyLength != 192 && keyLength != 256) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
key = new ECPublicKeyImpl(keyType, keyLength);
break;
case TYPE_EC_FP_PRIVATE:
- if (keyLength != 112 && keyLength != 128 && keyLength != 160 && keyLength != 192) {
+ if (keyLength != 112 && keyLength != 128 && keyLength != 160 && keyLength != 192 && keyLength != 256) {
CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
}
key = new ECPrivateKeyImpl(keyType, keyLength);
@@ -308,10 +368,19 @@ public static Key buildKey(byte keyType, short keyLength, boolean keyEncryption)
key = new SymmetricKeyImpl(keyType, keyLength);
break;
+ // hmac
+ case TYPE_HMAC_TRANSIENT_RESET:
+ case TYPE_HMAC_TRANSIENT_DESELECT:
+ case TYPE_HMAC:
+ key = new SymmetricKeyImpl(keyType, keyLength);
+ break;
+
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
break;
}
return key;
}
+
+ private KeyBuilder() {}
}
\ No newline at end of file
diff --git a/src/main/java/javacard/security/KeyPair.java b/src/main/java/javacard/security/KeyPair.java
index 94dc77f4..ce42c1b4 100644
--- a/src/main/java/javacard/security/KeyPair.java
+++ b/src/main/java/javacard/security/KeyPair.java
@@ -67,7 +67,7 @@ public final class KeyPair {
*
keyLength size and
* implement the appropriate Key interface associated with the specified algorithm
* (example - RSAPublicKey interface for the public key and RSAPrivateKey
- * interface for the private key within an ALG_RSA key pair).
+ * interface for the private key within an ALG_RSA key pair).
*
Notes:
KeyPair object
* need not support the KeyEncryption interface.
@@ -115,8 +115,8 @@ public final void genKeyPair()
* associated with the specified type, size of key is not supported.KoreanSEEDKey contains an 16-byte key for Korean Seed Algorithm
+ * operations.
+ * When the key data is set, the key is initialized and ready for use. + *
+ *
+ * @since 2.2.2
+ * @see KeyBuilder
+ * @see Signature
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
+ *
+ */
+public interface KoreanSEEDKey extends SecretKey
+{
+ /**
+ * Sets the Key data. The plain text length of input key data is
+ * The data format is big-endian and right-aligned (the least significant bit is the least significant
+ * bit of last byte). Input key data is copied into the internal representation.
+ *
Note:
javacardx.crypto.KeyEncryption
+ * interface and the Cipher object specified via setKeyCipher()
+ * is not null, keyData is decrypted using the Cipher object.
+ * + * + * @param keyData byte array containing key initialization data + * @param kOff offset within keyData to start + * @throws CryptoException with the following reason code:
CryptoException.ILLEGAL_VALUE if input data decryption is required and fails.
+ * Key data in plain text. The length of output key data
+ * is 16 bytes for Korean Seed Algorithm.
+ * The data format is big-endian and right-aligned
+ * (the least significant bit is the least significant
+ * bit of last byte).
+ * + * + * @param keyData byte array to return key data + * @param kOff offset within keyData to start + * @return the byte length of the key data returned + * @throws CryptoException with the following reason code:
CryptoException.UNINITIALIZED_KEY if the key data has not been successfully initialized since the time the initialized state of the key was set to false.
+ * MessageDigest object instance of the selected algorithm.
* @param algorithm the desired message digest algorithm.
@@ -61,26 +100,51 @@ protected MessageDigest() {
* or shared access mode is not supported.InitializedMessageDigest object instance of the selected algorithm.
+ *
+ *
+ * @param algorithm the desired message digest algorithm. Valid codes listed in ALG_* constants above,
+ * for example, {@link #ALG_SHA}.
+ * @param externalAccess true indicates that the instance will be shared among multiple applet
+ * instances and that the InitializedMessageDigest instance will also be accessed (via a Shareable. interface)
+ * when the owner of the InitializedMessageDigest instance is not the currently selected applet.
+ * If true the implementation must not allocate CLEAR_ON_DESELECT transient space for internal data.
+ * @return the InitializedMessageDigest object instance of the requested algorithm
+ * @throws CryptoException with the following reason codes: CryptoException.NO_SUCH_ALGORITHM
+ * if the requested algorithm or shared access mode is not supported.
+ * @since 2.2.2
+ */
+ public static final InitializedMessageDigest getInitializedMessageDigestInstance(byte algorithm,
+ boolean externalAccess) throws CryptoException {
+ if (externalAccess) {
+ CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
+ }
+ InitializedMessageDigest instance = new MessageDigestImpl(algorithm);
+ return instance;
+ }
+
/**
* Gets the Message digest algorithm.
* @return the algorithm code defined above
*/
public abstract byte getAlgorithm();
-
+
/**
* Returns the byte length of the hash.
* @return hash length
*/
public abstract byte getLength();
-
+
/**
* Generates a hash of all/last input data.
* Completes and returns the hash computation after performing final operations such as padding.
@@ -92,9 +156,12 @@ public static final MessageDigest getInstance(byte algorithm, boolean externalAc
* @param outBuff the output buffer, may be the same as the input buffer
* @param outOffset the offset into the output buffer where the resulting hash value begins
* @return number of bytes of hash output in outBuff
+ * @throws CryptoException with the following reason codes:
CryptoException.ILLEGAL_USE if the accumulated message length is greater than the maximum length supported by the algorithm.
+ * CryptoException.ILLEGAL_USE if the accumulated message length is greater than the maximum length supported by the algorithm.
+ * MessageDigest object to the initial state for further use.
*/
public abstract void reset();
-
-}
\ No newline at end of file
+
+}
diff --git a/src/main/java/javacard/security/RSAPrivateCrtKey.java b/src/main/java/javacard/security/RSAPrivateCrtKey.java
index 71016b47..91eea459 100644
--- a/src/main/java/javacard/security/RSAPrivateCrtKey.java
+++ b/src/main/java/javacard/security/RSAPrivateCrtKey.java
@@ -40,8 +40,8 @@
* @see RSAPublicKey
* @see KeyBuilder
* @see Signature
- * @see Cipher
- * @see KeyEncryption
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
*
*/
public interface RSAPrivateCrtKey
diff --git a/src/main/java/javacard/security/RSAPrivateKey.java b/src/main/java/javacard/security/RSAPrivateKey.java
index 2dff9ec4..ecacff04 100644
--- a/src/main/java/javacard/security/RSAPrivateKey.java
+++ b/src/main/java/javacard/security/RSAPrivateKey.java
@@ -27,8 +27,8 @@
* @see RSAPrivateCrtKey
* @see KeyBuilder
* @see Signature
- * @see Cipher
- * @see KeyEncryption
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
*/
public interface RSAPrivateKey
extends PrivateKey {
diff --git a/src/main/java/javacard/security/RSAPublicKey.java b/src/main/java/javacard/security/RSAPublicKey.java
index 02203585..36be4435 100644
--- a/src/main/java/javacard/security/RSAPublicKey.java
+++ b/src/main/java/javacard/security/RSAPublicKey.java
@@ -25,8 +25,8 @@
* @see RSAPrivateCrtKey
* @see KeyBuilder
* @see Signature
- * @see Cipher
- * @see KeyEncryption
+ * @see javacardx.crypto.Cipher
+ * @see javacardx.crypto.KeyEncryption
*
*/
public interface RSAPublicKey
diff --git a/src/main/java/javacard/security/Signature.java b/src/main/java/javacard/security/Signature.java
index 39261682..0ab70f44 100644
--- a/src/main/java/javacard/security/Signature.java
+++ b/src/main/java/javacard/security/Signature.java
@@ -100,7 +100,7 @@ public abstract class Signature {
*/
public static final byte ALG_DES_MAC4_PKCS5 = 7;
/**
- * Signature algorithm ALG_DES_MAC8_PKCS5 generates an 8-byte MAC
+ * Signature algorithm ALG_DES_MAC8_PKCS5 generates an 8-byte MAC
* using DES in CBC mode or triple DES in outer CBC mode.
* Input data is padded according to the PKCS#5 scheme.
* Note: @@ -141,7 +141,7 @@ public abstract class Signature { * and encrypts it using RSA. *
Note:
Note:
init() methods to indicate signature sign mode.
*/
@@ -290,6 +357,7 @@ public static final Signature getInstance(byte algorithm, boolean externalAccess
case ALG_RSA_RIPEMD160_ISO9796:
case ALG_RSA_RIPEMD160_PKCS1:
case ALG_ECDSA_SHA:
+ case ALG_RSA_SHA_ISO9796_MR:
instance = new AsymmetricSignatureImpl(algorithm);
break;
case ALG_DES_MAC4_NOPAD:
@@ -298,8 +366,16 @@ public static final Signature getInstance(byte algorithm, boolean externalAccess
case ALG_DES_MAC8_ISO9797_M1:
case ALG_DES_MAC4_ISO9797_M2:
case ALG_DES_MAC8_ISO9797_M2:
+ case ALG_DES_MAC8_ISO9797_1_M2_ALG3:
case ALG_DES_MAC4_PKCS5:
case ALG_DES_MAC8_PKCS5:
+ case ALG_AES_MAC_128_NOPAD:
+ case ALG_HMAC_SHA1:
+ case ALG_HMAC_SHA_256:
+ case ALG_HMAC_SHA_384:
+ case ALG_HMAC_SHA_512:
+ case ALG_HMAC_MD5:
+ case ALG_HMAC_RIPEMD160:
instance = new SymmetricSignatureImpl(algorithm);
break;
@@ -324,6 +400,8 @@ public static final Signature getInstance(byte algorithm, boolean externalAccess
* Note:
MODE_SIGN or MODE_VERIFY
@@ -350,6 +428,8 @@ public abstract void init(Key theKey, byte theMode)
* bArray.
* CryptoException.ILLEGAL_VALUE.
+ * MODE_SIGN or MODE_VERIFY
@@ -487,4 +567,4 @@ public abstract short sign(byte[] inBuff, short inOffset, short inLength, byte[]
public abstract boolean verify(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset, short sigLength)
throws CryptoException;
-}
\ No newline at end of file
+}
diff --git a/src/main/java/javacard/security/SignatureMessageRecovery.java b/src/main/java/javacard/security/SignatureMessageRecovery.java
new file mode 100644
index 00000000..79ebc613
--- /dev/null
+++ b/src/main/java/javacard/security/SignatureMessageRecovery.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2014 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package javacard.security;
+
+/**
+ * A subclass of the abstract
+ * Signature class must implement this
+ * SignatureMessageRecovery interface to provide message recovery functionality.
+ * An instance implementing this interface is returned by the
+ * {@link javacard.security.Signature#getInstance(byte, boolean)} method when algorithm type with suffix
+ * *_MR is specified. e.g.{@link javacard.security.Signature#ALG_RSA_SHA_ISO9796_MR}.
+ *
+ * This interface provides specialized versions of some of the methods defined in the
+ * Signature
+ * class to provide message recovery functions. An alternate version of the
+ * sign() and
+ * verify() methods is supported here along with a
+ * new
+ * beginVerify method to allow the message encoded in the signature to be recovered.
+ *
+ *
For signing a message with message recovery functionality, the user must cast the
+ * Signature object to this interface, initialize the object for signing with a
+ * private key using the
+ * init() method, and issue 0 or more
+ * update() method
+ * calls and then finally call the
+ * sign() method to obtain the signature.
+ *
+ *
For recovering the encoded message and verifying functionality, the user must
+ * cast the
+ * Signature object to this interface, initialize the object for
+ * verifying with a public key using the
+ * init() method, first recover the
+ * message using the
+ * beginVerify() method and then issue 0 or more
+ * update()
+ * method calls and then finally call the
+ * verify() method to verify the
+ * signature.
+ *
+ *
Note:
+ * A
+ * Signature object implementing this interface must throw
+ * CryptoException with
+ * CryptoException.ILLEGAL_USE reason code when one of the
+ * following methods applicable only to a
+ * Signature object which does not
+ * include message recovery functionality, is called:
+ *
Signature object with the appropriate
+ * Key.
+ * This method should be used for algorithms which do not need initialization parameters
+ * or use default parameter values.
+ * init() must be used to update the
+ * Signature object with a new key.
+ * If the
+ * Key object is modified after invoking the
+ * init() method,
+ * the behavior of the
+ * update(),
+ * sign(), and
+ * verify()
+ * methods is unspecified.
+ *
+ *
+ * @param theKey the key object to use for signing or verifying
+ * @param theMode one of MODE_SIGN or MODE_VERIFY
+ * @throws CryptoException with the following reason codes: CryptoException.ILLEGAL_VALUE if theMode option is an undefined value or if the Key is inconsistent with theMode or with the Signature implementation. CryptoException.UNINITIALIZED_KEY if theKey instance is uninitialized.
+ */
+ void init(Key theKey, byte theMode) throws CryptoException;
+
+ /**
+ * This method begins the verification sequence by recovering the message
+ * encoded within the signature itself and initializing the internal hash
+ * function. The recovered message data overwrites the signature data in the
+ * sigAndRecDataBuff input byte array.
+ *
Notes:
update() or the verify() methods during verification.
+ * sigLength - recovered message length) bytes of
+ * signature data in sigAndRecDataBuff may also be overwritten
+ * by this method.
+ * + * + * @param sigAndRecDataBuff contains the signature data as input and also contains the recoverable part of the message as output. + * @param buffOffset offset into the sigAndRecDataBuff array where data begins for signature and where this method will start writing recovered message data. + * @param sigLength the length of signature data + * @return byte length of recovered message data written to sigAndRecDataBuff + * @throws CryptoException with the following reason codes: CryptoException.ILLEGAL_USE for the following conditions: if this object is initialized for signature sign mode if sigLength is inconsistent with this Signature algorithm if the decrypted message representative does not meet the algorithm specifications if the bit length of the decrypted message representative is not a multiple of 8. CryptoException.UNINITIALIZED_KEY if key not initialized. CryptoException.INVALID_INIT if this Signature object is not initialized. + */ + short beginVerify(byte[] sigAndRecDataBuff, short buffOffset, short sigLength) throws CryptoException; + + /** + * Generates the signature of all/last input data. In addition, this method + * returns the number of bytes beginning with the first byte of the message + * that was encoded into the signature itself. The encoded message is called + * the recoverable message and its length is called + * the recoverable message length. This recoverable message + * need not be transmitted and can be recovered during verification. + *
A call to this method also resets this
+ * Signature object to the state it was in
+ * when previously initialized via a call to
+ * init().
+ * That is, the object is reset and available to sign another message.
+ *
The input and output buffer data may overlap. + *
+ * + * @param inBuff the input buffer of data to be signed + * @param inOffset the offset into the input buffer at which to begin signature generation + * @param inLength the byte length to sign + * @param sigBuff the output buffer to store signature data + * @param sigOffset the offset into sigBuff at which to begin signature data + * @param recMsgLen the output buffer containing the number of bytes of the recoverable message beginning with the first byte of the message that was encoded into the signature itself + * @param recMsgLenOffset offset into the recMsgLen output buffer where the byte length of the recoverable message is stored. Note that a single short value is stored at recMsgLenOffset offset. + * @return number of bytes of signature output in sigBuff + * @throws CryptoException with the following reason codes: CryptoException.UNINITIALIZED_KEY if key not initialized. CryptoException.INVALID_INIT if this Signature object is not initialized or initialized for signature verify mode. + */ + short sign(byte[] inBuff, short inOffset, short inLength, byte[] sigBuff, short sigOffset, short[] recMsgLen, short recMsgLenOffset) throws CryptoException; + + /** + * Verifies the signature of all/last input data against the passed in signature. + *
A call to this method also resets this
+ * Signature object to the state it was in
+ * when previously initialized via a call to
+ * init().
+ * That is, the object is reset and available to verify another message.
+ *
+ * + * @param inBuff the input buffer of data to be verified + * @param inOffset the offset into the input buffer at which to begin signature generation + * @param inLength the byte length to sign + * @return true if the signature verifies, false otherwise + * @throws CryptoException with the following reason codes: CryptoException.UNINITIALIZED_KEY if key not initialized. CryptoException.INVALID_INIT if this Signature object is not initialized or initialized for signature sign mode. CryptoException.ILLEGAL_USE if one of the following conditions is met: if beginVerify method has not been called. + */ + boolean verify(byte[] inBuff, short inOffset, short inLength) throws CryptoException; + + /** + * Gets the Signature algorithm. + *
+ * + * + * @return the algorithm code implemented by this Signature instance. + */ + byte getAlgorithm(); + + /** + * Returns the byte length of the signature data. + *
+ *
+ *
+ * @return the byte length of the signature data
+ * @throws CryptoException with the following reason codes: CryptoException.INVALID_INIT if this Signature object is not initialized. CryptoException.UNINITIALIZED_KEY if key not initialized.
+ */
+ short getLength() throws CryptoException;
+
+ /**
+ * Accumulates a signature of the input data. This method requires temporary storage of
+ * intermediate results. In addition, if the input data length is not block aligned
+ * (multiple of block size)
+ * then additional internal storage may be allocated at this time to store a partial
+ * input data block.
+ * This may result in additional resource consumption and/or slow performance.
+ * This method should only be used if all the input data required for signing/verifying
+ * is not available in one byte array. If all of the input data required for
+ * signing/verifying is located in a single byte array, use of the
+ * sign()
+ * or
+ * beginVerify method and
+ * verify() method is recommended.
+ * The
+ * sign() or
+ * verify()
+ * method must be called to complete processing of input data accumulated by one or more
+ * calls to the
+ * update() method.
+ *
Note:
inLength is 0 this method does nothing.
+ * + * + * @param inBuff the input buffer of data to be signed/verified + * @param inOffset the offset into the input buffer where input data begins + * @param inLength the byte length to sign/verify + * @throws CryptoException with the following reason codes: CryptoException.UNINITIALIZED_KEY if key not initialized. CryptoException.INVALID_INIT if this Signature object is not initialized. CryptoException.ILLEGAL_USE if the mode set in the init() method is MODE_VERIFY and the beginVerify() method is not yet called. + * @see #sign(byte[], short, short, byte[], short, short[], short) + * @see #verify(byte[], short, short) + */ + void update(byte[] inBuff, short inOffset, short inLength) throws CryptoException; +} diff --git a/src/main/java/javacard/security/package-info.java b/src/main/java/javacard/security/package-info.java new file mode 100644 index 00000000..9191d315 --- /dev/null +++ b/src/main/java/javacard/security/package-info.java @@ -0,0 +1,4 @@ +/** + * JavaCard API. + */ +package javacard.security; diff --git a/src/main/java/javacardx/apdu/ExtendedLength.java b/src/main/java/javacardx/apdu/ExtendedLength.java new file mode 100644 index 00000000..1c19f62b --- /dev/null +++ b/src/main/java/javacardx/apdu/ExtendedLength.java @@ -0,0 +1,34 @@ +/* + * Copyright 2014 Licel LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package javacardx.apdu; + +/** + * The ExtendedLength interface serves as a tagging interface to indicate that + * the applet supports extended length APDU. If this interface is implemented by + * the applet instance, the applet may receive and send up to 32767 bytes of + * APDU data. + * + *
The APDU command header in the APDU buffer will use the variable + * length header defined in ISO7816-4 with a 3 byte Lc value when the Lc field + * in the incoming APDU header is 3 bytes long. The incoming data in that case + * will begin at APDU buffer offset 7. + * + *
See Runtime Environment Specification for the Java Card Platform for details.
+ *
+ * @since 2.2.2
+ */
+public interface ExtendedLength {
+}
\ No newline at end of file
diff --git a/src/main/java/javacardx/apdu/package-info.java b/src/main/java/javacardx/apdu/package-info.java
new file mode 100644
index 00000000..42c5858c
--- /dev/null
+++ b/src/main/java/javacardx/apdu/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JavaCard API.
+ */
+package javacardx.apdu;
diff --git a/src/main/java/javacardx/crypto/Cipher.java b/src/main/java/javacardx/crypto/Cipher.java
index 718c8584..fdc0cfd5 100644
--- a/src/main/java/javacardx/crypto/Cipher.java
+++ b/src/main/java/javacardx/crypto/Cipher.java
@@ -15,7 +15,7 @@
*/
package javacardx.crypto;
-import com.licel.jcardsim.crypto.AssymetricCipherImpl;
+import com.licel.jcardsim.crypto.AsymmetricCipherImpl;
import com.licel.jcardsim.crypto.SymmetricCipherImpl;
import javacard.security.CryptoException;
import javacard.security.Key;
@@ -160,6 +160,30 @@ public abstract class Cipher {
* pads input data according to the PKCS#1-OAEP scheme (IEEE 1363-2000).
*/
public static final byte ALG_RSA_PKCS1_OAEP = 15;
+
+ /**
+ * Cipher algorithm ALG_KOREAN_SEED_ECB_NOPAD provides a cipher using the
+ * Korean SEED algorithm specified in the Korean SEED Algorithm
+ * specification provided by KISA, Korea Information Security Agency in ECB
+ * mode and does not pad input data. If the input data is not block aligned
+ * it throws CryptoException with the reason code ILLEGAL_USE.
+ *
+ * @since 2.2.2
+ */
+ public static final byte ALG_KOREAN_SEED_ECB_NOPAD = 16;
+
+ /**
+ * Cipher algorithm ALG_KOREAN_SEED_CBC_NOPAD provides a cipher using the
+ * Korean SEED algorithm specified in the Korean SEED Algorithm
+ * specification provided by KISA, Korea Information Security Agency in ECB
+ * mode and does not pad input data. If the input data is not block aligned
+ * it throws CryptoException with the reason code ILLEGAL_USE.
+ *
+ *
+ * @since 2.2.2
+ */
+ public static final byte ALG_KOREAN_SEED_CBC_NOPAD = 17;
+
/**
* Used in init() methods to indicate decryption mode.
*/
@@ -214,7 +238,7 @@ public static final Cipher getInstance(byte algorithm, boolean externalAccess)
case ALG_RSA_ISO14888:
case ALG_RSA_ISO9796:
case ALG_RSA_PKCS1_OAEP:
- instance = new AssymetricCipherImpl(algorithm);
+ instance = new AsymmetricCipherImpl(algorithm);
break;
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
@@ -236,6 +260,8 @@ public static final Cipher getInstance(byte algorithm, boolean externalAccess)
*
MODE_DECRYPT or MODE_ENCRYPT
@@ -264,6 +290,8 @@ public abstract void init(Key theKey, byte theMode)
* the initial vector(IV) in bArray.
* CryptoException.ILLEGAL_VALUE.
+ * MODE_DECRYPT or MODE_ENCRYPT
@@ -305,11 +333,11 @@ public abstract void init(Key theKey, byte theMode, byte[] bArray, short bOff, s
* outBuff
* are the same array, then the output data area must not partially overlap the input data area such that
* the input data is modified before it is used;
- * if inBuff==outBuff andinOffset < outOffset < inOffset+inLength,
+ * if inBuff==outBuff andinOffset < outOffset < inOffset+inLength,
* incorrect output may result.
* inBuff==outBuff andoutOffset < inOffset+inLength,
+ * if inBuff==outBuff andoutOffset < inOffset+inLength,
* incorrect output may result.
* outBuff
* are the same array, then the output data area must not partially overlap the input data area such that
* the input data is modified before it is used;
- * if inBuff==outBuff andinOffset < outOffset < inOffset+inLength,
+ * if inBuff==outBuff andinOffset < outOffset < inOffset+inLength,
* incorrect output may result.
* inBuff==outBuff andoutOffset < inOffset+inLength,
+ * if inBuff==outBuff andoutOffset < inOffset+inLength,
* incorrect output may result.
* outBuff.
diff --git a/src/main/java/javacardx/crypto/KeyEncryption.java b/src/main/java/javacardx/crypto/KeyEncryption.java
index c4059364..c06ebe66 100644
--- a/src/main/java/javacardx/crypto/KeyEncryption.java
+++ b/src/main/java/javacardx/crypto/KeyEncryption.java
@@ -19,7 +19,6 @@
/**
*KeyEncryption interface defines the methods used to enable encrypted
* key data access to a key implementation.
- *
*/
public interface KeyEncryption {
diff --git a/src/main/java/javacardx/crypto/package-info.java b/src/main/java/javacardx/crypto/package-info.java
new file mode 100644
index 00000000..ef7c2e0e
--- /dev/null
+++ b/src/main/java/javacardx/crypto/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * JavaCard API.
+ */
+package javacardx.crypto;
diff --git a/src/test/java/com/licel/jcardsim/DocumentationCodeSamplesTest.java b/src/test/java/com/licel/jcardsim/DocumentationCodeSamplesTest.java
new file mode 100644
index 00000000..0c895d14
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/DocumentationCodeSamplesTest.java
@@ -0,0 +1,189 @@
+package com.licel.jcardsim;
+
+import com.licel.jcardsim.samples.HelloWorldApplet;
+import com.licel.jcardsim.smartcardio.CardSimulator;
+import com.licel.jcardsim.smartcardio.CardTerminalSimulator;
+import com.licel.jcardsim.utils.AIDUtil;
+import com.licel.jcardsim.utils.ByteUtil;
+import javacard.framework.AID;
+import junit.framework.TestCase;
+
+import javax.smartcardio.*;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+
+/**
+ * Contains all listing from the documentation
+ */
+public class DocumentationCodeSamplesTest extends TestCase {
+ public void testCodeListingReadme() {
+ // 1. Create simulator
+ CardSimulator simulator = new CardSimulator();
+
+ // 2. Install applet
+ AID appletAID = AIDUtil.create("F000000001");
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+
+ // 3. Select applet
+ simulator.selectApplet(appletAID);
+
+ // 4. Send APDU
+ CommandAPDU commandAPDU = new CommandAPDU(0x00, 0x01, 0x00, 0x00);
+ ResponseAPDU response = simulator.transmitCommand(commandAPDU);
+
+ // 5. Check response status word
+ assertEquals(0x9000, response.getSW());
+ }
+
+ public void testCodeListing1() {
+ // 1. Create simulator
+ CardSimulator simulator = new CardSimulator();
+
+ // 2. Install applet
+ AID appletAID = AIDUtil.create("F000000001");
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+
+ // 3. Select applet
+ simulator.selectApplet(appletAID);
+
+ // 4. Send APDU
+ CommandAPDU commandAPDU = new CommandAPDU(0x00, 0x01, 0x00, 0x00);
+ ResponseAPDU response = simulator.transmitCommand(commandAPDU);
+
+ // 5. Check response status word
+ assertEquals(0x9000, response.getSW());
+ }
+
+
+ public void testCodeListing2() {
+ CardSimulator simulator = new CardSimulator();
+
+ byte[] appletAIDBytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
+ AID appletAID = new AID(appletAIDBytes, (short) 0, (byte) appletAIDBytes.length);
+
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+ simulator.selectApplet(appletAID);
+
+ // test NOP
+ ResponseAPDU response = simulator.transmitCommand(new CommandAPDU(0x00, 0x02, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+
+ // test hello world from card
+ response = simulator.transmitCommand(new CommandAPDU(0x00, 0x01, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+ assertEquals("Hello world !", new String(response.getData()));
+
+ // test echo
+ CommandAPDU echo = new CommandAPDU(0x00, 0x01, 0x01, 0x00, ("Hello javacard world !").getBytes());
+ response = simulator.transmitCommand(echo);
+ assertEquals(0x9000, response.getSW());
+ assertEquals("Hello javacard world !", new String(response.getData()));
+ }
+
+ public void testCodeListing3() {
+ CardSimulator simulator = new CardSimulator();
+
+ byte[] appletAIDBytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
+ AID appletAID = new AID(appletAIDBytes, (short) 0, (byte) appletAIDBytes.length);
+
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+ simulator.selectApplet(appletAID);
+
+ // test NOP
+ byte[] response = simulator.transmitCommand(new byte[]{0x00, 0x02, 0x00, 0x00});
+ ByteUtil.requireSW(response, 0x9000);
+ }
+
+ public void testCodeListing4() {
+ // AID from byte array
+ AID applet1AID = AIDUtil.create(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9});
+
+ // AID form String
+ AID applet2AID = AIDUtil.create("010203040506070809");
+
+ assertEquals(applet1AID, applet2AID);
+
+ // String to byte array
+ String hexString = ByteUtil.hexString(new byte[]{0,2,0,0});
+
+ // byte array from String
+ byte[] bytes = ByteUtil.byteArray("00 02 00 00");
+
+ assertEquals("00020000", hexString);
+ assertEquals("00020000", ByteUtil.hexString(bytes));
+ }
+
+ public void testCodeListing5() throws CardException {
+ // 1. Create simulator and install applet
+ CardSimulator simulator = new CardSimulator();
+ AID appletAID = AIDUtil.create("F000000001");
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+
+ // 2. Create Terminal
+ CardTerminal terminal = CardTerminalSimulator.terminal(simulator);
+
+ // 3. Connect to Card
+ Card card = terminal.connect("T=1");
+ CardChannel channel = card.getBasicChannel();
+
+ // 4. Select applet
+ CommandAPDU selectCommand = new CommandAPDU(AIDUtil.select(appletAID));
+ channel.transmit(selectCommand);
+
+ // 5. Send APDU
+ CommandAPDU commandAPDU = new CommandAPDU(0x00, 0x01, 0x00, 0x00);
+ ResponseAPDU response = simulator.transmitCommand(commandAPDU);
+
+ // 6. Check response status word
+ assertEquals(0x9000, response.getSW());
+ }
+
+ public void testCodeListing6() throws CardException {
+ // Obtain CardTerminal
+ CardTerminals cardTerminals = CardTerminalSimulator.terminals("My terminal 1", "My terminal 2");
+ CardTerminal terminal1 = cardTerminals.getTerminal("My terminal 1");
+ CardTerminal terminal2 = cardTerminals.getTerminal("My terminal 2");
+
+ assertEquals(false, terminal1.isCardPresent());
+ assertEquals(false, terminal2.isCardPresent());
+
+ // Create simulator and install applet
+ CardSimulator simulator = new CardSimulator();
+ AID appletAID = AIDUtil.create("F000000001");
+ simulator.installApplet(appletAID, HelloWorldApplet.class);
+
+ // Insert Card into "My terminal 1"
+ simulator.assignToTerminal(terminal1);
+ assertEquals(true, terminal1.isCardPresent());
+ assertEquals(false, terminal2.isCardPresent());
+ }
+
+ public void testCodeListing7() throws CardException, NoSuchAlgorithmException {
+ // Register provider
+ if (Security.getProvider("CardTerminalSimulator") == null) {
+ Security.addProvider(new CardTerminalSimulator.SecurityProvider());
+ }
+
+ // Get TerminalFactory
+ TerminalFactory factory = TerminalFactory.getInstance("CardTerminalSimulator", null);
+ CardTerminals cardTerminals = factory.terminals();
+
+ // Get CardTerminal
+ CardTerminal terminal = cardTerminals.getTerminal("jCardSim.Terminal");
+ assertNotNull(terminal);
+ }
+
+ public void testCodeListing8() throws CardException, NoSuchAlgorithmException {
+ // Register provider
+ if (Security.getProvider("CardTerminalSimulator") == null) {
+ Security.addProvider(new CardTerminalSimulator.SecurityProvider());
+ }
+
+ // Get TerminalFactory with custom names
+ String[] names = new String[] {"My terminal 1", "My terminal 2"};
+ TerminalFactory factory = TerminalFactory.getInstance("CardTerminalSimulator", names);
+ CardTerminals cardTerminals = factory.terminals();
+ assertNotNull(cardTerminals.getTerminal("My terminal 1"));
+ assertNotNull(cardTerminals.getTerminal("My terminal 2"));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/ApduContextTest.java b/src/test/java/com/licel/jcardsim/base/ApduContextTest.java
new file mode 100644
index 00000000..f8c926fe
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/ApduContextTest.java
@@ -0,0 +1,116 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.HelloWorldApplet;
+import com.licel.jcardsim.utils.AIDUtil;
+import com.licel.jcardsim.utils.ByteUtil;
+import javacard.framework.*;
+import junit.framework.TestCase;
+
+public class ApduContextTest extends TestCase {
+ private static class DummyApplet extends Applet implements AppletEvent {
+ public static boolean exceptionInSelect = false;
+ public static boolean exceptionInInstall = false;
+ public static boolean exceptionInDeselect = false;
+ public static boolean exceptionInUninstall = false;
+ public static boolean exceptionIllegalUse1 = false;
+ public static boolean exceptionIllegalUse2 = false;
+
+ @SuppressWarnings("unused")
+ public static void install(byte[] bArray, short bOffset, byte bLength) {
+ exceptionInSelect = false;
+ exceptionInInstall = false;
+ exceptionInDeselect = false;
+ exceptionInUninstall = false;
+
+
+ try {
+ APDU.getCurrentAPDU();
+ }
+ catch (SecurityException se) {
+ exceptionInInstall = true;
+ }
+
+ new DummyApplet().register();
+ }
+
+ @Override
+ public boolean select() {
+ try {
+ APDU.getCurrentAPDU();
+ }
+ catch (SecurityException se) {
+ exceptionInSelect = true;
+ }
+ return true;
+ }
+
+ @Override
+ public void process(APDU a) throws ISOException {
+ APDU apdu = APDU.getCurrentAPDU();
+ try {
+ apdu.getIncomingLength();
+ exceptionIllegalUse1 = false;
+ }
+ catch (APDUException e) {
+ exceptionIllegalUse1 = e.getReason() == APDUException.ILLEGAL_USE;
+ }
+ try {
+ apdu.getOffsetCdata();
+ exceptionIllegalUse2 = false;
+ }
+ catch (APDUException e) {
+ exceptionIllegalUse2 = e.getReason() == APDUException.ILLEGAL_USE;
+ }
+ apdu.setIncomingAndReceive();
+ apdu.getIncomingLength();
+ apdu.getOffsetCdata();
+ }
+
+ @Override
+ public void deselect() {
+ try {
+ APDU.getCurrentAPDU();
+ }
+ catch (SecurityException se) {
+ exceptionInDeselect = true;
+ }
+ }
+
+ public void uninstall() {
+ try {
+ APDU.getCurrentAPDU();
+ }
+ catch (SecurityException se) {
+ exceptionInUninstall = true;
+ }
+ }
+ }
+
+ public ApduContextTest(String name) {
+ super(name);
+ }
+
+ public void testCallingGetCurrentAPDUinWrongContextThrows() {
+ Simulator simulator = new Simulator();
+ AID otherAppletAID = AIDUtil.create("d0000cafe00001");
+ AID dummyAppletAID = AIDUtil.create("d0000cafe00002");
+
+ simulator.installApplet(otherAppletAID, HelloWorldApplet.class);
+ simulator.installApplet(dummyAppletAID, DummyApplet.class);
+ assertTrue(DummyApplet.exceptionInInstall);
+
+ simulator.selectApplet(dummyAppletAID);
+ assertTrue(DummyApplet.exceptionInSelect);
+
+ byte[] response = simulator.transmitCommand(new byte[]{(byte) 0x80,0,0,0});
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(response));
+ assertTrue(DummyApplet.exceptionIllegalUse1);
+ assertTrue(DummyApplet.exceptionIllegalUse2);
+
+ simulator.selectApplet(otherAppletAID);
+ assertTrue(DummyApplet.exceptionInDeselect);
+
+ simulator.deleteApplet(dummyAppletAID);
+ assertTrue(DummyApplet.exceptionInUninstall);
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/DeleteTest.java b/src/test/java/com/licel/jcardsim/base/DeleteTest.java
new file mode 100644
index 00000000..2156f255
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/DeleteTest.java
@@ -0,0 +1,51 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.MultiInstanceApplet;
+import com.licel.jcardsim.utils.AIDUtil;
+import com.licel.jcardsim.utils.ByteUtil;
+import javacard.framework.AID;
+import javacard.framework.ISO7816;
+import junit.framework.TestCase;
+
+public class DeleteTest extends TestCase {
+ private static final byte CLA = (byte) 0x80;
+ private static final byte INS_GET_COUNT = 2;
+
+ public DeleteTest(String name) {
+ super(name);
+ }
+
+ public void testDeleteWorks() {
+ byte[] result;
+ AID aid1 = AIDUtil.create("d0000cafe00001");
+ AID aid2 = AIDUtil.create("d0000cafe00002");
+
+ Simulator simulator = new Simulator();
+
+ // install first instance
+ simulator.installApplet(aid1, MultiInstanceApplet.class);
+ simulator.selectApplet(aid1);
+
+ // check instance counter == 1
+ result = simulator.transmitCommand(new byte[]{CLA, INS_GET_COUNT, 0, 0});
+ assertEquals(1, ByteUtil.getShort(result, 0));
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(result));
+
+ // install second instance
+ simulator.installApplet(aid2, MultiInstanceApplet.class);
+
+ // check instance counter == 2
+ result = simulator.transmitCommand(new byte[]{CLA, INS_GET_COUNT, 0, 0});
+ assertEquals(2, ByteUtil.getShort(result, 0));
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(result));
+
+ // delete instance 1
+ simulator.deleteApplet(aid1);
+
+ // check instance counter == 1
+ simulator.selectApplet(aid2);
+ result = simulator.transmitCommand(new byte[]{CLA, INS_GET_COUNT, 0, 0});
+ assertEquals(1, ByteUtil.getShort(result, 0));
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(result));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/ExtendedLengthTest.java b/src/test/java/com/licel/jcardsim/base/ExtendedLengthTest.java
new file mode 100644
index 00000000..fb14786a
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/ExtendedLengthTest.java
@@ -0,0 +1,160 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.Sha1Applet;
+import javacard.framework.AID;
+import junit.framework.TestCase;
+import org.bouncycastle.util.encoders.Hex;
+
+import javax.smartcardio.ResponseAPDU;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+public class ExtendedLengthTest extends TestCase {
+ private static final byte CLA = (byte) 0x80;
+ private static final byte INS_DIGEST = 0;
+ private static final byte INS_ECHO = 2;
+ private static final byte INS_LEN = 4;
+ private static final byte P1 = (byte) 0;
+ private static final byte P2 = (byte) 0;
+ private static final byte DUMMY = (byte) 0x41;
+
+ private static final byte[] TEST_APPLET_AID_BYTES = Hex.decode("0102030405cafe01");
+
+ public ExtendedLengthTest(String testName) {
+ super(testName);
+ }
+
+ private Simulator prepareSimulator() {
+ Simulator instance = new Simulator();
+ AID aid = new AID(TEST_APPLET_AID_BYTES, (short) 0, (byte) TEST_APPLET_AID_BYTES.length);
+ instance.installApplet(aid, Sha1Applet.class);
+ instance.selectApplet(aid);
+ return instance;
+ }
+
+ public void testRegularApduDigest() throws NoSuchAlgorithmException {
+ MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ byte[] expectedOutput = sha1.digest(new byte[]{DUMMY});
+
+ Simulator instance = prepareSimulator();
+
+ byte[] apdu = new byte[]{CLA, INS_DIGEST, P1, P2, 1, DUMMY};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testRegularApduLcLe() {
+ byte lc = 1;
+ byte le = (byte) 0xA0;
+ byte[] expectedOutput = new byte[]{0, lc, 0, le};
+
+ Simulator instance = prepareSimulator();
+
+ byte[] apdu = new byte[]{CLA, INS_LEN, P1, P2, lc, 0, le};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testRegularApduEcho() throws NoSuchAlgorithmException {
+ byte[] expectedOutput = new byte[]{DUMMY};
+
+ Simulator instance = prepareSimulator();
+
+ byte[] apdu = new byte[]{CLA, INS_ECHO, 0, 0, 1, DUMMY};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testExtendedApduDigestWith1Byte() throws NoSuchAlgorithmException {
+ MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ byte[] input = new byte[]{DUMMY};
+ byte[] expectedOutput = sha1.digest(input);
+
+ Simulator instance = prepareSimulator();
+
+ byte[] apdu = new byte[]{CLA, INS_DIGEST, 0, 0, 0, 0, 1, DUMMY};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testExtendedApduLcLe() {
+ byte[] expectedOutput = {0x0, 0x1, 0x1F, (byte) 0xCA};
+
+ Simulator instance = prepareSimulator();
+
+ byte[] apdu = new byte[]{CLA, INS_LEN, P1, P2, 0, 0, 1, DUMMY, 0x1F, (byte) 0xCA};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testExtendedApduEchoWith1Byte() throws NoSuchAlgorithmException {
+ byte[] expectedOutput = {0x41};
+
+ Simulator instance = prepareSimulator();
+ byte[] apdu = new byte[]{CLA, INS_ECHO, 0, 0, 0, 0, 1, DUMMY};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testExtendedApduDigest() throws NoSuchAlgorithmException {
+ MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ byte[] input = new byte[Short.MAX_VALUE];
+ Arrays.fill(input, DUMMY);
+ byte[] expectedOutput = sha1.digest(input);
+
+ Simulator instance = prepareSimulator();
+
+ ByteBuffer inputApdu = ByteBuffer.wrap(new byte[input.length + 7]);
+ inputApdu.put(CLA);
+ inputApdu.put(INS_DIGEST);
+ inputApdu.put(P1);
+ inputApdu.put(P2);
+ inputApdu.put((byte) 0).putShort((short) input.length); // Lc
+ inputApdu.put(input);
+
+ byte[] result = instance.transmitCommand(inputApdu.array());
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+ }
+
+ public void testExtendedApduEcho() {
+ byte[] input = new byte[Short.MAX_VALUE - 2];
+ Arrays.fill(input, (byte) 0x41);
+
+ Simulator instance = prepareSimulator();
+
+ ByteBuffer inputApdu = ByteBuffer.wrap(new byte[input.length + 7]);
+ inputApdu.put(CLA);
+ inputApdu.put(INS_ECHO);
+ inputApdu.put(P1);
+ inputApdu.put(P2);
+ inputApdu.put((byte) 0).putShort((short) input.length); // Lc
+ inputApdu.put(input);
+
+ byte[] result = instance.transmitCommand(inputApdu.array());
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(input), Arrays.toString(responseApdu.getData()));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/ProtocolTest.java b/src/test/java/com/licel/jcardsim/base/ProtocolTest.java
new file mode 100644
index 00000000..35f189f4
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/ProtocolTest.java
@@ -0,0 +1,58 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.DualInterfaceApplet;
+import com.licel.jcardsim.utils.AIDUtil;
+import com.licel.jcardsim.utils.ByteUtil;
+import javacard.framework.AID;
+import javacard.framework.APDU;
+import javacard.framework.ISO7816;
+import junit.framework.TestCase;
+
+public class ProtocolTest extends TestCase {
+ private static final byte CLA = (byte) 0x80;
+ private static final byte INS_READ = 0;
+ private static final byte INS_WRITE = 2;
+ private static final byte INS_INFO = 4;
+
+ private final AID aid = AIDUtil.create("D0000CAFE00001");
+
+ public ProtocolTest(String name) {
+ super(name);
+ }
+
+ public void testDualInterfaceApplet() {
+ final String expectedOutput = "CAFE9000";
+ byte[] response;
+
+ Simulator simulator = new Simulator();
+ simulator.installApplet(aid, DualInterfaceApplet.class);
+ simulator.selectApplet(aid);
+
+ // check interface is T=0 (contacted)
+ response = simulator.transmitCommand(new byte[]{CLA, INS_INFO, 0, 0});
+ assertEquals(APDU.PROTOCOL_T0, response[0]);
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(response));
+
+ // store data
+ response = simulator.transmitCommand(new byte[]{CLA,INS_WRITE,0,0,2, (byte) 0xCA, (byte) 0xFE});
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(response));
+
+ // read data
+ response = simulator.transmitCommand(new byte[]{CLA, INS_READ, 0, 0});
+ assertEquals(expectedOutput, ByteUtil.hexString(response));
+
+ // change protocol
+ simulator.changeProtocol("T=CL");
+ response = simulator.transmitCommand(new byte[]{CLA, INS_INFO, 0, 0});
+ assertEquals(APDU.PROTOCOL_MEDIA_CONTACTLESS_TYPE_A, response[0]);
+ assertEquals(ISO7816.SW_NO_ERROR, ByteUtil.getSW(response));
+
+ // read data
+ response = simulator.transmitCommand(new byte[]{CLA, INS_READ, 0, 0});
+ assertEquals(expectedOutput, ByteUtil.hexString(response));
+
+ // store data should fail
+ response = simulator.transmitCommand(new byte[]{CLA,INS_WRITE,0,0,2, (byte) 0xBA, (byte) 0xD0});
+ assertEquals(ISO7816.SW_CONDITIONS_NOT_SATISFIED, ByteUtil.getSW(response));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/SelectTest.java b/src/test/java/com/licel/jcardsim/base/SelectTest.java
new file mode 100644
index 00000000..a781c077
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/SelectTest.java
@@ -0,0 +1,134 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.MultiInstanceApplet;
+import com.licel.jcardsim.utils.AIDUtil;
+import com.licel.jcardsim.utils.ByteUtil;
+import javacard.framework.*;
+import junit.framework.TestCase;
+import org.bouncycastle.util.encoders.Hex;
+
+import java.util.Arrays;
+
+public class SelectTest extends TestCase {
+ private static final byte CLA = (byte) 0x80;
+ private static final byte INS_GET_FULL_AID = 0;
+
+ private static boolean selectedCalled;
+
+ private static class UnselectableApplet extends Applet {
+ @SuppressWarnings("unused")
+ public static void install(byte[] bArray, short bOffset, byte bLength) {
+ new UnselectableApplet().register();
+ }
+
+ @Override
+ public boolean select() {
+ selectedCalled = true;
+ return false;
+ }
+
+ @Override
+ public void process(APDU apdu) throws ISOException {
+ }
+ }
+
+ public SelectTest(String name) {
+ super(name);
+ }
+
+ public void testAidComparator() {
+ AID[] input = new AID[] {
+ AIDUtil.create("A000008812"),
+ AIDUtil.create("FF00066767"),
+ AIDUtil.create("D0000CAFE001"),
+ AIDUtil.create("D0000CAFE000"),
+ AIDUtil.create("D0000CAFE00023"),
+ AIDUtil.create("D0000CAFE00001"),
+ AIDUtil.create("0100CAFE01"),
+ AIDUtil.create("0200888888")
+ };
+ Arrays.sort(input, AIDUtil.comparator());
+
+ String[] tmp = new String[input.length];
+ for (int i = 0; i < input.length; i++) {
+ tmp[i] = AIDUtil.toString(input[i]);
+ }
+ String expected = "[0100CAFE01, 0200888888, A000008812, " +
+ "D0000CAFE000, D0000CAFE00001, D0000CAFE00023, D0000CAFE001, FF00066767]";
+
+ assertEquals(expected, Arrays.toString(tmp));
+ }
+
+ private Simulator prepareSimulator() {
+ AID aid0 = AIDUtil.create("010203040506070809");
+ AID aid1 = AIDUtil.create("d0000cafe00001");
+ AID aid2 = AIDUtil.create("d0000cafe00002");
+
+ Simulator simulator = new Simulator();
+ simulator.installApplet(aid0, MultiInstanceApplet.class);
+ simulator.installApplet(aid2, MultiInstanceApplet.class);
+ simulator.installApplet(aid1, MultiInstanceApplet.class);
+ return simulator;
+ }
+
+ public void testPartialSelectWorks1() {
+ Simulator simulator = prepareSimulator();
+
+ // should select d0000cafe00001
+ assertTrue(simulator.selectApplet(AIDUtil.create("d0000cafe0")));
+ byte[] expected = Hex.decode("d0000cafe000019000");
+ byte[] actual = simulator.transmitCommand(new byte[]{CLA,INS_GET_FULL_AID,0,0});
+ assertEquals(Arrays.toString(expected), Arrays.toString(actual));
+ }
+
+ public void testPartialSelectWorks2() {
+ Simulator simulator = prepareSimulator();
+
+ // should select d0000cafe00001
+ simulator.transmitCommand(new byte[]{0, ISO7816.INS_SELECT, 4, 0, 1, (byte) 0xD0});
+
+ byte[] expected = Hex.decode("d0000cafe000019000");
+ byte[] actual = simulator.transmitCommand(new byte[]{CLA,INS_GET_FULL_AID,0,0});
+ assertEquals(Arrays.toString(expected), Arrays.toString(actual));
+ }
+
+ public void testEmptySelectWorks() {
+ final byte[] expected = Hex.decode("0102030405060708099000");
+ Simulator simulator = prepareSimulator();
+
+ // should select 010203040506070809
+ simulator.transmitCommand(new byte[]{0, ISO7816.INS_SELECT, 4, 0});
+ byte[] actual = simulator.transmitCommand(new byte[]{CLA,INS_GET_FULL_AID, 0, 0});
+ assertEquals(Arrays.toString(expected), Arrays.toString(actual));
+
+ // should select 010203040506070809
+ simulator.transmitCommand(new byte[]{0, ISO7816.INS_SELECT, 4, 0, 0});
+ actual = simulator.transmitCommand(new byte[]{CLA,INS_GET_FULL_AID,0,0});
+ assertEquals(Arrays.toString(expected), Arrays.toString(actual));
+ }
+
+ public void testCanNotSelectUnselectableApplet() {
+ selectedCalled = false;
+
+ AID aid = AIDUtil.create("010203040506070809");
+ Simulator simulator = new Simulator();
+ simulator.installApplet(aid, UnselectableApplet.class);
+
+ byte[] result = simulator.selectAppletWithResult(aid);
+ assertEquals(2, result.length);
+ assertEquals(ISO7816.SW_APPLET_SELECT_FAILED, Util.getShort(result, (short)0));
+ assertTrue(selectedCalled);
+ }
+
+ public void testApduWithoutSelectedAppletFails() {
+ Simulator simulator = new Simulator();
+ byte[] cmd = new byte[]{CLA, INS_GET_FULL_AID, 0, 0};
+ byte[] result;
+
+ result = simulator.transmitCommand(cmd);
+ assertEquals(ISO7816.SW_COMMAND_NOT_ALLOWED, ByteUtil.getSW(result));
+
+ result = CardManager.dispatchApdu(simulator, new byte[]{CLA,INS_GET_FULL_AID, 0, 0});
+ assertEquals(ISO7816.SW_COMMAND_NOT_ALLOWED, ByteUtil.getSW(result));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/SimulatorTest.java b/src/test/java/com/licel/jcardsim/base/SimulatorTest.java
new file mode 100644
index 00000000..dbd094d3
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/SimulatorTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.HelloWorldApplet;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import javacard.framework.AID;
+import javacard.framework.Applet;
+import javacard.framework.ISO7816;
+import javacard.framework.Util;
+import junit.framework.TestCase;
+import org.bouncycastle.util.Arrays;
+import org.bouncycastle.util.encoders.Hex;
+
+/**
+ *
+ */
+public class SimulatorTest extends TestCase {
+
+ private static final byte[] ETALON_ATR = Hex.decode("3BFA1800008131FE454A434F5033315632333298");
+ private static final byte[] TEST_APPLET_AID_BYTES = Hex.decode("010203040506070809");
+ private static final Class extends Applet> TEST_APPLET_CLASS = HelloWorldApplet.class;
+ private static final String TEST_APPLET_CLASSNAME = "com.licel.jcardsim.samples.HelloWorldApplet";
+ private static final AID TEST_APPLET_AID = new AID(TEST_APPLET_AID_BYTES, (short)0, (byte) TEST_APPLET_AID_BYTES.length);
+ private static final byte[] TEST_APPLET1_AID_BYTES = Hex.decode("01020304050607080A");
+ private static final String TEST_APPLET1_CLASSNAME = "com.licel.jcardsim.samples.HelloWorldApplet1";
+ private static final AID TEST_APPLET1_AID = new AID(TEST_APPLET1_AID_BYTES, (short)0, (byte) TEST_APPLET1_AID_BYTES.length);
+
+ byte[] createData = null;
+ byte[] appletJarContents = null;
+
+ public SimulatorTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ createData = new byte[1+TEST_APPLET_AID_BYTES.length+1+2+3];
+ createData[0] = (byte) TEST_APPLET_AID_BYTES.length;
+ System.arraycopy(TEST_APPLET_AID_BYTES, 0, createData, 1, TEST_APPLET_AID_BYTES.length);
+ createData[1+TEST_APPLET_AID_BYTES.length] = (byte) 5;
+ createData[2+TEST_APPLET_AID_BYTES.length] = 0; // aid
+ createData[3+TEST_APPLET_AID_BYTES.length] = 0; // control
+ createData[4+TEST_APPLET_AID_BYTES.length] = 2; // params
+ createData[5+TEST_APPLET_AID_BYTES.length] = 0xF; // params
+ createData[6+TEST_APPLET_AID_BYTES.length] = 0xF; // params
+ InputStream is = SimulatorTest.class.getResourceAsStream("helloworld.jar");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] chunk = new byte[1024];
+ int readed = is.read(chunk);
+ while (readed > 0) {
+ bos.write(chunk, 0, readed);
+ readed = is.read(chunk);
+ }
+ appletJarContents = bos.toByteArray();
+ bos.close();
+ is.close();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of loadApplet method, of class Simulator.
+ */
+ public void testLoadApplet_3args() {
+ System.out.println("loadApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.loadApplet(TEST_APPLET1_AID, TEST_APPLET1_CLASSNAME, appletJarContents).equals(TEST_APPLET1_AID),true);
+ }
+
+ /**
+ * Test of loadApplet method, of class Simulator.
+ */
+ public void testLoadApplet_AID_String() {
+ System.out.println("loadApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.loadApplet(TEST_APPLET_AID, TEST_APPLET_CLASSNAME).equals(TEST_APPLET_AID),true);
+ }
+
+ /**
+ * Test of loadApplet method, of class Simulator.
+ */
+ public void testLoadApplet_AID_Class() {
+ System.out.println("loadApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.loadApplet(TEST_APPLET_AID, TEST_APPLET_CLASS).equals(TEST_APPLET_AID),true);
+ }
+
+ /**
+ * Test of createApplet method, of class Simulator.
+ */
+ public void testCreateApplet() {
+ System.out.println("createApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.loadApplet(TEST_APPLET_AID, TEST_APPLET_CLASS).equals(TEST_APPLET_AID),true);
+ assertEquals(instance.createApplet(TEST_APPLET_AID, createData, (short)0, (byte) createData.length).equals(TEST_APPLET_AID),true);
+ }
+
+ /**
+ * Test of installApplet method, of class Simulator.
+ */
+ public void testInstallApplet_AID_Class() {
+ System.out.println("installApplet");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ assertEquals(instance.selectApplet(TEST_APPLET_AID), true);
+ }
+
+ /**
+ * Test of installApplet method, of class Simulator.
+ */
+ public void testInstallApplet_5args_1() {
+ System.out.println("installApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS, createData, (short)0, (byte) createData.length).equals(TEST_APPLET_AID),true);
+ }
+
+ /**
+ * Test of installApplet method, of class Simulator.
+ */
+ public void testInstallApplet_5args_2() {
+ System.out.println("installApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASSNAME, createData, (short)0, (byte) createData.length).equals(TEST_APPLET_AID),true);
+ }
+
+ /**
+ * Test of installApplet method, of class Simulator.
+ */
+ public void testInstallApplet_6args() {
+ System.out.println("installApplet");
+ Simulator instance = new Simulator();
+ assertEquals(instance.installApplet(TEST_APPLET1_AID, TEST_APPLET1_CLASSNAME, appletJarContents, createData, (short)0, (byte) createData.length).equals(TEST_APPLET1_AID),true);
+ assertEquals(instance.selectApplet(TEST_APPLET1_AID), true);
+ // test NOP
+ byte[] response = instance.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00});
+ assertEquals(Arrays.areEqual(new byte[]{(byte)0x90, 0x00}, response), true);
+ }
+
+ public void testNopWithLengthExtensionsFails() {
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ instance.selectApplet(TEST_APPLET_AID);
+ // test NOP with Lc=1
+ byte[] response1 = instance.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00, 0, 0, 1, 0xA});
+ assertEquals(ISO7816.SW_WRONG_LENGTH, Util.getShort(response1, (short) 0));
+ // test NOP with Le=1
+ byte[] response2 = instance.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00, 0, 0, 1});
+ assertEquals(ISO7816.SW_WRONG_LENGTH, Util.getShort(response2, (short) 0));
+ // test NOP with Lc=1, Le=1
+ byte[] response3 = instance.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00, 0, 0, 1, 0xA, 0, 1});
+ assertEquals(ISO7816.SW_WRONG_LENGTH, Util.getShort(response3, (short) 0));
+ }
+
+ /**
+ * Test of selectApplet method, of class Simulator.
+ */
+ public void testSelectApplet() {
+ System.out.println("selectApplet");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ assertEquals(instance.selectApplet(TEST_APPLET_AID), true);
+ }
+
+ /**
+ * Test of selectAppletWithResult method, of class Simulator.
+ */
+ public void testSelectAppletWithResult() {
+ System.out.println("selectApplet");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ byte[] result = instance.selectAppletWithResult(TEST_APPLET_AID);
+ assertEquals(result[0], (byte)0x90);
+ assertEquals(result[1], 0x00);
+ }
+
+ /**
+ * Test of transmitCommand method, of class Simulator.
+ */
+ public void testTransmitCommand() {
+ System.out.println("transmitCommand");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ assertEquals(instance.selectApplet(TEST_APPLET_AID), true);
+ // test NOP
+ byte[] response = instance.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00});
+ assertEquals(Arrays.areEqual(new byte[]{(byte)0x90, 0x00}, response), true);
+ }
+
+ /**
+ * Test of reset method, of class Simulator.
+ */
+ public void testReset() {
+ System.out.println("reset");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ instance.reset();
+ // after reset installed applets not deleted
+ assertEquals(instance.selectApplet(TEST_APPLET_AID), true);
+ }
+
+ /**
+ * Test of resetRuntime method, of class Simulator.
+ */
+ public void testResetRuntime() {
+ System.out.println("resetRuntime");
+ Simulator instance = new Simulator();
+ instance.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ instance.resetRuntime();
+ // after reset runtime all applets removed
+ assertEquals(instance.selectApplet(TEST_APPLET_AID), false);
+ }
+
+ /**
+ * Test of getATR method, of class Simulator.
+ */
+ public void testGetATR() {
+ System.out.println("getATR");
+ Simulator instance = new Simulator();
+ byte[] result = instance.getATR();
+ assertEquals(Arrays.areEqual(ETALON_ATR, result), true);
+ }
+
+ /**
+ * Test of selectApplet method, of class Simulator.
+ */
+ public void testSelectAppletWith2Simulators() {
+ System.out.println("selectAppletWith2Simulators");
+ Simulator instance1 = new Simulator(new SimulatorRuntime());
+ Simulator instance2 = new Simulator(new SimulatorRuntime());
+
+ instance1.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ assertTrue(instance1.selectApplet(TEST_APPLET_AID));
+ assertFalse(instance2.selectApplet(TEST_APPLET_AID));
+
+ instance2.installApplet(TEST_APPLET_AID, TEST_APPLET_CLASS);
+ assertTrue(instance1.selectApplet(TEST_APPLET_AID));
+ assertTrue(instance2.selectApplet(TEST_APPLET_AID));
+
+ instance2.resetRuntime();
+ assertTrue(instance1.selectApplet(TEST_APPLET_AID));
+ assertFalse(instance2.selectApplet(TEST_APPLET_AID));
+
+ instance1.resetRuntime();
+ assertFalse(instance1.selectApplet(TEST_APPLET_AID));
+ assertFalse(instance2.selectApplet(TEST_APPLET_AID));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/base/TransientMemoryTest.java b/src/test/java/com/licel/jcardsim/base/TransientMemoryTest.java
new file mode 100644
index 00000000..b83009e8
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/base/TransientMemoryTest.java
@@ -0,0 +1,161 @@
+package com.licel.jcardsim.base;
+
+import com.licel.jcardsim.samples.Sha1Applet;
+import com.licel.jcardsim.utils.AIDUtil;
+import javacard.framework.AID;
+import javacard.framework.JCSystem;
+import javacard.framework.SystemException;
+import junit.framework.TestCase;
+
+import javax.smartcardio.ResponseAPDU;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+public class TransientMemoryTest extends TestCase {
+ private static final byte CLA = (byte) 0x80;
+ private static final byte INS_DIGEST = 0;
+ private static final byte INS_LAST_DIGEST = 6;
+
+ public TransientMemoryTest(String name) {
+ super(name);
+ }
+
+ public void testMemoryManagementWorks() {
+ final Object dummy1 = new Object();
+
+ final short size = 1;
+ TransientMemory transientMemory = new TransientMemory();
+
+ byte[] corBytes = transientMemory.makeByteArray(size, JCSystem.CLEAR_ON_RESET);
+ short[] corShorts = transientMemory.makeShortArray(size, JCSystem.CLEAR_ON_RESET);
+ boolean[] corBooleans = transientMemory.makeBooleanArray(size, JCSystem.CLEAR_ON_RESET);
+
+ Object[] corObjects = transientMemory.makeObjectArray(size, JCSystem.CLEAR_ON_RESET);
+ corBytes[0] = 123;
+ corShorts[0] = 123;
+ corBooleans[0] = true;
+ corObjects[0] = dummy1;
+
+ byte[] codBytes = transientMemory.makeByteArray(size, JCSystem.CLEAR_ON_DESELECT);
+ short[] codShorts = transientMemory.makeShortArray(size, JCSystem.CLEAR_ON_DESELECT);
+ boolean[] codBooleans = transientMemory.makeBooleanArray(size, JCSystem.CLEAR_ON_DESELECT);
+
+ Object[] codObjects = transientMemory.makeObjectArray(size, JCSystem.CLEAR_ON_DESELECT);
+ codBytes[0] = 123;
+ codShorts[0] = 123;
+ codBooleans[0] = true;
+ codObjects[0] = dummy1;
+
+ transientMemory.clearOnDeselect();
+ assertTrue(codBytes[0] == 0 && corBytes[0] != 0);
+ assertTrue(codShorts[0] == 0 && corShorts[0] != 0);
+ assertTrue(codObjects[0] == null && corObjects[0] == dummy1);
+ assertTrue(!codBooleans[0] && corBooleans[0]);
+
+ codBytes[0] = 123;
+ codShorts[0] = 123;
+ codBooleans[0] = true;
+ codObjects[0] = dummy1;
+
+ transientMemory.clearOnReset();
+ assertTrue(codBytes[0] == 0 && corBytes[0] == 0);
+ assertTrue(codShorts[0] == 0 && corShorts[0] == 0);
+ assertTrue(codObjects[0] == null && corObjects[0] == null);
+ assertTrue(!codBooleans[0] && !corBooleans[0]);
+
+ assertEquals(JCSystem.CLEAR_ON_RESET, transientMemory.isTransient(corBytes));
+ assertEquals(JCSystem.CLEAR_ON_RESET, transientMemory.isTransient(corShorts));
+ assertEquals(JCSystem.CLEAR_ON_RESET, transientMemory.isTransient(corBooleans));
+ assertEquals(JCSystem.CLEAR_ON_RESET, transientMemory.isTransient(corObjects));
+
+ assertEquals(JCSystem.CLEAR_ON_DESELECT, transientMemory.isTransient(codBytes));
+ assertEquals(JCSystem.CLEAR_ON_DESELECT, transientMemory.isTransient(codShorts));
+ assertEquals(JCSystem.CLEAR_ON_DESELECT, transientMemory.isTransient(codBooleans));
+ assertEquals(JCSystem.CLEAR_ON_DESELECT, transientMemory.isTransient(codObjects));
+
+ transientMemory.forgetBuffers();
+
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(corBytes));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(corShorts));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(corBooleans));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(corObjects));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(codBytes));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(codShorts));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(codBooleans));
+ assertEquals(JCSystem.NOT_A_TRANSIENT_OBJECT, transientMemory.isTransient(codObjects));
+ }
+
+
+ public void testInvalidEventThrows() {
+ final byte invalid = JCSystem.CLEAR_ON_DESELECT + JCSystem.CLEAR_ON_RESET;
+ TransientMemory transientMemory = new TransientMemory();
+
+ try {
+ transientMemory.makeByteArray(2, invalid);
+ fail("No exception");
+ }
+ catch (SystemException e) {
+ assertEquals(SystemException.ILLEGAL_VALUE, e.getReason());
+ }
+
+ try {
+ transientMemory.makeBooleanArray((short) 1, invalid);
+ fail("No exception");
+ }
+ catch (SystemException e) {
+ assertEquals(SystemException.ILLEGAL_VALUE, e.getReason());
+ }
+
+ try {
+ transientMemory.makeObjectArray((short) 1, invalid);
+ fail("No exception");
+ }
+ catch (SystemException e) {
+ assertEquals(SystemException.ILLEGAL_VALUE, e.getReason());
+ }
+
+ try {
+ transientMemory.makeBooleanArray((short) 1, invalid);
+ fail("No exception");
+ }
+ catch (SystemException e) {
+ assertEquals(SystemException.ILLEGAL_VALUE, e.getReason());
+ }
+ }
+
+ public void testCleanOnDeselectWorks() throws NoSuchAlgorithmException {
+ MessageDigest sha1 = MessageDigest.getInstance("SHA1");
+ byte[] expectedOutput = sha1.digest(new byte[]{'A'});
+ AID aid = AIDUtil.create("0102030405");
+
+ Simulator instance = new Simulator();
+ instance.installApplet(aid, Sha1Applet.class);
+ instance.selectApplet(aid);
+
+ // calculate SHA1
+ byte[] apdu = new byte[]{CLA, INS_DIGEST, 0, 0, 1, 'A'};
+ byte[] result = instance.transmitCommand(apdu);
+
+ ResponseAPDU responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+
+ // check last digest
+ apdu = new byte[]{CLA, INS_LAST_DIGEST, 0, 0};
+ result = instance.transmitCommand(apdu);
+ responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(expectedOutput), Arrays.toString(responseApdu.getData()));
+
+ // trigger clean on deselect
+ instance.selectApplet(aid);
+
+ // check last digest is all zero
+ apdu = new byte[]{CLA, INS_LAST_DIGEST, 0, 0};
+ result = instance.transmitCommand(apdu);
+ responseApdu = new ResponseAPDU(result);
+ assertEquals(0x9000, responseApdu.getSW());
+ assertEquals(Arrays.toString(new byte[20]), Arrays.toString(responseApdu.getData()));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/crypto/AssymetricCipherImplTest.java b/src/test/java/com/licel/jcardsim/crypto/AsymmetricCipherImplTest.java
similarity index 78%
rename from src/test/java/com/licel/jcardsim/crypto/AssymetricCipherImplTest.java
rename to src/test/java/com/licel/jcardsim/crypto/AsymmetricCipherImplTest.java
index fd144530..da4f7291 100644
--- a/src/test/java/com/licel/jcardsim/crypto/AssymetricCipherImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/AsymmetricCipherImplTest.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.RandomData;
@@ -27,9 +26,9 @@
* Test for AsymmetricCipherImpl
* Test data from NXP JCOP31-36 JavaCard
*/
-public class AssymetricCipherImplTest extends TestCase {
+public class AsymmetricCipherImplTest extends TestCase {
- public AssymetricCipherImplTest(String testName) {
+ public AsymmetricCipherImplTest(String testName) {
super(testName);
}
@@ -42,7 +41,7 @@ protected void tearDown() throws Exception {
}
/**
- * SelfTest of RSA Encryption/Decryption, of class AssymetricCipherImpl.
+ * SelfTest of RSA Encryption/Decryption, of class AsymmetricCipherImpl.
*/
public void testSelftRSA() {
Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
@@ -50,14 +49,14 @@ public void testSelftRSA() {
kp.genKeyPair();
cipher.init(kp.getPublic(), Cipher.MODE_ENCRYPT);
- byte[] msg = JCSystem.makeTransientByteArray((short) 127, JCSystem.CLEAR_ON_RESET);
- byte[] encryptedMsg = JCSystem.makeTransientByteArray((short) 128, JCSystem.CLEAR_ON_RESET);
+ byte[] msg = new byte[127];
+ byte[] encryptedMsg = new byte[128];
RandomData rnd = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
rnd.generateData(msg, (short) 0, (short) msg.length);
cipher.doFinal(msg, (short) 0, (short) msg.length, encryptedMsg, (short) 0);
cipher.init(kp.getPrivate(), Cipher.MODE_DECRYPT);
- byte[] decryptedMsg = JCSystem.makeTransientByteArray((short) msg.length, JCSystem.CLEAR_ON_RESET);
+ byte[] decryptedMsg = new byte[msg.length];
cipher.doFinal(encryptedMsg, (short) 0, (short) encryptedMsg.length, decryptedMsg, (short) 0);
assertEquals(true, Arrays.areEqual(msg, decryptedMsg));
diff --git a/src/test/java/com/licel/jcardsim/crypto/AsymmetricSignatureImplTest.java b/src/test/java/com/licel/jcardsim/crypto/AsymmetricSignatureImplTest.java
index 744fe3e8..2cb1d62b 100644
--- a/src/test/java/com/licel/jcardsim/crypto/AsymmetricSignatureImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/AsymmetricSignatureImplTest.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.KeyBuilder;
import javacard.security.KeyPair;
import javacard.security.PrivateKey;
@@ -48,6 +47,11 @@ public class AsymmetricSignatureImplTest extends TestCase {
"2BCBD3220787D8D621526FBF88E852158FB37B46A339EAAF64742548155C7A48DA3ED9D41B9A29BAB2582A81329411C9FB0FDE0BFCF962438440C68828C1FDC3B33A4F0FEE318FA9DA3802A5CBAA9E9D6EA3618A2626E9FDA6F5613335F868442E20B3EB2E5C0580CE6E999BBD33A9BD5C633FE18930916586D91527781F1081"
};
+ // RSA 2048-bit public key data from card
+ final static String RSA_2048_MODULUS = "8D4E29049C1C1861557F78B399665AAF957B73EBCCF5A436ED204A3B2C88F7A73ACE693147A6A731FFC297FBDFEABBA3658FDA68F0C3A60C2D8A96F874293FADE00F6AF600091A59118E8388DC69FD2D737882FBBB624A1A8BBD89641CFE33FC9C85BBC99017FCFE5CD5D13A3FE70524BE870171B0DBC870CB2F123CA5540C3B0759B71871A08EE3521C66261DCC1BD8F95DC850B730D8B8F0CF80F19C71B35FCB0439F419E7BD8E7B6A55203EFC6191D79DEF46B8A8F47EDF38F9E618A885BDFB8B212919D41CA1AB2B9B48328A9F4CF552FC157B8A1361A5ACABEE27725E835622D633569291532384EE47817AEB75119294E8522444FCCCB4F54073C2E121";
+ // RSA 2048-bit Signature
+ final static String RSA_2048_SIGNATURE = "27E3B9410C261BE66534B9FC8CB272902B8BFB06077CA973B39B512C48DD878FA4B00259E7B58ECD5F236127990DC6E10DAB1CAF4C967689C1D1A03A5C5EBD6EA617D5F0AEE09851207EC4BCE67287687F21AC450693B9B22CEC7EA87679FC6BCE1B2DA56F41BF9BD433932370379C103D269E9E529E46699E03E243B589DE5469B12E27B1F95E8FE6F872010A64126760AC51AEF44CDABE4D9FBC7568B12A077943E8CF3A4C3C1674B3600B1AA01CB2D290A0DC7968F1509BEB5ECC47C48789870D5279E675D67E262AF96CD8750D9C4CE450D64FDC8D135573B9BB0497B4A6F3F3034832707C116D2E3E51EC85D6BCF8AF681AC96245CD03D50CF5D391B0AF";
+
public AsymmetricSignatureImplTest(String testName) {
super(testName);
}
@@ -71,6 +75,13 @@ public void testVerifyRSA() {
byte[] exponent = Hex.decode(RSA_ETALON_EXP);
publicKey.setModulus(modulus, (short) 0, (short) modulus.length);
publicKey.setExponent(exponent, (short) 0, (short) exponent.length);
+
+ RSAPublicKey publicKey2048 = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC,
+ KeyBuilder.LENGTH_RSA_2048, false);
+ byte[] modulus2048 = Hex.decode(RSA_2048_MODULUS);
+ publicKey2048.setModulus(modulus2048, (short) 0, (short) modulus2048.length);
+ publicKey2048.setExponent(exponent, (short) 0, (short) exponent.length);
+
// verify signs
Signature signature = Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796, false);
testEngineVerify(signature, publicKey, Hex.decode(MESSAGE),
@@ -80,6 +91,10 @@ public void testVerifyRSA() {
testEngineVerify(signature, publicKey, Hex.decode(MESSAGE),
Hex.decode(RSA_SIGNATURES[1]), (short) 0);
+ signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
+ testEngineVerify(signature, publicKey2048, new byte[24],
+ Hex.decode(RSA_2048_SIGNATURE), (short) 0);
+
signature = Signature.getInstance(Signature.ALG_RSA_MD5_PKCS1, false);
testEngineVerify(signature, publicKey, Hex.decode(MESSAGE),
Hex.decode(RSA_SIGNATURES[2]), (short) 0);
@@ -90,15 +105,16 @@ public void testVerifyRSA() {
* SelfTest of RSA sign/verify method, of class AsymmetricSignatureImpl.
*/
public void testSelfSignVerifyRSA() {
- System.out.println("selft test sign/verify rsa");
+ System.out.println("self test sign/verify rsa");
testSelfSignVerify(KeyPair.ALG_RSA_CRT, RSA_ETALON_KEY_SIZE, Signature.ALG_RSA_SHA_PKCS1);
}
+
/**
* SelfTest of ECDSA sign/verify method, of class AsymmetricSignatureImpl.
*/
public void testSelfSignVerifyECDSA() {
- System.out.println("selft test sign/verify ecdsa");
+ System.out.println("self test sign/verify ecdsa");
// ecf2m keys
testSelfSignVerify(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_113, Signature.ALG_ECDSA_SHA);
// ecfp keys
@@ -122,8 +138,8 @@ public void testSelfSignVerify(byte keyAlg, short keySize, byte signAlg) {
Signature signEngine = Signature.getInstance(signAlg, false);
signEngine.init(privateKey, Signature.MODE_SIGN);
// sign length + extra space
- byte[] signature = JCSystem.makeTransientByteArray((short) (128 + 10), JCSystem.CLEAR_ON_RESET);
- byte[] msg = JCSystem.makeTransientByteArray((short) 65, JCSystem.CLEAR_ON_RESET);
+ byte[] signature = new byte[128 + 10];
+ byte[] msg = new byte[65];
RandomData rnd = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
rnd.generateData(msg, (short) 0, (short) msg.length);
short signLen = signEngine.sign(msg, (short) 0, (short) msg.length, signature, (short) 10);
@@ -163,5 +179,5 @@ public void testEngineVerify(Signature engine, PublicKey publicKey,
boolean result = engine.verify(etalonMsg, (short) 0, (short) etalonMsg.length,
etalonSign, etalonSignOffset, (short)(etalonSignLength!=0?etalonSignLength:etalonSign.length));
assertEquals(true, result);
- }
+ }
}
diff --git a/src/test/java/com/licel/jcardsim/crypto/ByteContainerTest.java b/src/test/java/com/licel/jcardsim/crypto/ByteContainerTest.java
new file mode 100644
index 00000000..08e9c3c7
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/crypto/ByteContainerTest.java
@@ -0,0 +1,55 @@
+package com.licel.jcardsim.crypto;
+
+import junit.framework.TestCase;
+
+import java.math.BigInteger;
+
+public class ByteContainerTest extends TestCase {
+ public ByteContainerTest(String name) {
+ super(name);
+ }
+
+ public void testPositiveIntegerWithLeadingZero() {
+ BigInteger expected = new BigInteger("4720643197658441292834747278018339");
+ assertTrue(expected.toByteArray()[0] == 0);
+ checkRoundTrip(expected);
+ }
+
+ public void testPositiveIntegerWithoutLeadingZero() {
+ BigInteger expected = new BigInteger("5192296858534827689835882578830703");
+ assertTrue(expected.toByteArray()[0] != 0);
+ checkRoundTrip(expected);
+ }
+
+ public void testZero() {
+ BigInteger expected = new BigInteger("0");
+ assertTrue(expected.toByteArray()[0] == 0);
+ checkRoundTrip(expected);
+ }
+
+ public void testNegativeNumber() {
+ BigInteger expected = new BigInteger("-123");
+
+ try {
+ new ByteContainer().setBigInteger(expected);
+ fail("No exception");
+ }
+ catch (IllegalArgumentException ignore) {
+ }
+
+ try {
+ new ByteContainer(expected);
+ fail("No exception");
+ }
+ catch (IllegalArgumentException ignore) {
+ }
+ }
+
+ private void checkRoundTrip(BigInteger expected) {
+ ByteContainer byteContainer = new ByteContainer();
+ byteContainer.setBigInteger(expected);
+ assertEquals(expected, byteContainer.getBigInteger());
+
+ assertEquals(expected, new ByteContainer(expected).getBigInteger());
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/crypto/CRC16Test.java b/src/test/java/com/licel/jcardsim/crypto/CRC16Test.java
index a189aec1..296ffbe9 100644
--- a/src/test/java/com/licel/jcardsim/crypto/CRC16Test.java
+++ b/src/test/java/com/licel/jcardsim/crypto/CRC16Test.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.Checksum;
import junit.framework.TestCase;
import org.bouncycastle.util.Arrays;
@@ -50,7 +49,7 @@ protected void tearDown() throws Exception {
public void testCrc16() {
System.out.println("test crc16");
Checksum crcEngine = Checksum.getInstance(Checksum.ALG_ISO3309_CRC16, false);
- byte[] crc = JCSystem.makeTransientByteArray((short) 2, JCSystem.CLEAR_ON_RESET);
+ byte[] crc = new byte[2];
byte[] msg = Hex.decode(MESSAGE);
crcEngine.doFinal(msg, (short) 0, (short) msg.length, crc, (short) 0);
assertEquals(true, Arrays.areEqual(Hex.decode(CRC), crc));
diff --git a/src/test/java/com/licel/jcardsim/crypto/CRC32Test.java b/src/test/java/com/licel/jcardsim/crypto/CRC32Test.java
index 945d456e..e15f1a88 100644
--- a/src/test/java/com/licel/jcardsim/crypto/CRC32Test.java
+++ b/src/test/java/com/licel/jcardsim/crypto/CRC32Test.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.Checksum;
import junit.framework.TestCase;
import org.bouncycastle.util.Arrays;
@@ -50,7 +49,7 @@ protected void tearDown() throws Exception {
public void testCrc32() {
System.out.println("test crc32");
Checksum crcEngine = Checksum.getInstance(Checksum.ALG_ISO3309_CRC32, false);
- byte[] crc = JCSystem.makeTransientByteArray((short) 4, JCSystem.CLEAR_ON_RESET);
+ byte[] crc = new byte[4];
byte[] msg = Hex.decode(MESSAGE);
crcEngine.doFinal(msg, (short) 0, (short) msg.length, crc, (short) 0);
assertEquals(true, Arrays.areEqual(Hex.decode(CRC), crc));
diff --git a/src/test/java/com/licel/jcardsim/crypto/ECKeyImplTest.java b/src/test/java/com/licel/jcardsim/crypto/ECKeyImplTest.java
new file mode 100644
index 00000000..f45f3d9b
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/crypto/ECKeyImplTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.crypto;
+
+import java.security.SecureRandom;
+import javacard.security.KeyBuilder;
+import junit.framework.TestCase;
+import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
+import org.bouncycastle.math.ec.ECCurve;
+
+/**
+ * Test for ECKeyImplTest.
+ */
+public class ECKeyImplTest extends TestCase {
+
+ public ECKeyImplTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+ /**
+ * Test of getKeyGenerationParameters method, of class ECKeyImpl.
+ */
+ public void testGetKeyGenerationParameters() {
+ System.out.println("getKeyGenerationParameters");
+ SecureRandom rnd = new SecureRandom();
+ // public
+ ECKeyImpl instance = new ECPublicKeyImpl(KeyBuilder.TYPE_EC_F2M_PUBLIC, KeyBuilder.LENGTH_EC_F2M_193);
+ ECKeyGenerationParameters result = (ECKeyGenerationParameters) instance.getKeyGenerationParameters(rnd);
+ assertEquals(result.getDomainParameters().getCurve()instanceof ECCurve.F2m, true);
+ instance = new ECPublicKeyImpl(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_192);
+ result = (ECKeyGenerationParameters) instance.getKeyGenerationParameters(rnd);
+ assertEquals(result.getDomainParameters().getCurve()instanceof ECCurve.Fp, true);
+ //private
+ instance = new ECPrivateKeyImpl(KeyBuilder.TYPE_EC_F2M_PRIVATE, KeyBuilder.LENGTH_EC_F2M_193);
+ result = (ECKeyGenerationParameters) instance.getKeyGenerationParameters(rnd);
+ assertEquals(result.getDomainParameters().getCurve()instanceof ECCurve.F2m, true);
+ instance = new ECPrivateKeyImpl(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_192);
+ result = (ECKeyGenerationParameters) instance.getKeyGenerationParameters(rnd);
+ assertEquals(result.getDomainParameters().getCurve()instanceof ECCurve.Fp, true);
+ }
+
+}
diff --git a/src/test/java/com/licel/jcardsim/crypto/KeyAgreementImplTest.java b/src/test/java/com/licel/jcardsim/crypto/KeyAgreementImplTest.java
index 24acec16..7b094a7a 100644
--- a/src/test/java/com/licel/jcardsim/crypto/KeyAgreementImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/KeyAgreementImplTest.java
@@ -71,17 +71,20 @@ public void testGenerateSecret(byte keyAlg, short keySize, byte keyAgreementAlg)
ECPublicKey publicKey2 = (ECPublicKey) kp.getPublic();
// generate first secret
KeyAgreement ka = KeyAgreement.getInstance(keyAgreementAlg, false);
- byte[] secret1 = new byte[128];
+ byte[] secret1 = new byte[20];
byte[] public2 = new byte[128];
short publicKeyLength = publicKey2.getW(public2, (short) 0);
ka.init(privateKey1);
- ka.generateSecret(public2, (short) 0, publicKeyLength, secret1, (short) 0);
+ short secret1Size = ka.generateSecret(public2, (short) 0, publicKeyLength, secret1, (short) 0);
// generate second secret
- byte[] secret2 = new byte[128];
+ byte[] secret2 = new byte[20];
byte[] public1 = new byte[128];
publicKeyLength = publicKey1.getW(public1, (short) 0);
ka.init(privateKey2);
- ka.generateSecret(public1, (short) 0, publicKeyLength, secret2, (short) 0);
+ short secret2Size = ka.generateSecret(public1, (short) 0, publicKeyLength, secret2, (short) 0);
+ // sha1 size = 20
+ assertEquals(secret1Size, 20);
+ assertEquals(secret2Size, 20);
assertEquals(true, Arrays.areEqual(secret1, secret2));
}
}
\ No newline at end of file
diff --git a/src/test/java/com/licel/jcardsim/crypto/KeyPairImplTest.java b/src/test/java/com/licel/jcardsim/crypto/KeyPairImplTest.java
index 5a572b58..4ae6b432 100644
--- a/src/test/java/com/licel/jcardsim/crypto/KeyPairImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/KeyPairImplTest.java
@@ -16,6 +16,7 @@
*/
import java.util.Arrays;
+import javacard.framework.Util;
import javacard.security.DSAPrivateKey;
import javacard.security.DSAPublicKey;
import javacard.security.ECPrivateKey;
@@ -27,9 +28,7 @@
import javacard.security.RSAPrivateCrtKey;
import javacard.security.RSAPrivateKey;
import javacard.security.RSAPublicKey;
-import javax.xml.bind.DatatypeConverter;
import junit.framework.TestCase;
-import org.bouncycastle.util.encoders.Hex;
/**
* Test for KeyPairImpl
@@ -62,6 +61,32 @@ protected void tearDown() throws Exception {
super.tearDown();
}
+
+ public void testConstructor(){
+ testConstructorRSA(KeyPair.ALG_RSA);
+ testConstructorRSA(KeyPair.ALG_RSA_CRT);
+ }
+ /**
+ * Test of constructor RSA/RSA_CRT
+ */
+ private void testConstructorRSA(byte algo){
+ KeyPair instance = null;
+ byte[] expBuf = new byte[3];
+ byte[] customExp = new byte[]{0x03};
+ for (int i = 0; i < RSA_SIZES.length; i++) {
+ instance = new KeyPair(algo, RSA_SIZES[i]);
+ // https://github.com/licel/jcardsim/issues/42
+ PublicKey publicKey = instance.getPublic();
+ assertEquals(true, publicKey!=null);
+ assertEquals(true, publicKey instanceof RSAPublicKey);
+ ((RSAPublicKey)publicKey).setExponent(customExp, (short)0, (short)customExp.length);
+ instance.genKeyPair();
+ short expSize = ((RSAPublicKey)publicKey).getExponent(expBuf, (short) 0);
+ assertEquals(customExp.length, expSize);
+ assertEquals(0, Util.arrayCompare(expBuf, (short)0, customExp, (short) 0, expSize));
+ }
+ }
+
/**
* Test of genKeyPair method, of class KeyPairImpl.
* algorithm RSA - NXP JCOP not support this algorithm
@@ -116,6 +141,26 @@ public void testGenKeyPairRSAWithCustomPublicExponent() {
publicKey.getExponent(generatedExponent, (short)0);
assertEquals(Arrays.equals(customExponent, generatedExponent), true);
}
+
+ /**
+ * Test of genKeyPair method, of class KeyPairImpl.
+ * algorithm EC - NXP JCOP not support this algorithm
+ * for on-card key generation
+ */
+ public void testGenKeyPairECWithCustomDomainParameters() {
+ System.out.println("genKeyPair EC (Custom Domain Parameters)");
+ KeyPair instance = new KeyPair(KeyPair.ALG_EC_F2M, KeyBuilder.LENGTH_EC_F2M_193);
+ instance.genKeyPair();
+ ECPublicKey ecPublicKey = (ECPublicKey)instance.getPublic();
+ KeyPair instance1 = new KeyPair(ecPublicKey, null);
+ instance1.genKeyPair();
+ ECPublicKey ecPublicKey1 = (ECPublicKey)instance1.getPublic();
+ byte[] a = new byte[266];
+ byte[] a1 = new byte[266];
+ ecPublicKey.getA(a, (short)0);
+ ecPublicKey1.getA(a1, (short)0);
+ assertEquals(Arrays.equals(a, a1), true);
+ }
/**
* Test of genKeyPair method, of class KeyPairImpl.
diff --git a/src/test/java/com/licel/jcardsim/crypto/MessageDigestImplTest.java b/src/test/java/com/licel/jcardsim/crypto/MessageDigestImplTest.java
index 55ca986c..2d06f387 100644
--- a/src/test/java/com/licel/jcardsim/crypto/MessageDigestImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/MessageDigestImplTest.java
@@ -15,7 +15,8 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
+import java.security.SecureRandom;
+
import javacard.security.MessageDigest;
import junit.framework.TestCase;
import org.bouncycastle.util.Arrays;
@@ -26,7 +27,7 @@
* Test data from NXP JCOP31-36 JavaCard
*/
public class MessageDigestImplTest extends TestCase {
-
+
static final String MESSAGE1 = "F9607F6E66B4162C";
static final String MESSAGE2 = "26C69FC4C14399A399B5B28AD9CC5B91796BC2565C5580BAC1BE10808F71949D8B";
// card response with algorithm MD5
@@ -35,21 +36,44 @@ public class MessageDigestImplTest extends TestCase {
// card response with algorithm SHA1
static final String MD_1_NXP_SHA1 = "94FF92DC796929290990BA74F4B125F04F9B510A";
static final String MD_2_NXP_SHA1 = "01793FF98B954C3F60F276B179186C499F619A9D";
- MessageDigest engineMD5 = new MessageDigestImpl(MessageDigest.ALG_MD5);
- MessageDigest engineSHA1 = new MessageDigestImpl(MessageDigest.ALG_SHA);
-
+ // card response with algorithm SHA256
+ static final String MD_1_NXP_SHA256 = "E700E0E6E5A4F3FF05CCBD4DA9CDBBEC712189DE65EF1ED19C351F7966270EF0";
+ static final String MD_2_NXP_SHA256 = "17CB067C5E384B85DF370B96A5C91817D908F0C760CB2D7539EF8B9A7C02AB80";
+ // NIST SHA-384 SHA ETALON MESSAGES
+ static final String MESSAGE_64_NIST_SHA384 = "DE60275BDAFCE4B1";
+ static final String MESSAGE_256_NIST_SHA384 = "BE01E520E69F04174CCF95455B1C81445298264D9ADC4958574A52843D95B8BA";
+ // NIST SHA-384 ETALON DIGESTS
+ static final String MD_64_NIST_SHA384 = "A3D861D866C1362423EB21C6BEC8E44B74CE993C55BAA2B6640567560EBECDAEDA07183DBBBD95E0F522CAEE5DDBDAF0";
+ static final String MD_256_NIST_SHA384 = "C5CF54B8E3105B1C7BF7A43754D915B0947F28B6DC94A019182929B5C848E11441C9E4E90C7449F4C3CD12954F0F5D99";
+ // NIST SHA-512 ETALON MESSAGES
+ static final String MESSAGE_64_NIST_SHA512 = "6F8D58B7CAB1888C";
+ static final String MESSAGE_256_NIST_SHA512 = "8CCB08D2A1A282AA8CC99902ECAF0F67A9F21CFFE28005CB27FCF129E963F99D";
+ // NIST SHA-512 ETALON DIGESTS
+ static final String MD_64_NIST_SHA512 = "A3941DEF2803C8DFC08F20C06BA7E9A332AE0C67E47AE57365C243EF40059B11BE22C91DA6A80C2CFF0742A8F4BCD941BDEE0B861EC872B215433CE8DCF3C031";
+ static final String MD_256_NIST_SHA512 = "4551DEF2F9127386EEA8D4DAE1EA8D8E49B2ADD0509F27CCBCE7D9E950AC7DB01D5BCA579C271B9F2D806730D88F58252FD0C2587851C3AC8A0E72B4E1DC0DA6";
+
+
+ MessageDigestImpl engineMD5 = new MessageDigestImpl(MessageDigest.ALG_MD5);
+ MessageDigestImpl engineRIPEMD160 = new MessageDigestImpl(MessageDigest.ALG_RIPEMD160);
+ MessageDigestImpl engineSHA1 = new MessageDigestImpl(MessageDigest.ALG_SHA);
+ MessageDigestImpl engineSHA256 = new MessageDigestImpl(MessageDigest.ALG_SHA_256);
+ MessageDigestImpl engineSHA384 = new MessageDigestImpl(MessageDigest.ALG_SHA_384);
+ MessageDigestImpl engineSHA512 = new MessageDigestImpl(MessageDigest.ALG_SHA_512);
+
+ SecureRandom rnd = new SecureRandom();
+
public MessageDigestImplTest(String testName) {
super(testName);
}
-
+
protected void setUp() throws Exception {
super.setUp();
}
-
+
protected void tearDown() throws Exception {
super.tearDown();
}
-
+
/**
* Test of getAlgorithm method, of class MessageDigestImpl.
*/
@@ -63,24 +87,39 @@ public void testGetAlgorithm() {
expResult = MessageDigest.ALG_SHA;
result = engineSHA1.getAlgorithm();
assertEquals(expResult, result);
-
+ // sha256
+ expResult = MessageDigest.ALG_SHA_256;
+ result = engineSHA256.getAlgorithm();
+ assertEquals(expResult, result);
+ // sha384
+ expResult = MessageDigest.ALG_SHA_384;
+ result = engineSHA384.getAlgorithm();
+ assertEquals(expResult, result);
+ // sha512
+ expResult = MessageDigest.ALG_SHA_512;
+ result = engineSHA512.getAlgorithm();
+ assertEquals(expResult, result);
}
-
+
/**
* Test of getLength method, of class MessageDigestImpl.
*/
public void testGetLength() {
System.out.println("getLength");
// md5
- byte expResult = 16;
- byte result = engineMD5.getLength();
- assertEquals(expResult, result);
+ assertEquals(engineMD5.getLength(), MessageDigest.LENGTH_MD5);
+ // ripemd160
+ assertEquals(engineRIPEMD160.getLength(), MessageDigest.LENGTH_RIPEMD160);
// sha1
- expResult = 20;
- result = engineSHA1.getLength();
- assertEquals(expResult, result);
+ assertEquals(engineSHA1.getLength(), MessageDigest.LENGTH_SHA);
+ // sha256
+ assertEquals(engineSHA256.getLength(), MessageDigest.LENGTH_SHA_256);
+ // sha384
+ assertEquals(engineSHA384.getLength(), MessageDigest.LENGTH_SHA_384);
+ // sha512
+ assertEquals(engineSHA512.getLength(), MessageDigest.LENGTH_SHA_512);
}
-
+
/**
* Test MD5 algorithm with card response
*/
@@ -90,7 +129,7 @@ public void testMD5() {
System.out.println("test MD5 doUpdate() + doFinal()");
testEngineDoUpdateFinal(engineMD5, Hex.decode(MESSAGE2), Hex.decode(MD_2_NXP_MD5));
}
-
+
/**
* Test SHA1 algorithm with card response
*/
@@ -100,7 +139,37 @@ public void testSHA() {
System.out.println("test SHA1 doUpdate() + doFinal()");
testEngineDoUpdateFinal(engineSHA1, Hex.decode(MESSAGE2), Hex.decode(MD_2_NXP_SHA1));
}
-
+
+ /**
+ * Test SHA256 algorithm with card response
+ */
+ public void testSHA256() {
+ System.out.println("test SHA256 doFinal()");
+ testEngineDoFinal(engineSHA256, Hex.decode(MESSAGE1), Hex.decode(MD_1_NXP_SHA256));
+ System.out.println("test SHA256 doUpdate() + doFinal()");
+ testEngineDoUpdateFinal(engineSHA256, Hex.decode(MESSAGE2), Hex.decode(MD_2_NXP_SHA256));
+ }
+
+ /**
+ * Test SHA384 algorithm with card response
+ */
+ public void testSHA384() {
+ System.out.println("test SHA384 doFinal()");
+ testEngineDoFinal(engineSHA384, Hex.decode(MESSAGE_64_NIST_SHA384), Hex.decode(MD_64_NIST_SHA384));
+ System.out.println("test SHA384 doUpdate() + doFinal()");
+ testEngineDoUpdateFinal(engineSHA384, Hex.decode(MESSAGE_256_NIST_SHA384), Hex.decode(MD_256_NIST_SHA384));
+ }
+
+ /**
+ * Test SHA512 algorithm with card response
+ */
+ public void testSHA512() {
+ System.out.println("test SHA512 doFinal()");
+ testEngineDoFinal(engineSHA512, Hex.decode(MESSAGE_64_NIST_SHA512), Hex.decode(MD_64_NIST_SHA512));
+ System.out.println("test SHA512 doUpdate() + doFinal()");
+ testEngineDoUpdateFinal(engineSHA512, Hex.decode(MESSAGE_256_NIST_SHA512), Hex.decode(MD_256_NIST_SHA512));
+ }
+
/**
* Test method doFinal
* @param engine tested engine
@@ -108,11 +177,11 @@ public void testSHA() {
* @param etalonDigest byte array contains etalon digest
*/
public void testEngineDoFinal(MessageDigest engine, byte[] msg, byte[] etalonDigest) {
- byte[] digest = JCSystem.makeTransientByteArray(engine.getLength(), JCSystem.CLEAR_ON_RESET);
+ byte[] digest = new byte[engine.getLength()];
engine.doFinal(msg, (short) 0, (short) msg.length, digest, (short) 0);
assertEquals(true, Arrays.areEqual(etalonDigest, digest));
}
-
+
/**
* Test sequence method's calls doUpdate();doFinal()
* @param engine tested engine
@@ -120,9 +189,41 @@ public void testEngineDoFinal(MessageDigest engine, byte[] msg, byte[] etalonDig
* @param etalonDigest byte array contains etalon digest
*/
public void testEngineDoUpdateFinal(MessageDigest engine, byte[] msg, byte[] etalonDigest) {
- byte[] digest = JCSystem.makeTransientByteArray(engine.getLength(), JCSystem.CLEAR_ON_RESET);
+ byte[] digest = new byte[engine.getLength()];
engine.update(msg, (short) 0, (short) 7);
engine.doFinal(msg, (short) 7, (short) (msg.length - 7), digest, (short) 0);
assertEquals(true, Arrays.areEqual(etalonDigest, digest));
}
-}
+
+ /**
+ * Test of setInitialDigest method, of class MessageDigestImpl.
+ */
+ public void testSetInitialDigest() {
+ byte[] initialDigestBuf = new byte[128];
+ byte[] inputData = new byte[254];
+ rnd.nextBytes(inputData);
+
+ MessageDigestImpl[] digests = new MessageDigestImpl[]{engineSHA1, engineMD5, engineRIPEMD160,
+ engineSHA256, engineSHA384, engineSHA512};
+
+ for (short i = 0; i < digests.length; i++) {
+ System.out.println("testSetInitialDigest() - "+digests[i].getAlgorithm());
+ byte[] digest = new byte[digests[i].getLength()];
+ byte[] etalonDigest = new byte[digests[i].getLength()];
+ // calc first part
+ short part = digests[i].getBlockSize();
+ digests[i].update(inputData, (short) 0, part);
+ short initialDigestOff = (short) rnd.nextInt(initialDigestBuf.length - digests[i].getLength());
+ digests[i].getIntermediateDigest(initialDigestBuf, initialDigestOff);
+ // doFinal
+ digests[i].doFinal(inputData, part, (short) (inputData.length - part), digest, (short) 0);
+ // etalon
+ digests[i].reset();
+ digests[i].update(inputData, (short) 0, part);
+ digests[i].doFinal(inputData, part, (short) (inputData.length - part), etalonDigest, (short) 0);
+ assertEquals(true, Arrays.areEqual(etalonDigest, digest));
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/licel/jcardsim/crypto/RSACipherPKCS1Test.java b/src/test/java/com/licel/jcardsim/crypto/RSACipherPKCS1Test.java
index a1f048a3..f3868570 100644
--- a/src/test/java/com/licel/jcardsim/crypto/RSACipherPKCS1Test.java
+++ b/src/test/java/com/licel/jcardsim/crypto/RSACipherPKCS1Test.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.KeyBuilder;
import javacard.security.RandomData;
import javacard.security.RSAPrivateKey;
@@ -76,7 +75,7 @@ protected void tearDown() throws Exception {
}
/**
- * SelfTest of RSA Encryption/Decryption, of class AssymetricCipherImpl and ALG_RSA_PKCS1 algorithm implementation.
+ * SelfTest of RSA Encryption/Decryption, of class AsymmetricCipherImpl and ALG_RSA_PKCS1 algorithm implementation.
*/
public void testRSAPKCS1() {
Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false);
@@ -90,14 +89,14 @@ public void testRSAPKCS1() {
publicKey.setModulus(rsaPrivateKeyModulus, (short) 0,(short) rsaPrivateKeyModulus.length);
cipher.init(publicKey, Cipher.MODE_ENCRYPT);
- byte[] msg = JCSystem.makeTransientByteArray((short) 53, JCSystem.CLEAR_ON_RESET);
- byte[] encryptedMsg = JCSystem.makeTransientByteArray((short) 64, JCSystem.CLEAR_ON_RESET);
+ byte[] msg = new byte[53];
+ byte[] encryptedMsg = new byte[64];
RandomData rnd = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
rnd.generateData(msg, (short) 0, (short) msg.length);
cipher.doFinal(msg, (short) 0, (short) msg.length, encryptedMsg, (short) 0);
cipher.init(privateKey, Cipher.MODE_DECRYPT);
- byte[] decryptedMsg = JCSystem.makeTransientByteArray((short) msg.length, JCSystem.CLEAR_ON_RESET);
+ byte[] decryptedMsg = new byte[msg.length];
cipher.doFinal(encryptedMsg, (short) 0, (short) encryptedMsg.length, decryptedMsg, (short) 0);
assertEquals(true, Arrays.areEqual(msg, decryptedMsg));
diff --git a/src/test/java/com/licel/jcardsim/crypto/RSACipherTest.java b/src/test/java/com/licel/jcardsim/crypto/RSACipherTest.java
index 3904c46a..a2b477e7 100644
--- a/src/test/java/com/licel/jcardsim/crypto/RSACipherTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/RSACipherTest.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.KeyBuilder;
import javacard.security.RandomData;
import javacard.security.RSAPrivateKey;
@@ -76,7 +75,7 @@ protected void tearDown() throws Exception {
}
/**
- * SelfTest of RSA Encryption/Decryption, of class AssymetricCipherImpl and ByteContainer.getBigInteger() method.
+ * SelfTest of RSA Encryption/Decryption, of class AsymmetricCipherImpl and ByteContainer.getBigInteger() method.
*/
public void testSelfRSA() {
Cipher cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
@@ -90,14 +89,14 @@ public void testSelfRSA() {
publicKey.setModulus(rsaPrivateKeyModulus, (short) 0,(short) rsaPrivateKeyModulus.length);
cipher.init(publicKey, Cipher.MODE_ENCRYPT);
- byte[] msg = JCSystem.makeTransientByteArray((short) 63, JCSystem.CLEAR_ON_RESET);
- byte[] encryptedMsg = JCSystem.makeTransientByteArray((short) 64, JCSystem.CLEAR_ON_RESET);
+ byte[] msg = new byte[63];
+ byte[] encryptedMsg = new byte[64];
RandomData rnd = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
rnd.generateData(msg, (short) 0, (short) msg.length);
cipher.doFinal(msg, (short) 0, (short) msg.length, encryptedMsg, (short) 0);
cipher.init(privateKey, Cipher.MODE_DECRYPT);
- byte[] decryptedMsg = JCSystem.makeTransientByteArray((short) msg.length, JCSystem.CLEAR_ON_RESET);
+ byte[] decryptedMsg = new byte[msg.length];
cipher.doFinal(encryptedMsg, (short) 0, (short) encryptedMsg.length, decryptedMsg, (short) 0);
assertEquals(true, Arrays.areEqual(msg, decryptedMsg));
diff --git a/src/test/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImplTest.java b/src/test/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImplTest.java
new file mode 100644
index 00000000..ecffd639
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/crypto/RSAPrivateCrtKeyImplTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.crypto;
+
+import junit.framework.TestCase;
+import org.bouncycastle.util.encoders.Hex;
+
+/**
+ * Test for RSAPrivateCrtKeyImpl
+ * Test data from NXP JCOP31-36 JavaCard*
+ */
+public class RSAPrivateCrtKeyImplTest extends TestCase {
+ // RSA CRT Private Key Components (2048-bit)
+
+ final static String P = "DA2CBBE7572AE9441538EFE23943A6C72B564482E482D50954769920AD4A45179D2842327BF8271C592FA9D6DCCAE737B45BCA4A3B026CF5C32E6008284D8ABA3A1B249EF900CCF40746C599D9217EC3D1179DC35976AE05A50CF6F8AE23E15B8E0D4481D1D6035826AB7F43CECEB511699814BF2EFCF0EA37E230C4F586E6C7";
+ final static String Q = "A5CDB97E613BDE20D7938C102DBB1D4F3B7BE88A1E7919329F7207F044B2A1560FB370C742A7E15C5BBF77AC2463AB9C00B7FF2B765E1EECF4ED5F2F5DDA8476BCF6F154286154C4CC9C51FDEBEAFE8630D299A03AE306B7179D83328A1D18301E2C66AA94A802EB4FF34291C43E2BA4A3642965B5322DBBDCF5D016718070D7";
+ final static String DP = "AA732286557A87ED91EAFEB6ADE865A6DAFBB5E0D12849C9D53C26DBF9A6B99DFE41129EA06DBA1892B1032E8326DE478DD7DC8DEBD6344C3925C50EFA75C23945E628D12E566AC907DA49CCAD6F56BB236320F51AB2F6B8203FA5BF99451CEE4B67A02B1045F42CED6134B7441E08264769F2637F114C22A0704D8BC30A96C7";
+ final static String DQ = "94B23E9437F1B011B6246E2DA845B25077A1757841420BB619C6F395A896A7187EB648037C2501788A13D9E8B92DE61EDF8A243F3F45C3E870F45D3426B0ADB1AB60B027F09AF1A2197A6C1214BD488CE2464D5EA4D12C199205423F561C27B027AF5C57C940307606DABC2DEC58715D92E76634FFDEC3A342D3F54DDB76FC3B";
+ final static String PQ = "92CC66692E8D14EB93D0705EFA58276CD7A1A8B82C17544E8D181C3F987ED62E83355844D2E89380A17169614D8367709CB62A3DF9339BD537078AD1629D1B87DCA66E31809ADB78746633C28A6EA064B34EF750C27E32800ECE3C5F17524D35EE3CEAE8989745EAECD411D519210D4FCD699F4218A22249F76BE75A2F8160A0";
+
+ public RSAPrivateCrtKeyImplTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Test of isInitialized method, of class RSAPrivateCrtKeyImpl.
+ */
+ public void testIsInitialized() {
+ System.out.println("isInitialized");
+ RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl((short)2048);
+ short compLen = (short) Hex.decode(P).length;
+ key.setP(Hex.decode(P), (short)0, compLen);
+ key.setQ(Hex.decode(Q), (short)0, compLen);
+ key.setDP1(Hex.decode(DP), (short)0, compLen);
+ key.setDQ1(Hex.decode(DQ), (short)0, compLen);
+ key.setPQ(Hex.decode(PQ), (short)0, compLen);
+ assertEquals(true, key.isInitialized());
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/crypto/RandomDataImplTest.java b/src/test/java/com/licel/jcardsim/crypto/RandomDataImplTest.java
index 1f9c2165..ab6c06b9 100644
--- a/src/test/java/com/licel/jcardsim/crypto/RandomDataImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/RandomDataImplTest.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.security.RandomData;
import junit.framework.TestCase;
@@ -41,7 +40,7 @@ protected void tearDown() throws Exception {
*/
public void testGenerateData() {
System.out.println("generateData");
- byte[] buffer = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] buffer = new byte[8];
RandomData instance = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
instance.generateData(buffer, (short) 0, (short) buffer.length);
instance = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
@@ -53,7 +52,7 @@ public void testGenerateData() {
*/
public void testSetSeed() {
System.out.println("setSeed");
- byte[] buffer = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] buffer = new byte[8];
RandomData instance = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM);
instance.setSeed(buffer, (short) 0, (short) buffer.length);
instance.generateData(buffer, (short) 0, (short) buffer.length);
diff --git a/src/test/java/com/licel/jcardsim/crypto/SignatureMessageRecoveryTest.java b/src/test/java/com/licel/jcardsim/crypto/SignatureMessageRecoveryTest.java
new file mode 100644
index 00000000..16083409
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/crypto/SignatureMessageRecoveryTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2014 Licel LLC.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.licel.jcardsim.crypto;
+
+import javacard.framework.JCSystem;
+import javacard.security.KeyBuilder;
+import javacard.security.KeyPair;
+import javacard.security.RSAPrivateKey;
+import javacard.security.RSAPublicKey;
+import javacard.security.Signature;
+import javacard.security.SignatureMessageRecovery;
+import junit.framework.TestCase;
+
+/**
+ * SignatureMessageRecovery Test
+ * based on JCDK Sample
+ */
+public class SignatureMessageRecoveryTest extends TestCase {
+
+ //--RSA Keypair data
+ private static final byte[] RSA_PUB_KEY_EXP = {(byte) 0x01, (byte) 0x00, (byte) 0x01};
+ private static final byte[] RSA_PUB_PRIV_KEY_MOD = {(byte) 0xbe, (byte) 0xdf,
+ (byte) 0xd3, (byte) 0x7a, (byte) 0x08, (byte) 0xe2, (byte) 0x9a, (byte) 0x58,
+ (byte) 0x27, (byte) 0x54, (byte) 0x2a, (byte) 0x49, (byte) 0x18, (byte) 0xce,
+ (byte) 0xe4, (byte) 0x1a, (byte) 0x60, (byte) 0xdc, (byte) 0x62, (byte) 0x75,
+ (byte) 0xbd, (byte) 0xb0, (byte) 0x8d, (byte) 0x15, (byte) 0xa3, (byte) 0x65,
+ (byte) 0xe6, (byte) 0x7b, (byte) 0xa9, (byte) 0xdc, (byte) 0x09, (byte) 0x11,
+ (byte) 0x5f, (byte) 0x9f, (byte) 0xbf, (byte) 0x29, (byte) 0xe6, (byte) 0xc2,
+ (byte) 0x82, (byte) 0xc8, (byte) 0x35, (byte) 0x6b, (byte) 0x0f, (byte) 0x10,
+ (byte) 0x9b, (byte) 0x19, (byte) 0x62, (byte) 0xfd, (byte) 0xbd, (byte) 0x96,
+ (byte) 0x49, (byte) 0x21, (byte) 0xe4, (byte) 0x22, (byte) 0x08, (byte) 0x08,
+ (byte) 0x80, (byte) 0x6c, (byte) 0xd1, (byte) 0xde, (byte) 0xa6, (byte) 0xd3,
+ (byte) 0xc3, (byte) 0x8f};
+ private static final byte[] RSA_PRIV_KEY_EXP = {(byte) 0x84, (byte) 0x21,
+ (byte) 0xfe, (byte) 0x0b, (byte) 0xa4, (byte) 0xca, (byte) 0xf9, (byte) 0x7d,
+ (byte) 0xbc, (byte) 0xfc, (byte) 0x0e, (byte) 0xa9, (byte) 0xbb, (byte) 0x7a,
+ (byte) 0xbd, (byte) 0x7d, (byte) 0x65, (byte) 0x40, (byte) 0x2b, (byte) 0x08,
+ (byte) 0xc6, (byte) 0xdf, (byte) 0xc9, (byte) 0x4b, (byte) 0x09, (byte) 0x6a,
+ (byte) 0x29, (byte) 0x3b, (byte) 0xc2, (byte) 0x42, (byte) 0x88, (byte) 0x23,
+ (byte) 0x44, (byte) 0xaf, (byte) 0x08, (byte) 0x82, (byte) 0x4c, (byte) 0xff,
+ (byte) 0x42, (byte) 0xa4, (byte) 0xb8, (byte) 0xd2, (byte) 0xda, (byte) 0xcc,
+ (byte) 0xee, (byte) 0xc5, (byte) 0x34, (byte) 0xed, (byte) 0x71, (byte) 0x01,
+ (byte) 0xab, (byte) 0x3b, (byte) 0x76, (byte) 0xde, (byte) 0x6c, (byte) 0xa2,
+ (byte) 0xcb, (byte) 0x7c, (byte) 0x38, (byte) 0xb6, (byte) 0x9a, (byte) 0x4b,
+ (byte) 0x28, (byte) 0x01};
+ RSAPublicKey pubKey;
+ RSAPrivateKey privKey;
+ SignatureMessageRecovery sig;
+ KeyPair selfTestKeys;
+
+ /**
+ * Only this class's install method should create the applet object.
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ pubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_512, false);
+ privKey = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_512, false);
+ privKey.setExponent(RSA_PRIV_KEY_EXP, (short) 0, (short) RSA_PRIV_KEY_EXP.length);
+ privKey.setModulus(RSA_PUB_PRIV_KEY_MOD, (short) 0, (short) RSA_PUB_PRIV_KEY_MOD.length);
+ pubKey.setExponent(RSA_PUB_KEY_EXP, (short) 0, (short) RSA_PUB_KEY_EXP.length);
+ pubKey.setModulus(RSA_PUB_PRIV_KEY_MOD, (short) 0, (short) RSA_PUB_PRIV_KEY_MOD.length);
+ sig = (SignatureMessageRecovery) Signature.getInstance(Signature.ALG_RSA_SHA_ISO9796_MR, false);
+ selfTestKeys = new KeyPair(KeyPair.ALG_RSA_CRT, KeyBuilder.LENGTH_RSA_2048);
+ selfTestKeys.genKeyPair();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ *
+ */
+ public void testCryptoSignAndVerifyFullMsgRecovery() {
+ byte[] buffer = new byte[1];
+
+ sig.init(pubKey, Signature.MODE_VERIFY);
+ byte[] etalonSign = {(byte) 0xa3, (byte) 0x49, (byte) 0x1d, (byte) 0x51, (byte) 0x55,
+ (byte) 0x05, (byte) 0x49, (byte) 0x71, (byte) 0xba, (byte) 0xdc, (byte) 0x77, (byte) 0x22,
+ (byte) 0xce, (byte) 0x9a, (byte) 0x51, (byte) 0x71, (byte) 0xf8, (byte) 0xb1, (byte) 0x88,
+ (byte) 0x8d, (byte) 0x55, (byte) 0x05, (byte) 0xd5, (byte) 0x2b, (byte) 0xae, (byte) 0xf6,
+ (byte) 0xb7, (byte) 0x04, (byte) 0xd9, (byte) 0x1d, (byte) 0x09, (byte) 0x35, (byte) 0x17,
+ (byte) 0xec, (byte) 0x73, (byte) 0x11, (byte) 0xd5, (byte) 0x7f, (byte) 0xfd, (byte) 0xeb,
+ (byte) 0xb3, (byte) 0xd9, (byte) 0x98, (byte) 0x45, (byte) 0xf7, (byte) 0x8a, (byte) 0xb6,
+ (byte) 0x72, (byte) 0x21, (byte) 0x44, (byte) 0xa1, (byte) 0x32, (byte) 0xb3, (byte) 0xa1,
+ (byte) 0xce, (byte) 0x72, (byte) 0xc5, (byte) 0x6d, (byte) 0xcc, (byte) 0xee, (byte) 0x18,
+ (byte) 0x64, (byte) 0x2e, (byte) 0x76};
+
+ short m1Length = sig.beginVerify(etalonSign, (short) 0, (short) etalonSign.length);
+ boolean verified = sig.verify(buffer, (short) 0, (short) 0);
+
+ assertEquals(m1Length, 1);
+
+ assertEquals(true, verified);
+
+ }
+
+ public void testSelfCryptoSignAndVerifyFullMsgRecovery() {
+ byte[] data = new byte[41];
+ for (byte i = 0; i < data.length; i++) {
+ data[i] = i;
+ }
+ short[] m1Data = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_DESELECT);
+ byte[] signature = new byte[(short)256];
+
+ sig.init(selfTestKeys.getPrivate(), Signature.MODE_SIGN);
+ short sigLen = sig.sign(data, (short) 0, (short) data.length, signature, (short) 0, m1Data, (short) 0);
+
+ sig.init(selfTestKeys.getPublic(), Signature.MODE_VERIFY);
+ short m1Length = sig.beginVerify(signature, (short) 0, sigLen);
+
+ boolean verified = sig.verify(data, (short) 0, (short) 0);
+
+ assertEquals(m1Length, m1Data[0]);
+
+ assertEquals(true, verified);
+
+ }
+
+ public void testCryptoVerifyPartMsgRecovery() {
+ byte[] data = new byte[70];
+ for (byte i = 0; i < data.length; i++) {
+ data[i] = i;
+ }
+
+ byte[] etalonSign = new byte[]{(byte) 0x2d, (byte) 0x15, (byte) 0x79, (byte) 0x89,
+ (byte) 0xba, (byte) 0x71, (byte) 0x6d, (byte) 0x31, (byte) 0x6c, (byte) 0x0e, (byte) 0x29,
+ (byte) 0x55, (byte) 0xc0, (byte) 0x0e, (byte) 0x80, (byte) 0xc3, (byte) 0x5c, (byte) 0xa3,
+ (byte) 0xe8, (byte) 0xa1, (byte) 0x12, (byte) 0x65, (byte) 0xe3, (byte) 0x6f, (byte) 0xb2,
+ (byte) 0x51, (byte) 0x44, (byte) 0x7d, (byte) 0x30, (byte) 0x4a, (byte) 0x24, (byte) 0xcf,
+ (byte) 0xa1, (byte) 0x1b, (byte) 0xaa, (byte) 0x30, (byte) 0x48, (byte) 0xd3, (byte) 0x70,
+ (byte) 0x4a, (byte) 0x0b, (byte) 0xe7, (byte) 0x9a, (byte) 0x05, (byte) 0x1f, (byte) 0x5f,
+ (byte) 0x87, (byte) 0xc7, (byte) 0x8f, (byte) 0xe4, (byte) 0xae, (byte) 0xbc, (byte) 0xde,
+ (byte) 0x0a, (byte) 0x63, (byte) 0x6a, (byte) 0x28, (byte) 0x48, (byte) 0x52, (byte) 0xc0,
+ (byte) 0xe7, (byte) 0xd2, (byte) 0x7f, (byte) 0xfe};
+
+ //recover the recoverable message from signature
+ sig.init(pubKey, Signature.MODE_VERIFY);
+ short m1Length = sig.beginVerify(etalonSign, (short) 0, (short) etalonSign.length);
+
+ assertEquals(m1Length, 42);
+
+
+ byte[] etalonNonRecMsg = new byte[]{(byte) 0x2b, (byte) 0x2c, (byte) 0x2d, (byte) 0x2e,
+ (byte) 0x2f, (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x36,
+ (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x3b, (byte) 0x3c, (byte) 0x3d, (byte) 0x3e,
+ (byte) 0x3f, (byte) 0x40, (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46};
+
+ boolean verified = sig.verify(etalonNonRecMsg, (short) 0, (short) etalonNonRecMsg.length);
+ assertEquals(true, verified);
+
+ }
+
+ public void testSelfCCryptoVerifyPartMsgRecovery() {
+ byte[] data = new byte[(short)256];
+ for (short i = 0; i < data.length; i++) {
+ data[i] = (byte)i;
+ }
+ short[] m1Data = JCSystem.makeTransientShortArray((short) 1, JCSystem.CLEAR_ON_DESELECT);
+ byte[] signature = new byte[(short)256];
+
+ sig.init(selfTestKeys.getPrivate(), Signature.MODE_SIGN);
+ short sigLen = sig.sign(data, (short) 0, (short) data.length, signature, (short) 0, m1Data, (short) 0);
+
+ sig.init(selfTestKeys.getPublic(), Signature.MODE_VERIFY);
+ short m1Length = sig.beginVerify(signature, (short) 0, sigLen);
+
+ boolean verified = sig.verify(data, m1Length, (short) (data.length - m1Length));
+
+ assertEquals(m1Length, m1Data[0]);
+
+ assertEquals(true, verified);
+
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/crypto/SymmetricCipherImplTest.java b/src/test/java/com/licel/jcardsim/crypto/SymmetricCipherImplTest.java
index d5ed92b1..212ead99 100644
--- a/src/test/java/com/licel/jcardsim/crypto/SymmetricCipherImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/SymmetricCipherImplTest.java
@@ -15,7 +15,6 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.AESKey;
import javacard.security.Key;
@@ -97,19 +96,20 @@ public class SymmetricCipherImplTest extends TestCase {
// ALG_DES_CBC_NOPAD
"81B2369E2773858F"
};
- // AES test data from NIST
- // AESVS VarTxt test data for ECB (Key length: 128bit)
- String[] AES_ECB_128_TEST = {"00000000000000000000000000000000", "80000000000000000000000000000000", "3ad78e726c1ec02b7ebfe92b23d9ec34"};
- // AESVS VarTxt test data for ECB (Key length: 192bit)
- String[] AES_ECB_192_TEST = {"000000000000000000000000000000000000000000000000", "80000000000000000000000000000000", "6cd02513e8d4dc986b4afe087a60bd0c"};
- // AESVS VarTxt test data for ECB (Key length: 256bit)
- String[] AES_ECB_256_TEST = {"0000000000000000000000000000000000000000000000000000000000000000", "80000000000000000000000000000000", "ddc6bf790c15760d8d9aeb6f9a75fd4e"};
- // AESVS VarKey test data for CBC (Key length: 128bit)
- String[] AES_CBC_128_TEST = {"80000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "0edd33d3c621e546455bd8ba1418bec8"};
- // AESVS VarKey test data for CBC (Key length: 192bit)
- String[] AES_CBC_192_TEST = {"800000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "de885dc87f5a92594082d02cc1e1b42c"};
- // AESVS VarKey test data for CBC (Key length: 256bit)
- String[] AES_CBC_256_TEST = {"8000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "e35a6dcb19b201a01ebcfa8aa22b5759"};
+ // AES test data from NIST (sp800-38a)
+ // FORMAT: key:[iv]:data:result
+ // Appendix F.1
+ String[] AES_ECB_128_TEST = {"2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"};
+ // Appendix F.1.3
+ String[] AES_ECB_192_TEST = {"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"};
+ // Appendix F.1.5
+ String[] AES_ECB_256_TEST = {"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"};
+ // Appendix F.2.1
+ String[] AES_CBC_128_TEST = {"2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"};
+ // Appendix F.2.3
+ String[] AES_CBC_192_TEST = {"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172a", "4f021db243bc633d7178183a9fa071e8"};
+ // Appendix F.2.5
+ String[] AES_CBC_256_TEST = {"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "000102030405060708090a0b0c0d0e0f", "6bc1bee22e409f96e93d7e117393172a", "f58c4c04d6e5f1ba779eabfb5f7bfbd6"};
public SymmetricCipherImplTest(String testName) {
super(testName);
@@ -213,7 +213,12 @@ public void testAESMode(short keyLen, byte mode, String[] testData) {
short processedBytes = engine.doFinal(Hex.decode(testData[needIV?2:1]), (short) 0, (short) 16, encrypted, (short) 0);
assertEquals(processedBytes, 16);
assertEquals(true, Arrays.areEqual(encrypted, Hex.decode(testData[needIV?3:2])));
- engine.init(aesKey, Cipher.MODE_DECRYPT);
+ if (needIV) {
+ byte[] iv = Hex.decode(testData[1]);
+ engine.init(aesKey, Cipher.MODE_DECRYPT, iv, (short)0, (short)iv.length);
+ } else {
+ engine.init(aesKey, Cipher.MODE_DECRYPT);
+ }
byte[] decrypted = new byte[16]; // AES 128
processedBytes = engine.doFinal(Hex.decode(testData[needIV?3:2]), (short) 0, (short) 16, decrypted, (short) 0);
assertEquals(processedBytes, 16);
@@ -237,7 +242,7 @@ public void testEngineDoFinal(Cipher engine, Key key, byte[] iv, byte[] msg, byt
} else {
engine.init(key, Cipher.MODE_ENCRYPT, iv, (short) 0, (short) iv.length);
}
- byte[] encrypted = JCSystem.makeTransientByteArray((short) encryptedEtalonMsg.length, JCSystem.CLEAR_ON_RESET);
+ byte[] encrypted = new byte[encryptedEtalonMsg.length];
short processedBytes = engine.doFinal(msg, (short) 0, (short) msg.length, encrypted, (short) 0);
assertEquals(true, Arrays.areEqual(encrypted, encryptedEtalonMsg));
assertEquals(processedBytes, encryptedEtalonMsg.length);
@@ -247,7 +252,7 @@ public void testEngineDoFinal(Cipher engine, Key key, byte[] iv, byte[] msg, byt
} else {
engine.init(key, Cipher.MODE_DECRYPT, iv, (short) 0, (short) iv.length);
}
- byte[] decrypted = JCSystem.makeTransientByteArray((short) msg.length, JCSystem.CLEAR_ON_RESET);
+ byte[] decrypted = new byte[msg.length];
processedBytes = engine.doFinal(encryptedEtalonMsg, (short) 0, (short) encryptedEtalonMsg.length, decrypted, (short) 0);
assertEquals(processedBytes, msg.length);
assertEquals(true, Arrays.areEqual(decrypted, msg));
diff --git a/src/test/java/com/licel/jcardsim/crypto/SymmetricKeyImplTest.java b/src/test/java/com/licel/jcardsim/crypto/SymmetricKeyImplTest.java
index 0cad46cf..439f7754 100644
--- a/src/test/java/com/licel/jcardsim/crypto/SymmetricKeyImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/SymmetricKeyImplTest.java
@@ -15,12 +15,10 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.AESKey;
import javacard.security.KeyBuilder;
import junit.framework.TestCase;
-import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.util.Arrays;
@@ -48,7 +46,7 @@ protected void tearDown() throws Exception {
public void testClearKey() {
System.out.println("clearKey");
SymmetricKeyImpl desKey = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES);
- byte[] key = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] key = new byte[8];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
desKey.setKey(key, (short) 0);
desKey.clearKey();
@@ -61,7 +59,7 @@ public void testClearKey() {
public void testSetKey() {
System.out.println("setKey");
SymmetricKeyImpl desKey = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES);
- byte[] key = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] key = new byte[8];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
desKey.setKey(key, (short) 0);
assertEquals(true, desKey.isInitialized());
@@ -73,10 +71,10 @@ public void testSetKey() {
public void testGetKey() {
System.out.println("getKey");
SymmetricKeyImpl desKey = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES);
- byte[] key = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] key = new byte[8];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
desKey.setKey(key, (short) 0);
- byte[] testKey = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] testKey = new byte[8];
desKey.getKey(testKey, (short) 0);
assertEquals(true, Arrays.areEqual(testKey, key));
}
@@ -88,31 +86,31 @@ public void testGetCipher() {
System.out.println("getCipher");
// des key
SymmetricKeyImpl desKey = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES);
- byte[] key = JCSystem.makeTransientByteArray((short) 8, JCSystem.CLEAR_ON_RESET);
+ byte[] key = new byte[8];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
desKey.setKey(key, (short) 0);
boolean isValidCipher = (desKey.getCipher() instanceof DESEngine);
assertEquals(true, isValidCipher);
// 3des key
SymmetricKeyImpl des3Key = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY);
- key = JCSystem.makeTransientByteArray((short) 24, JCSystem.CLEAR_ON_RESET);
+ key = new byte[24];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
des3Key.setKey(key, (short) 0);
isValidCipher = (des3Key.getCipher() instanceof DESedeEngine);
assertEquals(true, isValidCipher);
// aes key - 128
AESKey aesKey = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
- key = JCSystem.makeTransientByteArray((short) 16, JCSystem.CLEAR_ON_RESET);
+ key = new byte[16];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
aesKey.setKey(key, (short) 0);
// aes key - 192
aesKey = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_192, false);
- key = JCSystem.makeTransientByteArray((short) 24, JCSystem.CLEAR_ON_RESET);
+ key = new byte[24];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
aesKey.setKey(key, (short) 0);
// aes key - 256
aesKey = (AESKey)KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
- key = JCSystem.makeTransientByteArray((short) 32, JCSystem.CLEAR_ON_RESET);
+ key = new byte[32];
Util.arrayFillNonAtomic(key, (short) 0, (short) key.length, (byte) 7);
aesKey.setKey(key, (short) 0);
// aes key - 256
diff --git a/src/test/java/com/licel/jcardsim/crypto/SymmetricSignatureImplTest.java b/src/test/java/com/licel/jcardsim/crypto/SymmetricSignatureImplTest.java
index e326ef5d..2a475c68 100644
--- a/src/test/java/com/licel/jcardsim/crypto/SymmetricSignatureImplTest.java
+++ b/src/test/java/com/licel/jcardsim/crypto/SymmetricSignatureImplTest.java
@@ -15,7 +15,7 @@
*/
package com.licel.jcardsim.crypto;
-import javacard.framework.JCSystem;
+import javacard.security.HMACKey;
import javacard.security.Key;
import javacard.security.KeyBuilder;
import javacard.security.Signature;
@@ -24,8 +24,9 @@
import org.bouncycastle.util.encoders.Hex;
/**
- * Test for SymmetricSignatureImpl
- * Test data from NXP JCOP31-36 JavaCard
+ * Test for
+ * SymmetricSignatureImpl
+ * Test data from NXP JCOP31-36/41 JavaCard
*/
public class SymmetricSignatureImplTest extends TestCase {
@@ -51,7 +52,10 @@ public class SymmetricSignatureImplTest extends TestCase {
// ALG_DES_MAC8_ISO9797_M1
"165DD117D24198B1",
// ALG_DES_MAC8_ISO9797_M2
- "C8D247D6209E2E44",};
+ "C8D247D6209E2E44",
+ // ALG_DES_MAC8_ISO9797_1_M2_ALG3
+ "706CAC8246DE7427",
+ };
// MESSAGE_15 MAC by card (DES key) with non-zero IV
String[] DES_MAC_15_IV = new String[]{
// ALG_DES_MAC8_ISO9797_M1
@@ -82,6 +86,214 @@ public class SymmetricSignatureImplTest extends TestCase {
// ALG_DES_MAC8_NOPAD
"81B2369E2773858F"
};
+ // etalon message for AES-CBC
+ String MESSAGE_16 = "6BC1BEE22E409F96E93D7E117393172A";
+ // etalon aes 128 key
+ String AES_128_KEY = "2B7E151628AED2A6ABF7158809CF4F3C";
+ // etalon mac
+ String AES_CBC_MAC = "3AD77BB40D7A3660A89ECAF32466EF97";
+ // hmac test vectors
+ // {SIGNATUTE_ID, ..}
+ byte[] HMAC_IDS = {
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_RIPEMD160,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_MD5,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA1,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ Signature.ALG_HMAC_SHA_256,
+ Signature.ALG_HMAC_SHA_384,
+ Signature.ALG_HMAC_SHA_512,
+ };
+ // {KEY, TEXT, MAC}, ..
+ String[][] HMAC_TESTS = {
+ // RFC - 2286 HMAC-RIPEMD160 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "24CB4BD67D20FC1A5D2ED7732DCC39377F0A5668"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "DDA6C0213A485A9E24F4742064A7F033B43C4069"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "B0B105360DE759960AB4F35298E116E295D8E7C1"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 4
+ {"0102030405060708090A0B0C0D0E0F10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "D5CA862F4D21D5E610E18B4CF1BEB97A4365ECF4"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 5
+ {"0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C",
+ "546573742057697468205472756E636174696F6E",
+ "7619693978F91D90539AE786500FF3D8E0518E39"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "6466CA07AC5EAC29E1BD523E5ADA7605B791FD8B"},
+ // RFC - 2286 HMAC-RIPEMD160 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B657920616E64204C6172676572205468616E204F6E6520426C6F636B2D53697A652044617461",
+ "69EA60798D71616CCE5FD0871E23754CD75D5A0A"},
+ // RFC - 2202 HMAC-MD5 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "9294727A3638BB1C13F48EF8158BFC9D"},
+ // RFC - 2202 HMAC-MD5 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "750C783E6AB0B503EAA86E310A5DB738"},
+ // RFC - 2202 HMAC-MD5 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "56BE34521D144C88DBB8C733F0E8B3F6"},
+ // RFC - 2202 HMAC-MD5 test case 4
+ {"0102030405060708090A0B0C0D0E0F10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "697EAF0ACA3A3AEA3A75164746FFAA79"},
+ // RFC - 2202 HMAC-MD5 test case 5
+ {"0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C",
+ "546573742057697468205472756E636174696F6E",
+ "56461EF2342EDC00F9BAB995690EFD4C"},
+ // RFC - 2202 HMAC-MD5 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "6B1AB7FE4BD7BF8F0B62E6CE61B9D0CD"},
+ // RFC - 2202 HMAC-MD5 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B657920616E64204C6172676572205468616E204F6E6520426C6F636B2D53697A652044617461",
+ "6F630FAD67CDA0EE1FB1F562DB3AA53E"},
+ // RFC - 2202 HMAC-SHA1 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "B617318655057264E28BC0B6FB378C8EF146BE00"},
+ // RFC - 2202 HMAC-SHA1 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79"},
+ // RFC - 2202 HMAC-SHA1 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "125D7342B9AC11CD91A39AF48AA17B4F63F175D3"},
+ // RFC - 2202 HMAC-SHA1 test case 4
+ {"0102030405060708090A0B0C0D0E0F10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "4C9007F4026250C6BC8414F9BF50C86C2D7235DA"},
+ // RFC - 2202 HMAC-SHA1 test case 5
+ {"0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C",
+ "546573742057697468205472756E636174696F6E",
+ "4C1A03424B55E07FE7F27BE1D58BB9324A9A5A04"},
+ // RFC - 2202 HMAC-SHA1 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "AA4AE5E15272D00E95705637CE8A3B55ED402112"},
+ // RFC - 2202 HMAC-SHA1 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B657920616E64204C6172676572205468616E204F6E6520426C6F636B2D53697A652044617461",
+ "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91"},
+ // RFC - 4231 HMAC-SHA-256 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32CFF7"},
+ // RFC - 4231 HMAC-SHA-384 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEBC59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6"},
+ // RFC - 4231 HMAC-SHA-512 test case 1
+ {"0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B",
+ "4869205468657265",
+ "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E17CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C203A126854"},
+ // RFC - 4231 HMAC-SHA-256 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC3843"},
+ // RFC - 4231 HMAC-SHA-384 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322445E8E2240CA5E69E2C78B3239ECFAB21649"},
+ // RFC - 4231 HMAC-SHA-512 test case 2
+ {"4A656665",
+ "7768617420646F2079612077616E7420666F72206E6F7468696E673F",
+ "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA2505549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A38BCE737"},
+ // RFC - 4231 HMAC-SHA-256 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED565FE"},
+ // RFC - 4231 HMAC-SHA-384 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966144B2A5AB39DC13814B94E3AB6E101A34F27"},
+ // RFC - 4231 HMAC-SHA-512 test case 3
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
+ "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B2279D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859E13292FB"},
+ // RFC - 4231 HMAC-SHA-256 test case 4
+ {"0102030405060708090A0B0C0D0E0F10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729665B"},
+ // RFC - 4231 HMAC-SHA-384 test case 4
+ {"0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F573B4E6801DD23C4A7D679CCF8A386C674CFFB"},
+ // RFC - 4231 HMAC-SHA-512 test case 4
+ {"0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD",
+ "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361EE3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB10A298DD"},
+ // RFC - 4231 HMAC-SHA-256 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE37F54"},
+ // RFC - 4231 HMAC-SHA-384 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033AC4C60C2EF6AB4030FE8296248DF163F44952"},
+ // RFC - 4231 HMAC-SHA-512 test case 6
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "54657374205573696E67204C6172676572205468616E20426C6F636B2D53697A65204B6579202D2048617368204B6579204669727374",
+ "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A985D786598"},
+ // RFC - 4231 HMAC-SHA-256 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "5468697320697320612074657374207573696E672061206C6172676572207468616E20626C6F636B2D73697A65206B657920616E642061206C6172676572207468616E20626C6F636B2D73697A6520646174612E20546865206B6579206E6565647320746F20626520686173686564206265666F7265206265696E6720757365642062792074686520484D414320616C676F726974686D2E",
+ "9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A35E2"},
+ // RFC - 4231 HMAC-SHA-384 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "5468697320697320612074657374207573696E672061206C6172676572207468616E20626C6F636B2D73697A65206B657920616E642061206C6172676572207468616E20626C6F636B2D73697A6520646174612E20546865206B6579206E6565647320746F20626520686173686564206265666F7265206265696E6720757365642062792074686520484D414320616C676F726974686D2E",
+ "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E99C5A678CC31E799176D3860E6110C46523E"},
+ // RFC - 4231 HMAC-SHA-512 test case 7
+ {"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ "5468697320697320612074657374207573696E672061206C6172676572207468616E20626C6F636B2D73697A65206B657920616E642061206C6172676572207468616E20626C6F636B2D73697A6520646174612E20546865206B6579206E6565647320746F20626520686173686564206265666F7265206265696E6720757365642062792074686520484D414320616C676F726974686D2E",
+ "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CDC944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440FA8C6A58"},
+ };
public SymmetricSignatureImplTest(String testName) {
super(testName);
@@ -105,6 +317,18 @@ public void testSignVerify3DES() {
DES3_MAC_15, DES3_MAC_8_IV, DES3_MAC_15_IV);
}
+ /**
+ * Test of sign/verify methods, of class SymmetricSignatureImpl with 2-key 3DES
+ */
+ public void testSignVerify2x3DES() {
+ SymmetricKeyImpl desKey = new SymmetricKeyImpl(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_2KEY);
+ desKey.setKey(Hex.decode(DES3_KEY), (short) 0);
+
+ Signature engine = Signature.getInstance(Signature.ALG_DES_MAC8_ISO9797_1_M2_ALG3, false);
+ testEngineSignVerify(engine, desKey, null, Hex.decode(MESSAGE_15), Hex.decode(DES3_MAC_15[2]));
+
+ }
+
/**
* Test of sign/verifys methods, of class SymmetricSignatureImpl with DES Key
*/
@@ -115,6 +339,29 @@ public void testSignVerifyDES() {
DES_MAC_15, DES_MAC_8_IV, DES_MAC_15_IV);
}
+ /**
+ * Test of sign/verifys methods, of class SymmetricSignatureImpl with AES Key
+ */
+ public void testSignVerifyAES() {
+ SymmetricKeyImpl aesKey = new SymmetricKeyImpl(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128);
+ aesKey.setKey(Hex.decode(AES_128_KEY), (short) 0);
+ Signature engine = Signature.getInstance(Signature.ALG_AES_MAC_128_NOPAD, false);
+ testEngineSignVerify(engine, aesKey, null, Hex.decode(MESSAGE_16), Hex.decode(AES_CBC_MAC));
+ }
+
+ /**
+ * Test of sign/verifys methods, of class SymmetricSignatureImpl with HMAC Key
+ */
+ public void testSignVerifyHMAC() {
+ for (int i = 0; i < HMAC_IDS.length; i++) {
+ byte[] hmacKeyBytes = Hex.decode(HMAC_TESTS[i][0]);
+ HMACKey hmacKey = (HMACKey)KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short)hmacKeyBytes.length, false);
+ hmacKey.setKey(hmacKeyBytes, (short) 0, (short)hmacKeyBytes.length);
+ Signature engine = Signature.getInstance(HMAC_IDS[i], false);
+ testEngineSignVerify(engine, hmacKey, null, Hex.decode(HMAC_TESTS[i][1]), Hex.decode(HMAC_TESTS[i][2]));
+ }
+ }
+
/**
* Test of sign/verify methods, of class SymmetricSignatureImpl with specified key
* and etalon data
@@ -131,7 +378,7 @@ public void testSignVerify(SymmetricKeyImpl desKey, String msg8, String msg15,
engine = Signature.getInstance(Signature.ALG_DES_MAC8_ISO9797_M2, false);
testEngineSignVerify(engine, desKey, null, Hex.decode(msg15), Hex.decode(enc15[1]));
-
+
// test DES MAC CBC with non-zero IV
byte[] iv = Hex.decode(IV);
engine = Signature.getInstance(Signature.ALG_DES_MAC8_NOPAD, false);
@@ -160,7 +407,7 @@ public void testEngineSignVerify(Signature engine, Key key, byte[] iv, byte[] ms
} else {
engine.init(key, Signature.MODE_SIGN, iv, (short) 0, (short) iv.length);
}
- byte[] mac = JCSystem.makeTransientByteArray((short) macEtalon.length, JCSystem.CLEAR_ON_RESET);
+ byte[] mac = new byte[macEtalon.length];
//
engine.sign(msg, (short) 0, (short) msg.length, mac, (short) 0);
assertEquals(true, Arrays.areEqual(mac, macEtalon));
diff --git a/src/test/java/com/licel/jcardsim/remote/JavaCardRemoteServerTest.java b/src/test/java/com/licel/jcardsim/remote/JavaCardRemoteServerTest.java
new file mode 100644
index 00000000..a2249446
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/remote/JavaCardRemoteServerTest.java
@@ -0,0 +1,38 @@
+package com.licel.jcardsim.remote;
+
+import com.licel.jcardsim.utils.AIDUtil;
+import javacard.framework.AID;
+import junit.framework.TestCase;
+import org.bouncycastle.util.Arrays;
+
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+
+public class JavaCardRemoteServerTest extends TestCase {
+ private static final String TEST_APPLET_AID = "010203040506070809";
+ private static final String TEST_APPLET_CLASS = "com.licel.jcardsim.samples.HelloWorldApplet";
+
+ public JavaCardRemoteServerTest(String name) {
+ super(name);
+ }
+
+ public void testServer() throws RemoteException, NotBoundException, InterruptedException {
+ System.out.println("testServer ...");
+ System.setProperty("com.licel.jcardsim.card.applet.0.AID", TEST_APPLET_AID);
+ System.setProperty("com.licel.jcardsim.card.applet.0.Class", TEST_APPLET_CLASS);
+
+ String host = "127.0.0.1";
+ int port = 7777;
+ new JavaCardRemoteServer(host, port);
+ JavaCardRemoteClient client = new JavaCardRemoteClient(host, port);
+
+ final AID aid = AIDUtil.create(TEST_APPLET_AID);
+ client.createApplet(aid, new byte[0], (short) 0, (byte) 0);
+
+ assertEquals(true, client.selectApplet(aid));
+ // test NOP
+ byte[] response = client.transmitCommand(new byte[]{0x01, 0x02, 0x00, 0x00});
+ assertEquals(Arrays.areEqual(new byte[]{(byte) 0x90, 0x00}, response), true);
+ System.out.println("testServer ... done");
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/smartcardio/CardTerminalSimulatorTest.java b/src/test/java/com/licel/jcardsim/smartcardio/CardTerminalSimulatorTest.java
new file mode 100644
index 00000000..17ef56cf
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/smartcardio/CardTerminalSimulatorTest.java
@@ -0,0 +1,325 @@
+package com.licel.jcardsim.smartcardio;
+
+import com.licel.jcardsim.utils.AutoResetEvent;
+import javacard.framework.ISO7816;
+import junit.framework.TestCase;
+import org.bouncycastle.util.encoders.Hex;
+
+import javax.smartcardio.*;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class CardTerminalSimulatorTest extends TestCase {
+ private static final ATR ETALON_ATR = new ATR(Hex.decode("3BFA1800008131FE454A434F5033315632333298"));
+ private static final String TEST_APPLET_AID = "010203040506070809";
+
+ public CardTerminalSimulatorTest(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ System.setProperty("com.licel.jcardsim.card.applet.0.AID", TEST_APPLET_AID);
+ System.setProperty("com.licel.jcardsim.card.applet.0.Class", "com.licel.jcardsim.samples.HelloWorldApplet");
+ }
+
+ public void testCreateSingleTerminal() throws CardException, InterruptedException {
+ final AutoResetEvent autoResetEvent = new AutoResetEvent();
+
+ // get instance
+ final CardTerminals terminals = CardTerminalSimulator.terminals("my terminal");
+ final CardTerminal terminal = terminals.getTerminal("my terminal");
+
+ // create and insert card
+ CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+ assertSame(terminal, cardSimulator.getAssignedCardTerminal());
+
+ // connect to card
+ Card card = terminal.connect("T=1");
+ test(card);
+
+ // assign same card
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ if (terminals.waitForChange(0)) {
+ autoResetEvent.signal();
+ }
+ } catch (CardException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }.start();
+ cardSimulator.assignToTerminal(terminal);
+ assertTrue(autoResetEvent.await(1, TimeUnit.SECONDS));
+ assertSame(terminal, cardSimulator.getAssignedCardTerminal());
+
+ // assign different card
+ CardSimulator cardSimulator2 = new CardSimulator();
+ assertNull(cardSimulator2.getAssignedCardTerminal());
+ cardSimulator2.assignToTerminal(terminal);
+
+ assertSame(terminal, cardSimulator2.getAssignedCardTerminal());
+ assertNull(cardSimulator.getAssignedCardTerminal());
+ }
+
+ public void testCreateTerminals() throws CardException {
+ // get instance
+ CardTerminals terminals = CardTerminalSimulator.terminals("terminal #1", "terminal #2");
+ CardTerminal terminal = terminals.getTerminal("terminal #2");
+
+ // create and insert card
+ CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+
+ // connect to card
+ Card card = terminal.connect("T=1");
+ test(card);
+ }
+
+ public void testProvider() throws CardException, NoSuchAlgorithmException {
+ // register security provider
+ if (Security.getProvider("CardTerminalSimulator") == null) {
+ Security.addProvider(new CardTerminalSimulator.SecurityProvider());
+ }
+
+ // get instance
+ TerminalFactory tf = TerminalFactory.getInstance("CardTerminalSimulator", null);
+ CardTerminals terminals = tf.terminals();
+ CardTerminal terminal = terminals.getTerminal("jCardSim.Terminal");
+
+ // create and insert card
+ CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+
+ // connect to card
+ Card card = terminal.connect("T=1");
+ test(card);
+ }
+
+ public void testProviderCustomNames() throws CardException, NoSuchAlgorithmException {
+ // register security provider
+ if (Security.getProvider("CardTerminalSimulator") == null) {
+ Security.addProvider(new CardTerminalSimulator.SecurityProvider());
+ }
+
+ // get instance
+ TerminalFactory tf = TerminalFactory.getInstance("CardTerminalSimulator", new String[]{"x", "y"});
+ CardTerminals terminals = tf.terminals();
+ CardTerminal terminal = terminals.getTerminal("y");
+
+ // create and insert card
+ CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+
+ // connect to card
+ Card card = terminal.connect("T=1");
+
+ test(card);
+ assertEquals(2, terminals.list().size());
+ assertEquals("x", terminals.list().get(0).getName());
+ assertEquals("y", terminals.list().get(1).getName());
+ }
+
+ public void testWaitForInsert() throws CardException, InterruptedException {
+ final AutoResetEvent autoResetEvent = new AutoResetEvent();
+ final CardTerminals terminals = CardTerminalSimulator.terminals("my terminal");
+ final CardTerminal terminal = terminals.getTerminal("my terminal");
+ assertEquals(true, terminal.waitForCardAbsent(1));
+ assertEquals(false, terminal.waitForCardPresent(1));
+
+ final CardSimulator cardSimulator = new CardSimulator();
+ new Thread() {
+ @Override
+ public void run() {
+ cardSimulator.assignToTerminal(terminal);
+ autoResetEvent.signal();
+ }
+ }.start();
+
+ autoResetEvent.await(1, TimeUnit.MINUTES);
+ assertEquals(true, terminal.waitForCardPresent(1));
+
+ // connect to card
+ Card card = terminal.connect("T=1");
+ test(card);
+ }
+
+ public void testWaitForCardAbsent() throws CardException, InterruptedException {
+ final CardTerminals terminals = CardTerminalSimulator.terminals("my terminal");
+ final CardTerminal terminal = terminals.getTerminal("my terminal");
+
+ final CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+
+ assertEquals(true, terminal.waitForCardPresent(1));
+ assertEquals(false, terminal.waitForCardAbsent(1));
+
+ new Thread() {
+ @Override
+ public void run() {
+ cardSimulator.assignToTerminal(null);
+ }
+ }.start();
+
+ assertEquals(true, terminal.waitForCardAbsent(0));
+ }
+
+ public void testWaitForCardChange() throws CardException, InterruptedException {
+ final CardTerminals terminals = CardTerminalSimulator.terminals("my terminal");
+
+ final CardSimulator cardSimulator = new CardSimulator();
+ assertEquals(false, terminals.waitForChange(1));
+
+ CardTerminal terminal = terminals.getTerminal("my terminal");
+ cardSimulator.assignToTerminal(terminal);
+
+ assertEquals(true, terminals.waitForChange(1));
+ assertEquals(false, terminals.waitForChange(1));
+ cardSimulator.assignToTerminal(null);
+ assertEquals(true, terminals.waitForChange(1));
+ }
+
+ public void testList() throws CardException, InterruptedException {
+ final CardTerminals terminals = CardTerminalSimulator.terminals("1", "2", "3", "4");
+
+ CardTerminal terminal1 = terminals.getTerminal("1");
+
+ assertEquals(4, terminals.list().size());
+ assertEquals(4, terminals.list(CardTerminals.State.ALL).size());
+
+ CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal1);
+ assertTrue(terminal1.isCardPresent());
+ assertEquals(3, terminals.list(CardTerminals.State.CARD_ABSENT).size());
+ assertEquals(3, terminals.list(CardTerminals.State.CARD_REMOVAL).size());
+ assertEquals(0, terminals.list(CardTerminals.State.CARD_PRESENT).size());
+ assertEquals(1, terminals.list(CardTerminals.State.CARD_INSERTION).size());
+ assertEquals(0, terminals.list(CardTerminals.State.CARD_PRESENT).size());
+
+ assertEquals(true, terminals.waitForChange(1));
+ assertEquals(1, terminals.list(CardTerminals.State.CARD_INSERTION).size());
+ assertEquals(0, terminals.list(CardTerminals.State.CARD_REMOVAL).size());
+
+ cardSimulator.assignToTerminal(null);
+ assertFalse(terminal1.isCardPresent());
+ assertEquals(true, terminals.waitForChange(1));
+
+ assertEquals(4, terminals.list(CardTerminals.State.ALL).size());
+ assertEquals(3, terminals.list(CardTerminals.State.CARD_ABSENT).size());
+ assertEquals(1, terminals.list(CardTerminals.State.CARD_REMOVAL).size());
+
+ assertEquals(0, terminals.list(CardTerminals.State.CARD_INSERTION).size());
+ assertEquals(0, terminals.list(CardTerminals.State.CARD_PRESENT).size());
+ assertEquals(4, terminals.list(CardTerminals.State.CARD_ABSENT).size());
+ }
+
+ public void testExclusive() throws CardException, InterruptedException {
+ final CardTerminal terminal = CardTerminalSimulator.terminal(new CardSimulator());
+ final AutoResetEvent autoResetEvent = new AutoResetEvent();
+ final AtomicBoolean gotException = new AtomicBoolean(false);
+
+ final CardSimulator cardSimulator = new CardSimulator();
+ cardSimulator.assignToTerminal(terminal);
+ final Card card = terminal.connect("T=1");
+ final CommandAPDU commandAPDU = new CommandAPDU(0, 0, 0, 0);
+
+ card.beginExclusive();
+ card.getBasicChannel().transmit(commandAPDU);
+
+ new Thread() {
+ @Override
+ public void run() {
+ try {
+ card.getBasicChannel().transmit(commandAPDU);
+ } catch (CardException e) {
+ gotException.set(true);
+ } finally {
+ autoResetEvent.signal();
+ }
+ autoResetEvent.signal();
+ }
+ }.start();
+
+ autoResetEvent.await(1, TimeUnit.MINUTES);
+ card.endExclusive();
+ }
+
+ private void test(Card jcsCard) throws CardException {
+ assertTrue(jcsCard != null);
+ // check card ATR
+ assertEquals(jcsCard.getATR(), ETALON_ATR);
+ // check card protocol
+ assertEquals(jcsCard.getProtocol(), "T=1");
+ // get basic channel
+ CardChannel jcsChannel = jcsCard.getBasicChannel();
+ assertTrue(jcsChannel != null);
+ // create applet data = aid len (byte), aid bytes, params length (byte), param
+ byte[] aidBytes = Hex.decode(TEST_APPLET_AID);
+ byte[] createData = new byte[1 + aidBytes.length + 1 + 2 + 3];
+ createData[0] = (byte) aidBytes.length;
+ System.arraycopy(aidBytes, 0, createData, 1, aidBytes.length);
+ createData[1 + aidBytes.length] = (byte) 5;
+ createData[2 + aidBytes.length] = 0; // aid
+ createData[3 + aidBytes.length] = 0; // control
+ createData[4 + aidBytes.length] = 2; // params
+ createData[5 + aidBytes.length] = 0xF; // params
+ createData[6 + aidBytes.length] = 0xF; // params
+ CommandAPDU createApplet = new CommandAPDU(0x80, 0xb8, 0, 0, createData);
+ ResponseAPDU response = jcsChannel.transmit(createApplet);
+ assertEquals(response.getSW(), 0x9000);
+ assertEquals(true, Arrays.equals(response.getData(), aidBytes));
+ // select applet
+ CommandAPDU selectApplet = new CommandAPDU(ISO7816.CLA_ISO7816, ISO7816.INS_SELECT, 4, 0, Hex.decode(TEST_APPLET_AID));
+ response = jcsChannel.transmit(selectApplet);
+ assertEquals(response.getSW(), 0x9000);
+ // test NOP
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x02, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+ // test SW_INS_NOT_SUPPORTED
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x05, 0x00, 0x00));
+ assertEquals(ISO7816.SW_INS_NOT_SUPPORTED, response.getSW());
+ // test hello world from card
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x01, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+ assertEquals("Hello world !", new String(response.getData()));
+ // test echo
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x01, 0x01, 0x00, ("Hello javacard world !").getBytes()));
+ assertEquals(0x9000, response.getSW());
+ assertEquals("Hello javacard world !", new String(response.getData()));
+ // test echo v2
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x03, 0x00, 0x00, ("Hello javacard world !").getBytes()));
+ assertEquals(0x9000, response.getSW());
+ assertEquals("Hello javacard world !", new String(response.getData()));
+ // test echo install params
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x04, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+ assertEquals(0xF, response.getData()[0]);
+ assertEquals(0xF, response.getData()[1]);
+ // test continued data
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x06, 0x00, 0x00));
+ assertEquals(0x6107, response.getSW());
+ assertEquals("Hello ", new String(response.getData()));
+ // test https://github.com/licel/jcardsim/issues/13
+ byte[] listObjectsCmd = new byte[5];
+ listObjectsCmd[0] = (byte) 0xb0;
+ listObjectsCmd[1] = (byte) 0x58;
+ listObjectsCmd[2] = (byte) 0x00;
+ listObjectsCmd[3] = (byte) 0x00;
+ listObjectsCmd[4] = (byte) 0x0E;
+ response = jcsChannel.transmit(new CommandAPDU(listObjectsCmd));
+ assertEquals(0x9C12, response.getSW());
+ // application specific sw + data
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x07, 0x00, 0x00));
+ assertEquals(0x9B00, response.getSW());
+ assertEquals("Hello world !", new String(response.getData()));
+ // sending maximum data
+ response = jcsChannel.transmit(new CommandAPDU(0x01, 0x08, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/smartcardio/JCardSimProviderTest.java b/src/test/java/com/licel/jcardsim/smartcardio/JCardSimProviderTest.java
index 6c07cb5f..74eb42fa 100644
--- a/src/test/java/com/licel/jcardsim/smartcardio/JCardSimProviderTest.java
+++ b/src/test/java/com/licel/jcardsim/smartcardio/JCardSimProviderTest.java
@@ -15,6 +15,8 @@
*/
package com.licel.jcardsim.smartcardio;
+import com.licel.jcardsim.base.SimulatorSystem;
+import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Arrays;
@@ -23,7 +25,6 @@
import javax.smartcardio.*;
import junit.framework.TestCase;
import org.bouncycastle.util.encoders.Hex;
-import com.licel.jcardsim.base.SimulatorSystem;
/**
* Test Java Card Terminal emulation.
@@ -32,7 +33,7 @@
*/
public class JCardSimProviderTest extends TestCase {
- private static final ATR ETALON_ATR = new ATR(Hex.decode(JCSCard.DEFAULT_ATR));
+ private static final ATR ETALON_ATR = new ATR(Hex.decode("3BFA1800008131FE454A434F5033315632333298"));
private static final String TEST_APPLET_AID = "010203040506070809";
protected void setUp() throws Exception {
@@ -43,10 +44,9 @@ protected void tearDown() throws Exception {
super.tearDown();
}
- public void testProvider() throws CardException, NoSuchAlgorithmException {
- SimulatorSystem.resetRuntime();
- System.setProperty("com.licel.jcardsim.smartcardio.applet.0.AID", TEST_APPLET_AID);
- System.setProperty("com.licel.jcardsim.smartcardio.applet.0.Class", "com.licel.jcardsim.samples.HelloWorldApplet");
+ public void testProvider() throws CardException, NoSuchAlgorithmException, UnsupportedEncodingException {
+ System.setProperty("com.licel.jcardsim.card.applet.0.AID", TEST_APPLET_AID);
+ System.setProperty("com.licel.jcardsim.card.applet.0.Class", "com.licel.jcardsim.samples.HelloWorldApplet");
if (Security.getProvider("jCardSim") == null) {
JCardSimProvider provider = new JCardSimProvider();
Security.addProvider(provider);
@@ -75,7 +75,7 @@ public void testProvider() throws CardException, NoSuchAlgorithmException {
// get basic channel
CardChannel jcsChannel = jcsCard.getBasicChannel();
assertTrue(jcsChannel != null);
- // create applet data = aid len (byte), aid bytes, params lenth (byte), param
+ // create applet data = aid len (byte), aid bytes, params length (byte), param
byte[] aidBytes = Hex.decode(TEST_APPLET_AID);
byte[] createData = new byte[1+aidBytes.length+1+2+3];
createData[0] = (byte) aidBytes.length;
@@ -91,31 +91,51 @@ public void testProvider() throws CardException, NoSuchAlgorithmException {
assertEquals(response.getSW(), 0x9000);
assertEquals(true, Arrays.equals(response.getData(), aidBytes));
// select applet
- CommandAPDU selectApplet = new CommandAPDU(ISO7816.CLA_ISO7816, ISO7816.INS_SELECT, 0, 0, Hex.decode(TEST_APPLET_AID));
+ CommandAPDU selectApplet = new CommandAPDU(ISO7816.CLA_ISO7816, ISO7816.INS_SELECT, 4, 0, Hex.decode(TEST_APPLET_AID));
response = jcsChannel.transmit(selectApplet);
assertEquals(response.getSW(), 0x9000);
// test NOP
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x02, 0x00, 0x00));
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x02, 0x00, 0x00));
assertEquals(0x9000, response.getSW());
// test SW_INS_NOT_SUPPORTED
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x05, 0x00, 0x00));
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x05, 0x00, 0x00));
assertEquals(ISO7816.SW_INS_NOT_SUPPORTED, response.getSW());
// test hello world from card
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x01, 0x00, 0x00));
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x01, 0x00, 0x00));
assertEquals(0x9000, response.getSW());
assertEquals("Hello world !", new String(response.getData()));
// test echo
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x01, 0x01, 0x00, ("Hello javacard world !").getBytes()));
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x01, 0x01, 0x00, ("Hello javacard world !").getBytes()));
assertEquals(0x9000, response.getSW());
assertEquals("Hello javacard world !", new String(response.getData()));
// test echo v2
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x03, 0x00, 0x00, ("Hello javacard world !").getBytes()));
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x03, 0x00, 0x00, ("Hello javacard world !").getBytes()));
assertEquals(0x9000, response.getSW());
assertEquals("Hello javacard world !", new String(response.getData()));
- // test echo intall params
- response = jcsChannel.transmit(new CommandAPDU(0x01, 0x04, 0x00, 0x00));
+ // test echo install params
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x04, 0x00, 0x00));
assertEquals(0x9000, response.getSW());
assertEquals(0xF, response.getData()[0]);
assertEquals(0xF, response.getData()[1]);
+ // test continued data
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x06, 0x00, 0x00));
+ assertEquals(0x6107, response.getSW());
+ assertEquals("Hello ", new String(response.getData()));
+ // test https://github.com/licel/jcardsim/issues/13
+ byte[] listObjectsCmd = new byte[5];
+ listObjectsCmd[0] = (byte) 0xb0;
+ listObjectsCmd[1] = (byte) 0x58;
+ listObjectsCmd[2] = (byte) 0x00;
+ listObjectsCmd[3] = (byte) 0x00;
+ listObjectsCmd[4] = (byte) 0x0E;
+ response = jcsChannel.transmit(new CommandAPDU(listObjectsCmd));
+ assertEquals(0x9C12, response.getSW());
+ // application specific sw + data
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x07, 0x00, 0x00));
+ assertEquals(0x9B00, response.getSW());
+ assertEquals("Hello world !", new String(response.getData()));
+ // sending maximum data
+ response = jcsChannel.transmit(new CommandAPDU(0x00, 0x08, 0x00, 0x00));
+ assertEquals(0x9000, response.getSW());
}
}
diff --git a/src/test/java/com/licel/jcardsim/utils/AIDUtilTest.java b/src/test/java/com/licel/jcardsim/utils/AIDUtilTest.java
new file mode 100644
index 00000000..b5483e5a
--- /dev/null
+++ b/src/test/java/com/licel/jcardsim/utils/AIDUtilTest.java
@@ -0,0 +1,21 @@
+package com.licel.jcardsim.utils;
+
+import javacard.framework.AID;
+import junit.framework.TestCase;
+
+public class AIDUtilTest extends TestCase {
+ public AIDUtilTest(String name) {
+ super(name);
+ }
+
+ public void testSelectString() {
+ assertEquals("00A4040005CAFECAFE0100" ,ByteUtil.hexString(AIDUtil.select("cafecafe01")));
+ assertEquals("00A4040001CA00" ,ByteUtil.hexString(AIDUtil.select("ca")));
+ assertEquals("00A404000000", ByteUtil.hexString(AIDUtil.select("")));
+ }
+
+ public void testSelectAID() {
+ AID aid = AIDUtil.create("cafecafe01");
+ assertEquals("00A4040005CAFECAFE0100" ,ByteUtil.hexString(AIDUtil.select(aid)));
+ }
+}
diff --git a/src/test/java/com/licel/jcardsim/utils/APDUScriptToolTest.java b/src/test/java/com/licel/jcardsim/utils/APDUScriptToolTest.java
index 17319b27..4d0585f8 100644
--- a/src/test/java/com/licel/jcardsim/utils/APDUScriptToolTest.java
+++ b/src/test/java/com/licel/jcardsim/utils/APDUScriptToolTest.java
@@ -15,11 +15,14 @@
*/
package com.licel.jcardsim.utils;
+import com.licel.jcardsim.base.SimulatorSystem;
+import junit.framework.TestCase;
+
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import java.io.PrintStream;
import java.util.Properties;
-import junit.framework.TestCase;
-import com.licel.jcardsim.base.SimulatorSystem;
/**
* Test class APDUScriptTool.
@@ -52,28 +55,44 @@ public void testExecuteCommands() throws Exception {
sb.append("//CREATE APPLET CMD\n");
sb.append("0x80 0xb8 0x00 0x00 0x10 0x9 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x8 0x09 0x05 0x00 0x00 0x02 0xF 0xF 0x7f;\n");
sb.append("// SELECT APPLET CMD\n");
- sb.append("0x00 0xa4 0x00 0x00 0x09 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x8 0x09 0x7f;\n");
+ sb.append("0x00 0xa4 0x04 0x00 0x09 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x8 0x09 0x7f;\n");
sb.append("// TEST NOP\n");
- sb.append("0x01 0x02 0x00 0x00 0x00 0x2; \n");
+ sb.append("0x00 0x02 0x00 0x00 0x00 0x2; \n");
sb.append("// TEST SW_INS_NOT_SUPPORTED\n");
- sb.append("0x01 0x05 0x00 0x00 0x00 0x2 ;\n");
+ sb.append("0x00 0x05 0x00 0x00 0x00 0x2 ;\n");
sb.append("// test hello world from card\n");
- sb.append("0x01 0x01 0x00 0x00 0x00 0x0d;\n");
+ sb.append("0x00 0x01 0x00 0x00 0x00 0x0d;\n");
sb.append("// test echo\n");
- sb.append("0x01 0x01 0x01 0x00 0x0d 0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x20 0x21 0x0d;\n");
+ sb.append("0x00 0x01 0x01 0x00 0x0d 0x48 0x65 0x6c 0x6c 0x6f 0x20 0x77 0x6f 0x72 0x6c 0x64 0x20 0x21 0x0d;\n");
sb.append("// test echo2\n");
- sb.append("0x01 0x03 0x01 0x02 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;");
+ sb.append("0x00 0x03 0x01 0x02 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;");
sb.append("powerdown;\n");
InputStream commandsStream = new ByteArrayInputStream(sb.toString().replaceAll("\n", System.getProperty("line.separator")).getBytes());
boolean isException = true;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
- SimulatorSystem.resetRuntime();
- APDUScriptTool.executeCommands(cfg, commandsStream, null);
+ APDUScriptTool.executeCommands(cfg, commandsStream, new PrintStream(baos));
isException = false;
} catch (Throwable t) {
t.printStackTrace();
}
+ finally {
+ commandsStream.close();
+ }
assertEquals(isException, false);
- commandsStream.close();
+
+ String expectedOutput =
+ "CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 10, 09, 01, 02, 03, 04, 05, 06, 07, 08, 09, 05, 00, 00, 02, 0f, 0f, Le: 09, 01, 02, 03, 04, 05, 06, 07, 08, 09, SW1: 90, SW2: 00\n" +
+ "CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 09, 01, 02, 03, 04, 05, 06, 07, 08, 09, Le: 00, SW1: 90, SW2: 00\n" +
+ "CLA: 00, INS: 02, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 90, SW2: 00\n" +
+ "CLA: 00, INS: 05, P1: 00, P2: 00, Lc: 00, Le: 00, SW1: 6d, SW2: 00\n" +
+ "CLA: 00, INS: 01, P1: 00, P2: 00, Lc: 00, Le: 0d, 48, 65, 6c, 6c, 6f, 20, 77, 6f, 72, 6c, 64, 20, 21, SW1: 90, SW2: 00\n" +
+ "CLA: 00, INS: 01, P1: 01, P2: 00, Lc: 0d, 48, 65, 6c, 6c, 6f, 20, 77, 6f, 72, 6c, 64, 20, 21, Le: 0d, 48, 65, 6c, 6c, 6f, 20, 77, 6f, 72, 6c, 64, 20, 21, SW1: 90, SW2: 00\n" +
+ "CLA: 00, INS: 03, P1: 01, P2: 02, Lc: 05, 01, 02, 03, 04, 05, Le: 05, 01, 02, 03, 04, 05, SW1: 90, SW2: 00\n";
+
+ String output = baos.toString("UTF-8");
+ System.out.print(output);
+ assertEquals(expectedOutput, output.replace("\r\n","\n"));
}
}
diff --git a/src/test/java/javacard/framework/UtilTest.java b/src/test/java/javacard/framework/UtilTest.java
new file mode 100644
index 00000000..6aa87af5
--- /dev/null
+++ b/src/test/java/javacard/framework/UtilTest.java
@@ -0,0 +1,44 @@
+package javacard.framework;
+
+import junit.framework.TestCase;
+
+public class UtilTest extends TestCase {
+
+ /**
+ *
+ */
+ public void testArrayCompare1() {
+ byte[] src = new byte[]{0x01};
+ byte[] dest = new byte[]{0x02};
+ byte res = Util.arrayCompare(src, (short) 0, dest, (short) 0, (short) 1);
+ assertEquals(-1, res);
+ }
+
+ /**
+ *
+ */
+ public void testArrayCompare2() {
+ byte[] src = new byte[]{(byte) 0xff};
+ byte[] dest = new byte[]{0x01};
+ byte res = Util.arrayCompare(src, (short) 0, dest, (short) 0, (short) 1);
+ assertEquals(1, res);
+ }
+
+ /**
+ * Test of arrayFillNonAtomic method, of class Util.
+ */
+ public void testArrayFillNonAtomic() {
+ System.out.println("arrayFillNonAtomic");
+ byte[] etalonArray = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0};
+ System.out.println(etalonArray.length);
+ byte[] bArray = new byte[16];
+ short bOff = 8;
+ short bLen = 7;
+ byte bValue = 1;
+ short expResult = (short) (bOff + bLen);
+ short result = Util.arrayFillNonAtomic(bArray, bOff, bLen, bValue);
+ assertEquals(expResult, result);
+ byte res = Util.arrayCompare(bArray, (short) 0, etalonArray, (short) 0, (short) 16);
+ assertEquals(0, res);
+ }
+}
diff --git a/src/test/resources/com/licel/jcardsim/base/helloworld.jar b/src/test/resources/com/licel/jcardsim/base/helloworld.jar
new file mode 100644
index 00000000..06762d6c
Binary files /dev/null and b/src/test/resources/com/licel/jcardsim/base/helloworld.jar differ