diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2023-09-27 02:09:29 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-09-27 02:09:29 +0000 |
commit | c916f41691f7ac9a6abbf41f1b77e0cbc3d24fbd (patch) | |
tree | 4f60a9ce6de621aa9720cd8b16d6184db78c2714 | |
parent | 3cd5cf2a272b54a741045d9098ce54791e3d3649 (diff) | |
parent | 5c854a6b055b233e1b06d66c6c646964b3678f38 (diff) | |
download | libese-c916f41691f7ac9a6abbf41f1b77e0cbc3d24fbd.tar.gz |
Merge "Support uint16/uint32 for ENUM Tag." into main am: 94791c4100 am: f6f34c5a08 am: 4fba3744eb am: 173be4a34b am: 5c854a6b05
Original change: https://android-review.googlesource.com/c/platform/external/libese/+/2670815
Change-Id: I325375c92779fc9c0d87feafa80fcaeaa95b0f47
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
7 files changed, 185 insertions, 68 deletions
diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMDecoder.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMDecoder.java index dd05b13..406f707 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMDecoder.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMDecoder.java @@ -483,31 +483,51 @@ public class KMDecoder { return arrPtr; } - private short decodeEnumTag(short exp) { - readTagKey(KMEnumTag.cast(exp).getTagType()); + private short createInstanceEnumType(short instanceType, byte[] buf, short offset, short len) { + byte type = KMType.getType(instanceType); + short ptr = KMType.INVALID_VALUE; + switch (type) { + case KMType.ENUM_TYPE: + ptr = KMEnum.instance(KMEnum.cast(instanceType).getEnumType(), buf, offset, len); + break; + case KMType.TAG_TYPE: + ptr = KMEnumTag.instance(scratchBuf[TAG_KEY_OFFSET], buf, offset, len); + break; + default: + ISOException.throwIt(ISO7816.SW_DATA_INVALID); + } + return ptr; + } + + private short decodeEnumAndCreateInstance(short instanceType) { byte[] buffer = (byte[]) bufferRef[0]; - short startOff = scratchBuf[START_OFFSET]; - // Enum Tag value will always be integer with max 1 byte length. - if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { + short offset = scratchBuf[START_OFFSET]; + if ((buffer[offset] & MAJOR_TYPE_MASK) != UINT_TYPE) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short len = (short) (buffer[startOff] & ADDITIONAL_MASK); - byte enumVal = 0; - if (len > UINT8_LENGTH) { + short addInfo = (short) (buffer[offset] & ADDITIONAL_MASK); + if (addInfo > UINT32_LENGTH) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } - if (len < UINT8_LENGTH) { - enumVal = (byte) (len & ADDITIONAL_MASK); - incrementStartOff((short) 1); - } else if (len == UINT8_LENGTH) { - incrementStartOff((short) 1); - // startOff is incremented so update the startOff - // with latest value before using it. - startOff = scratchBuf[START_OFFSET]; - enumVal = buffer[startOff]; + if (addInfo >= UINT8_LENGTH) { incrementStartOff((short) 1); + offset = scratchBuf[START_OFFSET]; + } + byte originalValue = buffer[offset]; + if (addInfo < UINT8_LENGTH) { + // In this case additional info is the actual enum value. + buffer[offset] = (byte) addInfo; } - return KMEnumTag.instance(scratchBuf[TAG_KEY_OFFSET], enumVal); + short len = (short) ((addInfo > UINT8_LENGTH) ? ((addInfo == UINT32_LENGTH) ? 4 : 2) : 1); + short ptr = createInstanceEnumType(instanceType, buffer, offset, len); + buffer[offset] = originalValue; + incrementStartOff(len); + return ptr; + } + + private short decodeEnumTag(short exp) { + readTagKey(KMEnumTag.cast(exp).getTagType()); + return decodeEnumAndCreateInstance(exp); } private short decodeBoolTag(short exp) { @@ -526,29 +546,7 @@ public class KMDecoder { } private short decodeEnum(short exp) { - byte[] buffer = (byte[]) bufferRef[0]; - short startOff = scratchBuf[START_OFFSET]; - // Enum value will always be integer with max 1 byte length. - if ((buffer[startOff] & MAJOR_TYPE_MASK) != UINT_TYPE) { - ISOException.throwIt(ISO7816.SW_DATA_INVALID); - } - short len = (short) (buffer[startOff] & ADDITIONAL_MASK); - byte enumVal; - if (len > UINT8_LENGTH) { - ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - } - if (len < UINT8_LENGTH) { - enumVal = (byte) (len & ADDITIONAL_MASK); - incrementStartOff((short) 1); - } else { - incrementStartOff((short) 1); - // startOff is incremented so update the startOff - // with latest value before using it. - startOff = scratchBuf[START_OFFSET]; - enumVal = buffer[startOff]; - incrementStartOff((short) 1); - } - return KMEnum.instance(KMEnum.cast(exp).getEnumType(), enumVal); + return decodeEnumAndCreateInstance(exp); } private short decodeSimpleValue(short exp) { diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 65394bd..2146c82 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -396,11 +396,19 @@ public class KMEncoder { private void encodeEnumTag(short obj) { writeTag(KMEnumTag.cast(obj).getTagType(), KMEnumTag.cast(obj).getKey()); - writeByteValue(KMEnumTag.cast(obj).getValue()); + encodeInteger( + KMEnumTag.cast(obj).getBuffer(), + KMEnumTag.cast(obj).length(), + KMEnumTag.cast(obj).getStartOffset(), + UINT_TYPE); } private void encodeEnum(short obj) { - writeByteValue(KMEnum.cast(obj).getVal()); + encodeInteger( + KMEnum.cast(obj).getBuffer(), + KMEnum.cast(obj).length(), + KMEnum.cast(obj).getStartOffset(), + UINT_TYPE); } private void encodeInteger(byte[] val, short len, short startOff, short majorType) { diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnum.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnum.java index 44bf477..7f13853 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnum.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnum.java @@ -73,7 +73,7 @@ public class KMEnum extends KMType { if (!validateEnum(enumType, NO_VALUE)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = KMType.instance(ENUM_TYPE, (short) 2); + short ptr = KMType.instance(ENUM_TYPE, (short) 2 /* TAG_KEY */); Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), enumType); return ptr; } @@ -82,12 +82,28 @@ public class KMEnum extends KMType { if (!validateEnum(enumType, val)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = KMType.instance(ENUM_TYPE, (short) 3); + short ptr = KMType.instance(ENUM_TYPE, (short) (2 /* TAG_KEY */ + 1 /* Byte value */)); Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), enumType); heap[(short) (ptr + TLV_HEADER_SIZE + 2)] = val; return ptr; } + public static short instance(short key, byte[] num, short srcOff, short length) { + if (length == 1) { + return instance(key, num[srcOff]); + } + if (!validateEnum(key, num, srcOff, length)) { + ISOException.throwIt(ISO7816.SW_DATA_INVALID); + } + short ptr = KMType.instance(ENUM_TYPE, (short) (2 /* TAG_KEY */ + KMInteger.UINT_32)); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), key); + short destValOff = (short) (ptr + TLV_HEADER_SIZE + 2); + Util.arrayFillNonAtomic(heap, destValOff, KMInteger.UINT_32, (byte) 0); + Util.arrayCopyNonAtomic( + num, srcOff, heap, (short) (destValOff + KMInteger.UINT_32 - length), length); + return ptr; + } + private static void create() { // The allowed enum values to corresponding enum types in the types array. if (enums == null) { @@ -145,13 +161,21 @@ public class KMEnum extends KMType { } public short length() { - return Util.getShort(heap, (short) (KMType.instanceTable[KM_ENUM_OFFSET] + 1)); + return (short) (Util.getShort(heap, (short) (KMType.instanceTable[KM_ENUM_OFFSET] + 1)) - 2); } public byte getVal() { return heap[(short) (KMType.instanceTable[KM_ENUM_OFFSET] + TLV_HEADER_SIZE + 2)]; } + public short value(byte[] dest, short destOff) { + return copyToUint32(heap, getStartOffset(), length(), dest, destOff); + } + + public short getStartOffset() { + return (short) (KMType.instanceTable[KM_ENUM_OFFSET] + TLV_HEADER_SIZE + 2); + } + public void setVal(byte val) { heap[(short) (KMType.instanceTable[KM_ENUM_OFFSET] + TLV_HEADER_SIZE + 2)] = val; } @@ -163,4 +187,20 @@ public class KMEnum extends KMType { public void setEnumType(short type) { Util.setShort(heap, (short) (KMType.instanceTable[KM_ENUM_OFFSET] + TLV_HEADER_SIZE), type); } + + public static boolean validateEnum(short key, byte[] buf, short off, short len) { + if (len != KMInteger.UINT_32) { + return false; + } + switch (key) { + case KMType.USER_AUTH_TYPE: + // HardwareAuthenticatorType::ANY - 0xFFFFFFFF + short highShort = Util.getShort(buf, off); + short lowShort = Util.getShort(buf, (short) (off + 2)); + return ((short) 0xFFFF == (short) (highShort & lowShort)); + + default: + return false; + } + } } diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnumTag.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnumTag.java index a7bcbe6..f4f7e29 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnumTag.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMEnumTag.java @@ -73,6 +73,24 @@ public class KMEnumTag extends KMTag { return ptr; } + public static short instance(short key, byte[] val, short valOff, short valLen) { + if (valLen == 1) { + return instance(key, val[valOff]); + } + if (!KMEnum.validateEnum(key, val, valOff, valLen)) { + ISOException.throwIt(ISO7816.SW_DATA_INVALID); + } + short ptr = + KMType.instance(TAG_TYPE, (short) (2 /* TAG_TYPE */ + 2 /* TAG_KEY */ + KMInteger.UINT_32)); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), ENUM_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); + short destValueOff = (short) (ptr + TLV_HEADER_SIZE + 4); + Util.arrayFillNonAtomic(heap, destValueOff, KMInteger.UINT_32, (byte) 0); + Util.arrayCopyNonAtomic( + val, valOff, heap, (short) (destValueOff + KMInteger.UINT_32 - valLen), valLen); + return ptr; + } + public static KMEnumTag cast(short ptr) { if (heap[ptr] != TAG_TYPE) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); @@ -137,6 +155,19 @@ public class KMEnumTag extends KMTag { return KMType.INVALID_VALUE; } + public short length() { + return (short) + (Util.getShort(heap, (short) (KMType.instanceTable[KM_ENUM_TAG_OFFSET] + 1)) - 4); + } + + public short getStartOffset() { + return (short) (KMType.instanceTable[KM_ENUM_TAG_OFFSET] + TLV_HEADER_SIZE + 4); + } + + public short value(byte[] dest, short destOff) { + return copyToUint32(heap, getStartOffset(), length(), dest, destOff); + } + public short getKey() { return Util.getShort( heap, (short) (KMType.instanceTable[KM_ENUM_TAG_OFFSET] + TLV_HEADER_SIZE + 2)); diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 715a119..a410e00 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3001,7 +3001,8 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe if (KMInteger.compare(data[OP_HANDLE], tmpVariables[0]) != 0) { KMException.throwIt(KMError.KEY_USER_NOT_AUTHENTICATED); } - if (!authTokenMatches(op.getUserSecureId(), op.getAuthType(), scratchPad)) { + short len = op.getAuthType(scratchPad, (short) 0); + if (!authTokenMatches(op.getUserSecureId(), scratchPad, (short) 0, len, scratchPad, len)) { KMException.throwIt(KMError.KEY_USER_NOT_AUTHENTICATED); } } @@ -3078,10 +3079,10 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe } // Now check if the device unlock requires password only authentication and whether // auth token is generated through password authentication or not. + scratchPad[0] = KMType.PASSWORD; + short authTypeLen = 1; if (kmDataStore.getDeviceLockPasswordOnly()) { - ptr = KMHardwareAuthToken.cast(data[HW_TOKEN]).getHwAuthenticatorType(); - ptr = KMEnum.cast(ptr).getVal(); - if (((byte) ptr & KMType.PASSWORD) == 0) { + if (!hwAuthTypeMatches(scratchPad, (short) 0, authTypeLen, scratchPad, authTypeLen)) { KMException.throwIt(KMError.DEVICE_LOCKED); } } @@ -3975,7 +3976,29 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe return false; } - private boolean authTokenMatches(short userSecureIdsPtr, short authType, byte[] scratchPad) { + public boolean hwAuthTypeMatches( + byte[] buf, short off, short len, byte[] scratchPad, short scratchOff) { + Util.arrayFillNonAtomic(scratchPad, scratchOff, (short) (2 * KMInteger.UINT_32), (byte) 0); + short enumPtr = KMHardwareAuthToken.cast(data[HW_TOKEN]).getHwAuthenticatorType(); + if (KMInteger.UINT_32 != KMEnum.cast(enumPtr).value(scratchPad, scratchOff)) { + return false; + } + Util.arrayCopyNonAtomic( + buf, off, scratchPad, (short) (scratchOff + 2 * KMInteger.UINT_32 - len), len); + short highShort = Util.getShort(scratchPad, scratchOff); + short lowShort = Util.getShort(scratchPad, (short) (scratchOff + 2)); + short otherHighShort = Util.getShort(scratchPad, (short) (scratchOff + KMInteger.UINT_32)); + short otherLowShort = Util.getShort(scratchPad, (short) (scratchOff + KMInteger.UINT_32 + 2)); + return (0 != (lowShort & otherLowShort) || 0 != (highShort & otherHighShort)); + } + + private boolean authTokenMatches( + short userSecureIdsPtr, + byte[] buf, + short off, + short len, + byte[] scratchPad, + short scratchOff) { if (data[HW_TOKEN] == KMType.INVALID_VALUE) { return false; } @@ -3983,12 +4006,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe return false; } // check auth type - tmpVariables[2] = KMHardwareAuthToken.cast(data[HW_TOKEN]).getHwAuthenticatorType(); - tmpVariables[2] = KMEnum.cast(tmpVariables[2]).getVal(); - if (((byte) tmpVariables[2] & (byte) authType) == 0) { - return false; - } - return true; + return hwAuthTypeMatches(buf, off, len, scratchPad, scratchOff); } private void authorizeUserSecureIdAuthTimeout(KMOperationState op, byte[] scratchPad) { @@ -4007,16 +4025,19 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe } // authenticator type must be provided. if (KMType.INVALID_VALUE - == (authType = KMEnumTag.getValue(KMType.USER_AUTH_TYPE, data[HW_PARAMETERS]))) { + == (authType = + KMKeyParameters.findTag( + KMType.ENUM_TAG, KMType.USER_AUTH_TYPE, data[HW_PARAMETERS]))) { // Authentication required, but no auth type found. KMException.throwIt(KMError.KEY_USER_NOT_AUTHENTICATED); } + short len = KMEnumTag.cast(authType).value(scratchPad, (short) 0); short authTimeoutTagPtr = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.AUTH_TIMEOUT, data[HW_PARAMETERS]); if (authTimeoutTagPtr != KMType.INVALID_VALUE) { // authenticate user - if (!authTokenMatches(userSecureIdPtr, authType, scratchPad)) { + if (!authTokenMatches(userSecureIdPtr, scratchPad, (short) 0, len, scratchPad, len)) { KMException.throwIt(KMError.KEY_USER_NOT_AUTHENTICATED); } @@ -4041,7 +4062,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // auth per operation required // store user secure id and authType in OperationState. op.setUserSecureId(userSecureIdPtr); - op.setAuthType((byte) authType); + op.setAuthType(scratchPad, (short) 0, len); // set flags op.setOneTimeAuthReqd(false); op.setAuthPerOperationReqd(true); @@ -4076,7 +4097,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe len += KMInteger.UINT_64; // concatenate authenticator type - 4 bytes ptr = KMHardwareAuthToken.cast(hwToken).getHwAuthenticatorType(); - scratchPad[(short) (len + 3)] = KMEnum.cast(ptr).getVal(); + KMEnum.cast(ptr).value(scratchPad, len); len += KMInteger.UINT_32; // concatenate timestamp -8 bytes ptr = KMHardwareAuthToken.cast(hwToken).getTimestamp(); @@ -4118,7 +4139,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe len += KMInteger.UINT_64; // concatenate authenticator type - 4 bytes ptr = KMHardwareAuthToken.cast(hwToken).getHwAuthenticatorType(); - scratchPad[(short) (len + 3)] = KMEnum.cast(ptr).getVal(); + KMEnum.cast(ptr).value(scratchPad, len); len += KMInteger.UINT_32; // concatenate timestamp - 8 bytes ptr = KMHardwareAuthToken.cast(hwToken).getTimestamp(); diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 2a53acd..6488577 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -31,7 +31,7 @@ public class KMOperationState { // sizes public static final byte OPERATION_HANDLE_SIZE = 8; - public static final byte DATA_SIZE = 11; + public static final byte DATA_SIZE = 12; public static final byte AUTH_TIME_SIZE = 8; // Secure user ids 5 * 8 = 40 bytes ( Considering Maximum 5 SECURE USER IDs) // First two bytes are reserved to store number of secure ids. So total 42 bytes. @@ -47,7 +47,7 @@ public class KMOperationState { private static final byte MAC_LENGTH = 7; private static final byte MGF_DIGEST = 8; private static final byte AUTH_TYPE = 9; - private static final byte MIN_MAC_LENGTH = 10; + private static final byte MIN_MAC_LENGTH = 11; private static final byte OPERATION = 0; private static final byte HMAC_SIGNER_OPERATION = 1; // Flag masks @@ -187,12 +187,16 @@ public class KMOperationState { } } - public short getAuthType() { - return data[AUTH_TYPE]; + public short getAuthType(byte[] buf, short offset) { + Util.arrayFillNonAtomic(buf, offset, (short) 4, (byte) 0); + offset = Util.setShort(buf, offset, data[AUTH_TYPE]); + Util.setShort(buf, offset, data[AUTH_TYPE + 1]); + return (short) 4; } - public void setAuthType(byte authType) { - data[AUTH_TYPE] = authType; + public void setAuthType(byte[] buf, short offset, short len) { + data[AUTH_TYPE] = Util.getShort(buf, offset); + data[(short) (AUTH_TYPE + 1)] = Util.getShort(buf, (short) (offset + 2)); } public short getUserSecureId() { diff --git a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMType.java b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMType.java index a18cb7f..fbee00b 100644 --- a/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/ready_se/google/keymint/KM200/Applet/src/com/android/javacard/keymaster/KMType.java @@ -388,6 +388,21 @@ public abstract class KMType { return Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); } + protected static short copyToUint32( + byte[] src, short srcOff, short srcLen, byte[] dest, short destOff) { + if (srcLen > KMInteger.UINT_32) { + ISOException.throwIt(ISO7816.SW_DATA_INVALID); + } + Util.arrayFillNonAtomic(dest, destOff, KMInteger.UINT_32, (byte) 0); + Util.arrayCopyNonAtomic( + src, srcOff, dest, (short) (destOff + KMInteger.UINT_32 - srcLen), srcLen); + return KMInteger.UINT_32; + } + + protected byte[] getBuffer() { + return heap; + } + protected static short instance(byte type, short length) { if (length < 0) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); |