Skip to content

Commit

Permalink
feat: extenting policy and added more features
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-sekanina committed Apr 6, 2023
1 parent fe91a00 commit 02ed072
Show file tree
Hide file tree
Showing 6 changed files with 434 additions and 127 deletions.
8 changes: 4 additions & 4 deletions applet/src/main/java/applet/GlobalUnsignedTXOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@

public class GlobalUnsignedTXOutput {
short value_start = -1;
short script_size_tart = -1;
short script_size_start = -1;
short script_size = -1;
short script_pub_key_start = -1;
short size = 0;

void fill(short start){
value_start = start;
script_size_tart = (short) (start + 8);
script_size = compactWeirdoInt(script_size_tart);
script_pub_key_start = (short) (script_size_tart + byteSizeOfCWI(script_size));
script_size_start = (short) (start + 8);
script_size = compactWeirdoInt(script_size_start);
script_pub_key_start = (short) (script_size_start + byteSizeOfCWI(script_size));
size = (short) (8 + byteSizeOfCWI(script_size) + script_size); // easier to read and understand this way
}
}
213 changes: 193 additions & 20 deletions applet/src/main/java/applet/MainApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import javacard.framework.*;
import javacard.security.RandomData;

import java.util.Arrays;


public class MainApplet extends Applet implements MultiSelectable {
public static final short MAX_SIZE_OF_PSBT = 1024 * 6;
Expand Down Expand Up @@ -44,7 +42,7 @@ public MainApplet(byte[] buffer, short offset, byte length) {
checkAgainstDataStorageOffsets = new short[STORAGE_AMOUNT];
PSBTdata = new byte[MAX_SIZE_OF_PSBT]; // to change PSBT max size change this constant
policy = new byte[MAX_SIZE_OF_POLICY];
controlArray = new byte[AppletInstructions.PACKET_BUFFER_SIZE]; // array that is sent back to computer as confirmation
controlArray = new byte[AppletInstructions.PACKET_BUFFER_SIZE]; // historical array that is sent back to computer as confirmation
controlArray[0] = 0;
controlArray[1] = 1;
controlArray[2] = 2;
Expand Down Expand Up @@ -110,33 +108,30 @@ public void process(APDU apdu) {
}
if (ins == AppletInstructions.INS_FINISH) {
policyUploadLocked = 1;
checkStorageUsage();
}
}
/**
* this uploads data(secrets and time signed by authority) for Policy
* this uploads additional data for Policy evaluation
*/
if (cla == AppletInstructions.CLASS_ADDITIONAL_DATA_UPLOAD && policyUploadLocked == 0) {
if (ins == AppletInstructions.INS_REQUEST) {
dataStorageOffsets[p1] = 0;
}
if (ins == AppletInstructions.INS_UPLOAD) {
Util.arrayCopyNonAtomic(apduBuffer, ISO7816.OFFSET_CDATA, additionalDataStorage[p1], dataStorageOffsets[p1], (short) (lc & 0xff));
System.out.print("SHit coppiedd" + System.lineSeparator());
System.out.print("SHit coppiedd: "+ Arrays.toString(additionalDataStorage[p1]) + System.lineSeparator());
dataStorageOffsets[p1] += (short) (lc & 0xff);
}
if (ins == AppletInstructions.INS_FINISH) {
}
}

if (cla == AppletInstructions.CLASS_ADDITIONAL_DATA_UPLOAD && policyUploadLocked == 1) {
if (cla == AppletInstructions.CLASS_ADDITIONAL_DATA_UPLOAD && policyUploadLocked == 1) { // Different Class for DATA upload after policy is locked
if (ins == AppletInstructions.INS_REQUEST) {
checkAgainstDataStorageOffsets[p1] = 0;
}
if (ins == AppletInstructions.INS_UPLOAD) {
Util.arrayCopyNonAtomic(apduBuffer, ISO7816.OFFSET_CDATA, checkAgainstDataStorage[p1], checkAgainstDataStorageOffsets[p1], (short) (lc & 0xff));
System.out.print("SH coppiedd" + System.lineSeparator());
System.out.print("SH coppiedd: "+ Arrays.toString(checkAgainstDataStorage[p1]) + System.lineSeparator());
checkAgainstDataStorageOffsets[p1] += (short) (lc & 0xff);
}
if (ins == AppletInstructions.INS_FINISH) {
Expand Down Expand Up @@ -253,40 +248,218 @@ short validatePolicy(){
if (policyOffset == 0) { // empty policy is valid policy
return 1;
}

while (stepCounter < policyOffset) {
System.out.print("policy[stepcounter]: " + policy[stepCounter] + System.lineSeparator());
System.out.print("orSection: " + orSection + System.lineSeparator());
switch (policy[stepCounter]) {
case PolicyInstruction.minTotalOutput:
case PolicyInstruction.maxTotalOutput:
case PolicyInstruction.minOutputToTargetAddress:
case PolicyInstruction.maxOutputToTargetAddress:
case PolicyInstruction.minAmountofInputs:
if (GlobalMap.PSBTversion == 0) {
if (policy[stepCounter + 1] <= psbt.global_map.globalUnsignedTX.input_count) {
orSection = 1;
}
}

if (GlobalMap.PSBTversion == 2) {
if (policy[stepCounter + 1] <= psbt.global_map.input_maps_total) {
orSection = 1;
}
}
stepCounter += 2;
break;

case PolicyInstruction.maxAmountofInputs:
if (GlobalMap.PSBTversion == 0) {
if (policy[stepCounter + 1] >= psbt.global_map.globalUnsignedTX.input_count) {
orSection = 1;
}
}

if (GlobalMap.PSBTversion == 2) {
if (policy[stepCounter + 1] >= psbt.global_map.input_maps_total) {
orSection = 1;
}
}
stepCounter += 2;
break;

case PolicyInstruction.minAmountofOutputs:
if (GlobalMap.PSBTversion == 0) {
if (policy[stepCounter + 1] <= psbt.global_map.globalUnsignedTX.output_count) {
orSection = 1;
}
}

if (GlobalMap.PSBTversion == 2) {
if (policy[stepCounter + 1] <= psbt.global_map.output_maps_total) {
orSection = 1;
}
}
stepCounter += 2;
break;

case PolicyInstruction.maxAmountofOutputs:
if (GlobalMap.PSBTversion == 0) {
if (policy[stepCounter + 1] >= psbt.global_map.globalUnsignedTX.output_count) {
orSection = 1;
}
}

if (GlobalMap.PSBTversion == 2) {
if (policy[stepCounter + 1] >= psbt.global_map.output_maps_total) {
orSection = 1;
}
}
stepCounter += 2;
break;

case PolicyInstruction.naiveTimeLapsed: // TODO delete
case PolicyInstruction.signedTmeLapse:
case PolicyInstruction.checkSecret:
if (equals(additionalDataStorage[policy[stepCounter + 1]], checkAgainstDataStorage[policy[stepCounter + 1]])) {
if ((Util.arrayCompare(additionalDataStorage[policy[stepCounter + 1]],(short) 0,checkAgainstDataStorage[policy[stepCounter + 1]],(short) 0, STORAGE_SIZE)) == 0) {
orSection = 1;
}
stepCounter += 2;
break;

case PolicyInstruction.transactionVersion:
if (policy[stepCounter + 1] == GlobalMap.PSBTversion) {
orSection = 1;
}
stepCounter += 2;
break;

case PolicyInstruction.policyAnd:
if (orSection == 0) {
return 0;
return validationReturnProcedure((short) 0);
}
orSection = 0;
stepCounter++;
break;

default:
return 0; // unknown instruction
return validationReturnProcedure((short) 0); // unknown instruction
}
}
System.out.print("policy[stepcounter]: " + policy[stepCounter] + System.lineSeparator());
System.out.print("validating 1" + System.lineSeparator());
return orSection;
System.out.print("orSection: " + orSection + System.lineSeparator());
return validationReturnProcedure(orSection);
}

private boolean equals(byte[] bytes, byte[] bytes2) { // checks two byte[] with size of STORAGE_SIZE
short j = 0;
while (j < STORAGE_SIZE) {
if (bytes[j] != bytes2[j]) {
return false;
boolean checkStorageUsage() {
short stepCounter = 0;
while (stepCounter < policyOffset) {
System.out.print("policy[stepcounter]: " + policy[stepCounter] + System.lineSeparator());
switch (policy[stepCounter]) {
case PolicyInstruction.minTotalOutput:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0){
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 2;
break;

case PolicyInstruction.maxTotalOutput:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0){
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 2;
break;

case PolicyInstruction.minOutputToTargetAddress:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0 || dataStorageOffsets[policy[stepCounter + 2]] == 0){
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 3;
break;

case PolicyInstruction.maxOutputToTargetAddress:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0 || dataStorageOffsets[policy[stepCounter + 2]] == 0){
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 3;
break;

case PolicyInstruction.minAmountofInputs:
stepCounter += 2;
break;
case PolicyInstruction.maxAmountofInputs:
stepCounter += 2;
break;
case PolicyInstruction.minAmountofOutputs:
stepCounter += 2;
break;
case PolicyInstruction.maxAmountofOutputs:
stepCounter += 2;
break;

case PolicyInstruction.naiveTimeLapsed:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0){
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 2;
break;

case PolicyInstruction.signedTmeLapse:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0 || dataStorageOffsets[policy[stepCounter + 2]] == 0) {
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 3;
break;

case PolicyInstruction.checkSecret:
if (dataStorageOffsets[policy[stepCounter + 1]] == 0) {
System.out.println("seems like unused storage in memory with pointer: " + policy[stepCounter + 1]);
System.out.println("with PolicyInstruction: " + policy[stepCounter]);
return false;
}
stepCounter += 2;
break;

case PolicyInstruction.transactionVersion:
stepCounter += 2;
break;

case PolicyInstruction.policyAnd:
stepCounter++;
break;
default:
}
j++;
}
System.out.print("policy[stepcounter]: " + policy[stepCounter] + System.lineSeparator());
return true;

}

private short validationReturnProcedure(short returnCode) {
// clears all temporary storages accessible after policy is locked
short i = 0;
short j = 0;
while (i < STORAGE_AMOUNT) {
while (j < STORAGE_SIZE) {
checkAgainstDataStorage[i][j] = (byte) 0; // deletes content
j++;
}
checkAgainstDataStorageOffsets[i] = 0; // deletes size
j = 0;
i++;
}
return returnCode;
}

public boolean select(boolean b) {
Expand Down
13 changes: 12 additions & 1 deletion applet/src/main/java/applet/PolicyInstruction.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
package applet;

public class PolicyInstruction {
public static final byte minTotalOutput = 0;
public static final byte maxTotalOutput = 1;
public static final byte minOutputToTargetAddress = 2;
public static final byte maxOutputToTargetAddress = 3;
public static final byte minAmountofInputs = 4;
public static final byte maxAmountofInputs = 5;
public static final byte minAmountofOutputs = 6;
public static final byte maxAmountofOutputs = 7;
public static final byte naiveTimeLapsed = 8;
public static final byte signedTmeLapse = 9;
public static final byte checkSecret = 10;
public static final byte policyAnd = 11;
public static final byte transactionVersion = 12;
public static final byte policyAnd = 13;
}
25 changes: 0 additions & 25 deletions applet/src/test/java/communication/Download.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,4 @@ public byte[] download(CardManager manager, byte downloadInstruction, short from
}
return res;
}

public byte[] fromHex(String hex){
// ukradeno
byte[] res = new byte[hex.length() / 2];

for (int i = 0; i < res.length; i++) {
int index = i * 2;
int j = Integer.parseInt(hex.substring(index, index + 2), 16);
res[i] = (byte) j;
}

return res;
}

public String bytesToHex(byte[] bytes) {
StringBuilder res = new StringBuilder();
int cb;

for (byte aByte : bytes) {
cb = aByte & 0xFF;
res.append(Integer.toHexString(cb / 16));
res.append(Integer.toHexString(cb % 16));
}
return res.toString();
}
}
28 changes: 28 additions & 0 deletions applet/src/test/java/communication/Tools.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package communication;

public class Tools {
public static byte[] fromHex(String hex){
// ukradeno
byte[] res = new byte[hex.length() / 2];

for (int i = 0; i < res.length; i++) {
int index = i * 2;
int j = Integer.parseInt(hex.substring(index, index + 2), 16);
res[i] = (byte) j;
}

return res;
}

public static String bytesToHex(byte[] bytes) {
StringBuilder res = new StringBuilder();
int cb;

for (byte aByte : bytes) {
cb = aByte & 0xFF;
res.append(Integer.toHexString(cb / 16));
res.append(Integer.toHexString(cb % 16));
}
return res.toString();
}
}
Loading

0 comments on commit 02ed072

Please sign in to comment.