Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vletoux committed Jan 11, 2016
0 parents commit c731d28
Show file tree
Hide file tree
Showing 24 changed files with 5,270 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
language: java

env:
- JC_HOME=$TRAVIS_BUILD_DIR/jckit/java_card_kit-2_2_2

before_script:
- mkdir jckit
- cd jckit
- "[ -f java_card_kit-2_2_2-linux.zip ] || curl -L http://download.oracle.com/otn-pub/java/java_card_kit/2.2.2/java_card_kit-2_2_2-linux.zip -o java_card_kit-2_2_2-linux.zip --cookie oraclelicense=accept-securebackup-cookie"
- unzip java_card_kit-2_2_2-linux.zip
- cd java_card_kit-2_2_2/
- unzip java_card_kit-2_2_2-rr-bin-linux-do.zip
- cd ../..
- mkdir ext
- cd ext
- mkdir ant
- cd ant
- "[ -f ant-javacard.jar ] || curl -L https://github.com/martinpaljak/ant-javacard/releases/download/v1.3/ant-javacard.jar -o ant-javacard.jar"
- cd ../..
- CLASSPATH=$CLASSPATH:$JC_HOME/lib

script: ant dist

cache:
files:
- $TRAVIS_BUILD_DIR/java_card_kit-2_2_2-linux.zip
19 changes: 19 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="Gids Applet" default="dist" basedir=".">
<description>Builds the project. </description>
<target name="dist" description="generate the distribution">
<tstamp/>

<!-- Create the distribution directory -->
<taskdef name="javacard" classname="pro.javacard.ant.JavaCard" classpath="ext/ant/ant-javacard.jar"/>
<javacard>
<cap aid="A0:00:00:03:97:42:54:46:59" output="GidsApplet.cap" sources="src/com/mysmartlogon/gidsApplet" version="1.0">
<applet class="com.mysmartlogon.gidsApplet.GidsApplet" aid="A0:00:00:03:97:42:54:46:59:02:01"/>
</cap>
</javacard>
</target>
<target name="clean" description="clean up">
<!-- Delete the built applet -->
<delete dir="GidsApplet.cap"/>
</target>
</project>
73 changes: 73 additions & 0 deletions src/com/mysmartlogon/gidsApplet/ApplicationFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.mysmartlogon.gidsApplet;

import javacard.framework.Util;

public class ApplicationFile extends DedicatedFile {


byte[] fileControlInformation = null;
byte[] fileManagementData = null;
public ApplicationFile(short fileID, byte[] fileControlParameter, byte[] fileControlInformation, byte[] fileManagementData) {
super(fileID, fileControlParameter);
this.fileControlInformation = fileControlInformation;
this.fileManagementData = fileManagementData;
}

/**
* \brief Check if this is the AID of the application
*
* \param name The array containing the name to compare with the file's name.
*
* \param offset The offset at where the name begins.
*
* \param length The length of the name.
*
* \return false if the DF has no name or the names do not match,
* true else.
*/
public boolean isName(byte[] name, short offset, short length) {
short namePos;
short aidlen = 0;
short i;
// Find the position of the AID tag (4F) in the fci.
try {
namePos = UtilTLV.findTag(fileControlInformation, (short)2, fileControlInformation[(short)1], (byte) 0x4F);
} catch (NotFoundException e) {
// This DF has no name.
return false;
} catch (InvalidArgumentsException e) {
return false;
}
// This ADF has a AID.
try {
aidlen = UtilTLV.decodeLengthField(fileControlInformation, (short)(namePos+1));
if (aidlen < length) {
// aid len to check is to big to match
return false;
}
} catch (InvalidArgumentsException e) {
return false;
}
// Advance namePos from "tag" to value.
try {
namePos += 1 + UtilTLV.getEncodingLengthFieldLength(length);
} catch(InvalidArgumentsException e) {
return false;
}
// check if the name can be a part of the AID
for (i = 0; i < (short)(aidlen - length +1); i++) {
if ((byte)0 == Util.arrayCompare(name, offset, fileControlInformation, (short)(namePos + i), length) ) {
return true;
}
}
return false;
}

public byte[] getFileManagementData() {
return fileManagementData;
}

public byte[] getFileControlInformation() {
return fileControlInformation;
}
}
185 changes: 185 additions & 0 deletions src/com/mysmartlogon/gidsApplet/BerTlvFile.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package com.mysmartlogon.gidsApplet;

import javacard.framework.JCSystem;
import javacard.framework.Util;

