diff options
author | Subrahmanya Manikanta Venkateswarlu Bhamidipati Kameswara Sri <subrahmanyaman@google.com> | 2023-09-27 00:34:15 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-09-27 00:34:15 +0000 |
commit | 3cd5cf2a272b54a741045d9098ce54791e3d3649 (patch) | |
tree | 19db13f10cae4335fe952d89e87544d629fe18a5 | |
parent | 1bb6d2202d0926e11c845b092b9b9c0c65de2527 (diff) | |
parent | fea89b639357f6a61a32b82697cf24632ee86a71 (diff) | |
download | libese-3cd5cf2a272b54a741045d9098ce54791e3d3649.tar.gz |
Support uint16/uint32 for ENUM Tag. am: 96396a3b9d am: a2549ab421 am: c11aa759c8 am: 6884cee1cb am: fea89b6393
Original change: https://android-review.googlesource.com/c/platform/external/libese/+/2661456
Change-Id: I3dd71d505a7ac6cb536313eb644b264755a60278
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/KM300/Applet/src/com/android/javacard/keymaster/KMDecoder.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMDecoder.java index dc0101a..6f4e6f4 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMDecoder.java +++ b/ready_se/google/keymint/KM300/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/KM300/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 941a0ac..98cad49 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/ready_se/google/keymint/KM300/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/KM300/Applet/src/com/android/javacard/keymaster/KMEnum.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEnum.java index 44bf477..7f13853 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEnum.java +++ b/ready_se/google/keymint/KM300/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/KM300/Applet/src/com/android/javacard/keymaster/KMEnumTag.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEnumTag.java index a7bcbe6..f4f7e29 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMEnumTag.java +++ b/ready_se/google/keymint/KM300/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/KM300/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 138e505..19c91dd 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3010,7 +3010,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); } } @@ -3087,10 +3088,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); } } @@ -3976,7 +3977,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; } @@ -3984,12 +4007,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) { @@ -4008,16 +4026,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); } @@ -4042,7 +4063,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); @@ -4077,7 +4098,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(); @@ -4119,7 +4140,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/KM300/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 2a53acd..6488577 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/ready_se/google/keymint/KM300/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/KM300/Applet/src/com/android/javacard/keymaster/KMType.java b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMType.java index dc89604..59f45da 100644 --- a/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/ready_se/google/keymint/KM300/Applet/src/com/android/javacard/keymaster/KMType.java @@ -390,6 +390,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); |