diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMAbortOperationCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMAbortOperationCmd.java deleted file mode 100644 index ee3e052a..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMAbortOperationCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMAbortOperationCmd extends KMAbstractCmd { - public static final byte INS_ABORT_OPERATION_CMD = 0x22; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_ABORT_OPERATION_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMAbstractCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMAbstractCmd.java deleted file mode 100644 index 02fad435..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMAbstractCmd.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public abstract class KMAbstractCmd implements KMCommand { - - /** - * Implements the KMCommand interface. - * - * @param context provides information required to execute the command. - */ - @Override - public void execute(KMContext context) { - // Assert the command's operational state - if (!this.validateState(context.getKeymasterState())) { - throw new KMException(KMException.CMD_NOT_ACCEPTED_WRONG_STATE); - } - KMEncoder encoder = context.getRepository().getEncoder(); - KMDecoder decoder = context.getRepository().getDecoder(); - // Get getExpectedArgs if expected - KMArray args = null; - if (hasArguments()) { - // Deserialize the getExpectedArgs - KMArray argsProto = getExpectedArgs(); - args = decoder.decode(argsProto, context.getBuffer(), (short) 0, context.getBufferLength()); - } - // Pass control to concrete command subclass - KMArray resp = this.process(args, context); - context.setBufferLength((short)0); - // If there is resp then serialize and send - if (resp != null) { - // set outgoing buffer - short len = encoder.encode(resp, context.getBuffer(), (short) 0, (short)context.getBuffer().length); - context.setBufferLength(len); - } - } - - /** - * Get the getExpectedArgs prototype expression from the concrete subclass. - * - * @return KMArray of KMType objects which provides expression for the command's getExpectedArgs.. - */ - protected abstract KMArray getExpectedArgs(); - - /** - * Implemented by the subclass to execute the command specific functionality. - * - * @param args which are decoded from the the apdu. - * @param context within which the command should be executed. - * @return Null or response having the result of the command's execution. - */ - protected abstract KMArray process(KMArray args, KMContext context); - - /** - * Validate the state required by the command to execute. By default all the commands can execute - * in active state. - * - * @param state is the current state of the applet - * @return true if the state is valid for command's execution else false is returned. - */ - protected boolean validateState(byte state) { - return (KMKeymasterApplet.ACTIVE_STATE == state); - } - - @Override - public boolean hasArguments(){ - return true; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMAddRngEntropyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMAddRngEntropyCmd.java deleted file mode 100644 index cb431b8f..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMAddRngEntropyCmd.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -import javacard.framework.ISO7816; -import javacard.framework.JCSystem; -import javacard.framework.Util; - -// This command adds entropy into the current entropy pool as per hal specifications. -public class KMAddRngEntropyCmd extends KMAbstractCmd { - public static final byte INS_ADD_RNG_ENTROPY_CMD = 0x18; - public static final short MAX_SEED_SIZE = 2048; - - @Override - protected KMArray getExpectedArgs() { - return KMArray.instance((short) 1).add((short) 0, KMByteBlob.instance()); - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - KMByteBlob blob = (KMByteBlob) args.get((short) 0); - // maximum 2KiB of seed is allowed. - if (blob.length() > MAX_SEED_SIZE) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); - } - KMUtil.init(context.getRepository()); - // Get existing entropy pool. - byte[] entPool = context.getRepository().getEntropyPool(); - // Create new temporary pool. - byte[] heapRef = context.getRepository().getByteHeapRef(); - short poolStart = context.getRepository().newByteArray((short) entPool.length); - // Populate the new pool with the entropy which is derived from current entropy pool. - KMUtil.newRandomNumber(heapRef, poolStart, (short) entPool.length); - // Copy the entropy to the current pool - updates the entropy pool. - Util.arrayCopy(heapRef, poolStart, entPool, (short) 0, (short) entPool.length); - short index = 0; - short randIndex = 0; - // Mix (XOR) the seed received from the master in the entropy pool - 32 bytes (entPool.length). - // at a time. - while (index < blob.length()) { - entPool[randIndex] = (byte) (entPool[randIndex] ^ blob.get(index)); - randIndex++; - index++; - if (randIndex >= entPool.length) { - randIndex = 0; - } - } - // TODO return success error code. - return null; - } - - @Override - public byte getIns() { - return INS_ADD_RNG_ENTROPY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMArray.java b/Applet/Applet/src/com/android/javacard/keymaster/KMArray.java index 23b5afe6..d2eed688 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMArray.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMArray.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMArray extends KMType { private KMType[] vals; @@ -67,7 +68,7 @@ public KMArray withLength(short length) { public KMArray add(short index, KMType val) { if (index >= length) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } vals[(short) (startOff + index)] = val; return this; @@ -75,7 +76,7 @@ public KMArray add(short index, KMType val) { public KMType get(short index) { if (index >= length) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } return vals[(short) (startOff + index)]; } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMAttestKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMAttestKeyCmd.java deleted file mode 100644 index 9d51e231..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMAttestKeyCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMAttestKeyCmd extends KMAbstractCmd { - public static final byte INS_ATTEST_KEY_CMD = 0x14; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_ATTEST_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMBeginOperationCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMBeginOperationCmd.java deleted file mode 100644 index 2ab55233..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMBeginOperationCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMBeginOperationCmd extends KMAbstractCmd { - public static final byte INS_BEGIN_OPERATION_CMD = 0x1F; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_BEGIN_OPERATION_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMBoolTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMBoolTag.java index 6cf41894..2e088893 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMBoolTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMBoolTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMBoolTag extends KMTag { @@ -81,7 +82,7 @@ public byte getVal() { // create default assignBlob without any value public static KMBoolTag instance(short key) { if (!validateKey(key)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMBoolTag tag = repository.newBoolTag(); tag.key = key; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMByteBlob.java b/Applet/Applet/src/com/android/javacard/keymaster/KMByteBlob.java index fca5b947..54b0e9e4 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMByteBlob.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMByteBlob.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.Util; // Byte val represents contiguous memory buffer. @@ -48,7 +49,7 @@ public static KMByteBlob instance() { // copy the blob public static KMByteBlob instance(byte[] blob, short startOff, short length) { if ((length <= 0) || ((short)(startOff+length) > blob.length)) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMByteBlob inst = instance(length); Util.arrayCopyNonAtomic(blob, startOff, inst.val, inst.startOff, inst.length); @@ -58,7 +59,7 @@ public static KMByteBlob instance(byte[] blob, short startOff, short length) { // returns empty blob with given length public static KMByteBlob instance(short length) { if (length <= 0) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMByteBlob inst = instance(); inst.startOff = repository.newByteArray(length); @@ -83,20 +84,20 @@ public KMByteBlob withLength(short len) { public void add(short index, byte val) { if (index >= this.length) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (this.val == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } this.val[(short) (startOff + index)] = val; } public byte get(short index) { if (index >= this.length) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (this.val == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } return this.val[(short) (startOff + index)]; } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMByteTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMByteTag.java index c415abbc..1569394c 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMByteTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMByteTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMByteTag extends KMTag { @@ -74,7 +75,7 @@ public static KMByteTag instance() { public static KMByteTag instance(short key) { if (!validateKey(key)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMByteTag tag = repository.newByteTag(); tag.key = key; @@ -93,7 +94,7 @@ public static void create(KMByteTag[] byteTagRefTable) { // create default assignBlob without any value public static KMByteTag instance(short key, KMByteBlob array) { if (!validateKey(key)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMByteTag tag = repository.newByteTag(); tag.key = key; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMCommand.java b/Applet/Applet/src/com/android/javacard/keymaster/KMCommand.java deleted file mode 100644 index 9e17dd58..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMCommand.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -import javacard.framework.APDU; - -/** This interface declares methods to be implemented by the command instances. */ -public interface KMCommand { - /** - * Execute this command within given context. If the command fails then it throws an exception - * - * @param context provides information required to execute the command. - */ - void execute(KMContext context); - - /** - * Return the instruction code associated with this command. The implementations will provide this - * code. - * - * @return instruction code which is related APDU INS. - */ - byte getIns(); - - /** - * Indicates whether command has arguments. - * @ return true if the command has arguments - */ - boolean hasArguments(); -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMComputeSharedHmacCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMComputeSharedHmacCmd.java deleted file mode 100644 index 5d2e0b46..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMComputeSharedHmacCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMComputeSharedHmacCmd extends KMAbstractCmd { - public static final byte INS_COMPUTE_SHARED_HMAC_CMD = 0x19; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_COMPUTE_SHARED_HMAC_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMContext.java b/Applet/Applet/src/com/android/javacard/keymaster/KMContext.java deleted file mode 100644 index 0d081f89..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMContext.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -/** - * This class provides data structure for information which is passed between the Keymaster Applet - * and the commands. It is created by applet and initialized for the process request. Applet sets - * repository, apdu and keymasterState. Command sets and uses incoming buffer information, outgoing - * buffer information and operation state (if command is an operation). - */ -public class KMContext { - private KMRepository repository; - private byte keymasterState; - private KMOperationState opState; - private byte[] buffer; - private short bufferLength; - /** - * Setter for the keymasterState. Set by the applet. - * - * @param keymasterState represents current applet state. - */ - public void setKeymasterState(byte keymasterState) { - this.keymasterState = keymasterState; - } - - /** - * Getter for keymasterState. Used by the commands. - * - * @return keymasterState represents current applets state. - */ - public byte getKeymasterState() { - return keymasterState; - } - - - /** - * Getter for buffer used for receiving or sending data to or from the master. Used by the - * messenger. - * - * @return buffer which is used to copying data to and from apdu's buffer. Start offset is always - * 0. - */ - public byte[] getBuffer() { - return buffer; - } - - /** - * Setter for buffer. Used by the repository. - * - * @param buffer which is used to copying data to and from apdu's buffer. - */ - public void setBuffer(byte[] buffer) { - this.buffer = buffer; - } - - /** - * Getter for buffer length. Used by the messenger and commands. - * - * @return buffer length. - */ - public short getBufferLength() { - return bufferLength; - } - - /** - * Setter for buffer length. Used by the messenger commands. - * - * @param length of buffer. - */ - public void setBufferLength(short length) { - this.bufferLength = length; - } - - /** - * Getter for repository instance. Used by commands. - * - * @return repository - */ - public KMRepository getRepository() { - return repository; - } - - /** - * Setter for the repository instance. Used by the applet. - * - * @param repository is repository of the KMType objects and other objects. - */ - public void setRepository(KMRepository repository) { - this.repository = repository; - } - - /** - * Getter for the OperationState for operation specific commands. Used by commands. - * - * @return Operation state associated with the command. - */ - public KMOperationState getOpState() { - return opState; - } - - /** Setter for the OperationState for operation specific commands. Used by commands. */ - public void setOpState(KMOperationState opState) { - this.opState = opState; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMDecoder.java b/Applet/Applet/src/com/android/javacard/keymaster/KMDecoder.java index 4cedfcaf..a1c43aa3 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMDecoder.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMDecoder.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.Util; // TODO Clean and refactor the code. public class KMDecoder { @@ -67,7 +68,7 @@ private KMIntegerArrayTag decode(KMIntegerArrayTag exp) { readTagKey(exp.getTagType()); // the values are array of integers. if (!(exp.getValues().getType() instanceof KMInteger)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } return exp.instance(this.tagKey, decode(exp.getValues(), (KMInteger) exp.getValues().getType())); } @@ -90,10 +91,10 @@ private KMBoolTag decode(KMBoolTag exp) { // BOOL Tag is a leaf node and it must always have tiny encoded uint value = 1. // TODO check this out. if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } if ((byte) (buffer[startOff] & ADDITIONAL_MASK) != 0x01) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } incrementStartOff((short) 1); return exp.instance(tagKey); @@ -104,12 +105,12 @@ private KMEnumTag decode(KMEnumTag exp) { // Enum Tag value will always be integer with max 1 byte length. // TODO Check this out. if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short len = (short) (buffer[startOff] & ADDITIONAL_MASK); byte enumVal = 0; if (len > UINT8_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (len < UINT8_LENGTH) { enumVal = (byte)(len & ADDITIONAL_MASK); @@ -126,12 +127,12 @@ private KMEnum decode(KMEnum exp) { // Enum value will always be integer with max 1 byte length. if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short len = (short) (buffer[startOff] & ADDITIONAL_MASK); byte enumVal = 0; if (len > UINT8_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (len < UINT8_LENGTH) { enumVal = (byte)(len & ADDITIONAL_MASK); @@ -147,9 +148,12 @@ private KMEnum decode(KMEnum exp) { private KMInteger decode(KMInteger exp) { KMInteger inst; if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short len = (short) (buffer[startOff] & ADDITIONAL_MASK); + if(len > UINT64_LENGTH){ + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } incrementStartOff((short) 1); if (len < UINT8_LENGTH) { inst = exp.uint_8((byte)(len & ADDITIONAL_MASK)); @@ -162,11 +166,9 @@ private KMInteger decode(KMInteger exp) { } else if (len == UINT32_LENGTH) { inst = exp.instance(buffer, startOff, (short) 4); incrementStartOff((short) 4); - } else if (len == UINT64_LENGTH) { + } else { inst = exp.instance(buffer, startOff, (short) 8); incrementStartOff((short) 8); - } else { - throw new KMException(ISO7816.SW_WRONG_LENGTH); } return inst; } @@ -181,7 +183,7 @@ private KMByteBlob decode(KMByteBlob exp) { private KMArray decode(KMArray exp) { short payloadLength = readMajorTypeWithPayloadLength(ARRAY_TYPE); if (exp.length() != payloadLength) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMArray inst = exp.instance(payloadLength); short index = 0; @@ -260,7 +262,7 @@ private KMType decode(KMType exp) { } if (exp instanceof KMVector) { if (!((((KMVector) exp).getType()) instanceof KMInteger)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } return decode((KMVector) exp, (KMInteger) ((KMVector) exp).getType()); } @@ -300,16 +302,17 @@ private KMType decode(KMType exp) { if (exp instanceof KMHardwareAuthToken) { return decode((KMHardwareAuthToken) exp); } - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); + return null; } private short peekTagType() { if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } if ((short) (buffer[startOff] & ADDITIONAL_MASK) != UINT32_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } return (short) ((Util.makeShort(buffer[(short) (startOff + 1)], buffer[(short) (startOff + 2)])) @@ -318,16 +321,16 @@ private short peekTagType() { private void readTagKey(short expectedTagType) { if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } if ((byte) (buffer[startOff] & ADDITIONAL_MASK) != UINT32_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } incrementStartOff((short) 1); this.tagType = readShort(); this.tagKey = readShort(); if (tagType != expectedTagType) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } } @@ -336,11 +339,11 @@ private short readMajorTypeWithPayloadLength(short majorType) { short payloadLength = 0; byte val = readByte(); if ((short) (val & MAJOR_TYPE_MASK) != majorType) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short lenType = (short) (val & ADDITIONAL_MASK); if (lenType > UINT16_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (lenType < UINT8_LENGTH) { payloadLength = lenType; @@ -367,7 +370,7 @@ private byte readByte() { private void incrementStartOff(short inc) { startOff += inc; if (startOff > this.length) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteAllKeysCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteAllKeysCmd.java deleted file mode 100644 index 5c476cd0..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteAllKeysCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMDeleteAllKeysCmd extends KMAbstractCmd { - public static final byte INS_DELETE_ALL_KEYS_CMD = 0x17; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_DELETE_ALL_KEYS_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteKeyCmd.java deleted file mode 100644 index ced6e7e4..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMDeleteKeyCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMDeleteKeyCmd extends KMAbstractCmd { - public static final byte INS_DELETE_KEY_CMD = 0x16; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_DELETE_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMDestroyAttestationIdsCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMDestroyAttestationIdsCmd.java deleted file mode 100644 index fa66ab1f..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMDestroyAttestationIdsCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMDestroyAttestationIdsCmd extends KMAbstractCmd { - public static final byte INS_DESTROY_ATT_IDS_CMD = 0x1A; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_DESTROY_ATT_IDS_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/Applet/src/com/android/javacard/keymaster/KMEncoder.java index a231563b..ec736de4 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.Util; public class KMEncoder { @@ -124,7 +125,7 @@ private void encode(KMType exp){ encode((KMHardwareAuthToken) exp); return; } - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } private void encode(KMKeyParameters obj) { @@ -288,7 +289,7 @@ private void writeByte(byte val){ private void incrementStartOff(short inc){ startOff += inc; if (startOff >= this.length) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMEnum.java b/Applet/Applet/src/com/android/javacard/keymaster/KMEnum.java index 7dad1d27..441fd833 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMEnum.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMEnum.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMEnum extends KMType { private static short[] types = {HARDWARE_TYPE, KEY_FORMAT, KEY_DERIVATION_FUNCTION}; @@ -48,7 +49,7 @@ public static KMEnum instance() { public static KMEnum instance(short enumType, byte val) { KMEnum inst = repository.newEnum(); if (!validateEnum(enumType, val)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } inst.type = enumType; inst.val = val; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java index 9c76ce66..30c40bad 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMEnumArrayTag extends KMTag { @@ -84,7 +85,7 @@ public static KMEnumArrayTag instance(short key) { // check if key is valid. byte[] vals = getAllowedEnumValues(key); if (vals == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMEnumArrayTag tag = repository.newEnumArrayTag(); tag.key = key; @@ -124,7 +125,7 @@ public static KMEnumArrayTag instance(short key, KMByteBlob blob) { // validate key byte[] allowedVals = getAllowedEnumValues(key); if (allowedVals == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short byteIndex = 0; while (byteIndex < blob.length()) { @@ -138,7 +139,7 @@ public static KMEnumArrayTag instance(short key, KMByteBlob blob) { enumIndex++; } if (!validValue) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } byteIndex++; } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMEnumTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMEnumTag.java index 3cfa840e..9a641425 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMEnumTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMEnumTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMEnumTag extends KMTag { @@ -60,13 +61,12 @@ public static KMEnumTag instance() { } public static KMEnumTag instance(short key) { - if (validateEnum(key, NO_VALUE)) { - KMEnumTag tag = repository.newEnumTag(); - tag.key = key; - return tag; - } else { - throw new KMException(ISO7816.SW_DATA_INVALID); + if(!validateEnum(key, NO_VALUE)){ + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } + KMEnumTag tag = repository.newEnumTag(); + tag.key = key; + return tag; } public static void create(KMEnumTag[] enumTagRefTable) { @@ -124,7 +124,7 @@ public byte getValue() { // instantiate enum tag. public static KMEnumTag instance(short key, byte val) { if (!validateEnum(key, val)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMEnumTag tag = instance(key); tag.val = val; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMException.java b/Applet/Applet/src/com/android/javacard/keymaster/KMException.java index 3e357613..3a26b047 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMException.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMException.java @@ -16,14 +16,13 @@ package com.android.javacard.keymaster; -import javacard.framework.ISOException; - -public class KMException extends ISOException { +public class KMException { // The Applet is not in a correct state in order to execute the command. public static final short CMD_NOT_ACCEPTED_WRONG_STATE = (short) 0x6901; - public KMException(short i) { - super(i); + + public static boolean handle(short reason) { + return false; } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMExportKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMExportKeyCmd.java deleted file mode 100644 index 05d28ef6..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMExportKeyCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMExportKeyCmd extends KMAbstractCmd { - public static final byte INS_EXPORT_KEY_CMD = 0x13; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_EXPORT_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMFinishOperationCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMFinishOperationCmd.java deleted file mode 100644 index 0267e4fb..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMFinishOperationCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMFinishOperationCmd extends KMAbstractCmd { - public static final byte INS_FINISH_OPERATION_CMD = 0x21; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_FINISH_OPERATION_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMGenerateKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMGenerateKeyCmd.java deleted file mode 100644 index 0c2d69d1..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMGenerateKeyCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMGenerateKeyCmd extends KMAbstractCmd { - public static final byte INS_GENERATE_KEY_CMD = 0x10; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_GENERATE_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMGetHWInfoCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMGetHWInfoCmd.java deleted file mode 100644 index 3f6cb8f8..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMGetHWInfoCmd.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMGetHWInfoCmd extends KMAbstractCmd { - public static final byte INS_GET_HW_INFO_CMD = 0x1E; - public static final byte[] JavacardKeymasterDevice = { - 0x4A, 0x61, 0x76, 0x61, 0x63, 0x61, 0x72, 0x64, 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, - 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - }; - public static final byte[] Google = {0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65}; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return KMArray.instance((short) 3) - .add((short) 0, KMEnum.instance(KMType.HARDWARE_TYPE, KMType.STRONGBOX)) - .add( - (short) 1, - KMByteBlob.instance( - JavacardKeymasterDevice, (short) 0, (short) JavacardKeymasterDevice.length)) - .add((short) 2, KMByteBlob.instance(Google, (short) 0, (short) Google.length)); - } - - @Override - public byte getIns() { - return INS_GET_HW_INFO_CMD; - } - - @Override - public boolean hasArguments() { - return false; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMGetHmacSharingParametersCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMGetHmacSharingParametersCmd.java deleted file mode 100644 index 19165531..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMGetHmacSharingParametersCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMGetHmacSharingParametersCmd extends KMAbstractCmd { - public static final byte INS_GET_HMAC_SHARING_PARAM_CMD = 0x1C; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_GET_HMAC_SHARING_PARAM_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMGetKeyCharacteristicsCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMGetKeyCharacteristicsCmd.java deleted file mode 100644 index 20fef22b..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMGetKeyCharacteristicsCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMGetKeyCharacteristicsCmd extends KMAbstractCmd { - public static final byte INS_GET_KEY_CHARACTERISTICS_CMD = 0x1D; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_GET_KEY_CHARACTERISTICS_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java b/Applet/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java index ca3c2804..9c188c67 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMHardwareAuthToken extends KMType { public static final byte CHALLENGE = 0x00; @@ -56,7 +57,7 @@ public static KMHardwareAuthToken instance() { public static KMHardwareAuthToken instance(KMArray vals) { if (vals.length() != 6) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMHardwareAuthToken inst = repository.newHwAuthToken(); inst.vals = vals; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java b/Applet/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java index ef08696b..a1fca4d1 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMHmacSharingParameters extends KMType { public static final byte SEED = 0x00; @@ -47,7 +48,7 @@ public static KMHmacSharingParameters instance() { public static KMHmacSharingParameters instance(KMArray vals) { if (vals.length() != 2) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMHmacSharingParameters inst = repository.newHmacSharingParameters(); inst.vals = vals; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMImportKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMImportKeyCmd.java deleted file mode 100644 index 6be0d0d7..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMImportKeyCmd.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMImportKeyCmd extends KMAbstractCmd { - public static final byte INS_IMPORT_KEY_CMD = 0x11; - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_IMPORT_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMImportWrappedKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMImportWrappedKeyCmd.java deleted file mode 100644 index e9896748..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMImportWrappedKeyCmd.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMImportWrappedKeyCmd extends KMAbstractCmd { - public static final byte INS_IMPORT_WRAPPED_KEY_CMD = 0x12; - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_IMPORT_WRAPPED_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/Applet/src/com/android/javacard/keymaster/KMInteger.java index 19996d18..987a0858 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.Util; // Represents 8 bit, 16 bit, 32 bit and 64 bit integers @@ -99,34 +100,35 @@ public KMInteger setValue(byte[] val) { public short getShort() { if (val == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } else if (val.length != 4) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } return Util.makeShort(val[2], val[3]); } public byte getByte() { if (val == null) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } else if (val.length != 4) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } return val[3]; } // copy the integer value from bytes public static KMInteger instance(byte[] num, short srcOff, short length) { + if(length > 8){ + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } if (length == 1) { return uint_8(num[srcOff]); } else if (length == 2) { return uint_16(Util.makeShort(num[srcOff], num[(short) (srcOff + 1)])); } else if (length == 4) { return uint_32(num, srcOff); - } else if (length == 8) { - return uint_64(num, srcOff); } else { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + return uint_64(num, srcOff); } } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java index 9c9258a2..df96e114 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMIntegerArrayTag extends KMTag { private static final short[] tags = {USER_SECURE_ID}; @@ -69,7 +70,7 @@ public KMIntegerArrayTag asUlongArray() { public static KMIntegerArrayTag instance(short key) { if (!validateKey(key)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMIntegerArrayTag tag = repository.newIntegerArrayTag(); tag.key = key; @@ -79,10 +80,10 @@ public static KMIntegerArrayTag instance(short key) { public static KMIntegerArrayTag instance(short key, KMVector val) { if (!(val.getType() instanceof KMInteger)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } if (!(validateKey(key))) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMIntegerArrayTag tag = repository.newIntegerArrayTag(); tag.key = key; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java b/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java index 00dbf256..d583f6b2 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; // Implements UINT, ULONG and DATE tags. public class KMIntegerTag extends KMTag { @@ -78,7 +79,7 @@ public static KMIntegerTag instance() { public static KMIntegerTag instance(short key) { if (!validateKey(key)) { - throw new KMException(ISO7816.SW_DATA_INVALID); + ISOException.throwIt(ISO7816.SW_DATA_INVALID); } KMIntegerTag tag = repository.newIntegerTag(); tag.key = key; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java b/Applet/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java index a6b5c7fe..d4c1a9b5 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMKeyCharacteristics extends KMType { public static final byte SOFTWARE_ENFORCED = 0x00; @@ -47,7 +48,7 @@ public static KMKeyCharacteristics instance() { public static KMKeyCharacteristics instance(KMArray vals) { if (vals.length() != 2) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMKeyCharacteristics inst = repository.newKeyCharacteristics(); inst.vals = vals; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 83512f92..0ee85ff1 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -19,7 +19,10 @@ import javacard.framework.APDU; import javacard.framework.Applet; import javacard.framework.AppletEvent; +import javacard.framework.CardRuntimeException; import javacard.framework.ISO7816; +import javacard.framework.ISOException; +import javacard.framework.JCSystem; import javacard.framework.Util; import javacardx.apdu.ExtendedLength; @@ -32,29 +35,63 @@ // - remove this in future. public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLength { // Constants. - public static final short MAX_LENGTH = (short) 0x04ff; // TODO: make this value configurable. + private static final short MAX_LENGTH = (short) 0x1000; // TODO: make this value configurable. private static final byte CLA_ISO7816_NO_SM_NO_CHAN = (byte) 0x80; - private static final byte KM_HAL_VERSION = (byte) 0x41; + private static final short KM_HAL_VERSION = (short) 0x4000; // Possible states of the applet. - public static final byte ILLEGAL_STATE = 0x00; - public static final byte INSTALL_STATE = 0x01; - public static final byte FIRST_SELECT_STATE = 0x02; - public static final byte ACTIVE_STATE = 0x03; - public static final byte INACTIVE_STATE = 0x04; - public static final byte UNINSTALLED_STATE = 0x05; + private static final byte ILLEGAL_STATE = 0x00; + private static final byte INSTALL_STATE = 0x01; + private static final byte FIRST_SELECT_STATE = 0x02; + private static final byte ACTIVE_STATE = 0x03; + private static final byte INACTIVE_STATE = 0x04; + private static final byte UNINSTALLED_STATE = 0x05; + + // Commands + private static final byte INS_GENERATE_KEY_CMD = 0x10; + private static final byte INS_IMPORT_KEY_CMD = 0x11; + private static final byte INS_IMPORT_WRAPPED_KEY_CMD = 0x12; + private static final byte INS_EXPORT_KEY_CMD = 0x13; + private static final byte INS_ATTEST_KEY_CMD = 0x14; + private static final byte INS_UPGRADE_KEY_CMD = 0x15; + private static final byte INS_DELETE_KEY_CMD = 0x16; + private static final byte INS_DELETE_ALL_KEYS_CMD = 0x17; + private static final byte INS_ADD_RNG_ENTROPY_CMD = 0x18; + private static final byte INS_COMPUTE_SHARED_HMAC_CMD = 0x19; + private static final byte INS_DESTROY_ATT_IDS_CMD = 0x1A; + private static final byte INS_VERIFY_AUTHORIZATION_CMD = 0x1B; + private static final byte INS_GET_HMAC_SHARING_PARAM_CMD = 0x1C; + private static final byte INS_GET_KEY_CHARACTERISTICS_CMD = 0x1D; + private static final byte INS_GET_HW_INFO_CMD = 0x1E; + private static final byte INS_BEGIN_OPERATION_CMD = 0x1F; + private static final byte INS_UPDATE_OPERATION_CMD = 0x20; + private static final byte INS_FINISH_OPERATION_CMD = 0x21; + private static final byte INS_ABORT_OPERATION_CMD = 0x22; + private static final byte INS_PROVISION_CMD = 0x23; + + // GetHwInfo information + // TODO change this to just filling the buffer + private static final byte[] JavacardKeymasterDevice = { + 0x4A, 0x61, 0x76, 0x61, 0x63, 0x61, 0x72, 0x64, 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, + 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + }; + private static final byte[] Google = {0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65}; + private static final short MAX_SEED_SIZE = 2048; // State of the applet. - private byte keymasterState = ILLEGAL_STATE; + private KMEncoder encoder; + private KMDecoder decoder; private KMRepository repository; + private byte keymasterState = ILLEGAL_STATE; + private byte[] buffer; - /** - * Registers this applet. - * - * @param repo reference to the repository which manages all the NVM objects. - */ - protected KMKeymasterApplet(KMRepository repo) { - repository = repo; + /** Registers this applet. */ + protected KMKeymasterApplet() { + keymasterState = KMKeymasterApplet.INSTALL_STATE; + repository = KMRepository.instance(); + KMUtil.init(); + encoder = new KMEncoder(); + decoder = new KMDecoder(); register(); } @@ -66,11 +103,7 @@ protected KMKeymasterApplet(KMRepository repo) { * @param bLength the length in bytes of the parameter data in bArray */ public static void install(byte[] bArray, short bOffset, byte bLength) { - KMRepository repo = new KMRepository(); - // TODO: Read the configuration from the package and pass the data in initialize method. - repo.initialize(); - KMKeymasterApplet keymaster = new KMKeymasterApplet(repo); - keymaster.setKeymasterState(KMKeymasterApplet.INSTALL_STATE); + KMKeymasterApplet keymaster = new KMKeymasterApplet(); } /** @@ -80,11 +113,11 @@ public static void install(byte[] bArray, short bOffset, byte bLength) { */ @Override public boolean select() { - repository.onSelect(); - if (getKeymasterState() == KMKeymasterApplet.INSTALL_STATE) { - setKeymasterState(KMKeymasterApplet.FIRST_SELECT_STATE); - } else if (getKeymasterState() == KMKeymasterApplet.INACTIVE_STATE) { - setKeymasterState(KMKeymasterApplet.ACTIVE_STATE); + KMRepository.instance().onSelect(); + if (keymasterState == KMKeymasterApplet.INSTALL_STATE) { + keymasterState = KMKeymasterApplet.FIRST_SELECT_STATE; + } else if (keymasterState == KMKeymasterApplet.INACTIVE_STATE) { + keymasterState = KMKeymasterApplet.ACTIVE_STATE; } else { return false; } @@ -94,34 +127,36 @@ public boolean select() { /** De-selects this applet. */ @Override public void deselect() { - repository.onDeselect(); - if (getKeymasterState() == KMKeymasterApplet.ACTIVE_STATE) { - setKeymasterState(KMKeymasterApplet.INACTIVE_STATE); + KMRepository.instance().onDeselect(); + if (keymasterState == KMKeymasterApplet.ACTIVE_STATE) { + keymasterState = KMKeymasterApplet.INACTIVE_STATE; } } /** Uninstalls the applet after cleaning the repository. */ @Override public void uninstall() { - repository.onUninstall(); - if (getKeymasterState() != KMKeymasterApplet.UNINSTALLED_STATE) { - setKeymasterState(KMKeymasterApplet.UNINSTALLED_STATE); + KMRepository.instance().onUninstall(); + if (keymasterState != KMKeymasterApplet.UNINSTALLED_STATE) { + keymasterState = KMKeymasterApplet.UNINSTALLED_STATE; } } /** * Processes an incoming APDU and handles it using command objects. * - * @see APDU * @param apdu the incoming APDU */ @Override public void process(APDU apdu) { - repository.onProcess(); + KMRepository.instance().onProcess(); + if (buffer == null) { + buffer = JCSystem.makeTransientByteArray(MAX_LENGTH, JCSystem.CLEAR_ON_RESET); + } // Verify whether applet is in correct state. - if ((getKeymasterState() != KMKeymasterApplet.ACTIVE_STATE) - && (getKeymasterState() != KMKeymasterApplet.FIRST_SELECT_STATE)) { - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if ((keymasterState != KMKeymasterApplet.ACTIVE_STATE) + && (keymasterState != KMKeymasterApplet.FIRST_SELECT_STATE)) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } // If this is select applet apdu which is selecting this applet then return if (apdu.isISOInterindustryCLA()) { @@ -129,105 +164,295 @@ public void process(APDU apdu) { return; } } - // Read the apdu header and buffer. - byte[] buffer = apdu.getBuffer(); - byte apduClass = buffer[ISO7816.OFFSET_CLA]; - byte apduIns = buffer[ISO7816.OFFSET_INS]; - byte halVersion = buffer[ISO7816.OFFSET_P1]; - byte apduP2 = buffer[ISO7816.OFFSET_P2]; - + byte[] apduBuffer = apdu.getBuffer(); + byte apduClass = apduBuffer[ISO7816.OFFSET_CLA]; + byte apduIns = apduBuffer[ISO7816.OFFSET_INS]; + short P1P2 = Util.getShort(apduBuffer, ISO7816.OFFSET_P1); // Validate APDU Header. if ((apduClass != CLA_ISO7816_NO_SM_NO_CHAN)) { - throw new KMException(ISO7816.SW_CLA_NOT_SUPPORTED); - } else if ((halVersion != KMKeymasterApplet.KM_HAL_VERSION) && (apduP2 != (byte) 0x00)) { - throw new KMException(ISO7816.SW_INCORRECT_P1P2); + ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); + } else if (P1P2 != KMKeymasterApplet.KM_HAL_VERSION) { + ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); } - - // Process the APDU. - try { - // Get the command object for specific INS from the repository. - KMCommand command = repository.getCommand(apduIns); - // Get the empty context object from the repository. - KMContext context = repository.getContext(); - // Initialize context - context.setKeymasterState(getKeymasterState()); - context.setBuffer(repository.getBuffer()); - if(command.hasArguments()){ - receiveIncoming(context, apdu); + // Validate whether INS can be supported + if (!(apduIns >= INS_GENERATE_KEY_CMD && apduIns <= INS_PROVISION_CMD)) { + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); + } + // Validate if INS is provision command if applet is in FIRST_SELECT_STATE. + if (keymasterState == KMKeymasterApplet.FIRST_SELECT_STATE) { + if (apduIns != INS_PROVISION_CMD) { + ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED); } - // Execute the command. If the execution fails then an exception is thrown. - command.execute(context); - - // context has data that needs to be sent - if(context.getBufferLength() >0 ){ - sendOutgoing(context, apdu); + } + // Process the apdu + try { + // Handle the command + handle(apduIns, apdu); + } catch (CardRuntimeException exception) { + if (!(KMException.handle(exception.getReason()))) { + CardRuntimeException.throwIt(exception.getReason()); } - - // Update the Keymaster state according to the context. - setKeymasterState(context.getKeymasterState()); - } catch (KMException exception) { - // TODO: error handling for command related error. - // TODO: This should result in ISOException or exception with keymaster specific error codes + } finally { + // Reset the buffer. + Util.arrayFillNonAtomic(buffer, (short) 0, MAX_LENGTH, (byte) 0); } } - /** - * Sends a response, may be extended response, as requested by the command. - * - * @param context of current command. - */ - public void sendOutgoing(KMContext context, APDU apdu) { - // Initialize source - short srcLength = context.getBufferLength(); + /** Sends a response, may be extended response, as requested by the command. */ + private void sendOutgoing(byte[] srcBuffer, short srcLength, APDU apdu) { if (srcLength > MAX_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // Send data - byte[] srcBuffer = context.getBuffer(); apdu.setOutgoing(); apdu.setOutgoingLength(srcLength); apdu.sendBytesLong(srcBuffer, (short) 0, srcLength); } - /** - * Receives data, which can be extended data, as requested by the command instance. - * - * @param context of current command. - */ - public void receiveIncoming(KMContext context, APDU apdu) { + /** Receives data, which can be extended data, as requested by the command instance. */ + private short receiveIncoming(byte[] destBuffer, APDU apdu) { // Initialize source byte[] srcBuffer = apdu.getBuffer(); // Initialize destination - byte[] destBuffer = context.getBuffer(); short destOffset = (short) 0; - // Receive data short recvLen = apdu.setIncomingAndReceive(); short srcOffset = apdu.getOffsetCdata(); short srcLength = apdu.getIncomingLength(); if (srcLength > MAX_LENGTH) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } while (recvLen > 0) { Util.arrayCopyNonAtomic(srcBuffer, srcOffset, destBuffer, destOffset, recvLen); destOffset += recvLen; recvLen = apdu.receiveBytes(srcOffset); } - // Update the Context - context.setBufferLength(srcLength); + return srcLength; } - /** - * Getter for keymaster state. - * - * @return keymasterState - current state of the applet. - */ - private byte getKeymasterState() { - return keymasterState; + // Commands + private void handle(byte ins, APDU apdu) { + switch (ins) { + case INS_GENERATE_KEY_CMD: + processGenerateKey(apdu); + break; + case INS_IMPORT_KEY_CMD: + processImportKeyCmd(apdu); + break; + case INS_IMPORT_WRAPPED_KEY_CMD: + processImportWrappedKeyCmd(apdu); + break; + case INS_EXPORT_KEY_CMD: + processExportKeyCmd(apdu); + break; + case INS_ATTEST_KEY_CMD: + processAttestKeyCmd(apdu); + break; + case INS_UPGRADE_KEY_CMD: + processUpgradeKeyCmd(apdu); + break; + case INS_DELETE_KEY_CMD: + processDeleteKeyCmd(apdu); + break; + case INS_DELETE_ALL_KEYS_CMD: + processDeleteAllKeysCmd(apdu); + break; + case INS_ADD_RNG_ENTROPY_CMD: + processAddRngEntropyCmd(apdu); + break; + case INS_COMPUTE_SHARED_HMAC_CMD: + processComputeSharedHmacCmd(apdu); + break; + case INS_DESTROY_ATT_IDS_CMD: + processDestroyAttIdsCmd(apdu); + break; + case INS_VERIFY_AUTHORIZATION_CMD: + processVerifyAuthenticationCmd(apdu); + break; + case INS_GET_HMAC_SHARING_PARAM_CMD: + processGetHmacSharingParamCmd(apdu); + break; + case INS_GET_KEY_CHARACTERISTICS_CMD: + processGetKeyCharacteristicsCmd(apdu); + break; + case INS_GET_HW_INFO_CMD: + processGetHwInfoCmd(apdu); + break; + case INS_BEGIN_OPERATION_CMD: + processBeginOperationCmd(apdu); + break; + case INS_UPDATE_OPERATION_CMD: + processUpdateOperationCmd(apdu); + break; + case INS_FINISH_OPERATION_CMD: + processFinishOperationCmd(apdu); + break; + case INS_ABORT_OPERATION_CMD: + processAbortOperationCmd(apdu); + break; + case INS_PROVISION_CMD: + processProvisionCmd(apdu); + break; + default: + ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); + } } - /** Setter for keymaster state. */ - private void setKeymasterState(byte keymasterState) { - this.keymasterState = keymasterState; + + private short processProvisionCmd(APDU apdu) { + // Receive the incoming request fully from the master. + short length = receiveIncoming(buffer, apdu); + // Re-purpose the apdu buffer as scratch pad. + byte[] scratchPad = apdu.getBuffer(); + Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) apdu.getBuffer().length, (byte) 0); + // Argument 1 + KMKeyParameters keyparams = KMKeyParameters.instance(); + // Argument 2 + KMEnum keyFormat = KMEnum.instance().setType(KMType.KEY_FORMAT); + // Argument 3 + KMByteBlob keyBlob = KMByteBlob.instance(); + // Array of expected arguments + KMArray argsProto = + KMArray.instance((short) 3) + .add((short) 0, keyparams) + .add((short) 1, keyFormat) + .add((short) 2, keyBlob); + // Decode the argument + KMArray args = decoder.decode(argsProto, buffer, (short) 0, length); + // TODO execute the function + // Change the state to ACTIVE + if (keymasterState == KMKeymasterApplet.FIRST_SELECT_STATE) { + keymasterState = KMKeymasterApplet.ACTIVE_STATE; + } + // nothing to return + return 0; + } + + private void processGetHwInfoCmd(APDU apdu) { + // No arguments expected + // Make the response + KMArray resp = + KMArray.instance((short) 3) + .add((short) 0, KMEnum.instance(KMType.HARDWARE_TYPE, KMType.STRONGBOX)) + .add( + (short) 1, + KMByteBlob.instance( + JavacardKeymasterDevice, (short) 0, (short) JavacardKeymasterDevice.length)) + .add((short) 2, KMByteBlob.instance(Google, (short) 0, (short) Google.length)); + // Reuse the buffer + Util.arrayFillNonAtomic(buffer, (short) 0, MAX_LENGTH, (byte) 0); + // Encode the response + short len = encoder.encode(resp, buffer, (short) 0, MAX_LENGTH); + sendOutgoing(buffer, len, apdu); + } + + private short processAddRngEntropyCmd(APDU apdu) { + // Receive the incoming request fully from the master. + short length = receiveIncoming(buffer, apdu); + // Re-purpose the apdu buffer as scratch pad. + byte[] scratchPad = apdu.getBuffer(); + Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) apdu.getBuffer().length, (byte) 0); + // Argument 1 + KMArray argsProto = KMArray.instance((short) 1).add((short) 0, KMByteBlob.instance()); + + // Decode the argument + KMArray args = decoder.decode(argsProto, buffer, (short) 0, length); + // Process + KMByteBlob blob = (KMByteBlob) args.get((short) 0); + // Maximum 2KiB of seed is allowed. + if (blob.length() > MAX_SEED_SIZE) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + // Get existing entropy pool. + byte[] entPool = KMUtil.getEntropyPool(); + // Create new temporary pool. + byte[] heapRef = repository.getByteHeapRef(); + short poolStart = repository.newByteArray((short) entPool.length); + // Populate the new pool with the entropy which is derived from current entropy pool. + KMUtil.newRandomNumber(heapRef, poolStart, (short) entPool.length); + // Copy the entropy to the current pool - updates the entropy pool. + Util.arrayCopy(heapRef, poolStart, entPool, (short) 0, (short) entPool.length); + short index = 0; + short randIndex = 0; + // Mix (XOR) the seed received from the master in the entropy pool - 32 bytes (entPool.length). + // at a time. + while (index < blob.length()) { + entPool[randIndex] = (byte) (entPool[randIndex] ^ blob.get(index)); + randIndex++; + index++; + if (randIndex >= entPool.length) { + randIndex = 0; + } + } + // Nothing to return + return 0; + } + + private short processAbortOperationCmd(APDU apdu) { + return 0; + } + + private short processFinishOperationCmd(APDU apdu) { + return 0; + } + + private short processUpdateOperationCmd(APDU apdu) { + return 0; + } + + private short processBeginOperationCmd(APDU apdu) { + return 0; + } + + private short processGetKeyCharacteristicsCmd(APDU apdu) { + return 0; + } + + private short processGetHmacSharingParamCmd(APDU apdu) { + return 0; + } + + private short processVerifyAuthenticationCmd(APDU apdu) { + return 0; + } + + private short processDestroyAttIdsCmd(APDU apdu) { + return 0; + } + + private short processComputeSharedHmacCmd(APDU apdu) { + return 0; + } + + private short processDeleteAllKeysCmd(APDU apdu) { + return 0; + } + + private short processDeleteKeyCmd(APDU apdu) { + return 0; + } + + private short processUpgradeKeyCmd(APDU apdu) { + return 0; + } + + private short processAttestKeyCmd(APDU apdu) { + return 0; + } + + private short processExportKeyCmd(APDU apdu) { + return 0; + } + + private short processImportWrappedKeyCmd(APDU apdu) { + return 0; + } + + private short processImportKeyCmd(APDU apdu) { + return 0; + } + + private short processGenerateKey(APDU apdu) { + return 0; } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMMessenger.java b/Applet/Applet/src/com/android/javacard/keymaster/KMMessenger.java deleted file mode 100644 index 3eb4b548..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMMessenger.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public interface KMMessenger { - void receiveIncoming(KMContext context); - void sendOutgoing(KMContext context); -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 5aaa9948..d1671328 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -23,12 +23,12 @@ public class KMOperationState { private KMOperationState() { operationHandle = null; } - +/* public static KMOperationState instance(KMContext context) { // TODO make operation handle return context.getRepository().newOperationState(); } - +*/ public static void create(KMOperationState[] opStateRefTable) { byte index = 0; while (index < opStateRefTable.length) { @@ -44,9 +44,11 @@ public KMInteger getOperationHandle() { public void setOperationHandle(KMInteger operationHandle) { this.operationHandle = operationHandle; } - +/* public void release(KMContext context) { // TODO release handle context.getRepository().releaseOperationState(this); } + + */ } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMProvisionCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMProvisionCmd.java deleted file mode 100644 index d1911f7e..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMProvisionCmd.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMProvisionCmd extends KMAbstractCmd { - public static final byte INS_PROVISION_CMD = 0x23; - - @Override - public byte getIns() { - return INS_PROVISION_CMD; - } - - @Override - public KMArray process(KMArray args, KMContext context) { - KMKeyParameters arg1 = (KMKeyParameters)args.get((short)0); - KMEnum arg2 = (KMEnum)args.get((short)1); - KMByteBlob arg3 = (KMByteBlob)args.get((short)2); - provision(arg1, arg2.getVal(),arg3); - context.setKeymasterState(KMKeymasterApplet.ACTIVE_STATE); - //nothing to return - return null; - } - - // TODO implement functionality - private void provision(KMKeyParameters params, byte keyFormat, KMByteBlob keyBlob){ - } - - @Override - protected boolean validateState(byte state) { - return (KMKeymasterApplet.FIRST_SELECT_STATE == state); - } - - // Uses import key command signature but does not return anything back. - protected KMArray getExpectedArgs() { - // Argument 1 - KMKeyParameters keyparams = KMKeyParameters.instance(); - // Argument 2 - KMEnum keyFormat = KMEnum.instance().setType(KMType.KEY_FORMAT); - // Argument 3 - KMByteBlob keyBlob = KMByteBlob.instance(); - // Array of expected arguments - return KMArray.instance((short) 3) - .add((short) 0, keyparams) - .add((short) 1, keyFormat) - .add((short) 2, keyBlob); - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/Applet/src/com/android/javacard/keymaster/KMRepository.java index 36d8f6f7..b71aea01 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.JCSystem; import javacard.framework.Util; import javacard.security.AESKey; @@ -27,20 +28,14 @@ // to handle onInstall and onSelect. public class KMRepository { - private static final byte CMD_TABLE_LENGTH = 20; private static final byte REF_TABLE_SIZE = 5; private static final short HEAP_SIZE = 0x1000; private static final byte INT_TABLE_SIZE = 10; private static final byte TYPE_ARRAY_SIZE = 100; private static final byte INT_SIZE = 4; private static final byte LONG_SIZE = 8; - private static final short ENTROPY_POOL_SIZE = 32; - - private KMCommand[] commandTable = null; - private KMContext context = null; - private byte[] buffer = null; + private static KMRepository repository; private AESKey masterKey = null; - private boolean contextLocked = false; private KMEncoder encoder = null; private KMDecoder decoder = null; @@ -91,38 +86,23 @@ public class KMRepository { private byte[] entropyPool = null; private byte[] counter; - public void initialize() { + public static KMRepository instance() { + if (repository == null) { + repository = new KMRepository(); + } + return repository; + } + + public KMRepository(){ + initialize(); + } + + private void initialize() { // Initialize buffers and context. JCSystem.beginTransaction(); encoder = new KMEncoder(); decoder = new KMDecoder(); - buffer = new byte[KMKeymasterApplet.MAX_LENGTH]; - context = new KMContext(); - context.setRepository(this); - contextLocked = false; operationStateTable = new KMOperationState[4]; - // Initialize command table. - commandTable = new KMCommand[CMD_TABLE_LENGTH]; - commandTable[0] = new KMProvisionCmd(); - commandTable[1] = new KMGenerateKeyCmd(); - commandTable[2] = new KMImportKeyCmd(); - commandTable[3] = new KMExportKeyCmd(); - commandTable[4] = new KMComputeSharedHmacCmd(); - commandTable[5] = new KMBeginOperationCmd(); - commandTable[6] = new KMUpdateOperationCmd(); - commandTable[7] = new KMFinishOperationCmd(); - commandTable[8] = new KMAbortOperationCmd(); - commandTable[9] = new KMVerifyAuthorizationCmd(); - commandTable[10] = new KMAddRngEntropyCmd(); - commandTable[11] = new KMImportWrappedKeyCmd(); - commandTable[12] = new KMAttestKeyCmd(); - commandTable[13] = new KMUpgradeKeyCmd(); - commandTable[14] = new KMDeleteKeyCmd(); - commandTable[15] = new KMDeleteAllKeysCmd(); - commandTable[16] = new KMDestroyAttestationIdsCmd(); - commandTable[17] = new KMGetHWInfoCmd(); - commandTable[18] = new KMGetKeyCharacteristicsCmd(); - commandTable[19] = new KMGetHmacSharingParametersCmd(); // Initialize masterkey - AES 256 bit key. if (masterKey == null) { masterKey = @@ -176,8 +156,6 @@ public void initialize() { uint64Array[index] = new byte[LONG_SIZE]; index++; } - entropyPool = new byte[ENTROPY_POOL_SIZE]; - counter = new byte[8]; JCSystem.commitTransaction(); } @@ -190,26 +168,6 @@ public KMDecoder getDecoder() { return decoder; } - public KMCommand getCommand(byte ins) throws KMException { - short cmdIndex = 0; - while (cmdIndex < CMD_TABLE_LENGTH) { - if (commandTable[cmdIndex].getIns() == ins) { - return commandTable[cmdIndex]; - } - cmdIndex++; - } - throw new KMException(ISO7816.SW_INS_NOT_SUPPORTED); - } - - public KMContext getContext() throws KMException { - if (!contextLocked) { - contextLocked = true; - return context; - } else { - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); - } - } - public void onUninstall() { masterKey = null; } @@ -219,11 +177,8 @@ public void onProcess() { } private void reset() { - contextLocked = false; - Util.arrayFillNonAtomic(buffer, (short) 0, (short) buffer.length, (byte) 0); - Util.arrayFillNonAtomic(byteHeap, (short) 0, (short) buffer.length, (byte) 0); + Util.arrayFillNonAtomic(byteHeap, (short) 0, (short) byteHeap.length, (byte) 0); byteHeapIndex = 0; - Util.arrayFillNonAtomic(buffer, (short) 0, (short) buffer.length, (byte) 0); short index = 0; while (index < typeRefTable.length) { typeRefTable[index] = null; @@ -285,10 +240,6 @@ public void onSelect() { // Nothing to be done currently. } - public byte[] getBuffer() { - return buffer; - } - public AESKey getMasterKey() { return masterKey; } @@ -298,7 +249,7 @@ public byte[] newIntegerArray(short length) { if (length == 4) { if (uint32Index >= uint32Array.length) { // TODO this is placeholder exception value. This needs to be replaced by 910E, 91A1 or 9210 - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } byte[] ret = (byte[]) uint32Array[uint32Index]; uint32Index++; @@ -306,20 +257,21 @@ public byte[] newIntegerArray(short length) { } else if (length == 8) { if (uint64Index >= uint64Array.length) { // TODO this is placeholder exception value. This needs to be replaced by 910E, 91A1 or 9210 - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } byte[] ret = (byte[]) uint64Array[uint64Index]; uint64Index++; return ret; } else { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } + return null;// this will never be executed. } public KMByteBlob newByteBlob() { if (blobRefIndex >= byteBlobRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMByteBlob ret = byteBlobRefTable[blobRefIndex]; blobRefIndex++; @@ -329,7 +281,7 @@ public KMByteBlob newByteBlob() { public KMInteger newInteger() { if (intRefIndex >= integerRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMInteger ret = integerRefTable[intRefIndex]; intRefIndex++; @@ -339,7 +291,7 @@ public KMInteger newInteger() { public KMEnumTag newEnumTag() { if (enumTagRefIndex >= enumTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMEnumTag ret = enumTagRefTable[enumTagRefIndex]; enumTagRefIndex++; @@ -349,7 +301,7 @@ public KMEnumTag newEnumTag() { public KMEnumArrayTag newEnumArrayTag() { if (enumArrayTagRefIndex >= enumArrayTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMEnumArrayTag ret = enumArrayTagRefTable[enumArrayTagRefIndex]; enumArrayTagRefIndex++; @@ -359,7 +311,7 @@ public KMEnumArrayTag newEnumArrayTag() { public KMIntegerTag newIntegerTag() { if (intTagRefIndex >= intTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMIntegerTag ret = intTagRefTable[intTagRefIndex]; intTagRefIndex++; @@ -369,7 +321,7 @@ public KMIntegerTag newIntegerTag() { public KMIntegerArrayTag newIntegerArrayTag() { if (intArrayTagRefIndex >= intArrayTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMIntegerArrayTag ret = intArrayTagRefTable[intArrayTagRefIndex]; intArrayTagRefIndex++; @@ -379,7 +331,7 @@ public KMIntegerArrayTag newIntegerArrayTag() { public KMBoolTag newBoolTag() { if (boolTagRefIndex >= boolTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMBoolTag ret = boolTagRefTable[boolTagRefIndex]; boolTagRefIndex++; @@ -389,7 +341,7 @@ public KMBoolTag newBoolTag() { public KMByteTag newByteTag() { if (byteTagRefIndex >= byteTagRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMByteTag ret = byteTagRefTable[byteTagRefIndex]; byteTagRefIndex++; @@ -399,7 +351,7 @@ public KMByteTag newByteTag() { public KMKeyParameters newKeyParameters() { if (keyParametersRefIndex >= keyParametersRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMKeyParameters ret = keyParametersRefTable[keyParametersRefIndex]; keyParametersRefIndex++; @@ -409,7 +361,7 @@ public KMKeyParameters newKeyParameters() { public KMArray newArray() { if (arrayRefIndex >= arrayRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMArray ret = arrayRefTable[arrayRefIndex]; arrayRefIndex++; @@ -419,7 +371,7 @@ public KMArray newArray() { public KMKeyCharacteristics newKeyCharacteristics() { if (keyCharRefIndex >= keyCharRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMKeyCharacteristics ret = keyCharRefTable[keyCharRefIndex]; keyCharRefIndex++; @@ -429,7 +381,7 @@ public KMKeyCharacteristics newKeyCharacteristics() { public KMHardwareAuthToken newHwAuthToken() { if (hwAuthTokenRefIndex >= hwAuthTokenRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMHardwareAuthToken ret = hwAuthTokenRefTable[hwAuthTokenRefIndex]; hwAuthTokenRefIndex++; @@ -439,7 +391,7 @@ public KMHardwareAuthToken newHwAuthToken() { public KMHmacSharingParameters newHmacSharingParameters() { if (hmacSharingParamsRefIndex >= hmacSharingParamsRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMHmacSharingParameters ret = hmacSharingParamsRefTable[hmacSharingParamsRefIndex]; hmacSharingParamsRefIndex++; @@ -449,7 +401,7 @@ public KMHmacSharingParameters newHmacSharingParameters() { public KMVerificationToken newVerificationToken() { if (verTokenRefIndex >= verTokenRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMVerificationToken ret = verTokenRefTable[verTokenRefIndex]; verTokenRefIndex++; @@ -459,7 +411,7 @@ public KMVerificationToken newVerificationToken() { public KMOperationState newOperationState() { if (opStateRefIndex >= opStateRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMOperationState ret = operationStateTable[opStateRefIndex]; opStateRefIndex++; @@ -469,14 +421,14 @@ public KMOperationState newOperationState() { public void releaseOperationState(KMOperationState state){ opStateRefIndex--; if(opStateRefIndex <0){ - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } opStateRefTable[opStateRefIndex] = state; } public KMVector newVector() { if (vectorRefIndex >= vectorRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMVector ret = vectorRefTable[vectorRefIndex]; vectorRefIndex++; @@ -486,7 +438,7 @@ public KMVector newVector() { public KMEnum newEnum() { if (enumRefIndex >= enumRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } KMEnum ret = enumRefTable[enumRefIndex]; enumRefIndex++; @@ -504,7 +456,7 @@ public byte[] getByteHeapRef(){ public short newTypeArray(short length) { if (((short) (typeRefIndex + length)) >= typeRefTable.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } typeRefIndex += length; return (short) (typeRefIndex - length); @@ -513,13 +465,9 @@ public short newTypeArray(short length) { public short newByteArray(short length) { if (((short) (byteHeapIndex + length)) >= byteHeap.length) { // TODO this is placeholder exception value. - throw new KMException(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } byteHeapIndex += length; return (short) (byteHeapIndex - length); } - - public byte[] getEntropyPool() { - return entropyPool; - } } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMUpdateOperationCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMUpdateOperationCmd.java deleted file mode 100644 index 5b1e58f6..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMUpdateOperationCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMUpdateOperationCmd extends KMAbstractCmd { - public static final byte INS_UPDATE_OPERATION_CMD = 0x20; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_UPDATE_OPERATION_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMUpgradeKeyCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMUpgradeKeyCmd.java deleted file mode 100644 index d883068f..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMUpgradeKeyCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMUpgradeKeyCmd extends KMAbstractCmd { - public static final byte INS_UPGRADE_KEY_CMD = 0x15; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_UPGRADE_KEY_CMD; - } -} diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMUtil.java b/Applet/Applet/src/com/android/javacard/keymaster/KMUtil.java index 5b42ae9d..0d1080df 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMUtil.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMUtil.java @@ -1,6 +1,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; import javacard.framework.Util; import javacard.security.AESKey; import javacard.security.CryptoException; @@ -9,27 +10,25 @@ import javacardx.crypto.Cipher; public class KMUtil { + private static final short ENTROPY_POOL_SIZE = 16; // simulator does not support 256 bit aes keys public static final byte AES_BLOCK_SIZE = 16; - private static KMRepository repository = null; + public static final byte[] aesICV = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; private static byte[] counter; - private static boolean initialized = false; private static AESKey aesKey; - private static Cipher aesEcb; - - public static void init(KMRepository repo) { - if (!initialized) { - KMUtil.repository = repo; - counter = repo.newIntegerArray((short) 8); - KMUtil.initEntropyPool(repo.getEntropyPool()); + private static Cipher aesCbc; + private static byte[] entropyPool; + public static void init() { + entropyPool = new byte[ENTROPY_POOL_SIZE]; + counter = KMRepository.instance().newIntegerArray((short) 8); + KMUtil.initEntropyPool(entropyPool); try { - aesEcb = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false); + //Note: ALG_AES_BLOCK_128_CBC_NOPAD not supported by simulator. + aesCbc = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false); } catch (CryptoException exp) { // TODO change this to proper error code - throw new KMException(ISO7816.SW_UNKNOWN); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } - aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); - initialized = true; - } + aesKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); } public static void initEntropyPool(byte[] pool) { @@ -40,26 +39,31 @@ public static void initEntropyPool(byte[] pool) { } try { trng = RandomData.getInstance(RandomData.ALG_TRNG); + trng.nextBytes(pool, (short) 0, (short) pool.length); } catch (CryptoException exp) { if (exp.getReason() == CryptoException.NO_SUCH_ALGORITHM) { //TODO change this when possible // simulator does not support TRNG algorithm. So, PRNG algorithm (deprecated) is used. trng = RandomData.getInstance(RandomData.ALG_PSEUDO_RANDOM); + trng.nextBytes(pool, (short) 0, (short) pool.length); } else { // TODO change this to proper error code - throw new KMException(ISO7816.SW_UNKNOWN); + ISOException.throwIt(ISO7816.SW_UNKNOWN); } } - trng.nextBytes(pool, (short) 0, (short) pool.length); + } // Generate a secure random number from existing entropy pool. This uses aes ecb algorithm with // 8 byte counter and 16 byte block size. public static void newRandomNumber(byte[] num, short startOff, short length) { + KMRepository repository = KMRepository.instance(); byte[] bufPtr = repository.getByteHeapRef(); short countBufInd = repository.newByteArray(AES_BLOCK_SIZE); short randBufInd = repository.newByteArray(AES_BLOCK_SIZE); short len = AES_BLOCK_SIZE; + aesKey.setKey(entropyPool, (short) 0); + aesCbc.init(aesKey, Cipher.MODE_ENCRYPT, aesICV, (short)0, (short)16); while (length > 0) { if (length < len ) len = length; // increment counter by one @@ -67,9 +71,7 @@ public static void newRandomNumber(byte[] num, short startOff, short length) { // copy the 8 byte counter into the 16 byte counter buffer. Util.arrayCopy(counter, (short) 0, bufPtr, countBufInd, (short) counter.length); // encrypt the counter buffer with existing entropy which forms the aes key. - aesKey.setKey(repository.getEntropyPool(), (short) 0); - aesEcb.init(aesKey, Cipher.MODE_ENCRYPT); - aesEcb.doFinal(bufPtr, countBufInd, AES_BLOCK_SIZE, bufPtr, randBufInd); + aesCbc.doFinal(bufPtr, countBufInd, AES_BLOCK_SIZE, bufPtr, randBufInd); // copy the encrypted counter block to buffer passed in the argument Util.arrayCopy(bufPtr, randBufInd, num, startOff, len); length = (short) (length - len); @@ -98,4 +100,9 @@ private static void incrementCounter() { } } } + + public static byte[] getEntropyPool() { + return entropyPool; + } + } diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java b/Applet/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java index f52fae55..d47c80e2 100644 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java +++ b/Applet/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java @@ -17,6 +17,7 @@ package com.android.javacard.keymaster; import javacard.framework.ISO7816; +import javacard.framework.ISOException; public class KMVerificationToken extends KMType { public static final byte CHALLENGE = 0x00; @@ -61,7 +62,7 @@ public static KMVerificationToken instance() { public static KMVerificationToken instance(KMArray vals) { if (vals.length() != 5) { - throw new KMException(ISO7816.SW_WRONG_LENGTH); + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } KMVerificationToken inst = repository.newVerificationToken(); inst.vals = vals; diff --git a/Applet/Applet/src/com/android/javacard/keymaster/KMVerifyAuthorizationCmd.java b/Applet/Applet/src/com/android/javacard/keymaster/KMVerifyAuthorizationCmd.java deleted file mode 100644 index 33289b44..00000000 --- a/Applet/Applet/src/com/android/javacard/keymaster/KMVerifyAuthorizationCmd.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright(C) 2020 The Android Open Source Project - * - * 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.android.javacard.keymaster; - -public class KMVerifyAuthorizationCmd extends KMAbstractCmd { - public static final byte INS_VERIFY_AUTHORIZATION_CMD = 0x1B; - - @Override - protected KMArray getExpectedArgs() { - return null; - } - - @Override - protected KMArray process(KMArray args, KMContext context) { - return null; - } - - @Override - public byte getIns() { - return INS_VERIFY_AUTHORIZATION_CMD; - } -}