public class BerTlvFile extends ElementaryFile {

private static final short ELEMENT_COUNT_START = 10;
private static final short ELEMENT_COUNT_MAX = 30; // set to max. 16383

private Record[] children;
private byte currentNumChildren;

/**
* \brief Instantiate a new BER-TLV EF. No data is being added at this point.
*
* \param fileControlInformation The array of bytes containing the valid (!) File Control Information.
* It must contain the File ID (Tag 83). No Copy is made.
*
* \param maxRecords The maximum amount of saved records.
*
* \attention No copy of the FCI is made. Do not pass any buffer that is altered
* later (e.g. the apdu buffer). Max length 257 bytes as the length
* of the FCI Tag (6F) must be a byte.
*
* \attention To be safe, use IsoFileSystem.getSafeFile() to instantiate files.
*
* \throw IllegalArgumentException If necessary tags in the FCI are missing.
*/
public BerTlvFile(short fileID, byte[] fileControlInformation) {
super(fileID, fileControlInformation);
this.children = new Record[ELEMENT_COUNT_START];
this.currentNumChildren = 0;
}

@Override
void clearContents() {
short i;

for(i = 0; i < currentNumChildren; i++) {
children[i].clearContents();
children[i] = null;
}

}

/**
* \brief Delete a DO
*
* This method requests garbage collection.
*
* \param childNum internal index
*/
protected void deleteChildren(short childNum) {

children[childNum] = null;
currentNumChildren--; // We have one less children now.

// Fill up empty field in children array.
// The last children is one ahead, so it is at currentNumChildren.
if(childNum < currentNumChildren) {
children[childNum] = children[currentNumChildren];
}

// Clean up the old file object.
if(JCSystem.isObjectDeletionSupported()) {
JCSystem.requestObjectDeletion();
}
}

/**
* \brief remove a DO
*
* \param children The children to add.
*
* \throw NotEnoughSpaceException If CHILDREN_COUNT_MAX is reached.
* @param size
* @param offset_cdata
*/
public Record addChildren(byte[] buffer, short offset, short wholelength, short lengthavailable) throws NotEnoughSpaceException {
// try to find a previous TLV
short i;
short lengthToCopy = (lengthavailable > wholelength ? wholelength: lengthavailable);
for(i = 0; i < currentNumChildren; i++) {
byte[] value = children[i].GetData();

if (UtilTLV.IsBERTLVTagEqual(buffer, offset, (short) (offset + lengthavailable), value)) {
// found => replace or erase ?

// erase if empty DO pushed and already empty DO stored
short oldlen = UtilTLV.GetBERTLVDataLen(value, (short) 0, (short) value.length);
short newlen = UtilTLV.GetBERTLVDataLen(buffer, offset, (short) (offset + lengthavailable));
if (oldlen == 0) {
if (newlen == 0) {
deleteChildren(i);
return null;
}
}
// replace
if (oldlen == newlen) {
// no need to add / remove data, just replace the buffer
Util.arrayCopyNonAtomic(buffer, offset, value, (short) 0, lengthToCopy);
} else {
// remove previous data, add new
byte[] data = new byte[wholelength];
Util.arrayCopyNonAtomic(buffer, offset, data, (short) 0, lengthToCopy);
children[i] = null;
if(JCSystem.isObjectDeletionSupported()) {
JCSystem.requestObjectDeletion();
}
children[i] = new Record(data);
}
return children[i];
}

}


// First we have to check for enough space.
if(currentNumChildren >= (short)children.length) {
Record[] newChildren = null;
// The array is full - we try to increase the size.
if((short)(children.length * 2) <= ELEMENT_COUNT_MAX) {
// Doubling the size is possible.
newChildren = new Record[(short)(children.length * 2)];
copyFileArrayRefs(children, newChildren);
} else {
// Doubling not possible - try to at least increase to CHILDREN_COUNT_MAX.
if(currentNumChildren < ELEMENT_COUNT_MAX) {
newChildren = new Record[ELEMENT_COUNT_MAX];
copyFileArrayRefs(children, newChildren);
} else {
// CHILDREN_COUNT_MAX exceeded. No "space" left. Fail.
throw NotEnoughSpaceException.getInstance();
}
}
children = newChildren; // Initial children array is now garbage.
if(JCSystem.isObjectDeletionSupported()) {
JCSystem.requestObjectDeletion();
}
} // We have enough space (now).
byte[] data = new byte[wholelength];
Util.arrayCopyNonAtomic(buffer, offset, data, (short) 0, lengthToCopy);
children[currentNumChildren++] = new Record(data);
return children[(short) (currentNumChildren-1)];
}

/**
* \brief Copies the references from one File array to the other.
*
* \attention Although only references are copied, this is probably still quite expensive because
* writing to the EEPROM is. Only use this for operations that are not called often (Creating and deleting files etc.).
*
* \param src The source File array to copy from.
*
* \param dest The destination File array to copy to. It MUST be at least of size of the src array.
*/
private static void copyFileArrayRefs(Record[] src, Record[] dest) {
short i = 0;
short length = src.length > dest.length ? (short)dest.length : (short)src.length;

for(i=0; i < length; i++) {
dest[i] = src[i];
}
return;
}

public Record getData(byte[] tag, short offset, short len) throws NotFoundException {
short i;

for(i = 0; i < currentNumChildren; i++) {
byte[] value = children[i].GetData();
if(UtilTLV.IsBERTLVTagEqual(tag, offset, len, value)) {
return children[i];
}
}

throw NotFoundException.getInstance();
}

public Record[] getAllData() {
return children;
}

}
Loading

0 comments on commit c731d28

Please sign in to comment.