aboutsummaryrefslogtreecommitdiff
path: root/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java
diff options
context:
space:
mode:
Diffstat (limited to 'ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java')
-rw-r--r--ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java215
1 files changed, 215 insertions, 0 deletions
diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java
new file mode 100644
index 0000000..b09de0f
--- /dev/null
+++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMInteger.java
@@ -0,0 +1,215 @@
+/*
+ * 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 com.android.javacard.seprovider.KMException;
+import javacard.framework.ISO7816;
+import javacard.framework.ISOException;
+import javacard.framework.Util;
+
+/**
+ * Represents 8 bit, 16 bit, 32 bit and 64 bit unsigned integer. It corresponds to CBOR uint type.
+ * struct{byte INTEGER_TYPE; short length; 4 or 8 bytes of value}
+ */
+public class KMInteger extends KMType {
+
+ public static final byte UINT_32 = 4;
+ public static final byte UINT_64 = 8;
+ private static KMInteger prototype;
+
+ protected KMInteger() {}
+
+ private static KMInteger proto(short ptr) {
+ if (prototype == null) {
+ prototype = new KMInteger();
+ }
+ KMType.instanceTable[KM_INTEGER_OFFSET] = ptr;
+ return prototype;
+ }
+
+ // | TYPE(1) | LEN(2) | DATA(4 / 8) |
+ public static short exp() {
+ return KMType.exp(INTEGER_TYPE);
+ }
+
+ // return an empty integer instance
+ public static short instance(short length) {
+ if ((length <= 0) || (length > 8)) {
+ ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
+ }
+ if (length > 4) {
+ length = UINT_64;
+ } else {
+ length = UINT_32;
+ }
+ return KMType.instance(INTEGER_TYPE, length);
+ }
+
+ public static short 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.getShort(num, srcOff));
+ } else if (length == 4) {
+ return uint_32(num, srcOff);
+ } else {
+ return uint_64(num, srcOff);
+ }
+ }
+
+ public static KMInteger cast(short ptr) {
+ byte[] heap = repository.getHeap();
+ if (heap[ptr] != INTEGER_TYPE) {
+ ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
+ }
+ if (Util.getShort(heap, (short) (ptr + 1)) == INVALID_VALUE) {
+ ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
+ }
+ return proto(ptr);
+ }
+
+ // create integer and copy byte value
+ public static short uint_8(byte num) {
+ short ptr = instance(UINT_32);
+ heap[(short) (ptr + TLV_HEADER_SIZE + 3)] = num;
+ return ptr;
+ }
+
+ // create integer and copy short value
+ public static short uint_16(short num) {
+ short ptr = instance(UINT_32);
+ Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), num);
+ return ptr;
+ }
+
+ // create integer and copy integer value
+ public static short uint_32(byte[] num, short offset) {
+ short ptr = instance(UINT_32);
+ Util.arrayCopy(num, offset, heap, (short) (ptr + TLV_HEADER_SIZE), UINT_32);
+ return ptr;
+ }
+
+ // create integer and copy integer value
+ public static short uint_64(byte[] num, short offset) {
+ short ptr = instance(UINT_64);
+ Util.arrayCopy(num, offset, heap, (short) (ptr + TLV_HEADER_SIZE), UINT_64);
+ return ptr;
+ }
+
+ public static short compare(short num1, short num2) {
+ short num1Buf = repository.alloc((short) 8);
+ short num2Buf = repository.alloc((short) 8);
+ Util.arrayFillNonAtomic(repository.getHeap(), num1Buf, (short) 8, (byte) 0);
+ Util.arrayFillNonAtomic(repository.getHeap(), num2Buf, (short) 8, (byte) 0);
+ short len = KMInteger.cast(num1).length();
+ KMInteger.cast(num1).getValue(repository.getHeap(), (short) (num1Buf + (short) (8 - len)), len);
+ len = KMInteger.cast(num2).length();
+ KMInteger.cast(num2).getValue(repository.getHeap(), (short) (num2Buf + (short) (8 - len)), len);
+ return KMInteger.unsignedByteArrayCompare(
+ repository.getHeap(), num1Buf, repository.getHeap(), num2Buf, (short) 8);
+ }
+
+ public static byte unsignedByteArrayCompare(
+ byte[] a1, short offset1, byte[] a2, short offset2, short length) {
+ byte count = (byte) 0;
+ short val1 = (short) 0;
+ short val2 = (short) 0;
+
+ for (; count < length; count++) {
+ val1 = (short) (a1[(short) (count + offset1)] & 0x00FF);
+ val2 = (short) (a2[(short) (count + offset2)] & 0x00FF);
+
+ if (val1 < val2) {
+ return -1;
+ }
+ if (val1 > val2) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ // Get the length of the integer
+ public short length() {
+ return Util.getShort(heap, (short) (getBaseOffset() + 1));
+ }
+
+ // Get the buffer pointer in which blob is contained.
+ public byte[] getBuffer() {
+ return heap;
+ }
+
+ // Get the start of value
+ public short getStartOff() {
+ return (short) (getBaseOffset() + TLV_HEADER_SIZE);
+ }
+
+ public void getValue(byte[] dest, short destOff, short length) {
+ if (length < length()) {
+ KMException.throwIt(KMError.UNKNOWN_ERROR);
+ }
+ if (length > length()) {
+ length = length();
+ destOff += length;
+ }
+ Util.arrayCopyNonAtomic(heap, getStartOff(), dest, destOff, length);
+ }
+
+ public void setValue(byte[] src, short srcOff) {
+ Util.arrayCopyNonAtomic(src, srcOff, heap, getStartOff(), length());
+ }
+
+ public short value(byte[] dest, short destOff) {
+ Util.arrayCopyNonAtomic(heap, getStartOff(), dest, destOff, length());
+ return length();
+ }
+
+ public short toLittleEndian(byte[] dest, short destOff) {
+ short index = (short) (length() - 1);
+ while (index >= 0) {
+ dest[destOff++] = heap[(short) (instanceTable[KM_INTEGER_OFFSET] + TLV_HEADER_SIZE + index)];
+ index--;
+ }
+ return length();
+ }
+
+ public short getShort() {
+ return Util.getShort(heap, (short) (getStartOff() + 2));
+ }
+
+ public short getSignificantShort() {
+ return Util.getShort(heap, getStartOff());
+ }
+
+ public byte getByte() {
+ return heap[(short) (getStartOff() + 3)];
+ }
+
+ public boolean isZero() {
+ if (getShort() == 0 && getSignificantShort() == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ protected short getBaseOffset() {
+ return instanceTable[KM_INTEGER_OFFSET];
+ }
+}