From e89620686eb77de8d674d8a0b9d1052d1321e95b Mon Sep 17 00:00:00 2001 From: mdwivedi Date: Tue, 9 Feb 2021 13:38:57 -0800 Subject: [PATCH 01/15] Update KMInteger.java adding unsigned compare to KMInteger to remove the dependency --- .../android/javacard/keymaster/KMInteger.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 18944e4d..3cc747dd 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -162,10 +162,29 @@ public static short compare(short num1, short num2){ 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 KMUtils.unsignedByteArrayCompare( + 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; + } } From a6054cf2f2b3222117f87153ea662806d5587e90 Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Tue, 9 Feb 2021 23:09:53 +0000 Subject: [PATCH 02/15] move_unsigned_compare to common code --- .../android/javacard/keymaster/KMUtils.java | 47 ++++++------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index 65e83415..cdd86665 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8); } // divide the given time with four yrs msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8, (short) 8); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one day msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one hour msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one minute msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one second msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,24 +244,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } - 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; - } public static short numberToString(short number, byte[] scratchPad, short offset) { @@ -311,7 +294,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { From 48ec0ee2850debb69449b1d08eb847d63557fcf4 Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Tue, 9 Feb 2021 23:10:44 +0000 Subject: [PATCH 03/15] move_unsigned_compare to common code --- .../android/javacard/keymaster/KMUtils.java | 49 ++++++------------- .../android/javacard/keymaster/KMInteger.java | 1 + .../javacard/keymaster/KMKeymasterApplet.java | 4 +- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index 65e83415..2e72ae6d 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8); } // divide the given time with four yrs msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8, (short) 8); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one day msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one hour msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one minute msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one second msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,25 +244,6 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } - 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; - } - public static short numberToString(short number, byte[] scratchPad, short offset) { byte zero = 0x30; @@ -311,7 +292,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 3cc747dd..44a0779a 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -187,4 +187,5 @@ public static byte unsignedByteArrayCompare(byte[] a1, short offset1, byte[] a2, return 0; } + } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index abf6e670..0e27cdc3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3526,7 +3526,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsVersion(); tmpVariables[1] = - KMUtils.unsignedByteArrayCompare( + KMInteger.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, @@ -3545,7 +3545,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsPatch(); tmpVariables[1] = - KMUtils.unsignedByteArrayCompare( + KMInteger.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, From 5575105a2a1dcd9bd4f0ae255b0bf9e6debf63de Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Wed, 10 Feb 2021 04:27:50 +0000 Subject: [PATCH 04/15] code cleanup --- .../keymaster/KMAttestationCertImpl.java | 1 - .../android/javacard/keymaster/KMCipher.java | 8 --- .../KMEcdsa256NoDigestSignature.java | 12 +--- .../javacard/keymaster/KMJCardSimulator.java | 66 ++++--------------- .../keymaster/KMRsa2048NoDigestSignature.java | 2 +- .../android/javacard/keymaster/KMUtils.java | 1 - .../javacard/keymaster/KMByteBlob.java | 6 -- .../android/javacard/keymaster/KMEncoder.java | 2 - .../javacard/keymaster/KMEnumArrayTag.java | 8 --- .../android/javacard/keymaster/KMError.java | 55 +++++----------- .../javacard/keymaster/KMOperationState.java | 2 +- .../javacard/keymaster/KMSEProvider.java | 6 +- .../android/javacard/keymaster/KMType.java | 3 - 13 files changed, 37 insertions(+), 135 deletions(-) diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 18e67e72..23e7a067 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -90,7 +90,6 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static byte[] stack; private static short start; private static short length; - // private static KMRepository repo; private static short uniqueId; private static short attChallenge; private static short notBefore; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java index 3e67ed5e..a5d06a39 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java @@ -24,19 +24,11 @@ public abstract class KMCipher { public abstract void updateAAD(byte[] buffer, short startOff, short length); - public abstract short getBlockMode(); - public abstract void setBlockMode(short mode); - public abstract short getPaddingAlgorithm(); - - public abstract short getCipherAlgorithm(); - public abstract void setPaddingAlgorithm(short alg); public abstract void setCipherAlgorithm(short alg); - public abstract short getCipherProvider(); - public abstract short getAesGcmOutputSize(short len, short macLength); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 42468363..56b8120f 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -85,18 +85,12 @@ public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec); sunSigner.initVerify(pubkey); } - } catch (NoSuchAlgorithmException e) { + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (NoSuchProviderException e) { - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch(InvalidParameterSpecException e) { - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch(InvalidKeySpecException e) { - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch(InvalidKeyException e) { + } catch(InvalidParameterSpecException | InvalidKeySpecException | InvalidKeyException e) { CryptoException.throwIt(CryptoException.INVALID_INIT); } - } + } @Override public void init(Key key, byte b) throws CryptoException { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 664ade77..de5389b2 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -73,9 +73,6 @@ public class KMJCardSimulator implements KMSEProvider { public static final byte[] aesICV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private static final short CERT_CHAIN_MAX_SIZE = 2500;//First 2 bytes for length. private static final short RSA_KEY_SIZE = 256; - - - public static boolean jcardSim = false; private static Signature kdf; private static Signature hmacSignature; @@ -117,13 +114,11 @@ public KMJCardSimulator() { jCardSimulator = this; } - public KeyPair createRsaKeyPair() { KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); rsaKeyPair.genKeyPair(); return rsaKeyPair; } - public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLength, byte[] privBuffer, short privOff, short privLength) { @@ -132,16 +127,13 @@ public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLengt privKey.setExponent(privBuffer, privOff, privLength); privKey.setModulus(modBuffer, modOff, modLength); return privKey; - } - public KeyPair createECKeyPair() { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); ecKeyPair.genKeyPair(); return ecKeyPair; } - public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLength) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -149,7 +141,6 @@ public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLeng privKey.setS(privBuffer,privOff, privLength); return privKey; } - public AESKey createAESKey(short keysize) { byte[] rndNum = new byte[(short) (keysize/8)]; @@ -169,13 +160,11 @@ public AESKey createAESKey(byte[] buf, short startOff, short length) { return key; } - public DESKey createTDESKey() { byte[] rndNum = new byte[24]; newRandomNumber(rndNum, (short) 0, (short)rndNum.length); return createTDESKey(rndNum, (short)0, (short)rndNum.length); } - public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLength) { DESKey triDesKey = @@ -183,7 +172,6 @@ public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLe triDesKey.setKey(secretBuffer, secretOff); return triDesKey; } - public HMACKey createHMACKey(short keysize) { if((keysize % 8 != 0) || !(keysize >= 64 && keysize <= 512)){ @@ -260,13 +248,13 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, short length) { switch(alg){ case KMType.AES: - AESKey aesKey = createAESKey(buf,startOff,length); + createAESKey(buf,startOff,length); break; case KMType.DES: - DESKey desKey = createTDESKey(buf,startOff,length); + createTDESKey(buf,startOff,length); break; case KMType.HMAC: - HMACKey hmacKey = createHMACKey(buf,startOff,length); + createHMACKey(buf,startOff,length); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -279,10 +267,10 @@ public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short sta public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { switch (alg){ case KMType.RSA: - RSAPrivateKey rsaKey = createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); + createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); break; case KMType.EC: - ECPrivateKey ecPrivKey = createEcKey(privKeyBuf,privKeyStart,privKeyLength); + createEcKey(privKeyBuf,privKeyStart,privKeyLength); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -364,13 +352,7 @@ public short aesGCMEncrypt( byte[] outputBuf = new byte[cipher.getOutputSize(secretLen)]; try { len = (short)(cipher.doFinal(secret,secretStart,secretLen,outputBuf,(short)0)); - } catch (ShortBufferException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (BadPaddingException e) { + } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -458,13 +440,7 @@ public boolean aesGCMDecrypt( } catch (AEADBadTagException e) { e.printStackTrace(); return false; - } catch (ShortBufferException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (BadPaddingException e) { + } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -692,19 +668,10 @@ private KMCipher createRsaOAEP256Cipher(byte mode,byte digest, } catch (NoSuchAlgorithmException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (InvalidKeySpecException e) { + } catch (InvalidKeySpecException | InvalidAlgorithmParameterException | NoSuchPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (InvalidKeyException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (NoSuchProviderException e) { + } catch (InvalidKeyException | NoSuchProviderException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.INVALID_INIT); } @@ -768,13 +735,7 @@ public Signature createEcSigner(short digest, byte[] secret, short secretStart, return ecSigner; } - - public KMCipher createSymmetricCipher( - short cipherAlg, short mode, short blockMode, short padding, byte[] secret, short secretStart, short secretLength) { - return createSymmetricCipher(cipherAlg, mode, blockMode, padding, secret,secretStart,secretLength,null,(short)0,(short)0); - } - public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, short padding, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -954,7 +915,6 @@ private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secret return ret; } - public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, short secretStart, short secretLength) { short alg = Signature.ALG_HMAC_SHA_256; if(digest != KMType.SHA2_256) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -964,7 +924,6 @@ public Signature createHmacSignerVerifier(short purpose, short digest, byte[] se hmacSignerVerifier.init(key,(byte)purpose); return hmacSignerVerifier; } - public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -1144,7 +1103,6 @@ public Signature createRsaVerifier(short digest, short padding, byte[] modBuffer public Signature createEcVerifier(short digest, byte[] pubKey, short pubKeyStart, short pubKeyLength) { short alg = mapSignature256Alg(KMType.EC, (byte)0); Signature ecVerifier; - //if(msgDigestAlg == MessageDigest.ALG_NULL) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); if(digest == KMType.DIGEST_NONE) { ecVerifier = new KMEcdsa256NoDigestSignature(Signature.MODE_VERIFY, pubKey, pubKeyStart, pubKeyLength); } else { @@ -1266,7 +1224,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { getTrueRandomNumber(keyData, (short) 0, keyLen); masterKey.setKey(keyData, (short) 0); } - return (KMMasterKey) masterKey; + return masterKey; } @Override @@ -1278,7 +1236,7 @@ public KMAttestationKey createAttestationKey(byte[] keyData, short offset, attestationKey = new KMECPrivateKey(ecKeyPair); } attestationKey.setS(keyData, offset, length); - return (KMAttestationKey) attestationKey; + return attestationKey; } @Override @@ -1293,7 +1251,7 @@ public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short len preSharedKey = new KMHmacKey(key); } preSharedKey.setKey(keyData, offset, length); - return (KMPreSharedKey) preSharedKey; + return preSharedKey; } @Override diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index 855a3104..b79cfb72 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -122,7 +122,7 @@ private boolean isValidData(byte[] buf, short start, short len) { if (padding == KMType.PADDING_NONE) { if (len > 256) return false; else if (len == 256) { - short v = KMUtils.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); + short v = KMInteger.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); if (v > 0) return false; } } else {//pkcs1 no digest diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index 2e72ae6d..c494bb34 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -52,7 +52,6 @@ public class KMUtils { public static final short year2051 = 2051; public static final short year2020 = 2020; - // -------------------------------------- public static short convertToDate(short time, byte[] scratchPad, boolean utcFlag) { diff --git a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java index 28b916db..eb065e10 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java @@ -115,10 +115,4 @@ public boolean isValid() { } return true; } - - public void decrementLength(short len) { - short length = Util.getShort(heap, (short) (instPtr + 1)); - length = (short) (length - len); - Util.setShort(heap, (short) (instPtr + 1), length); - } } diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 685ba468..b4055f04 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -38,7 +38,6 @@ public class KMEncoder { private static final byte UINT64_LENGTH = (byte) 0x1B; private static final short TINY_PAYLOAD = 0x17; private static final short SHORT_PAYLOAD = 0x100; - //TODO make this static. private byte[] buffer; private short startOff; private short length; @@ -73,7 +72,6 @@ public short encode(short object, byte[] buffer, short startOff) { }else{ this.length = (short)buffer.length; } - //this.length = (short)(startOff + length); push(object); encode(); return (short)(this.startOff - startOff); diff --git a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java index 37e23286..98ec05f7 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java @@ -279,12 +279,4 @@ public boolean isValidPurpose(byte alg) { } return true; } - - public boolean isValidBlockMode(byte alg) { - if (alg == KMType.AES || alg == KMType.DES) { - return true; - } else { - return false; - } - } } diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 83eb8c7c..0a52da0a 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -21,82 +21,61 @@ */ public class KMError { public static final short OK = 0; - public static final short ROOT_OF_TRUST_ALREADY_SET = 1; + public static final short UNSUPPORTED_PURPOSE = 2; public static final short INCOMPATIBLE_PURPOSE = 3; public static final short UNSUPPORTED_ALGORITHM = 4; public static final short INCOMPATIBLE_ALGORITHM = 5; public static final short UNSUPPORTED_KEY_SIZE = 6; - public static final short UNSUPPORTED_BLOCK_MODE = 7; + public static final short INCOMPATIBLE_BLOCK_MODE = 8; public static final short UNSUPPORTED_MAC_LENGTH = 9; public static final short UNSUPPORTED_PADDING_MODE = 10; public static final short INCOMPATIBLE_PADDING_MODE = 11; public static final short UNSUPPORTED_DIGEST = 12; public static final short INCOMPATIBLE_DIGEST = 13; - public static final short INVALID_EXPIRATION_TIME = 14; - public static final short INVALID_USER_ID = 15; - public static final short INVALID_AUTHORIZATION_TIMEOUT = 16; - public static final short UNSUPPORTED_KEY_FORMAT = 17; - public static final short INCOMPATIBLE_KEY_FORMAT = 18; + public static final short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; - /** For PKCS8 & PKCS12 */ - public static final short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; - /** For PKCS8 & PKCS12 */ + + /** For PKCS8 & PKCS12 */ public static final short INVALID_INPUT_LENGTH = 21; - public static final short KEY_EXPORT_OPTIONS_INVALID = 22; - public static final short DELEGATION_NOT_ALLOWED = 23; - public static final short KEY_NOT_YET_VALID = 24; - public static final short KEY_EXPIRED = 25; + public static final short KEY_USER_NOT_AUTHENTICATED = 26; - public static final short OUTPUT_PARAMETER_NULL = 27; + public static final short INVALID_OPERATION_HANDLE = 28; - public static final short INSUFFICIENT_BUFFER_SPACE = 29; + public static final short VERIFICATION_FAILED = 30; public static final short TOO_MANY_OPERATIONS = 31; - public static final short UNEXPECTED_NULL_POINTER = 32; public static final short INVALID_KEY_BLOB = 33; - public static final short IMPORTED_KEY_NOT_ENCRYPTED = 34; - public static final short IMPORTED_KEY_DECRYPTION_FAILED = 35; - public static final short IMPORTED_KEY_NOT_SIGNED = 36; - public static final short IMPORTED_KEY_VERIFICATION_FAILED = 37; + public static final short INVALID_ARGUMENT = 38; public static final short UNSUPPORTED_TAG = 39; public static final short INVALID_TAG = 40; - public static final short MEMORY_ALLOCATION_FAILED = 41; + public static final short IMPORT_PARAMETER_MISMATCH = 44; - public static final short SECURE_HW_ACCESS_DENIED = 45; public static final short OPERATION_CANCELLED = 46; - public static final short CONCURRENT_ACCESS_CONFLICT = 47; - public static final short SECURE_HW_BUSY = 48; - public static final short SECURE_HW_COMMUNICATION_FAILED = 49; - public static final short UNSUPPORTED_EC_FIELD = 50; + public static final short MISSING_NONCE = 51; public static final short INVALID_NONCE = 52; public static final short MISSING_MAC_LENGTH = 53; - public static final short KEY_RATE_LIMIT_EXCEEDED = 54; + public static final short CALLER_NONCE_PROHIBITED = 55; - public static final short KEY_MAX_OPS_EXCEEDED = 56; + public static final short INVALID_MAC_LENGTH = 57; public static final short MISSING_MIN_MAC_LENGTH = 58; public static final short UNSUPPORTED_MIN_MAC_LENGTH = 59; - public static final short UNSUPPORTED_KDF = 60; + public static final short UNSUPPORTED_EC_CURVE = 61; public static final short KEY_REQUIRES_UPGRADE = 62; - public static final short ATTESTATION_CHALLENGE_MISSING = 63; - public static final short KEYMASTER_NOT_CONFIGURED = 64; + public static final short ATTESTATION_APPLICATION_ID_MISSING = 65; - public static final short CANNOT_ATTEST_IDS = 66; public static final short ROLLBACK_RESISTANCE_UNAVAILABLE = 67; - public static final short HARDWARE_TYPE_UNAVAILABLE = 68; - public static final short PROOF_OF_PRESENCE_REQUIRED = 69; - public static final short CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; - public static final short NO_USER_CONFIRMATION = 71; + public static final short DEVICE_LOCKED = 72; public static final short EARLY_BOOT_ENDED = 73; + public static final short UNIMPLEMENTED = 100; - public static final short VERSION_MISMATCH = 101; public static final short UNKNOWN_ERROR = 1000; //Extended errors diff --git a/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 6ea96941..6d033443 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -41,7 +41,7 @@ public class KMOperationState { // short type private static final byte KEY_SIZE = 6; private static final byte MAC_LENGTH = 8; - // Handle - currently this is short + private static final byte OP_HANDLE = 10; // Auth time 64 bits private static final byte AUTH_TIME = 12; diff --git a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java index a057eb9e..0719d04b 100644 --- a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java +++ b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java @@ -220,7 +220,7 @@ boolean aesGCMDecrypt( * This is a oneshot operation that performs key derivation function using cmac kdf (CKDF) as * defined in android keymaster hal definition. * - * @param instance of pre-shared key. + * @param hmacKey instance of pre-shared key. * @param label is the label to be used for ckdf. * @param labelStart is the start of label. * @param labelLen is the length of the label. @@ -269,7 +269,7 @@ short hmacSign( * This is a oneshot operation that signs the data using hmac algorithm. * This is used to derive the key, which is used to encrypt the keyblob. * - * @param instance of masterkey. + * @param masterkey instance of masterkey. * @param data is the buffer containing data to be signed. * @param dataStart is the start of the data. * @param dataLength is the length of the data. @@ -344,7 +344,7 @@ short rsaDecipherOAEP256( /** * This is a oneshot operation that signs the data using EC private key. * - * @param instance of KMAttestationKey. + * @param ecPrivKey instance of KMAttestationKey. * @param inputDataBuf is the buffer of the input data. * @param inputDataStart is the start of the input data buffer. * @param inputDataLength is the length of the inpur data buffer in bytes. diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 4d81de45..53442440 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -41,7 +41,6 @@ public abstract class KMType { public static final byte HW_AUTH_TOKEN_TYPE = 0x08; public static final byte VERIFICATION_TOKEN_TYPE = 0x09; public static final byte HMAC_SHARING_PARAM_TYPE = 0x0A; - public static final byte X509_CERT = 0x0B; // Tag Types public static final short INVALID_TAG = 0x0000; public static final short ENUM_TAG = 0x1000; @@ -51,7 +50,6 @@ public abstract class KMType { public static final short ULONG_TAG = 0x5000; public static final short DATE_TAG = 0x6000; public static final short BOOL_TAG = 0x7000; - public static final short BIGNUM_TAG = (short) 0x8000; public static final short BYTES_TAG = (short) 0x9000; public static final short ULONG_ARRAY_TAG = (short) 0xA000; public static final short TAG_TYPE_MASK = (short) 0xF000; @@ -271,7 +269,6 @@ public abstract class KMType { // Confirmation Token public static final short CONFIRMATION_TOKEN = (short) 0x03ED; - public static final short LENGTH_FROM_PDU = (short) 0xFFFF; public static final byte NO_VALUE = (byte) 0xff; From 2f15f3db95da4579acef968ea34b234452c71f80 Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Wed, 10 Feb 2021 20:49:57 +0530 Subject: [PATCH 05/15] Removed public key operations from Applet and provider code --- .../keymaster/KMAndroidSEProvider.java | 90 +--- .../KMEcdsa256NoDigestSignature.java | 22 +- .../javacard/keymaster/KMOperationImpl.java | 13 - .../javacard/keymaster/KMCipherImpl.java | 16 +- .../KMEcdsa256NoDigestSignature.java | 9 +- .../javacard/keymaster/KMJCardSimulator.java | 59 +-- .../keymaster/KMRsa2048NoDigestSignature.java | 3 +- .../javacard/test/KMFunctionalTest.java | 395 ++++++++++++++---- .../javacard/keymaster/KMKeymasterApplet.java | 77 +--- 9 files changed, 326 insertions(+), 358 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java index 78b90b57..ac4ae426 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java @@ -40,6 +40,8 @@ import com.android.javacard.keymaster.KMAESKey; import com.android.javacard.keymaster.KMAttestationKey; import com.android.javacard.keymaster.KMECPrivateKey; +import com.android.javacard.keymaster.KMError; +import com.android.javacard.keymaster.KMException; import com.android.javacard.keymaster.KMHmacKey; import com.android.javacard.keymaster.KMMasterKey; import com.android.javacard.keymaster.KMPreSharedKey; @@ -1018,51 +1020,6 @@ public Signature createRsaSigner(short digest, short padding, byte[] secret, return rsaSigner; } - public Signature createRsaVerifier(short digest, short padding, - byte[] modBuffer, short modOff, short modLength) { - try { - byte alg = mapSignature256Alg(KMType.RSA, (byte) padding, (byte) digest); - if (digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - - Signature rsaVerifier = getSignatureInstanceFromPool(alg); - RSAPublicKey key = (RSAPublicKey) rsaKeyPair.getPublic(); - // setExponent - Util.setShort(tmpArray, (short) 0, (short) 0x0001); - Util.setShort(tmpArray, (short) 2, (short) 0x0001); - key.setExponent(tmpArray, (short) 0, (short) 4); - key.setModulus(modBuffer, modOff, modLength); - rsaVerifier.init(key, Signature.MODE_VERIFY); - return rsaVerifier; - } finally { - clean(); - } - } - - public Cipher createRsaCipher(short padding, short digest, byte[] modBuffer, - short modOff, short modLength) { - try { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte)digest); - // Java Card does not support MGF1-SHA1 and digest as SHA256. - // Both digest should be SHA256 as per Java Card, but as per Keymaster - // MGF should use SHA1 and message digest should be SHA256. - if (cipherAlg == Cipher.ALG_RSA_PKCS1_OAEP) { - KMException.throwIt(KMError.UNIMPLEMENTED); - } - Cipher rsaCipher = getCipherInstanceFromPool(cipherAlg); - RSAPublicKey key = (RSAPublicKey) rsaKeyPair.getPublic(); - // setExponent - Util.setShort(tmpArray, (short) 0, (short) 0x0001); - Util.setShort(tmpArray, (short) 2, (short) 0x0001); - key.setExponent(tmpArray, (short) 0, (short) 4); - key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key, Cipher.MODE_ENCRYPT); - return rsaCipher; - } finally { - clean(); - } - } - public Cipher createRsaDecipher(short padding, short digest, byte[] secret, short secretStart, short secretLength, byte[] modBuffer, short modOff, short modLength) { @@ -1086,17 +1043,6 @@ public Signature createEcSigner(short digest, byte[] secret, return ecSigner; } - public Signature createEcVerifier(short digest, byte[] pubKey, - short pubKeyStart, short pubKeyLength) { - byte alg = mapSignature256Alg(KMType.EC, (byte) 0, (byte) digest); - Signature ecVerifier = null; - ECPublicKey key = (ECPublicKey) ecKeyPair.getPublic(); - key.setW(pubKey, pubKeyStart, pubKeyLength); - ecVerifier = getSignatureInstanceFromPool(alg); - ecVerifier.init(key, Signature.MODE_VERIFY); - return ecVerifier; - } - @Override public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, byte digest, byte[] privKeyBuf, short privKeyStart, @@ -1116,28 +1062,6 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, opr.setMode(purpose); JCSystem.commitTransaction(); break; - case KMType.VERIFY: - Signature verifier = createRsaVerifier(digest, padding, pubModBuf, - pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(verifier); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; - case KMType.ENCRYPT: - Cipher cipher = createRsaCipher(padding, digest, pubModBuf, - pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setCipher(cipher); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; case KMType.DECRYPT: Cipher decipher = createRsaDecipher(padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); @@ -1150,6 +1074,7 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, JCSystem.commitTransaction(); break; default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); break; } } else if (alg == KMType.EC) { @@ -1162,13 +1087,8 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, opr.setSignature(signer); JCSystem.commitTransaction(); break; - case KMType.VERIFY: - Signature verifier = createEcVerifier(digest, pubModBuf, pubModStart, - pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(verifier); - JCSystem.commitTransaction(); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); break; } } else { diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 3f11a3b1..51ac435b 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -112,28 +112,14 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, @Override public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - try { - if (i1 > MAX_NO_DIGEST_MSG_LEN) - CryptoException.throwIt(CryptoException.ILLEGAL_USE); - // add zeros to the left - if (i1 < MAX_NO_DIGEST_MSG_LEN) { - Util.arrayFillNonAtomic(KMAndroidSEProvider.getInstance().tmpArray, - (short) 0, (short) MAX_NO_DIGEST_MSG_LEN, (byte) 0); - } - Util.arrayCopyNonAtomic(bytes, i, - KMAndroidSEProvider.getInstance().tmpArray, - (short) (MAX_NO_DIGEST_MSG_LEN - i1), i1); - return inst.verifyPreComputedHash( - KMAndroidSEProvider.getInstance().tmpArray, (short) 0, - (short) MAX_NO_DIGEST_MSG_LEN, bytes1, i2, i3); - } finally { - KMAndroidSEProvider.getInstance().clean(); - } + //Verification is handled inside HAL + return false; } @Override public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - return inst.verify(bytes, i, i1, bytes1, i2, i3); + //Verification is handled inside HAL + return false; } } \ No newline at end of file diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java index a38ee518..0eb7c4e7 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java @@ -125,19 +125,6 @@ public short finish(byte[] inputDataBuf, short inputDataStart, if (mode == KMType.DECRYPT) { inputDataLen = (short) (inputDataLen - macLength); } - } else if (cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && - mode == KMType.ENCRYPT) { - // Length cannot be greater then key size according to Java Card - if (inputDataLen > 256) - KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - // make input equal to 255 bytes - Util.arrayFillNonAtomic(tmpArray, (short) 0, (short) 256, (byte) 0); - Util.arrayCopyNonAtomic(inputDataBuf, inputDataStart, tmpArray, - (short) (256 - inputDataLen), inputDataLen); - inputDataStart = 0; - inputDataLen = 256; - inputDataBuf = tmpArray; - } else if ((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding == KMType.PKCS7 && mode == KMType.ENCRYPT) { byte blkSize = 16; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java index bc07be8d..95e5cb83 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java @@ -81,21 +81,7 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } } else{ - if(cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.ENCRYPT ){ - // Length cannot be greater then key size according to JcardSim - if(length >= 256) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - // make input equal to 255 bytes - byte[] tmp = new byte[255]; - Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); - Util.arrayCopyNonAtomic( - buffer, - startOff, - tmp, (short)(255 - length),length); - startOff = 0; - length = 255; - buffer = tmp; - - }else if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){ + if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){ byte blkSize = 16; byte paddingBytes; short len = length; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 42468363..904353b1 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -173,14 +173,7 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, @Override public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - // Cannot support this method as javacard cipher api does not allow 256 byte for public key - // encryption without padding. It only allows 255 bytes data. - try { - update(bytes, i , i1); - return sunSigner.verify(bytes1, i2, i3); - } catch (SignatureException e) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + // Public key operations not handled here. return false; } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 664ade77..0dad8f77 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -605,17 +605,13 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, pubModStart, pubModLength); return new KMOperationImpl(signer); - case KMType.VERIFY: - Signature verifier = createRsaVerifier(digest, padding, pubModBuf, pubModStart, pubModLength); - return new KMOperationImpl(verifier); - case KMType.ENCRYPT: - KMCipher cipher = createRsaCipher(padding, digest, pubModBuf, pubModStart, pubModLength); - return new KMOperationImpl(cipher); case KMType.DECRYPT: KMCipher decipher = createRsaDecipher( padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); return new KMOperationImpl(decipher); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } }else if(alg == KMType.EC){ switch(purpose){ @@ -623,9 +619,8 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, Signature signer = createEcSigner(digest,privKeyBuf,privKeyStart,privKeyLength); return new KMOperationImpl(signer); - case KMType.VERIFY: - Signature verifier = createEcVerifier(digest,pubModBuf,pubModStart,pubModLength); - return new KMOperationImpl(verifier); + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -1110,52 +1105,6 @@ public void addRngEntropy(byte[] num, short offset, short length) { } } - - public KMCipher createRsaCipher(short padding, short digest, byte[] modBuffer, short modOff, short modLength) { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte)padding, (byte)0); - if (cipherAlg == Cipher.ALG_RSA_PKCS1_OAEP) { - return createRsaOAEP256Cipher(KMType.ENCRYPT, (byte)digest, null,(short)0,(short)0,modBuffer,modOff,modLength); - } - Cipher rsaCipher = Cipher.getInstance(cipherAlg,false); - RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); - byte[] exponent = new byte[]{0x01,0x00,0x01}; - key.setExponent(exponent,(short)0,(short)3); - key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key,Cipher.MODE_ENCRYPT); - KMCipherImpl inst = new KMCipherImpl(rsaCipher); - inst.setCipherAlgorithm(KMType.RSA); - inst.setMode(KMType.ENCRYPT); - inst.setPaddingAlgorithm(padding); - return inst; - } - - public Signature createRsaVerifier(short digest, short padding, byte[] modBuffer, short modOff, short modLength) { - short alg = mapSignature256Alg(KMType.RSA,(byte)padding); - if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - Signature rsaVerifier = Signature.getInstance((byte)alg, false); - RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); - byte[] exponent = new byte[]{0x01,0x00,0x01}; - key.setExponent(exponent,(short)0,(short)3); - key.setModulus(modBuffer, modOff, modLength); - rsaVerifier.init(key,Signature.MODE_VERIFY); - return rsaVerifier; - } - - public Signature createEcVerifier(short digest, byte[] pubKey, short pubKeyStart, short pubKeyLength) { - short alg = mapSignature256Alg(KMType.EC, (byte)0); - Signature ecVerifier; - //if(msgDigestAlg == MessageDigest.ALG_NULL) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - if(digest == KMType.DIGEST_NONE) { - ecVerifier = new KMEcdsa256NoDigestSignature(Signature.MODE_VERIFY, pubKey, pubKeyStart, pubKeyLength); - } else { - ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); - key.setW(pubKey,pubKeyStart,pubKeyLength); - ecVerifier = Signature.getInstance((byte)alg,false); - ecVerifier.init(key,Signature.MODE_VERIFY); - } - return ecVerifier; - } - @Override public KMAttestationCert getAttestationCert(boolean rsaCert) { return KMAttestationCertImpl.instance(rsaCert); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index 855a3104..fc953d73 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -89,8 +89,7 @@ public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, @Override public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { - // Cannot support this method as javacard cipher api does not allow 256 byte for public key - // encryption without padding. It only allows 255 bytes data. + // Public key operations not handled here. return false; } diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index a6308513..ec5a1b54 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -20,6 +20,8 @@ import com.android.javacard.keymaster.KMBoolTag; import com.android.javacard.keymaster.KMByteBlob; import com.android.javacard.keymaster.KMByteTag; +import com.android.javacard.keymaster.KMEcdsa256NoDigestSignature; +import com.android.javacard.keymaster.KMException; import com.android.javacard.keymaster.KMJCardSimApplet; import com.android.javacard.keymaster.KMJCardSimulator; import com.android.javacard.keymaster.KMSEProvider; @@ -43,10 +45,44 @@ import com.licel.jcardsim.utils.AIDUtil; import javacard.framework.AID; +import javacard.framework.ISOException; import javacard.framework.Util; +import javacard.security.CryptoException; +import javacard.security.ECPrivateKey; +import javacard.security.ECPublicKey; +import javacard.security.KeyBuilder; +import javacard.security.KeyPair; +import javacard.security.RSAPrivateKey; +import javacard.security.RSAPublicKey; +import javacard.security.Signature; +import javacardx.crypto.Cipher; + +import java.math.BigInteger; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.InvalidParameterSpecException; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.RSAPrivateKeySpec; +import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.Random; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -776,16 +812,6 @@ public void testHmacImportKeySuccess() { @Test public void testRsaImportKeySuccess() { init(); - /* - KeyPair rsaKeyPair = cryptoProvider.createRsaKeyPair(); - byte[] pub = new byte[4]; - short len = ((RSAPublicKey)rsaKeyPair.getPublic()).getExponent(pub,(short)1); - byte[] priv = new byte[256]; - byte[] mod = new byte[256]; - len = ((RSAPrivateKey)rsaKeyPair.getPrivate()).getModulus(mod,(short)0); - len = ((RSAPrivateKey)rsaKeyPair.getPrivate()).getExponent(priv,(short)0); - */ - byte[] pub = new byte[]{0x00,0x01,0x00,0x01}; byte[] mod = new byte[256]; byte[] priv = new byte[256]; @@ -1035,13 +1061,6 @@ private short signVerificationToken(short verToken) { @Test public void testEcImportKeySuccess() { init(); - /* - KeyPair ecKeyPair = cryptoProvider.createECKeyPair(); - byte[] pub = new byte[128]; - short len = ((ECPublicKey)ecKeyPair.getPublic()).getW(pub,(short)0); - byte[] priv = new byte[128]; - len = ((ECPrivateKey)ecKeyPair.getPrivate()).getS(priv,(short)0); - */ byte[] pub = new byte[128]; byte[] priv = new byte[128]; short[] lengths = new short[2]; @@ -1107,7 +1126,7 @@ public void testEcImportKeySuccess() { cleanUp(); } - private short extractKeyBlobArray(short keyBlob) { + private short extractKeyBlobArray(byte[] buf, short off, short buflen) { short ret = KMArray.instance((short) 5); KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_SECRET, KMByteBlob.exp()); KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, KMByteBlob.exp()); @@ -1118,15 +1137,18 @@ private short extractKeyBlobArray(short keyBlob) { ret = decoder.decodeArray( ret, - KMByteBlob.cast(keyBlob).getBuffer(), - KMByteBlob.cast(keyBlob).getStartOff(), - KMByteBlob.cast(keyBlob).length()); + buf, off, buflen); short len = KMArray.cast(ret).length(); ptr = KMArray.cast(ret).get((short)4); // print(KMByteBlob.cast(ptr).getBuffer(),KMByteBlob.cast(ptr).getStartOff(),KMByteBlob.cast(ptr).length()); return ret; } + private short extractKeyBlobArray(short keyBlob) { + return extractKeyBlobArray(KMByteBlob.cast(keyBlob).getBuffer(), KMByteBlob + .cast(keyBlob).getStartOff(), KMByteBlob.cast(keyBlob).length()); + } + @Test public void testRsaGenerateKeySuccess() { init(); @@ -1532,10 +1554,7 @@ public void testComputeHmacParams(){ KMByteBlob.cast(num).getBuffer(), KMByteBlob.cast(num).getStartOff(), KMByteBlob.cast(num).length()); - // cryptoProvider.newRandomNumber( -// KMByteBlob.cast(num).getBuffer(), -// KMByteBlob.cast(num).getStartOff(), -// KMByteBlob.cast(num).length()); + KMHmacSharingParameters.cast(params1).setNonce(num); short params2 = KMHmacSharingParameters.instance(); KMHmacSharingParameters.cast(params2).setSeed(KMByteBlob.instance((short)0)); @@ -1612,10 +1631,8 @@ public void testImportWrappedKey(){ byte[] wrappedKey = new byte[16]; cryptoProvider.newRandomNumber(wrappedKey,(short)0,(short)16); byte[] encWrappedKey = new byte[16]; - //AESKey transportKey = cryptoProvider.createAESKey((short)256); byte[] transportKeyMaterial = new byte[32]; cryptoProvider.newRandomNumber(transportKeyMaterial,(short)0,(short)32); - //transportKey.setKey(transportKeyMaterial,(short)0); byte[] nonce = new byte[12]; cryptoProvider.newRandomNumber(nonce,(short)0,(short)12); byte[] authData = "Auth Data".getBytes(); @@ -1635,17 +1652,16 @@ public void testImportWrappedKey(){ Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length); - short inParams = getRsaParams(KMType.SHA2_256, KMType.RSA_OAEP); - short ret = processMessage(maskedTransportKey, - KMByteBlob.instance(wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false,false - ); - keyBlobPtr = KMArray.cast(ret).get((short)2); - byte[] encTransportKey = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - encTransportKey,(short)0, (short)encTransportKey.length); + + byte[] output = new byte[256]; + short outlen = rsaOaepEncryptMessage(wrappingKeyBlob, KMType.SHA2_256, + maskedTransportKey, (short)0, (short)maskedTransportKey.length, + output, (short)0); + byte[] encTransportKey = new byte[outlen]; + Util.arrayCopyNonAtomic(output, (short)0, encTransportKey, (short)0, + outlen); + //Clean the heap. + KMRepository.instance().clean(); short tagCount = 7; short arrPtr = KMArray.instance(tagCount); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); @@ -1689,7 +1705,7 @@ public void testImportWrappedKey(){ CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_WRAPPED_KEY_CMD, arr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); - ret = KMArray.instance((short) 3); + short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); KMArray.cast(ret).add((short)1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); @@ -1787,11 +1803,6 @@ public void testDeleteKeySuccess() { Assert.assertEquals(error, KMError.OK); ret = deleteKey(KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); Assert.assertEquals(ret, KMError.OK); -/* ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); - short err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - - */ cleanUp(); } @@ -1811,14 +1822,6 @@ public void testDeleteAllKeySuccess() { ResponseAPDU response = simulator.transmitCommand(apdu); byte[] respBuf = response.getBytes(); Assert.assertEquals(respBuf[0], KMError.OK); -/* short ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob1,(short)0,(short)keyBlob1.length)); - short err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - ret = getKeyCharacteristics(KMByteBlob.instance(keyBlob2,(short)0,(short)keyBlob2.length)); - err = KMByteBlob.cast(ret).get((short)1); - Assert.assertEquals(KMError.INVALID_KEY_BLOB,err); - - */ cleanUp(); } @@ -2027,6 +2030,218 @@ public void testSignWithRsaNonePkcs1(){ cleanUp(); } + public short getPublicKey(byte[] keyBlob, short off, short len, + byte[] pubKey, short pubKeyOff) { + short keyBlobPtr = extractKeyBlobArray(keyBlob, off, len); + short arrayLen = KMArray.cast(keyBlobPtr).length(); + if (arrayLen < 5) { + KMException.throwIt(KMError.INVALID_KEY_BLOB); + } + short pubKeyPtr = KMArray.cast(keyBlobPtr).get( + KMKeymasterApplet.KEY_BLOB_PUB_KEY); + Util.arrayCopy(KMByteBlob.cast(pubKeyPtr).getBuffer(), + KMByteBlob.cast(pubKeyPtr).getStartOff(), pubKey, pubKeyOff, + KMByteBlob.cast(pubKeyPtr).length()); + return KMByteBlob.cast(pubKeyPtr).length(); + } + + private String toHexString(byte[] num){ + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < num.length; i++){ + sb.append(String.format("%02X", num[i])) ; + } + return sb.toString(); + } + + public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte[] input, short inputOff, short inputlen, + byte[] output, short outputOff) { + byte alg = Cipher.ALG_RSA_PKCS1; + byte[] tmp = null; + short inLen = inputlen; + if (padding == KMType.PADDING_NONE) { + alg = Cipher.ALG_RSA_NOPAD; + // Length cannot be greater then key size according to JcardSim + if(inLen >= 256) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + // make input equal to 255 bytes + tmp = new byte[255]; + Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); + Util.arrayCopyNonAtomic( + input, + inputOff, + tmp, (short)(255 - inLen),inLen); + inLen = 255; + inputOff = 0; + } else if(padding == KMType.RSA_PKCS1_1_5_ENCRYPT) { + tmp = input; + } else { + /*Fail */ + Assert.assertTrue(false); + } + byte[] pubKey = new byte[256]; + KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); + RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyPair.getPublic(); + getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0); + byte[] exponent = new byte[]{0x01,0x00,0x01}; + rsaPubKey.setModulus(pubKey, (short) 0, (short) pubKey.length); + rsaPubKey.setExponent(exponent, (short) 0, (short) exponent.length); + + Cipher rsaCipher = Cipher.getInstance(alg, false); + rsaCipher.init(rsaPubKey, Cipher.MODE_ENCRYPT); + return rsaCipher.doFinal(tmp, inputOff, inLen, output, outputOff); + } + + public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, short inputOff, short inputlen, + byte[] output, short outputOff) { + byte[] mod = new byte[256]; + getPublicKey(keyBlob, (short)0, (short)keyBlob.length, mod, (short)0); + byte[] exponent = new byte[]{0x01,0x00,0x01}; + + // Convert byte arrays into keys + String modString = toHexString(mod); + String expString = toHexString(exponent); + BigInteger modInt = new BigInteger(modString,16); + BigInteger expInt = new BigInteger(expString,16); + javax.crypto.Cipher rsaCipher = null; + try{ + KeyFactory kf = KeyFactory.getInstance("RSA"); + // Create cipher with oaep padding + OAEPParameterSpec oaepSpec = null; + if(digest == KMType.SHA2_256){ + oaepSpec= new OAEPParameterSpec("SHA-256", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + }else{ + oaepSpec= new OAEPParameterSpec("SHA1", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + } + rsaCipher = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPPadding", "SunJCE"); + + RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modInt, expInt); + java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf.generatePublic(pubSpec); + rsaCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, pubKey, oaepSpec); + byte[] cipherOut = rsaCipher.doFinal(input, inputOff, inputlen); + + if(cipherOut != null) { + Util.arrayCopyNonAtomic(cipherOut, (short) 0, output, outputOff, (short) cipherOut.length); + } + return (short) cipherOut.length; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (InvalidKeyException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + return 0; + } + + public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, + short inputlen, byte[] sign, short signOff, short signLen, + byte[] keyBlob) { + KeyFactory kf; + byte[] pubKey = new byte[128]; + short keyStart = 0; + short keyLength = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, + pubKey, (short) 0); + try { + java.security.Signature sunSigner = java.security.Signature.getInstance( + "NONEwithECDSA", "SunEC"); + kf = KeyFactory.getInstance("EC"); + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", + "SunEC"); + // Supported curve secp256r1 + parameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec ecParameters = parameters + .getParameterSpec(ECParameterSpec.class); + + // Check if the first byte is 04 and remove it. + if (pubKey[keyStart] == 0x04) { + // uncompressed format. + keyStart++; + keyLength--; + } + short i = 0; + byte[] pubx = new byte[keyLength / 2]; + for (; i < keyLength / 2; i++) { + pubx[i] = pubKey[keyStart + i]; + } + byte[] puby = new byte[keyLength / 2]; + for (i = 0; i < keyLength / 2; i++) { + puby[i] = pubKey[keyStart + keyLength / 2 + i]; + } + BigInteger bIX = new BigInteger(pubx); + BigInteger bIY = new BigInteger(puby); + ECPoint point = new ECPoint(bIX, bIY); + ECPublicKeySpec pubkeyspec = new ECPublicKeySpec(point, ecParameters); + java.security.interfaces.ECPublicKey ecPubkey = (java.security.interfaces.ECPublicKey) kf + .generatePublic(pubkeyspec); + sunSigner.initVerify(ecPubkey); + sunSigner.update(input, inputOff, inputlen); + return sunSigner.verify(sign, signOff, signLen); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (InvalidParameterSpecException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (SignatureException e) { + e.printStackTrace(); + } + return false; + } + + public boolean ecVerifyMessage(byte[] input, short inputOff, short inputlen, + byte[] sign, short signOff, short signLen, byte[] keyBlob) { + Signature ecVerifier; + byte[] pubKey = new byte[128]; + short len = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, + pubKey, (short) 0); + ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey( + KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); + key.setW(pubKey, (short) 0, len); + ecVerifier = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); + ecVerifier.init(key, Signature.MODE_VERIFY); + return ecVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); + } + + public boolean rsaVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] sign, short signOff, short signLen, + short digest,short padding, byte[] keyBlob) { + if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + byte[] pubKey = new byte[256]; + getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0); + short alg = Signature.ALG_RSA_SHA_256_PKCS1_PSS; + + if (padding == KMType.RSA_PKCS1_1_5_SIGN) + alg = Signature.ALG_RSA_SHA_256_PKCS1; + + Signature rsaVerifier = Signature.getInstance((byte)alg, false); + RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); + byte[] exponent = new byte[]{0x01,0x00,0x01}; + key.setExponent(exponent,(short)0,(short)exponent.length); + key.setModulus(pubKey, (short)0, (short)pubKey.length); + rsaVerifier.init(key,Signature.MODE_VERIFY); + return rsaVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); + } + public byte[] EncryptMessage(byte[] input, short params, byte[] keyBlob) { short ret = begin(KMType.ENCRYPT, KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), @@ -2141,13 +2356,19 @@ public void testVtsRsaPkcs1Success() { short pkcs1Params = getRsaParams(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_ENCRYPT); - byte[] cipherText1 = EncryptMessage(message, pkcs1Params, keyBlob); - Assert.assertEquals((2048 / 8), cipherText1.length); + byte[] cipherText1 = new byte[256]; + short cipherText1Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, + message, (short)0, (short)message.length, + cipherText1, (short)0); + Assert.assertEquals((2048 / 8), cipherText1Len); pkcs1Params = getRsaParams(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_ENCRYPT); - byte[] cipherText2 = EncryptMessage(message, pkcs1Params, keyBlob); - Assert.assertEquals((2048 / 8), cipherText2.length); + byte[] cipherText2 = new byte[256]; + short cipherText2Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, + message, (short)0, (short)message.length, + cipherText2, (short)0); + Assert.assertEquals((2048 / 8), cipherText2Len); // PKCS1 v1.5 randomizes padding so every result should be different. Assert.assertFalse(Arrays.equals(cipherText1, cipherText2)); @@ -2275,15 +2496,6 @@ public void testAttestEcKey(){ } public void testAttestKey(byte[] keyBlob){ - /* - short key = generateRsaKey(null,null); - short keyBlobPtr = KMArray.cast(key).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic( - KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); - */ short arrPtr = KMArray.instance((short)2); KMArray.cast(arrPtr).add((short)0, KMByteTag.instance(KMType.ATTESTATION_APPLICATION_ID, KMByteBlob.instance(attAppId,(short)0,(short)attAppId.length))); @@ -2471,19 +2683,19 @@ public void testEncryptDecryptWithRsa(byte digest, byte padding){ keyBlob,(short)0, (short)keyBlob.length); short inParams = getRsaParams(digest, padding); byte[] plainData = "Hello World 123!".getBytes(); + byte[] cipherData = new byte[256]; + short cipherDataLen = 0; //Encrypt - short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false, false - ); + if (padding == KMType.RSA_OAEP) { + cipherDataLen = rsaOaepEncryptMessage(keyBlob, digest, plainData, + (short) 0, (short) plainData.length, cipherData, (short) 0); + } else { + cipherDataLen = rsaEncryptMessage(keyBlob, padding, digest, plainData, + (short) 0, (short) plainData.length, cipherData, (short) 0); + } + Assert.assertTrue((cipherDataLen == 256)); inParams = getRsaParams(digest, padding); - keyBlobPtr = KMArray.cast(ret).get((short)2); - byte[] cipherData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - cipherData,(short)0, (short)cipherData.length); - ret = processMessage(cipherData, + short ret = processMessage(cipherData, KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), KMType.DECRYPT, KMKeyParameters.instance(inParams), @@ -2522,14 +2734,10 @@ public void testSignVerifyWithRsa(byte digest, byte padding, boolean update, boo Assert.assertEquals(signatureData.length,256); return; } - ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.VERIFY, - KMKeyParameters.instance(inParams), - (short)0,signatureData,update,false - ); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); + boolean verify = rsaVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + digest, padding, keyBlob); + Assert.assertTrue(verify); } public void testSignVerifyWithEcdsa(byte digest, boolean update){ @@ -2553,14 +2761,17 @@ public void testSignVerifyWithEcdsa(byte digest, boolean update){ byte[] signatureData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), signatureData,(short)0, (short)signatureData.length); - ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.VERIFY, - KMKeyParameters.instance(inParams), - (short)0,signatureData,update,false - ); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); + boolean verify = false; + if (digest == KMType.DIGEST_NONE) { + verify = ecNoDigestVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + keyBlob); + } else { + verify = ecVerifyMessage(plainData, (short)0, (short)plainData.length, + signatureData, (short)0, (short)signatureData.length, + keyBlob); + } + Assert.assertTrue(verify); } public void testSignVerifyWithHmac(byte digest, boolean update){ short hmacKeyArr = generateHmacKey(null, null); diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index abf6e670..a6fce8bc 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1613,18 +1613,6 @@ private void processFinishOperationCmd(APDU apdu) { private void finishEncryptOperation(KMOperationState op, byte[] scratchPad) { short len = KMByteBlob.cast(data[INPUT_DATA]).length(); switch (op.getAlgorithm()) { - case KMType.RSA: - // Output size is always 256 bytes - data[OUTPUT_DATA] = KMByteBlob.instance((short) 256); - Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); - op.getOperation() - .finish( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[INPUT_DATA]).length(), - KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); - break; case KMType.AES: case KMType.DES: if (op.getAlgorithm() == KMType.AES) { @@ -1785,17 +1773,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); } else { - if (!op.getOperation() - .verify( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[INPUT_DATA]).length(), - KMByteBlob.cast(data[SIGNATURE]).getBuffer(), - KMByteBlob.cast(data[SIGNATURE]).getStartOff(), - KMByteBlob.cast(data[SIGNATURE]).length())) { - KMException.throwIt(KMError.VERIFICATION_FAILED); - } - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } } catch (CryptoException e) { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -1818,17 +1797,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch (short) 0); data[OUTPUT_DATA] = KMByteBlob.instance(scratchPad, (short) 0, len); } else { - if (!op.getOperation() - .verify( - KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - len, - KMByteBlob.cast(data[SIGNATURE]).getBuffer(), - KMByteBlob.cast(data[SIGNATURE]).getStartOff(), - KMByteBlob.cast(data[SIGNATURE]).length())) { - KMException.throwIt(KMError.VERIFICATION_FAILED); - } - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } break; case KMType.HMAC: // As per Keymaster HAL documentation, the length of the Hmac output can @@ -2484,18 +2454,7 @@ private void beginCipherOperation(KMOperationState op) { KMByteBlob.cast(data[PUB_KEY]).getStartOff(), KMByteBlob.cast(data[PUB_KEY]).length())); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -2548,18 +2507,7 @@ private void beginSignVerifyOperation(KMOperationState op) { KMByteBlob.cast(data[PUB_KEY]).getStartOff(), KMByteBlob.cast(data[PUB_KEY]).length())); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -2581,18 +2529,7 @@ private void beginSignVerifyOperation(KMOperationState op) { (short) 0, (short) 0)); } else { - op.setOperation( - seProvider.initAsymmetricOperation( - (byte) op.getPurpose(), - op.getAlgorithm(), - op.getPadding(), - op.getDigest(), - null, - (short) 0, - (short) 0, - KMByteBlob.cast(data[PUB_KEY]).getBuffer(), - KMByteBlob.cast(data[PUB_KEY]).getStartOff(), - KMByteBlob.cast(data[PUB_KEY]).length())); + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } } catch (CryptoException exp) { // Javacard does not support NO digest based signing. From 206c520423dea4bd1018092535113dba011b58e2 Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Wed, 10 Feb 2021 21:47:39 +0530 Subject: [PATCH 06/15] updated readROT function --- .../javacard/keymaster/KMKeymasterApplet.java | 6 +++ .../javacard/keymaster/KMRepository.java | 53 ++++++++++--------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index a6fce8bc..cb76aee4 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3521,6 +3521,9 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { makeKeyCharacteristics(scratchPad); // make root of trust blob data[ROT] = repository.readROT(); + if (data[ROT] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } // make hidden key params list data[HIDDEN_PARAMETERS] = @@ -3580,6 +3583,9 @@ private static void parseEncryptedKeyBlob(byte[] scratchPad) { data[SW_PARAMETERS] = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getSoftwareEnforced(); data[ROT] = repository.readROT(); + if (data[ROT] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } data[HIDDEN_PARAMETERS] = KMKeyParameters.makeHidden(data[APP_ID], data[APP_DATA], data[ROT], scratchPad); diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index ee7cc6a8..47ad740a 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -502,35 +502,40 @@ public short getOsPatch(){ } public short readROT() { + short totalLength = 0; short length = dataLength(BOOT_VERIFIED_BOOT_KEY); - length += dataLength(BOOT_VERIFIED_BOOT_HASH); - length += dataLength(BOOT_VERIFIED_BOOT_STATE); - length += dataLength(BOOT_DEVICE_LOCKED_STATUS); - short blob = KMByteBlob.instance(length); - if((length = readDataEntry( - BOOT_VERIFIED_BOOT_KEY, - KMByteBlob.cast(blob).getBuffer(), - KMByteBlob.cast(blob).getStartOff())) == 0){ - return 0; + if (length == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_VERIFIED_BOOT_HASH, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_VERIFIED_BOOT_HASH)) == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_VERIFIED_BOOT_STATE, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_VERIFIED_BOOT_STATE)) == 0) { + return KMType.INVALID_VALUE; } - if((length += readDataEntry( - BOOT_DEVICE_LOCKED_STATUS, - KMByteBlob.cast(blob).getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length))) == 0){ - return 0; + totalLength += length; + if ((length = dataLength(BOOT_DEVICE_LOCKED_STATUS)) == 0) { + return KMType.INVALID_VALUE; } + totalLength += length; + + short blob = KMByteBlob.instance(totalLength); + length = readDataEntry(BOOT_VERIFIED_BOOT_KEY, KMByteBlob.cast(blob) + .getBuffer(), KMByteBlob.cast(blob).getStartOff()); + + length += readDataEntry(BOOT_VERIFIED_BOOT_HASH, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); + + length += readDataEntry(BOOT_VERIFIED_BOOT_STATE, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); + + readDataEntry(BOOT_DEVICE_LOCKED_STATUS, KMByteBlob.cast(blob) + .getBuffer(), + (short) (KMByteBlob.cast(blob).getStartOff() + length)); return blob; } From 96e16fe4d5ab3bef315de1c8d055cef3c4e223ee Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Wed, 10 Feb 2021 22:15:31 +0530 Subject: [PATCH 07/15] Added validation for block mode --- .../javacard/keymaster/KMKeymasterApplet.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index cb76aee4..e1e8214d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -2319,6 +2319,16 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { KMIntegerTag.getShortValue(KMType.UINT_TAG, KMType.MAC_LENGTH, data[KEY_PARAMETERS]); switch (op.getAlgorithm()) { case KMType.AES: + //Validate the block mode. + switch(param) { + case KMType.ECB: + case KMType.CBC: + case KMType.CTR: + case KMType.GCM: + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); + } if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); if (param == KMType.GCM) { if (op.getPadding() != KMType.PADDING_NONE) { @@ -2338,6 +2348,14 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { } break; case KMType.DES: + //Validate the block mode. + switch(param) { + case KMType.ECB: + case KMType.CBC: + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); + } if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); break; case KMType.HMAC: From 9b13537f106645ac85af17b900c949bb36ee756c Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Wed, 10 Feb 2021 22:57:52 +0530 Subject: [PATCH 08/15] Removed unwanted exceptions from KMFunctionTest --- .../javacard/test/KMFunctionalTest.java | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index ec5a1b54..3e0653eb 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -20,8 +20,6 @@ import com.android.javacard.keymaster.KMBoolTag; import com.android.javacard.keymaster.KMByteBlob; import com.android.javacard.keymaster.KMByteTag; -import com.android.javacard.keymaster.KMEcdsa256NoDigestSignature; -import com.android.javacard.keymaster.KMException; import com.android.javacard.keymaster.KMJCardSimApplet; import com.android.javacard.keymaster.KMJCardSimulator; import com.android.javacard.keymaster.KMSEProvider; @@ -45,14 +43,10 @@ import com.licel.jcardsim.utils.AIDUtil; import javacard.framework.AID; -import javacard.framework.ISOException; import javacard.framework.Util; -import javacard.security.CryptoException; -import javacard.security.ECPrivateKey; import javacard.security.ECPublicKey; import javacard.security.KeyBuilder; import javacard.security.KeyPair; -import javacard.security.RSAPrivateKey; import javacard.security.RSAPublicKey; import javacard.security.Signature; import javacardx.crypto.Cipher; @@ -68,12 +62,10 @@ import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; import java.security.spec.ECPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.MGF1ParameterSpec; -import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.Random; @@ -1657,6 +1649,7 @@ public void testImportWrappedKey(){ short outlen = rsaOaepEncryptMessage(wrappingKeyBlob, KMType.SHA2_256, maskedTransportKey, (short)0, (short)maskedTransportKey.length, output, (short)0); + Assert.assertTrue((outlen == 256)); byte[] encTransportKey = new byte[outlen]; Util.arrayCopyNonAtomic(output, (short)0, encTransportKey, (short)0, outlen); @@ -2035,7 +2028,7 @@ public short getPublicKey(byte[] keyBlob, short off, short len, short keyBlobPtr = extractKeyBlobArray(keyBlob, off, len); short arrayLen = KMArray.cast(keyBlobPtr).length(); if (arrayLen < 5) { - KMException.throwIt(KMError.INVALID_KEY_BLOB); + return 0; } short pubKeyPtr = KMArray.cast(keyBlobPtr).get( KMKeymasterApplet.KEY_BLOB_PUB_KEY); @@ -2061,7 +2054,8 @@ public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte if (padding == KMType.PADDING_NONE) { alg = Cipher.ALG_RSA_NOPAD; // Length cannot be greater then key size according to JcardSim - if(inLen >= 256) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + if(inLen >= 256) + return 0; // make input equal to 255 bytes tmp = new byte[255]; Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); @@ -2080,7 +2074,9 @@ public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte byte[] pubKey = new byte[256]; KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyPair.getPublic(); - getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0); + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + return 0; + byte[] exponent = new byte[]{0x01,0x00,0x01}; rsaPubKey.setModulus(pubKey, (short) 0, (short) pubKey.length); rsaPubKey.setExponent(exponent, (short) 0, (short) exponent.length); @@ -2093,7 +2089,8 @@ public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, short inputOff, short inputlen, byte[] output, short outputOff) { byte[] mod = new byte[256]; - getPublicKey(keyBlob, (short)0, (short)keyBlob.length, mod, (short)0); + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, mod, (short)0)) + return 0; byte[] exponent = new byte[]{0x01,0x00,0x01}; // Convert byte arrays into keys @@ -2126,22 +2123,16 @@ public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, s return (short) cipherOut.length; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); } catch (InvalidKeySpecException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } catch (InvalidKeyException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.INVALID_INIT); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } catch (NoSuchPaddingException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } catch (NoSuchProviderException e) { e.printStackTrace(); - CryptoException.throwIt(CryptoException.INVALID_INIT); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { @@ -2158,6 +2149,8 @@ public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, short keyStart = 0; short keyLength = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, pubKey, (short) 0); + if (keyLength == 0) + return false; try { java.security.Signature sunSigner = java.security.Signature.getInstance( "NONEwithECDSA", "SunEC"); @@ -2215,6 +2208,9 @@ public boolean ecVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] pubKey = new byte[128]; short len = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, pubKey, (short) 0); + if (len == 0) { + return false; + } ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey( KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); key.setW(pubKey, (short) 0, len); @@ -2225,9 +2221,11 @@ public boolean ecVerifyMessage(byte[] input, short inputOff, short inputlen, public boolean rsaVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] sign, short signOff, short signLen, short digest,short padding, byte[] keyBlob) { - if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) + return false; byte[] pubKey = new byte[256]; - getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0); + if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + return false; short alg = Signature.ALG_RSA_SHA_256_PKCS1_PSS; if (padding == KMType.RSA_PKCS1_1_5_SIGN) From 5e0dba3642a41c88cee8dd493a52b8221800a862 Mon Sep 17 00:00:00 2001 From: mdwivedi Date: Wed, 10 Feb 2021 13:24:19 -0800 Subject: [PATCH 09/15] Revert "Move unsigned compare" --- .../android/javacard/keymaster/KMUtils.java | 47 +++++++++----- .../keymaster/KMAttestationCertImpl.java | 1 + .../android/javacard/keymaster/KMCipher.java | 8 +++ .../KMEcdsa256NoDigestSignature.java | 12 +++- .../javacard/keymaster/KMJCardSimulator.java | 65 +++++++++++++++---- .../keymaster/KMRsa2048NoDigestSignature.java | 2 +- .../android/javacard/keymaster/KMUtils.java | 50 +++++++++----- .../javacard/keymaster/KMByteBlob.java | 6 ++ .../android/javacard/keymaster/KMEncoder.java | 2 + .../javacard/keymaster/KMEnumArrayTag.java | 8 +++ .../android/javacard/keymaster/KMError.java | 55 +++++++++++----- .../android/javacard/keymaster/KMInteger.java | 22 +------ .../javacard/keymaster/KMKeymasterApplet.java | 4 +- .../javacard/keymaster/KMOperationState.java | 2 +- .../javacard/keymaster/KMSEProvider.java | 6 +- .../android/javacard/keymaster/KMType.java | 3 + 16 files changed, 203 insertions(+), 90 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index cdd86665..65e83415 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } // divide the given time with four yrs msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ public static short convertToDate(short time, byte[] scratchPad, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ public static short convertToDate(short time, byte[] scratchPad, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8, (short) 8); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one day msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one hour msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one minute msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one second msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,7 +244,24 @@ public static short convertToDate(short time, byte[] scratchPad, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } + 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; + } public static short numberToString(short number, byte[] scratchPad, short offset) { @@ -294,7 +311,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 23e7a067..18e67e72 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -90,6 +90,7 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static byte[] stack; private static short start; private static short length; + // private static KMRepository repo; private static short uniqueId; private static short attChallenge; private static short notBefore; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java index a5d06a39..3e67ed5e 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java @@ -24,11 +24,19 @@ public abstract class KMCipher { public abstract void updateAAD(byte[] buffer, short startOff, short length); + public abstract short getBlockMode(); + public abstract void setBlockMode(short mode); + public abstract short getPaddingAlgorithm(); + + public abstract short getCipherAlgorithm(); + public abstract void setPaddingAlgorithm(short alg); public abstract void setCipherAlgorithm(short alg); + public abstract short getCipherProvider(); + public abstract short getAesGcmOutputSize(short len, short macLength); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 56eaba5a..904353b1 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -85,12 +85,18 @@ public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec); sunSigner.initVerify(pubkey); } - } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + } catch (NoSuchAlgorithmException e) { CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch(InvalidParameterSpecException | InvalidKeySpecException | InvalidKeyException e) { + } catch (NoSuchProviderException e) { + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } catch(InvalidParameterSpecException e) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch(InvalidKeySpecException e) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch(InvalidKeyException e) { CryptoException.throwIt(CryptoException.INVALID_INIT); } - } + } @Override public void init(Key key, byte b) throws CryptoException { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 7e2f0760..0dad8f77 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -73,6 +73,9 @@ public class KMJCardSimulator implements KMSEProvider { public static final byte[] aesICV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private static final short CERT_CHAIN_MAX_SIZE = 2500;//First 2 bytes for length. private static final short RSA_KEY_SIZE = 256; + + + public static boolean jcardSim = false; private static Signature kdf; private static Signature hmacSignature; @@ -114,11 +117,13 @@ public KMJCardSimulator() { jCardSimulator = this; } + public KeyPair createRsaKeyPair() { KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); rsaKeyPair.genKeyPair(); return rsaKeyPair; } + public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLength, byte[] privBuffer, short privOff, short privLength) { @@ -127,13 +132,16 @@ public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLengt privKey.setExponent(privBuffer, privOff, privLength); privKey.setModulus(modBuffer, modOff, modLength); return privKey; + } + public KeyPair createECKeyPair() { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); ecKeyPair.genKeyPair(); return ecKeyPair; } + public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLength) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -141,6 +149,7 @@ public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLeng privKey.setS(privBuffer,privOff, privLength); return privKey; } + public AESKey createAESKey(short keysize) { byte[] rndNum = new byte[(short) (keysize/8)]; @@ -160,11 +169,13 @@ public AESKey createAESKey(byte[] buf, short startOff, short length) { return key; } + public DESKey createTDESKey() { byte[] rndNum = new byte[24]; newRandomNumber(rndNum, (short) 0, (short)rndNum.length); return createTDESKey(rndNum, (short)0, (short)rndNum.length); } + public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLength) { DESKey triDesKey = @@ -172,6 +183,7 @@ public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLe triDesKey.setKey(secretBuffer, secretOff); return triDesKey; } + public HMACKey createHMACKey(short keysize) { if((keysize % 8 != 0) || !(keysize >= 64 && keysize <= 512)){ @@ -248,13 +260,13 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, short length) { switch(alg){ case KMType.AES: - createAESKey(buf,startOff,length); + AESKey aesKey = createAESKey(buf,startOff,length); break; case KMType.DES: - createTDESKey(buf,startOff,length); + DESKey desKey = createTDESKey(buf,startOff,length); break; case KMType.HMAC: - createHMACKey(buf,startOff,length); + HMACKey hmacKey = createHMACKey(buf,startOff,length); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -267,10 +279,10 @@ public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short sta public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { switch (alg){ case KMType.RSA: - createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); + RSAPrivateKey rsaKey = createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); break; case KMType.EC: - createEcKey(privKeyBuf,privKeyStart,privKeyLength); + ECPrivateKey ecPrivKey = createEcKey(privKeyBuf,privKeyStart,privKeyLength); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -352,7 +364,13 @@ public short aesGCMEncrypt( byte[] outputBuf = new byte[cipher.getOutputSize(secretLen)]; try { len = (short)(cipher.doFinal(secret,secretStart,secretLen,outputBuf,(short)0)); - } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { + } catch (ShortBufferException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -440,7 +458,13 @@ public boolean aesGCMDecrypt( } catch (AEADBadTagException e) { e.printStackTrace(); return false; - } catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) { + } catch (ShortBufferException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (BadPaddingException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -663,10 +687,19 @@ private KMCipher createRsaOAEP256Cipher(byte mode,byte digest, } catch (NoSuchAlgorithmException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (InvalidKeySpecException | InvalidAlgorithmParameterException | NoSuchPaddingException e) { + } catch (InvalidKeySpecException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (InvalidKeyException | NoSuchProviderException e) { + } catch (InvalidKeyException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (NoSuchProviderException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.INVALID_INIT); } @@ -730,7 +763,13 @@ public Signature createEcSigner(short digest, byte[] secret, short secretStart, return ecSigner; } + + public KMCipher createSymmetricCipher( + short cipherAlg, short mode, short blockMode, short padding, byte[] secret, short secretStart, short secretLength) { + return createSymmetricCipher(cipherAlg, mode, blockMode, padding, secret,secretStart,secretLength,null,(short)0,(short)0); + } + public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, short padding, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -910,6 +949,7 @@ private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secret return ret; } + public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, short secretStart, short secretLength) { short alg = Signature.ALG_HMAC_SHA_256; if(digest != KMType.SHA2_256) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -919,6 +959,7 @@ public Signature createHmacSignerVerifier(short purpose, short digest, byte[] se hmacSignerVerifier.init(key,(byte)purpose); return hmacSignerVerifier; } + public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { @@ -1174,7 +1215,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { getTrueRandomNumber(keyData, (short) 0, keyLen); masterKey.setKey(keyData, (short) 0); } - return masterKey; + return (KMMasterKey) masterKey; } @Override @@ -1186,7 +1227,7 @@ public KMAttestationKey createAttestationKey(byte[] keyData, short offset, attestationKey = new KMECPrivateKey(ecKeyPair); } attestationKey.setS(keyData, offset, length); - return attestationKey; + return (KMAttestationKey) attestationKey; } @Override @@ -1201,7 +1242,7 @@ public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short len preSharedKey = new KMHmacKey(key); } preSharedKey.setKey(keyData, offset, length); - return preSharedKey; + return (KMPreSharedKey) preSharedKey; } @Override diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index de97d02c..fc953d73 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -121,7 +121,7 @@ private boolean isValidData(byte[] buf, short start, short len) { if (padding == KMType.PADDING_NONE) { if (len > 256) return false; else if (len == 256) { - short v = KMInteger.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); + short v = KMUtils.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); if (v > 0) return false; } } else {//pkcs1 no digest diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index c494bb34..65e83415 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -52,6 +52,7 @@ public class KMUtils { public static final short year2051 = 2051; public static final short year2020 = 2020; + // -------------------------------------- public static short convertToDate(short time, byte[] scratchPad, boolean utcFlag) { @@ -69,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -95,7 +96,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } // divide the given time with four yrs msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -115,9 +116,9 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -131,12 +132,12 @@ public static short convertToDate(short time, byte[] scratchPad, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -151,7 +152,7 @@ public static short convertToDate(short time, byte[] scratchPad, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -174,7 +175,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8, (short) 8); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -187,7 +188,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one day msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -198,7 +199,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one hour msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -208,7 +209,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one minute msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -218,7 +219,7 @@ public static short convertToDate(short time, byte[] scratchPad, } // divide the given time with one second msec count - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -243,6 +244,25 @@ public static short convertToDate(short time, byte[] scratchPad, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } + 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; + } + public static short numberToString(short number, byte[] scratchPad, short offset) { byte zero = 0x30; @@ -291,7 +311,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java index eb065e10..28b916db 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java @@ -115,4 +115,10 @@ public boolean isValid() { } return true; } + + public void decrementLength(short len) { + short length = Util.getShort(heap, (short) (instPtr + 1)); + length = (short) (length - len); + Util.setShort(heap, (short) (instPtr + 1), length); + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index b4055f04..685ba468 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -38,6 +38,7 @@ public class KMEncoder { private static final byte UINT64_LENGTH = (byte) 0x1B; private static final short TINY_PAYLOAD = 0x17; private static final short SHORT_PAYLOAD = 0x100; + //TODO make this static. private byte[] buffer; private short startOff; private short length; @@ -72,6 +73,7 @@ public short encode(short object, byte[] buffer, short startOff) { }else{ this.length = (short)buffer.length; } + //this.length = (short)(startOff + length); push(object); encode(); return (short)(this.startOff - startOff); diff --git a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java index 98ec05f7..37e23286 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java @@ -279,4 +279,12 @@ public boolean isValidPurpose(byte alg) { } return true; } + + public boolean isValidBlockMode(byte alg) { + if (alg == KMType.AES || alg == KMType.DES) { + return true; + } else { + return false; + } + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 0a52da0a..83eb8c7c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -21,61 +21,82 @@ */ public class KMError { public static final short OK = 0; - + public static final short ROOT_OF_TRUST_ALREADY_SET = 1; public static final short UNSUPPORTED_PURPOSE = 2; public static final short INCOMPATIBLE_PURPOSE = 3; public static final short UNSUPPORTED_ALGORITHM = 4; public static final short INCOMPATIBLE_ALGORITHM = 5; public static final short UNSUPPORTED_KEY_SIZE = 6; - + public static final short UNSUPPORTED_BLOCK_MODE = 7; public static final short INCOMPATIBLE_BLOCK_MODE = 8; public static final short UNSUPPORTED_MAC_LENGTH = 9; public static final short UNSUPPORTED_PADDING_MODE = 10; public static final short INCOMPATIBLE_PADDING_MODE = 11; public static final short UNSUPPORTED_DIGEST = 12; public static final short INCOMPATIBLE_DIGEST = 13; - + public static final short INVALID_EXPIRATION_TIME = 14; + public static final short INVALID_USER_ID = 15; + public static final short INVALID_AUTHORIZATION_TIMEOUT = 16; + public static final short UNSUPPORTED_KEY_FORMAT = 17; + public static final short INCOMPATIBLE_KEY_FORMAT = 18; public static final short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; - - /** For PKCS8 & PKCS12 */ + /** For PKCS8 & PKCS12 */ + public static final short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; + /** For PKCS8 & PKCS12 */ public static final short INVALID_INPUT_LENGTH = 21; - + public static final short KEY_EXPORT_OPTIONS_INVALID = 22; + public static final short DELEGATION_NOT_ALLOWED = 23; + public static final short KEY_NOT_YET_VALID = 24; + public static final short KEY_EXPIRED = 25; public static final short KEY_USER_NOT_AUTHENTICATED = 26; - + public static final short OUTPUT_PARAMETER_NULL = 27; public static final short INVALID_OPERATION_HANDLE = 28; - + public static final short INSUFFICIENT_BUFFER_SPACE = 29; public static final short VERIFICATION_FAILED = 30; public static final short TOO_MANY_OPERATIONS = 31; + public static final short UNEXPECTED_NULL_POINTER = 32; public static final short INVALID_KEY_BLOB = 33; - + public static final short IMPORTED_KEY_NOT_ENCRYPTED = 34; + public static final short IMPORTED_KEY_DECRYPTION_FAILED = 35; + public static final short IMPORTED_KEY_NOT_SIGNED = 36; + public static final short IMPORTED_KEY_VERIFICATION_FAILED = 37; public static final short INVALID_ARGUMENT = 38; public static final short UNSUPPORTED_TAG = 39; public static final short INVALID_TAG = 40; - + public static final short MEMORY_ALLOCATION_FAILED = 41; public static final short IMPORT_PARAMETER_MISMATCH = 44; + public static final short SECURE_HW_ACCESS_DENIED = 45; public static final short OPERATION_CANCELLED = 46; - + public static final short CONCURRENT_ACCESS_CONFLICT = 47; + public static final short SECURE_HW_BUSY = 48; + public static final short SECURE_HW_COMMUNICATION_FAILED = 49; + public static final short UNSUPPORTED_EC_FIELD = 50; public static final short MISSING_NONCE = 51; public static final short INVALID_NONCE = 52; public static final short MISSING_MAC_LENGTH = 53; - + public static final short KEY_RATE_LIMIT_EXCEEDED = 54; public static final short CALLER_NONCE_PROHIBITED = 55; - + public static final short KEY_MAX_OPS_EXCEEDED = 56; public static final short INVALID_MAC_LENGTH = 57; public static final short MISSING_MIN_MAC_LENGTH = 58; public static final short UNSUPPORTED_MIN_MAC_LENGTH = 59; - + public static final short UNSUPPORTED_KDF = 60; public static final short UNSUPPORTED_EC_CURVE = 61; public static final short KEY_REQUIRES_UPGRADE = 62; - + public static final short ATTESTATION_CHALLENGE_MISSING = 63; + public static final short KEYMASTER_NOT_CONFIGURED = 64; public static final short ATTESTATION_APPLICATION_ID_MISSING = 65; + public static final short CANNOT_ATTEST_IDS = 66; public static final short ROLLBACK_RESISTANCE_UNAVAILABLE = 67; - + public static final short HARDWARE_TYPE_UNAVAILABLE = 68; + public static final short PROOF_OF_PRESENCE_REQUIRED = 69; + public static final short CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; + public static final short NO_USER_CONFIRMATION = 71; public static final short DEVICE_LOCKED = 72; public static final short EARLY_BOOT_ENDED = 73; - public static final short UNIMPLEMENTED = 100; + public static final short VERSION_MISMATCH = 101; public static final short UNKNOWN_ERROR = 1000; //Extended errors diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 44a0779a..18944e4d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -162,30 +162,10 @@ public static short compare(short num1, short num2){ 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( + return KMUtils.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; - } - } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 3942a891..e1e8214d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3481,7 +3481,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsVersion(); tmpVariables[1] = - KMInteger.unsignedByteArrayCompare( + KMUtils.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, @@ -3500,7 +3500,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsPatch(); tmpVariables[1] = - KMInteger.unsignedByteArrayCompare( + KMUtils.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, diff --git a/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 6d033443..6ea96941 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -41,7 +41,7 @@ public class KMOperationState { // short type private static final byte KEY_SIZE = 6; private static final byte MAC_LENGTH = 8; - + // Handle - currently this is short private static final byte OP_HANDLE = 10; // Auth time 64 bits private static final byte AUTH_TIME = 12; diff --git a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java index 0719d04b..a057eb9e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java +++ b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java @@ -220,7 +220,7 @@ boolean aesGCMDecrypt( * This is a oneshot operation that performs key derivation function using cmac kdf (CKDF) as * defined in android keymaster hal definition. * - * @param hmacKey instance of pre-shared key. + * @param instance of pre-shared key. * @param label is the label to be used for ckdf. * @param labelStart is the start of label. * @param labelLen is the length of the label. @@ -269,7 +269,7 @@ short hmacSign( * This is a oneshot operation that signs the data using hmac algorithm. * This is used to derive the key, which is used to encrypt the keyblob. * - * @param masterkey instance of masterkey. + * @param instance of masterkey. * @param data is the buffer containing data to be signed. * @param dataStart is the start of the data. * @param dataLength is the length of the data. @@ -344,7 +344,7 @@ short rsaDecipherOAEP256( /** * This is a oneshot operation that signs the data using EC private key. * - * @param ecPrivKey instance of KMAttestationKey. + * @param instance of KMAttestationKey. * @param inputDataBuf is the buffer of the input data. * @param inputDataStart is the start of the input data buffer. * @param inputDataLength is the length of the inpur data buffer in bytes. diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 53442440..4d81de45 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -41,6 +41,7 @@ public abstract class KMType { public static final byte HW_AUTH_TOKEN_TYPE = 0x08; public static final byte VERIFICATION_TOKEN_TYPE = 0x09; public static final byte HMAC_SHARING_PARAM_TYPE = 0x0A; + public static final byte X509_CERT = 0x0B; // Tag Types public static final short INVALID_TAG = 0x0000; public static final short ENUM_TAG = 0x1000; @@ -50,6 +51,7 @@ public abstract class KMType { public static final short ULONG_TAG = 0x5000; public static final short DATE_TAG = 0x6000; public static final short BOOL_TAG = 0x7000; + public static final short BIGNUM_TAG = (short) 0x8000; public static final short BYTES_TAG = (short) 0x9000; public static final short ULONG_ARRAY_TAG = (short) 0xA000; public static final short TAG_TYPE_MASK = (short) 0xF000; @@ -269,6 +271,7 @@ public abstract class KMType { // Confirmation Token public static final short CONFIRMATION_TOKEN = (short) 0x03ED; + public static final short LENGTH_FROM_PDU = (short) 0xFFFF; public static final byte NO_VALUE = (byte) 0xff; From a900964b4cf5caf2eadf9d34da5d26a8770e47d1 Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Wed, 10 Feb 2021 22:42:48 +0000 Subject: [PATCH 10/15] Moving unsigned compare to KMInteger --- .../android/javacard/keymaster/KMUtils.java | 49 ++++++------------- .../keymaster/KMRsa2048NoDigestSignature.java | 2 +- .../android/javacard/keymaster/KMUtils.java | 49 ++++++------------- .../android/javacard/keymaster/KMInteger.java | 20 +++++++- .../javacard/keymaster/KMKeymasterApplet.java | 4 +- 5 files changed, 52 insertions(+), 72 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index 65e83415..2e72ae6d 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8); } // divide the given time with four yrs msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8, (short) 8); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one day msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one hour msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one minute msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one second msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,25 +244,6 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } - 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; - } - public static short numberToString(short number, byte[] scratchPad, short offset) { byte zero = 0x30; @@ -311,7 +292,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index fc953d73..de97d02c 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -121,7 +121,7 @@ private boolean isValidData(byte[] buf, short start, short len) { if (padding == KMType.PADDING_NONE) { if (len > 256) return false; else if (len == 256) { - short v = KMUtils.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); + short v = KMInteger.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); if (v > 0) return false; } } else {//pkcs1 no digest diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index 65e83415..2e72ae6d 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -70,17 +70,17 @@ public static short convertToDate(short time, byte[] scratchPad, (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) .length()); // If the time is less then 1 Jan 2020 then it is an error - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -96,7 +96,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8); } // divide the given time with four yrs msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -116,9 +116,9 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || ((leapYrIdx != 0) && - (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { @@ -132,12 +132,12 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, (short) 8); if (((short) (i + 1) == leapYrIdx)) { - if (unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) < 0) { break; } } else { - if (unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) < 0) { break; } @@ -152,7 +152,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, yrsCount = (short) (year2051 + yrsCount); // divide the given time with one month msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { @@ -175,7 +175,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 8, (short) 8); } - if (unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -188,7 +188,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one day msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -199,7 +199,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one hour msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -209,7 +209,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one minute msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -219,7 +219,7 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, } // divide the given time with one second msec count - if (unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, (short) 8); @@ -244,25 +244,6 @@ && unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY } - 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; - } - public static short numberToString(short number, byte[] scratchPad, short offset) { byte zero = 0x30; @@ -311,7 +292,7 @@ public static void copy(byte[] buf, short from, short to) { } public static byte compare(byte[] buf, short lhs, short rhs) { - return unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); + return KMInteger.unsignedByteArrayCompare(buf, lhs, buf, rhs, (short) 8); } public static void shiftLeft(byte[] buf, short start) { diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 18944e4d..541eae8b 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -162,10 +162,28 @@ public static short compare(short num1, short num2){ 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 KMUtils.unsignedByteArrayCompare( + 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; + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index e1e8214d..3942a891 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3481,7 +3481,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsVersion(); tmpVariables[1] = - KMUtils.unsignedByteArrayCompare( + KMInteger.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, @@ -3500,7 +3500,7 @@ private void checkVersionAndPatchLevel(byte[] scratchPad) { if (tmpVariables[0] != KMType.INVALID_VALUE) { tmpVariables[1] = repository.getOsPatch(); tmpVariables[1] = - KMUtils.unsignedByteArrayCompare( + KMInteger.unsignedByteArrayCompare( KMInteger.cast(tmpVariables[1]).getBuffer(), KMInteger.cast(tmpVariables[1]).getStartOff(), scratchPad, From 5c1e3bd16dcd8aeecf856ad9d7fa82b591e26d55 Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Wed, 10 Feb 2021 23:00:35 +0000 Subject: [PATCH 11/15] Removing error code --- .../android/javacard/keymaster/KMEncoder.java | 1 - .../android/javacard/keymaster/KMError.java | 43 +++---------------- 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 685ba468..431d84e3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -38,7 +38,6 @@ public class KMEncoder { private static final byte UINT64_LENGTH = (byte) 0x1B; private static final short TINY_PAYLOAD = 0x17; private static final short SHORT_PAYLOAD = 0x100; - //TODO make this static. private byte[] buffer; private short startOff; private short length; diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 83eb8c7c..76ec8560 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -21,7 +21,6 @@ */ public class KMError { public static final short OK = 0; - public static final short ROOT_OF_TRUST_ALREADY_SET = 1; public static final short UNSUPPORTED_PURPOSE = 2; public static final short INCOMPATIBLE_PURPOSE = 3; public static final short UNSUPPORTED_ALGORITHM = 4; @@ -34,69 +33,41 @@ public class KMError { public static final short INCOMPATIBLE_PADDING_MODE = 11; public static final short UNSUPPORTED_DIGEST = 12; public static final short INCOMPATIBLE_DIGEST = 13; - public static final short INVALID_EXPIRATION_TIME = 14; - public static final short INVALID_USER_ID = 15; - public static final short INVALID_AUTHORIZATION_TIMEOUT = 16; - public static final short UNSUPPORTED_KEY_FORMAT = 17; - public static final short INCOMPATIBLE_KEY_FORMAT = 18; + public static final short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; - /** For PKCS8 & PKCS12 */ - public static final short UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = 20; + /** For PKCS8 & PKCS12 */ public static final short INVALID_INPUT_LENGTH = 21; - public static final short KEY_EXPORT_OPTIONS_INVALID = 22; - public static final short DELEGATION_NOT_ALLOWED = 23; - public static final short KEY_NOT_YET_VALID = 24; - public static final short KEY_EXPIRED = 25; + public static final short KEY_USER_NOT_AUTHENTICATED = 26; - public static final short OUTPUT_PARAMETER_NULL = 27; public static final short INVALID_OPERATION_HANDLE = 28; - public static final short INSUFFICIENT_BUFFER_SPACE = 29; public static final short VERIFICATION_FAILED = 30; public static final short TOO_MANY_OPERATIONS = 31; - public static final short UNEXPECTED_NULL_POINTER = 32; public static final short INVALID_KEY_BLOB = 33; - public static final short IMPORTED_KEY_NOT_ENCRYPTED = 34; - public static final short IMPORTED_KEY_DECRYPTION_FAILED = 35; - public static final short IMPORTED_KEY_NOT_SIGNED = 36; - public static final short IMPORTED_KEY_VERIFICATION_FAILED = 37; + public static final short INVALID_ARGUMENT = 38; public static final short UNSUPPORTED_TAG = 39; public static final short INVALID_TAG = 40; - public static final short MEMORY_ALLOCATION_FAILED = 41; public static final short IMPORT_PARAMETER_MISMATCH = 44; - public static final short SECURE_HW_ACCESS_DENIED = 45; public static final short OPERATION_CANCELLED = 46; - public static final short CONCURRENT_ACCESS_CONFLICT = 47; - public static final short SECURE_HW_BUSY = 48; - public static final short SECURE_HW_COMMUNICATION_FAILED = 49; - public static final short UNSUPPORTED_EC_FIELD = 50; + public static final short MISSING_NONCE = 51; public static final short INVALID_NONCE = 52; public static final short MISSING_MAC_LENGTH = 53; - public static final short KEY_RATE_LIMIT_EXCEEDED = 54; public static final short CALLER_NONCE_PROHIBITED = 55; - public static final short KEY_MAX_OPS_EXCEEDED = 56; public static final short INVALID_MAC_LENGTH = 57; public static final short MISSING_MIN_MAC_LENGTH = 58; public static final short UNSUPPORTED_MIN_MAC_LENGTH = 59; - public static final short UNSUPPORTED_KDF = 60; public static final short UNSUPPORTED_EC_CURVE = 61; public static final short KEY_REQUIRES_UPGRADE = 62; - public static final short ATTESTATION_CHALLENGE_MISSING = 63; - public static final short KEYMASTER_NOT_CONFIGURED = 64; + public static final short ATTESTATION_APPLICATION_ID_MISSING = 65; - public static final short CANNOT_ATTEST_IDS = 66; public static final short ROLLBACK_RESISTANCE_UNAVAILABLE = 67; - public static final short HARDWARE_TYPE_UNAVAILABLE = 68; - public static final short PROOF_OF_PRESENCE_REQUIRED = 69; - public static final short CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = 70; - public static final short NO_USER_CONFIRMATION = 71; + public static final short DEVICE_LOCKED = 72; public static final short EARLY_BOOT_ENDED = 73; public static final short UNIMPLEMENTED = 100; - public static final short VERSION_MISMATCH = 101; public static final short UNKNOWN_ERROR = 1000; //Extended errors From 67309ab1a2d35c76c28d93d9948e43149c703140 Mon Sep 17 00:00:00 2001 From: Manish Dwivedi Date: Wed, 10 Feb 2021 23:24:57 +0000 Subject: [PATCH 12/15] code reformatting --- Applet/AndroidSEProvider/build.xml | 106 +- .../android/javacard/keymaster/KMAESKey.java | 3 +- .../javacard/keymaster/KMAndroidSEApplet.java | 29 +- .../keymaster/KMAndroidSEProvider.java | 698 ++--- .../keymaster/KMAttestationCertImpl.java | 169 +- .../javacard/keymaster/KMECPrivateKey.java | 2 +- .../KMEcdsa256NoDigestSignature.java | 13 +- .../android/javacard/keymaster/KMHmacKey.java | 2 + .../javacard/keymaster/KMInstance.java | 1 + .../javacard/keymaster/KMOperationImpl.java | 16 +- .../keymaster/KMRsa2048NoDigestSignature.java | 6 +- .../javacard/keymaster/KMRsaOAEPEncoding.java | 92 +- .../android/javacard/keymaster/KMUtils.java | 183 +- Applet/JCardSimProvider/build.xml | 46 +- .../android/javacard/keymaster/KMAESKey.java | 3 +- .../keymaster/KMAttestationCertImpl.java | 169 +- .../android/javacard/keymaster/KMCipher.java | 7 +- .../javacard/keymaster/KMCipherImpl.java | 136 +- .../javacard/keymaster/KMECPrivateKey.java | 2 +- .../KMEcdsa256NoDigestSignature.java | 155 +- .../android/javacard/keymaster/KMHmacKey.java | 1 + .../javacard/keymaster/KMJCardSimApplet.java | 5 +- .../javacard/keymaster/KMJCardSimulator.java | 583 ++-- .../javacard/keymaster/KMOperationImpl.java | 32 +- .../keymaster/KMRsa2048NoDigestSignature.java | 51 +- .../android/javacard/keymaster/KMUtils.java | 183 +- .../javacard/test/KMFunctionalTest.java | 2685 +++++++++-------- Applet/build.xml | 26 +- .../android/javacard/keymaster/KMArray.java | 27 +- .../javacard/keymaster/KMAttestationCert.java | 28 +- .../javacard/keymaster/KMAttestationKey.java | 7 +- .../android/javacard/keymaster/KMBoolTag.java | 61 +- .../javacard/keymaster/KMByteBlob.java | 24 +- .../android/javacard/keymaster/KMByteTag.java | 80 +- .../android/javacard/keymaster/KMDecoder.java | 61 +- .../android/javacard/keymaster/KMEncoder.java | 176 +- .../android/javacard/keymaster/KMEnum.java | 60 +- .../javacard/keymaster/KMEnumArrayTag.java | 40 +- .../android/javacard/keymaster/KMEnumTag.java | 66 +- .../android/javacard/keymaster/KMError.java | 7 +- .../javacard/keymaster/KMException.java | 16 +- .../keymaster/KMHardwareAuthToken.java | 49 +- .../keymaster/KMHmacSharingParameters.java | 36 +- .../android/javacard/keymaster/KMInteger.java | 71 +- .../javacard/keymaster/KMIntegerArrayTag.java | 44 +- .../javacard/keymaster/KMIntegerTag.java | 74 +- .../keymaster/KMKeyCharacteristics.java | 38 +- .../javacard/keymaster/KMKeyParameters.java | 123 +- .../javacard/keymaster/KMKeymasterApplet.java | 368 ++- .../javacard/keymaster/KMMasterKey.java | 7 +- .../javacard/keymaster/KMOperation.java | 10 +- .../javacard/keymaster/KMOperationState.java | 42 +- .../javacard/keymaster/KMPreSharedKey.java | 7 +- .../javacard/keymaster/KMRepository.java | 333 +- .../javacard/keymaster/KMSEProvider.java | 104 +- .../com/android/javacard/keymaster/KMTag.java | 23 +- .../android/javacard/keymaster/KMType.java | 23 +- .../javacard/keymaster/KMUpgradable.java | 7 +- .../keymaster/KMVerificationToken.java | 50 +- ...ardware.keymaster@4.1-javacard.service.xml | 10 +- 60 files changed, 4093 insertions(+), 3383 deletions(-) diff --git a/Applet/AndroidSEProvider/build.xml b/Applet/AndroidSEProvider/build.xml index 04b1dee6..137c169a 100644 --- a/Applet/AndroidSEProvider/build.xml +++ b/Applet/AndroidSEProvider/build.xml @@ -1,58 +1,60 @@ - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - + - + - + @@ -60,18 +62,20 @@ + to="AndroidSE.\2" + casesensitive="yes"/> - - + + - - + + \ No newline at end of file diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAESKey.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAESKey.java index afdfb08e..cec6388e 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAESKey.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAESKey.java @@ -22,6 +22,7 @@ import javacard.security.AESKey; public class KMAESKey implements KMMasterKey { + private AESKey aesKey; public KMAESKey(AESKey key) { @@ -35,7 +36,7 @@ public void setKey(byte[] keyData, short kOff) { public AESKey getKey() { return aesKey; } - + public short getKeySizeBits() { return aesKey.getSize(); } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java index bb6a2e86..7c6f31fe 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java @@ -21,19 +21,20 @@ public class KMAndroidSEApplet extends KMKeymasterApplet implements OnUpgradeListener { - KMAndroidSEApplet(){ - super(new KMAndroidSEProvider()); - } - /** - * Installs this applet. - * - * @param bArray the array containing installation parameters - * @param bOffset the starting offset in bArray - * @param bLength the length in bytes of the parameter data in bArray - */ - public static void install(byte[] bArray, short bOffset, byte bLength) { - new KMAndroidSEApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]); - } + KMAndroidSEApplet() { + super(new KMAndroidSEProvider()); + } + + /** + * Installs this applet. + * + * @param bArray the array containing installation parameters + * @param bOffset the starting offset in bArray + * @param bLength the length in bytes of the parameter data in bArray + */ + public static void install(byte[] bArray, short bOffset, byte bLength) { + new KMAndroidSEApplet().register(bArray, (short) (bOffset + 1), bArray[bOffset]); + } @Override public void onCleanup() { @@ -66,7 +67,7 @@ public Element onSave() { // Create element. Element element = UpgradeManager.createElement(Element.TYPE_SIMPLE, - primitiveCount, objectCount); + primitiveCount, objectCount); element.write(provisionStatus); element.write(keymasterState); repository.onSave(element); diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java index ac4ae426..369276c7 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java @@ -47,66 +47,67 @@ import com.android.javacard.keymaster.KMPreSharedKey; public class KMAndroidSEProvider implements KMSEProvider { + // static final variables // -------------------------------------------------------------- // P-256 Curve Parameters static final byte[] secp256r1_P = { - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF }; + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF}; static final byte[] secp256r1_A = { - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xFC }; + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFC}; static final byte[] secp256r1_B = { - (byte) 0x5A, (byte) 0xC6, (byte) 0x35, (byte) 0xD8, (byte) 0xAA, - (byte) 0x3A, (byte) 0x93, (byte) 0xE7, (byte) 0xB3, (byte) 0xEB, - (byte) 0xBD, (byte) 0x55, (byte) 0x76, (byte) 0x98, (byte) 0x86, - (byte) 0xBC, (byte) 0x65, (byte) 0x1D, (byte) 0x06, (byte) 0xB0, - (byte) 0xCC, (byte) 0x53, (byte) 0xB0, (byte) 0xF6, (byte) 0x3B, - (byte) 0xCE, (byte) 0x3C, (byte) 0x3E, (byte) 0x27, (byte) 0xD2, - (byte) 0x60, (byte) 0x4B }; + (byte) 0x5A, (byte) 0xC6, (byte) 0x35, (byte) 0xD8, (byte) 0xAA, + (byte) 0x3A, (byte) 0x93, (byte) 0xE7, (byte) 0xB3, (byte) 0xEB, + (byte) 0xBD, (byte) 0x55, (byte) 0x76, (byte) 0x98, (byte) 0x86, + (byte) 0xBC, (byte) 0x65, (byte) 0x1D, (byte) 0x06, (byte) 0xB0, + (byte) 0xCC, (byte) 0x53, (byte) 0xB0, (byte) 0xF6, (byte) 0x3B, + (byte) 0xCE, (byte) 0x3C, (byte) 0x3E, (byte) 0x27, (byte) 0xD2, + (byte) 0x60, (byte) 0x4B}; static final byte[] secp256r1_S = { - (byte) 0xC4, (byte) 0x9D, (byte) 0x36, (byte) 0x08, (byte) 0x86, - (byte) 0xE7, (byte) 0x04, (byte) 0x93, (byte) 0x6A, (byte) 0x66, - (byte) 0x78, (byte) 0xE1, (byte) 0x13, (byte) 0x9D, (byte) 0x26, - (byte) 0xB7, (byte) 0x81, (byte) 0x9F, (byte) 0x7E, (byte) 0x90 }; + (byte) 0xC4, (byte) 0x9D, (byte) 0x36, (byte) 0x08, (byte) 0x86, + (byte) 0xE7, (byte) 0x04, (byte) 0x93, (byte) 0x6A, (byte) 0x66, + (byte) 0x78, (byte) 0xE1, (byte) 0x13, (byte) 0x9D, (byte) 0x26, + (byte) 0xB7, (byte) 0x81, (byte) 0x9F, (byte) 0x7E, (byte) 0x90}; // Uncompressed form static final byte[] secp256r1_UCG = { - (byte) 0x04, (byte) 0x6B, (byte) 0x17, (byte) 0xD1, (byte) 0xF2, - (byte) 0xE1, (byte) 0x2C, (byte) 0x42, (byte) 0x47, (byte) 0xF8, - (byte) 0xBC, (byte) 0xE6, (byte) 0xE5, (byte) 0x63, (byte) 0xA4, - (byte) 0x40, (byte) 0xF2, (byte) 0x77, (byte) 0x03, (byte) 0x7D, - (byte) 0x81, (byte) 0x2D, (byte) 0xEB, (byte) 0x33, (byte) 0xA0, - (byte) 0xF4, (byte) 0xA1, (byte) 0x39, (byte) 0x45, (byte) 0xD8, - (byte) 0x98, (byte) 0xC2, (byte) 0x96, (byte) 0x4F, (byte) 0xE3, - (byte) 0x42, (byte) 0xE2, (byte) 0xFE, (byte) 0x1A, (byte) 0x7F, - (byte) 0x9B, (byte) 0x8E, (byte) 0xE7, (byte) 0xEB, (byte) 0x4A, - (byte) 0x7C, (byte) 0x0F, (byte) 0x9E, (byte) 0x16, (byte) 0x2B, - (byte) 0xCE, (byte) 0x33, (byte) 0x57, (byte) 0x6B, (byte) 0x31, - (byte) 0x5E, (byte) 0xCE, (byte) 0xCB, (byte) 0xB6, (byte) 0x40, - (byte) 0x68, (byte) 0x37, (byte) 0xBF, (byte) 0x51, (byte) 0xF5 }; + (byte) 0x04, (byte) 0x6B, (byte) 0x17, (byte) 0xD1, (byte) 0xF2, + (byte) 0xE1, (byte) 0x2C, (byte) 0x42, (byte) 0x47, (byte) 0xF8, + (byte) 0xBC, (byte) 0xE6, (byte) 0xE5, (byte) 0x63, (byte) 0xA4, + (byte) 0x40, (byte) 0xF2, (byte) 0x77, (byte) 0x03, (byte) 0x7D, + (byte) 0x81, (byte) 0x2D, (byte) 0xEB, (byte) 0x33, (byte) 0xA0, + (byte) 0xF4, (byte) 0xA1, (byte) 0x39, (byte) 0x45, (byte) 0xD8, + (byte) 0x98, (byte) 0xC2, (byte) 0x96, (byte) 0x4F, (byte) 0xE3, + (byte) 0x42, (byte) 0xE2, (byte) 0xFE, (byte) 0x1A, (byte) 0x7F, + (byte) 0x9B, (byte) 0x8E, (byte) 0xE7, (byte) 0xEB, (byte) 0x4A, + (byte) 0x7C, (byte) 0x0F, (byte) 0x9E, (byte) 0x16, (byte) 0x2B, + (byte) 0xCE, (byte) 0x33, (byte) 0x57, (byte) 0x6B, (byte) 0x31, + (byte) 0x5E, (byte) 0xCE, (byte) 0xCB, (byte) 0xB6, (byte) 0x40, + (byte) 0x68, (byte) 0x37, (byte) 0xBF, (byte) 0x51, (byte) 0xF5}; static final byte[] secp256r1_N = { - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, (byte) 0xBC, (byte) 0xE6, (byte) 0xFA, (byte) 0xAD, - (byte) 0xA7, (byte) 0x17, (byte) 0x9E, (byte) 0x84, (byte) 0xF3, - (byte) 0xB9, (byte) 0xCA, (byte) 0xC2, (byte) 0xFC, (byte) 0x63, - (byte) 0x25, (byte) 0x51 }; + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, (byte) 0xBC, (byte) 0xE6, (byte) 0xFA, (byte) 0xAD, + (byte) 0xA7, (byte) 0x17, (byte) 0x9E, (byte) 0x84, (byte) 0xF3, + (byte) 0xB9, (byte) 0xCA, (byte) 0xC2, (byte) 0xFC, (byte) 0x63, + (byte) 0x25, (byte) 0x51}; static final short secp256r1_H = 1; // -------------------------------------------------------------- public static final short AES_GCM_TAG_LENGTH = 16; @@ -118,24 +119,24 @@ public class KMAndroidSEProvider implements KMSEProvider { public static final short CERT_CHAIN_MAX_SIZE = 2500;//First 2 bytes for length. final byte[] CIPHER_ALGS = { - Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, - Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, - Cipher.ALG_DES_CBC_NOPAD, - Cipher.ALG_DES_ECB_NOPAD, - Cipher.ALG_AES_CTR, - Cipher.ALG_RSA_PKCS1, - KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1, - Cipher.ALG_RSA_NOPAD, - AEADCipher.ALG_AES_GCM }; + Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, + Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, + Cipher.ALG_DES_CBC_NOPAD, + Cipher.ALG_DES_ECB_NOPAD, + Cipher.ALG_AES_CTR, + Cipher.ALG_RSA_PKCS1, + KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1, + Cipher.ALG_RSA_NOPAD, + AEADCipher.ALG_AES_GCM}; final byte[] SIG_ALGS = { - Signature.ALG_RSA_SHA_256_PKCS1, - Signature.ALG_RSA_SHA_256_PKCS1_PSS, - Signature.ALG_ECDSA_SHA_256, - Signature.ALG_HMAC_SHA_256, - KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD, - KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST, - KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST}; + Signature.ALG_RSA_SHA_256_PKCS1, + Signature.ALG_RSA_SHA_256_PKCS1_PSS, + Signature.ALG_ECDSA_SHA_256, + Signature.ALG_HMAC_SHA_256, + KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD, + KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST, + KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST}; // AESKey private AESKey aesKeys[]; @@ -215,8 +216,9 @@ public KMAndroidSEProvider() { // Random number generator initialisation. rng = RandomData.getInstance(RandomData.ALG_KEYGENERATION); //Allocate buffer for certificate chain. - if(!isUpgrading()) + if (!isUpgrading()) { certificateChain = new byte[CERT_CHAIN_MAX_SIZE]; + } androidSEProvider = this; } @@ -305,7 +307,7 @@ private Cipher getCipherInstance(byte alg) { } private byte getCipherAlgorithm(Cipher c) { - return c.getAlgorithm(); + return c.getAlgorithm(); } // Create a cipher instance of each algorithm once. @@ -513,18 +515,18 @@ public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, public short createSymmetricKey(byte alg, short keysize, byte[] buf, short startOff) { switch (alg) { - case KMType.AES: - AESKey aesKey = createAESKey(keysize); - return aesKey.getKey(buf, startOff); - case KMType.DES: - DESKey desKey = createTDESKey(); - return desKey.getKey(buf, startOff); - case KMType.HMAC: - HMACKey hmacKey = createHMACKey(keysize); - return hmacKey.getKey(buf, startOff); - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case KMType.AES: + AESKey aesKey = createAESKey(keysize); + return aesKey.getKey(buf, startOff); + case KMType.DES: + DESKey desKey = createTDESKey(); + return desKey.getKey(buf, startOff); + case KMType.HMAC: + HMACKey hmacKey = createHMACKey(keysize); + return hmacKey.getKey(buf, startOff); + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return 0; } @@ -534,42 +536,44 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength, short[] lengths) { switch (alg) { - case KMType.RSA: - if (RSA_KEY_SIZE != privKeyLength || RSA_KEY_SIZE != pubModLength) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } - KeyPair rsaKey = createRsaKeyPair(); - RSAPrivateKey privKey = (RSAPrivateKey) rsaKey.getPrivate(); - //Copy exponent. - Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); - lengths[0] = privKey.getExponent(tmpArray, (short)0); - if (lengths[0] > privKeyLength) - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte)0); - Util.arrayCopyNonAtomic(tmpArray, (short)0, - privKeyBuf, (short)(privKeyStart + privKeyLength - lengths[0]), lengths[0]); - //Copy modulus - Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); - lengths[1] = privKey.getModulus(tmpArray, (short)0); - if (lengths[1] > pubModLength) - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte)0); - Util.arrayCopyNonAtomic(tmpArray, (short)0, - pubModBuf, (short)(pubModStart + pubModLength - lengths[1]), lengths[1]); - break; - case KMType.EC: - KeyPair ecKey = createECKeyPair(); - ECPublicKey ecPubKey = (ECPublicKey) ecKey.getPublic(); - ECPrivateKey ecPrivKey = (ECPrivateKey) ecKey.getPrivate(); - lengths[0] = ecPrivKey.getS(privKeyBuf, privKeyStart); - lengths[1] = ecPubKey.getW(pubModBuf, pubModStart); - if (lengths[0] > privKeyLength || lengths[1] > pubModLength) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } - break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case KMType.RSA: + if (RSA_KEY_SIZE != privKeyLength || RSA_KEY_SIZE != pubModLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + KeyPair rsaKey = createRsaKeyPair(); + RSAPrivateKey privKey = (RSAPrivateKey) rsaKey.getPrivate(); + //Copy exponent. + Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); + lengths[0] = privKey.getExponent(tmpArray, (short) 0); + if (lengths[0] > privKeyLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte) 0); + Util.arrayCopyNonAtomic(tmpArray, (short) 0, + privKeyBuf, (short) (privKeyStart + privKeyLength - lengths[0]), lengths[0]); + //Copy modulus + Util.arrayFillNonAtomic(tmpArray, (short) 0, RSA_KEY_SIZE, (byte) 0); + lengths[1] = privKey.getModulus(tmpArray, (short) 0); + if (lengths[1] > pubModLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte) 0); + Util.arrayCopyNonAtomic(tmpArray, (short) 0, + pubModBuf, (short) (pubModStart + pubModLength - lengths[1]), lengths[1]); + break; + case KMType.EC: + KeyPair ecKey = createECKeyPair(); + ECPublicKey ecPubKey = (ECPublicKey) ecKey.getPublic(); + ECPrivateKey ecPrivKey = (ECPrivateKey) ecKey.getPrivate(); + lengths[0] = ecPrivKey.getS(privKeyBuf, privKeyStart); + lengths[1] = ecPubKey.getW(pubModBuf, pubModStart); + if (lengths[0] > privKeyLength || lengths[1] > pubModLength) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } } @@ -577,18 +581,18 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, short length) { switch (alg) { - case KMType.AES: - createAESKey(buf, startOff, length); - break; - case KMType.DES: - createTDESKey(buf, startOff, length); - break; - case KMType.HMAC: - createHMACKey(buf, startOff, length); - break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case KMType.AES: + createAESKey(buf, startOff, length); + break; + case KMType.DES: + createTDESKey(buf, startOff, length); + break; + case KMType.HMAC: + createHMACKey(buf, startOff, length); + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return true; } @@ -598,16 +602,16 @@ public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { switch (alg) { - case KMType.RSA: - createRsaKey(pubModBuf, pubModStart, pubModLength, privKeyBuf, - privKeyStart, privKeyLength); - break; - case KMType.EC: - createEcKey(privKeyBuf, privKeyStart, privKeyLength); - break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case KMType.RSA: + createRsaKey(pubModBuf, pubModStart, pubModLength, privKeyBuf, + privKeyStart, privKeyLength); + break; + case KMType.EC: + createEcKey(privKeyBuf, privKeyStart, privKeyLength); + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return true; } @@ -628,10 +632,10 @@ public void addRngEntropy(byte[] num, short offset, short length) { } public short aesGCMEncrypt(AESKey key, - byte[] secret, short secretStart, short secretLen, byte[] encSecret, - short encSecretStart, byte[] nonce, short nonceStart, short nonceLen, - byte[] authData, short authDataStart, short authDataLen, byte[] authTag, - short authTagStart, short authTagLen) { + byte[] secret, short secretStart, short secretLen, byte[] encSecret, + short encSecretStart, byte[] nonce, short nonceStart, short nonceLen, + byte[] authData, short authDataStart, short authDataLen, byte[] authTag, + short authTagStart, short authTagLen) { if (authTagLen != AES_GCM_TAG_LENGTH) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -659,21 +663,21 @@ public short aesGCMEncrypt(byte[] aesKey, short aesKeyStart, short aesKeyLen, AESKey key = createAESKey(aesKey, aesKeyStart, aesKeyLen); return aesGCMEncrypt( - key, - secret, - secretStart, - secretLen, - encSecret, - encSecretStart, - nonce, - nonceStart, - nonceLen, - authData, - authDataStart, - authDataLen, - authTag, - authTagStart, - authTagLen); + key, + secret, + secretStart, + secretLen, + encSecret, + encSecretStart, + nonce, + nonceStart, + nonceLen, + authData, + authDataStart, + authDataLen, + authTag, + authTagStart, + authTagLen); } @Override @@ -698,7 +702,8 @@ public boolean aesGCMDecrypt(byte[] aesKey, short aesKeyStart, return verification; } - public HMACKey cmacKdf(KMPreSharedKey preSharedKey, byte[] label, short labelStart, short labelLen, + public HMACKey cmacKdf(KMPreSharedKey preSharedKey, byte[] label, short labelStart, + short labelLen, byte[] context, short contextStart, short contextLength) { try { // This is hardcoded to requirement - 32 byte output with two concatenated @@ -711,7 +716,7 @@ public HMACKey cmacKdf(KMPreSharedKey preSharedKey, byte[] label, short labelSta }; // byte final byte[] zero = { - 0 + 0 }; // [i] counter - 32 bits short iBufLen = 4; @@ -770,14 +775,14 @@ public short hmacSign(byte[] keyBuf, short keyStart, short keyLength, @Override public short hmacKDF(KMMasterKey masterkey, byte[] data, short dataStart, - short dataLength, byte[] signature, short signatureStart) { + short dataLength, byte[] signature, short signatureStart) { try { AESKey aesKey = ((KMAESKey) masterkey).getKey(); aesKey.getKey(tmpArray, (short) 0); HMACKey key = createHMACKey(tmpArray, (short) 0, - (short) (aesKey.getSize() / 8)); + (short) (aesKey.getSize() / 8)); return hmacSign(key, data, dataStart, dataLength, signature, - signatureStart); + signatureStart); } finally { clean(); } @@ -798,107 +803,111 @@ public short rsaDecipherOAEP256(byte[] secret, short secretStart, byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate(); - key.setExponent(secret, (short)secretStart, (short)secretLength); - key.setModulus(modBuffer, (short)modOff, (short)modLength); + key.setExponent(secret, (short) secretStart, (short) secretLength); + key.setModulus(modBuffer, (short) modOff, (short) modLength); rsaOaepDecipher.init(key, Cipher.MODE_DECRYPT); - return rsaOaepDecipher.doFinal(inputDataBuf, (short)inputDataStart, (short)inputDataLength, + return rsaOaepDecipher.doFinal(inputDataBuf, (short) inputDataStart, (short) inputDataLength, outputDataBuf, (short) outputDataStart); } public short ecSign256(KMAttestationKey attestationKey, - byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] outputDataBuf, short outputDataStart) { + byte[] inputDataBuf, short inputDataStart, short inputDataLength, + byte[] outputDataBuf, short outputDataStart) { Signature.OneShot signer = null; try { signer = Signature.OneShot.open(MessageDigest.ALG_SHA_256, Signature.SIG_CIPHER_ECDSA, Cipher.PAD_NULL); - signer.init(((KMECPrivateKey)attestationKey).getPrivateKey(), Signature.MODE_SIGN); + signer.init(((KMECPrivateKey) attestationKey).getPrivateKey(), Signature.MODE_SIGN); return signer.sign(inputDataBuf, inputDataStart, inputDataLength, outputDataBuf, outputDataStart); } finally { - if (signer != null) + if (signer != null) { signer.close(); + } } } private byte mapPurpose(short purpose) { switch (purpose) { - case KMType.ENCRYPT: - return Cipher.MODE_ENCRYPT; - case KMType.DECRYPT: - return Cipher.MODE_DECRYPT; - case KMType.SIGN: - return Signature.MODE_SIGN; - case KMType.VERIFY: - return Signature.MODE_VERIFY; + case KMType.ENCRYPT: + return Cipher.MODE_ENCRYPT; + case KMType.DECRYPT: + return Cipher.MODE_DECRYPT; + case KMType.SIGN: + return Signature.MODE_SIGN; + case KMType.VERIFY: + return Signature.MODE_VERIFY; } return -1; } private byte mapSignature256Alg(byte alg, byte padding, byte digest) { switch (alg) { - case KMType.RSA: - switch (padding) { - case KMType.RSA_PKCS1_1_5_SIGN: { - if (digest == KMType.DIGEST_NONE) - return KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST; - else - return Signature.ALG_RSA_SHA_256_PKCS1; - } - case KMType.RSA_PSS: - return Signature.ALG_RSA_SHA_256_PKCS1_PSS; - case KMType.PADDING_NONE: - return KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD; - } - break; - case KMType.EC: - if (digest == KMType.DIGEST_NONE) - return KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST; - else - return Signature.ALG_ECDSA_SHA_256; - case KMType.HMAC: - return Signature.ALG_HMAC_SHA_256; + case KMType.RSA: + switch (padding) { + case KMType.RSA_PKCS1_1_5_SIGN: { + if (digest == KMType.DIGEST_NONE) { + return KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST; + } else { + return Signature.ALG_RSA_SHA_256_PKCS1; + } + } + case KMType.RSA_PSS: + return Signature.ALG_RSA_SHA_256_PKCS1_PSS; + case KMType.PADDING_NONE: + return KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD; + } + break; + case KMType.EC: + if (digest == KMType.DIGEST_NONE) { + return KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST; + } else { + return Signature.ALG_ECDSA_SHA_256; + } + case KMType.HMAC: + return Signature.ALG_HMAC_SHA_256; } return -1; } private byte mapCipherAlg(byte alg, byte padding, byte blockmode, byte digest) { switch (alg) { - case KMType.AES: - switch (blockmode) { - case KMType.ECB: - return Cipher.ALG_AES_BLOCK_128_ECB_NOPAD; - case KMType.CBC: - return Cipher.ALG_AES_BLOCK_128_CBC_NOPAD; - case KMType.CTR: - return Cipher.ALG_AES_CTR; - case KMType.GCM: - return AEADCipher.ALG_AES_GCM; - } - break; - case KMType.DES: - switch (blockmode) { - case KMType.ECB: - return Cipher.ALG_DES_ECB_NOPAD; - case KMType.CBC: - return Cipher.ALG_DES_CBC_NOPAD; - } - break; - case KMType.RSA: - switch (padding) { - case KMType.PADDING_NONE: - return Cipher.ALG_RSA_NOPAD; - case KMType.RSA_PKCS1_1_5_ENCRYPT: - return Cipher.ALG_RSA_PKCS1; - case KMType.RSA_OAEP: { - if (digest == KMType.SHA2_256) - return KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1; - else - KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); - } - } - break; + case KMType.AES: + switch (blockmode) { + case KMType.ECB: + return Cipher.ALG_AES_BLOCK_128_ECB_NOPAD; + case KMType.CBC: + return Cipher.ALG_AES_BLOCK_128_CBC_NOPAD; + case KMType.CTR: + return Cipher.ALG_AES_CTR; + case KMType.GCM: + return AEADCipher.ALG_AES_GCM; + } + break; + case KMType.DES: + switch (blockmode) { + case KMType.ECB: + return Cipher.ALG_DES_ECB_NOPAD; + case KMType.CBC: + return Cipher.ALG_DES_CBC_NOPAD; + } + break; + case KMType.RSA: + switch (padding) { + case KMType.PADDING_NONE: + return Cipher.ALG_RSA_NOPAD; + case KMType.RSA_PKCS1_1_5_ENCRYPT: + return Cipher.ALG_RSA_PKCS1; + case KMType.RSA_OAEP: { + if (digest == KMType.SHA2_256) { + return KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1; + } else { + KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); + } + } + } + break; } return -1; } @@ -909,45 +918,45 @@ public Cipher createSymmetricCipher(short alg, short purpose, Key key = null; Cipher symmCipher = null; switch (secretLength) { - case 32: - key = aesKeys[KEYSIZE_256_OFFSET]; - ((AESKey) key).setKey(secret, secretStart); - break; - case 16: - key = aesKeys[KEYSIZE_128_OFFSET]; - ((AESKey) key).setKey(secret, secretStart); - break; - case 24: - key = triDesKey; - ((DESKey) key).setKey(secret, secretStart); - break; - default: - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - break; + case 32: + key = aesKeys[KEYSIZE_256_OFFSET]; + ((AESKey) key).setKey(secret, secretStart); + break; + case 16: + key = aesKeys[KEYSIZE_128_OFFSET]; + ((AESKey) key).setKey(secret, secretStart); + break; + case 24: + key = triDesKey; + ((DESKey) key).setKey(secret, secretStart); + break; + default: + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + break; } - short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte)0); + short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); symmCipher = getCipherInstanceFromPool((byte) cipherAlg); switch (cipherAlg) { - case Cipher.ALG_AES_BLOCK_128_CBC_NOPAD: - case Cipher.ALG_AES_CTR: - symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, ivLength); - break; - case Cipher.ALG_AES_BLOCK_128_ECB_NOPAD: - case Cipher.ALG_DES_ECB_NOPAD: - symmCipher.init(key, mapPurpose(purpose)); - break; - case Cipher.ALG_DES_CBC_NOPAD: - // Consume only 8 bytes of iv. the random number for iv is of 16 bytes. - // While sending back the iv, send only 8 bytes. - symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, (short) 8); - break; - case AEADCipher.ALG_AES_GCM: - ((AEADCipher) symmCipher).init(key, mapPurpose(purpose), ivBuffer, - ivStart, ivLength); - break; - default:// This should never happen - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case Cipher.ALG_AES_BLOCK_128_CBC_NOPAD: + case Cipher.ALG_AES_CTR: + symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, ivLength); + break; + case Cipher.ALG_AES_BLOCK_128_ECB_NOPAD: + case Cipher.ALG_DES_ECB_NOPAD: + symmCipher.init(key, mapPurpose(purpose)); + break; + case Cipher.ALG_DES_CBC_NOPAD: + // Consume only 8 bytes of iv. the random number for iv is of 16 bytes. + // While sending back the iv, send only 8 bytes. + symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, (short) 8); + break; + case AEADCipher.ALG_AES_GCM: + ((AEADCipher) symmCipher).init(key, mapPurpose(purpose), ivBuffer, + ivStart, ivLength); + break; + default:// This should never happen + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return symmCipher; } @@ -955,8 +964,9 @@ public Cipher createSymmetricCipher(short alg, short purpose, public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, short secretStart, short secretLength) { byte alg = Signature.ALG_HMAC_SHA_256; - if (digest != KMType.SHA2_256) + if (digest != KMType.SHA2_256) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } Signature hmacSignerVerifier = getSignatureInstanceFromPool(alg); HMACKey key = createHMACKey(secret, secretStart, secretLength); hmacSignerVerifier.init(key, (byte) mapPurpose(purpose)); @@ -970,33 +980,33 @@ public KMOperation initSymmetricOperation(byte purpose, byte alg, short macLength) { KMOperationImpl opr = null; switch (alg) { - case KMType.AES: - case KMType.DES: - Cipher cipher = createSymmetricCipher(alg, purpose, blockMode, padding, - keyBuf, keyStart, keyLength, ivBuf, ivStart, ivLength); - opr = getOperationInstanceFromPool(); - // Convert macLength to bytes - macLength = (short) (macLength / 8); - JCSystem.beginTransaction(); - opr.setCipher(cipher); - opr.setCipherAlgorithm(alg); - opr.setBlockMode(blockMode); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - opr.setMacLength(macLength); - JCSystem.commitTransaction(); - break; - case KMType.HMAC: - Signature signerVerifier = createHmacSignerVerifier(purpose, digest, - keyBuf, keyStart, keyLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(signerVerifier); - JCSystem.commitTransaction(); - break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + case KMType.AES: + case KMType.DES: + Cipher cipher = createSymmetricCipher(alg, purpose, blockMode, padding, + keyBuf, keyStart, keyLength, ivBuf, ivStart, ivLength); + opr = getOperationInstanceFromPool(); + // Convert macLength to bytes + macLength = (short) (macLength / 8); + JCSystem.beginTransaction(); + opr.setCipher(cipher); + opr.setCipherAlgorithm(alg); + opr.setBlockMode(blockMode); + opr.setPaddingAlgorithm(padding); + opr.setMode(purpose); + opr.setMacLength(macLength); + JCSystem.commitTransaction(); + break; + case KMType.HMAC: + Signature signerVerifier = createHmacSignerVerifier(purpose, digest, + keyBuf, keyStart, keyLength); + opr = getOperationInstanceFromPool(); + JCSystem.beginTransaction(); + opr.setSignature(signerVerifier); + JCSystem.commitTransaction(); + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return opr; } @@ -1023,7 +1033,7 @@ public Signature createRsaSigner(short digest, short padding, byte[] secret, public Cipher createRsaDecipher(short padding, short digest, byte[] secret, short secretStart, short secretLength, byte[] modBuffer, short modOff, short modLength) { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte)digest); + byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte) digest); Cipher rsaCipher = getCipherInstanceFromPool(cipherAlg); RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate(); key.setExponent(secret, secretStart, secretLength); @@ -1051,45 +1061,45 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, KMOperationImpl opr = null; if (alg == KMType.RSA) { switch (purpose) { - case KMType.SIGN: - Signature signer = createRsaSigner(digest, padding, privKeyBuf, - privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(signer); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; - case KMType.DECRYPT: - Cipher decipher = createRsaDecipher(padding, digest, privKeyBuf, - privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setCipher(decipher); - opr.setCipherAlgorithm(alg); - opr.setPaddingAlgorithm(padding); - opr.setMode(purpose); - JCSystem.commitTransaction(); - break; - default: - KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); - break; + case KMType.SIGN: + Signature signer = createRsaSigner(digest, padding, privKeyBuf, + privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); + opr = getOperationInstanceFromPool(); + JCSystem.beginTransaction(); + opr.setSignature(signer); + opr.setCipherAlgorithm(alg); + opr.setPaddingAlgorithm(padding); + opr.setMode(purpose); + JCSystem.commitTransaction(); + break; + case KMType.DECRYPT: + Cipher decipher = createRsaDecipher(padding, digest, privKeyBuf, + privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); + opr = getOperationInstanceFromPool(); + JCSystem.beginTransaction(); + opr.setCipher(decipher); + opr.setCipherAlgorithm(alg); + opr.setPaddingAlgorithm(padding); + opr.setMode(purpose); + JCSystem.commitTransaction(); + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + break; } } else if (alg == KMType.EC) { switch (purpose) { - case KMType.SIGN: - Signature signer = createEcSigner(digest, privKeyBuf, privKeyStart, - privKeyLength); - opr = getOperationInstanceFromPool(); - JCSystem.beginTransaction(); - opr.setSignature(signer); - JCSystem.commitTransaction(); - break; - default: - KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); - break; + case KMType.SIGN: + Signature signer = createEcSigner(digest, privKeyBuf, privKeyStart, + privKeyLength); + opr = getOperationInstanceFromPool(); + JCSystem.beginTransaction(); + opr.setSignature(signer); + JCSystem.commitTransaction(); + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + break; } } else { CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -1105,17 +1115,17 @@ public KMAttestationCert getAttestationCert(boolean rsaCert) { @Override public short cmacKDF(KMPreSharedKey pSharedKey, byte[] label, - short labelStart, short labelLen, byte[] context, short contextStart, - short contextLength, byte[] keyBuf, short keyStart) { + short labelStart, short labelLen, byte[] context, short contextStart, + short contextLength, byte[] keyBuf, short keyStart) { HMACKey key = cmacKdf(pSharedKey, label, labelStart, labelLen, context, - contextStart, contextLength); + contextStart, contextLength); return key.getKey(keyBuf, keyStart); } @Override public void clearCertificateChain() { JCSystem.beginTransaction(); - Util.arrayFillNonAtomic(certificateChain, (short)0, CERT_CHAIN_MAX_SIZE, (byte) 0); + Util.arrayFillNonAtomic(certificateChain, (short) 0, CERT_CHAIN_MAX_SIZE, (byte) 0); JCSystem.commitTransaction(); } @@ -1140,20 +1150,20 @@ public void persistPartialCertificateChain(byte[] buf, short offset, short len, JCSystem.beginTransaction(); Util.setShort(certificateChain, (short) 0, (short) (len + persistedLen)); Util.arrayCopyNonAtomic(buf, offset, certificateChain, - (short) (persistedLen+2), len); + (short) (persistedLen + 2), len); JCSystem.commitTransaction(); } @Override public short readCertificateChain(byte[] buf, short offset) { - short len = Util.getShort(certificateChain, (short)0); - Util.arrayCopyNonAtomic(certificateChain, (short)2, buf, offset, len); + short len = Util.getShort(certificateChain, (short) 0); + Util.arrayCopyNonAtomic(certificateChain, (short) 2, buf, offset, len); return len; } @Override public short getCertificateChainLength() { - return Util.getShort(certificateChain, (short)0); + return Util.getShort(certificateChain, (short) 0); } @Override @@ -1162,7 +1172,7 @@ public boolean isBootSignalEventSupported() { } @Override - public boolean isDeviceRebooted() { + public boolean isDeviceRebooted() { return false; } @@ -1190,7 +1200,7 @@ public void onRestore(Element element) { @Override public short getBackupPrimitiveByteCount() { short count = - (short) (KMAESKey.getBackupPrimitiveByteCount() + + (short) (KMAESKey.getBackupPrimitiveByteCount() + KMECPrivateKey.getBackupPrimitiveByteCount() + KMHmacKey.getBackupPrimitiveByteCount()); return count; @@ -1199,7 +1209,7 @@ public short getBackupPrimitiveByteCount() { @Override public short getBackupObjectCount() { short count = - (short) (1 /*Certificate chain */ + + (short) (1 /*Certificate chain */ + KMAESKey.getBackupObjectCount() + KMECPrivateKey.getBackupObjectCount() + KMHmacKey.getBackupObjectCount()); @@ -1207,7 +1217,7 @@ public short getBackupObjectCount() { } @Override - public boolean isUpgrading() { + public boolean isUpgrading() { return UpgradeManager.isUpgrading(); } @@ -1216,7 +1226,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { try { if (masterKey == null) { AESKey key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, - keySizeBits, false); + keySizeBits, false); masterKey = new KMAESKey(key); short keyLen = (short) (keySizeBits / 8); getTrueRandomNumber(tmpArray, (short) 0, keyLen); @@ -1230,7 +1240,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { @Override public KMAttestationKey createAttestationKey(byte[] keyData, short offset, - short length) { + short length) { if (attestationKey == null) { // Strongbox supports only P-256 curve for EC key. KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -1243,13 +1253,13 @@ public KMAttestationKey createAttestationKey(byte[] keyData, short offset, @Override public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short length) { - short lengthInBits = (short)(length * 8); + short lengthInBits = (short) (length * 8); if ((lengthInBits % 8 != 0) || !(lengthInBits >= 64 && lengthInBits <= 512)) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } if (preSharedKey == null) { HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, lengthInBits, - false); + false); preSharedKey = new KMHmacKey(key); } preSharedKey.setKey(keyData, offset, length); diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 637a2fba..1e3eae79 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -31,50 +31,53 @@ // The certificate is assembled with leafs first and then the sequences. public class KMAttestationCertImpl implements KMAttestationCert { + private static final byte MAX_PARAMS = 30; // DER encoded object identifiers required by the cert. // rsaEncryption - 1.2.840.113549.1.1.1 private static final byte[] rsaEncryption = { - 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01 + 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01 }; // ecPublicKey - 1.2.840.10045.2.1 private static final byte[] eccPubKey = { - 0x06, 0x07, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x02, 0x01 + 0x06, 0x07, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x02, 0x01 }; // prime256v1 curve - 1.2.840.10045.3.1.7 private static final byte[] prime256v1 = { - 0x06, 0x08, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x03, 0x01, 0x07 + 0x06, 0x08, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x03, 0x01, 0x07 }; // Key Usage Extn - 2.5.29.15 private static final byte[] keyUsageExtn = {0x06, 0x03, 0x55, 0x1D, 0x0F}; // Android Extn - 1.3.6.1.4.1.11129.2.1.17 private static final byte[] androidExtn = { - 0x06, 0x0A, 0X2B, 0X06, 0X01, 0X04, 0X01, (byte) 0XD6, 0X79, 0X02, 0X01, 0X11 + 0x06, 0x0A, 0X2B, 0X06, 0X01, 0X04, 0X01, (byte) 0XD6, 0X79, 0X02, 0X01, 0X11 }; private static final short ECDSA_MAX_SIG_LEN = 72; //Signature algorithm identifier - always ecdsaWithSha256 - 1.2.840.10045.4.3.2 //SEQUENCE of alg OBJ ID and parameters = NULL. private static final byte[] X509SignAlgIdentifier = { - 0x30, - 0x0A, - 0x06, - 0x08, - 0x2A, - (byte) 0x86, - 0x48, - (byte) 0xCE, - (byte) 0x3D, - 0x04, - 0x03, - 0x02 + 0x30, + 0x0A, + 0x06, + 0x08, + 0x2A, + (byte) 0x86, + 0x48, + (byte) 0xCE, + (byte) 0x3D, + 0x04, + 0x03, + 0x02 }; // Validity is not fixed field // Subject is a fixed field with only CN= Android Keystore Key - same for all the keys private static final byte[] X509Subject = { - 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x41, 0x6e, 0x64, - 0x72, 0x6f, 0x69, 0x64, 0x20, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x4B, 0x65, - 0x79 + 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x41, 0x6e, + 0x64, + 0x72, 0x6f, 0x69, 0x64, 0x20, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x4B, + 0x65, + 0x79 }; private static final byte keyUsageSign = (byte) 0x80; // 0 bit @@ -117,10 +120,13 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static short issuer; private static short signPriv; - private KMAttestationCertImpl() {} + private KMAttestationCertImpl() { + } public static KMAttestationCert instance(boolean rsaCert) { - if (inst == null) inst = new KMAttestationCertImpl(); + if (inst == null) { + inst = new KMAttestationCertImpl(); + } init(); KMAttestationCertImpl.rsaCert = rsaCert; return inst; @@ -190,18 +196,19 @@ public KMAttestationCert notBefore(short obj, byte[] scratchpad) { @Override public KMAttestationCert notAfter(short usageExpiryTimeObj, - short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { + short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { if (usageExpiryTimeObj != KMType.INVALID_VALUE) { // compare if the expiry time is greater then 2051 then use generalized // time format else use utc time format. usageExpiryTimeObj = KMIntegerTag.cast(usageExpiryTimeObj).getValue(); tmpVar = KMInteger.uint_64(KMUtils.firstJan2051, (short) 0); - if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) + if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) { usageExpiryTimeObj = KMUtils.convertToDate(usageExpiryTimeObj, scratchPad, - false); - else + false); + } else { usageExpiryTimeObj = KMUtils - .convertToDate(usageExpiryTimeObj, scratchPad, true); + .convertToDate(usageExpiryTimeObj, scratchPad, true); + } notAfter = usageExpiryTimeObj; } else { notAfter = certExpirtyTimeObj; @@ -211,8 +218,11 @@ public KMAttestationCert notAfter(short usageExpiryTimeObj, @Override public KMAttestationCert deviceLocked(boolean val) { - if (val) deviceLocked = (byte) 0xFF; - else deviceLocked = 0; + if (val) { + deviceLocked = (byte) 0xFF; + } else { + deviceLocked = 0; + } return this; } @@ -302,7 +312,9 @@ private static void pushTbsCert(boolean rsaCert) { private static void pushExtensions() { short last = stackPtr; - if (keyUsage != 0) pushKeyUsage(keyUsage, unusedBits); + if (keyUsage != 0) { + pushKeyUsage(keyUsage, unusedBits); + } pushKeyDescription(); pushSequenceHeader((short) (last - stackPtr)); // Extensions have explicit tag of [3] @@ -366,6 +378,7 @@ private static void pushRsaSubjectKeyInfo() { pushRsaEncryption(); pushSequenceHeader((short) (last - stackPtr)); } + // SEQUENCE{SEQUENCE{ecPubKey, prime256v1}, bitString{pubKey}} private static void pushEccSubjectKeyInfo() { short last = stackPtr; @@ -391,6 +404,7 @@ private static void pushRsaEncryption() { pushBytes(rsaEncryption, (short) 0, (short) rsaEncryption.length); pushSequenceHeader((short) (last - stackPtr)); } + // KeyDescription ::= SEQUENCE { // attestationVersion INTEGER, # Value 3 // attestationSecurityLevel SecurityLevel, # See below @@ -433,9 +447,9 @@ private static void pushSWParams() { short last = stackPtr; // Below are the allowed softwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { - KMType.ATTESTATION_APPLICATION_ID, KMType.CREATION_DATETIME, - KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, - KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED }; + KMType.ATTESTATION_APPLICATION_ID, KMType.CREATION_DATETIME, + KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, + KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED}; byte index = 0; do { pushParams(swParams, swParamsIndex, tagIds[index]); @@ -447,15 +461,15 @@ private static void pushHWParams() { short last = stackPtr; // Below are the allowed hardwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { - KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, - KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.APPLICATION_ID, - KMType.TRUSTED_CONFIRMATION_REQUIRED, - KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, - KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, - KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, - KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, - KMType.ALGORITHM, KMType.PURPOSE }; + KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, + KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, + KMType.ORIGIN, KMType.APPLICATION_ID, + KMType.TRUSTED_CONFIRMATION_REQUIRED, + KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, + KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, + KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, + KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, + KMType.ALGORITHM, KMType.PURPOSE}; byte index = 0; do { @@ -463,7 +477,9 @@ private static void pushHWParams() { pushRoT(); continue; } - if (pushParams(hwParams, hwParamsIndex, tagIds[index])) continue; + if (pushParams(hwParams, hwParamsIndex, tagIds[index])) { + continue; + } } while (++index < tagIds.length); pushSequenceHeader((short) (last - stackPtr)); } @@ -531,6 +547,7 @@ private static void pushTag(short tag) { break; } } + // RootOfTrust ::= SEQUENCE { // verifiedBootKey OCTET_STRING, // deviceLocked BOOLEAN, @@ -594,6 +611,7 @@ private static void pushEnumArrayTag(short tagId, byte[] buf, short start, short pushSetHeader((short) (last - stackPtr)); pushTagIdHeader(tagId, (short) (last - stackPtr)); } + // Only SET of INTEGERS supported are padding, digest, purpose and blockmode // All of these are enum array tags i.e. byte long values private static void pushIntegerArrayTag(short tagId, short arr) { @@ -652,13 +670,16 @@ private static void pushIntegerTag(short tagId, byte[] buf, short start, short l pushInteger(buf, start, len); pushTagIdHeader(tagId, (short) (last - stackPtr)); } + // Ignore leading zeros. Only Unsigned Integers are required hence if MSB is set then add 0x00 // as most significant byte. private static void pushInteger(byte[] buf, short start, short len) { short last = stackPtr; byte index = 0; while (index < (byte) len) { - if (buf[(short) (start + index)] != 0) break; + if (buf[(short) (start + index)] != 0) { + break; + } index++; } if (index == (byte) len) { @@ -671,6 +692,7 @@ private static void pushInteger(byte[] buf, short start, short len) { } pushIntegerHeader((short) (last - stackPtr)); } + // Bytes Tag is a octet string and tag id is added explicitly private static void pushBytesTag(short tagId, byte[] buf, short start, short len) { short last = stackPtr; @@ -696,6 +718,7 @@ private static void pushTagIdHeader(short tagId, short len) { pushByte((byte) (0xA0 | (byte) tagId)); } } + // SEQUENCE {ObjId, OCTET STRING{BIT STRING{keyUsage}}} private static void pushKeyUsage(byte keyUsage, byte unusedBits) { short last = stackPtr; @@ -762,7 +785,9 @@ private static void pushBytes(byte[] buf, short start, short len) { private static void decrementStackPtr(short cnt) { stackPtr = (short) (stackPtr - cnt); - if (start > stackPtr) KMException.throwIt(KMError.UNKNOWN_ERROR); + if (start > stackPtr) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } } @Override @@ -805,39 +830,39 @@ public void build() { KMAndroidSEProvider androidSeProvider = KMAndroidSEProvider.getInstance(); short sigLen = androidSeProvider .ecSign256( - androidSeProvider.getAttestationKey(), - stack, - tbsOffset, - tbsLength, - stack, - signatureOffset); - if(sigLen != ECDSA_MAX_SIG_LEN) { + androidSeProvider.getAttestationKey(), + stack, + tbsOffset, + tbsLength, + stack, + signatureOffset); + if (sigLen != ECDSA_MAX_SIG_LEN) { // Update the lengths appropriately. - stackPtr = (short)(signatureOffset - 1); - pushLength((short)(sigLen + 1)); + stackPtr = (short) (signatureOffset - 1); + pushLength((short) (sigLen + 1)); stackPtr = tbsOffset; - last -= (short)(ECDSA_MAX_SIG_LEN - sigLen); - pushLength((short)(last - stackPtr)); - length -= (short)(ECDSA_MAX_SIG_LEN - sigLen); + last -= (short) (ECDSA_MAX_SIG_LEN - sigLen); + pushLength((short) (last - stackPtr)); + length -= (short) (ECDSA_MAX_SIG_LEN - sigLen); } } @Override public KMAttestationCert makeUniqueId(byte[] scratchPad, short scratchPadOff, - byte[] creationTime, short timeOffset, short creationTimeLen, - byte[] attestAppId, short appIdOff, short attestAppIdLen, - byte resetSinceIdRotation, KMMasterKey masterKey) { + byte[] creationTime, short timeOffset, short creationTimeLen, + byte[] attestAppId, short appIdOff, short attestAppIdLen, + byte resetSinceIdRotation, KMMasterKey masterKey) { // Concatenate T||C||R // temporal count T short temp = KMUtils.countTemporalCount(creationTime, timeOffset, - creationTimeLen, scratchPad, scratchPadOff); + creationTimeLen, scratchPad, scratchPadOff); Util.setShort(scratchPad, (short) scratchPadOff, temp); temp = scratchPadOff; scratchPadOff += 2; // Application Id C Util.arrayCopyNonAtomic(attestAppId, appIdOff, scratchPad, scratchPadOff, - attestAppIdLen); + attestAppIdLen); scratchPadOff += attestAppIdLen; // Reset After Rotation R @@ -847,19 +872,19 @@ public KMAttestationCert makeUniqueId(byte[] scratchPad, short scratchPadOff, timeOffset = KMByteBlob.instance((short) 32); //Get the key data from the master key and use it for HMAC Sign. AESKey aesKey = ((KMAESKey) masterKey).getKey(); - short mKeyData = KMByteBlob.instance((short) (aesKey.getSize() / 8)); + short mKeyData = KMByteBlob.instance((short) (aesKey.getSize() / 8)); aesKey.getKey( - KMByteBlob.cast(mKeyData).getBuffer(), - KMByteBlob.cast(mKeyData).getStartOff()); + KMByteBlob.cast(mKeyData).getBuffer(), + KMByteBlob.cast(mKeyData).getStartOff()); appIdOff = KMAndroidSEProvider.getInstance().hmacSign( - KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ - KMByteBlob.cast(mKeyData).getStartOff(), /* Key start*/ - KMByteBlob.cast(mKeyData).length(), /* Key length*/ - scratchPad, /* data */ - temp, /* data start */ - scratchPadOff, /* data length */ - KMByteBlob.cast(timeOffset).getBuffer(), /* signature buffer */ - KMByteBlob.cast(timeOffset).getStartOff()); /* signature start */ + KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ + KMByteBlob.cast(mKeyData).getStartOff(), /* Key start*/ + KMByteBlob.cast(mKeyData).length(), /* Key length*/ + scratchPad, /* data */ + temp, /* data start */ + scratchPadOff, /* data length */ + KMByteBlob.cast(timeOffset).getBuffer(), /* signature buffer */ + KMByteBlob.cast(timeOffset).getStartOff()); /* signature start */ if (appIdOff != 32) { KMException.throwIt(KMError.UNKNOWN_ERROR); } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java index fe6a636f..3188ad19 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java @@ -42,7 +42,7 @@ public short getS(byte[] buffer, short offset) { ECPrivateKey ecPriv = (ECPrivateKey) ecKeyPair.getPrivate(); return ecPriv.getS(buffer, offset); } - + public ECPrivateKey getPrivateKey() { return (ECPrivateKey) ecKeyPair.getPrivate(); } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 51ac435b..f90b834f 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -41,13 +41,13 @@ public void init(Key key, byte b) throws CryptoException { @Override public void init(Key key, byte b, byte[] bytes, short i, short i1) - throws CryptoException { + throws CryptoException { inst.init(key, b, bytes, i, i1); } @Override public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, - short i2, short i3) throws CryptoException { + short i2, short i3) throws CryptoException { } @@ -78,7 +78,7 @@ public short getLength() throws CryptoException { @Override public void update(byte[] message, short msgStart, short messageLength) - throws CryptoException { + throws CryptoException { // HAL accumulates the data and send it at finish operation. } @@ -86,8 +86,9 @@ public void update(byte[] message, short msgStart, short messageLength) public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException { try { - if (i1 > MAX_NO_DIGEST_MSG_LEN) + if (i1 > MAX_NO_DIGEST_MSG_LEN) { CryptoException.throwIt(CryptoException.ILLEGAL_USE); + } // add zeros to the left if (i1 < MAX_NO_DIGEST_MSG_LEN) { Util.arrayFillNonAtomic(KMAndroidSEProvider.getInstance().tmpArray, @@ -105,7 +106,7 @@ public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) @Override public short signPreComputedHash(byte[] bytes, short i, short i1, - byte[] bytes1, short i2) throws CryptoException { + byte[] bytes1, short i2) throws CryptoException { return inst.sign(bytes, i, i1, bytes1, i2); } @@ -118,7 +119,7 @@ public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, @Override public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, - byte[] bytes1, short i2, short i3) throws CryptoException { + byte[] bytes1, short i2, short i3) throws CryptoException { //Verification is handled inside HAL return false; } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMHmacKey.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMHmacKey.java index b4ca3af4..b2a38b24 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMHmacKey.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMHmacKey.java @@ -22,6 +22,7 @@ import javacard.security.HMACKey; public class KMHmacKey implements KMPreSharedKey { + private HMACKey hmacKey; public KMHmacKey(HMACKey key) { @@ -39,6 +40,7 @@ public byte getKey(byte[] keyData, short kOff) { public short getKeySizeBits() { return hmacKey.getSize(); } + public static void onSave(Element element, KMHmacKey kmKey) { element.write(kmKey.hmacKey); } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMInstance.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMInstance.java index 12655bc4..5178d4e2 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMInstance.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMInstance.java @@ -16,6 +16,7 @@ package com.android.javacard.keymaster; public class KMInstance { + public byte reserved; public Object object; public byte instanceCount; diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java index 0eb7c4e7..502f3fb5 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMOperationImpl.java @@ -130,8 +130,9 @@ public short finish(byte[] inputDataBuf, short inputDataStart, byte blkSize = 16; byte paddingBytes; short inputlen = inputDataLen; - if (cipherAlg == KMType.DES) + if (cipherAlg == KMType.DES) { blkSize = 8; + } // padding bytes if (inputlen % blkSize == 0) { paddingBytes = blkSize; @@ -155,20 +156,22 @@ public short finish(byte[] inputDataBuf, short inputDataStart, if ((cipherAlg == KMType.AES || cipherAlg == KMType.DES) && padding == KMType.PKCS7 && mode == KMType.DECRYPT) { byte blkSize = 16; - if (cipherAlg == KMType.DES) + if (cipherAlg == KMType.DES) { blkSize = 8; + } if (len > 0) { // verify if padding is corrupted. byte paddingByte = outputDataBuf[(short) (outputDataStart + len - 1)]; // padding byte always should be <= block size - if ((short) paddingByte > blkSize || (short) paddingByte <= 0) + if ((short) paddingByte > blkSize || (short) paddingByte <= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); + } - for(short j = 1; j <= paddingByte; ++j) { + for (short j = 1; j <= paddingByte; ++j) { if (outputDataBuf[(short) (outputDataStart + len - j)] != paddingByte) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - } + } len = (short) (len - (short) paddingByte);// remove the padding bytes } } else if (cipherAlg == KMType.AES && blockMode == KMType.GCM) { @@ -178,8 +181,9 @@ public short finish(byte[] inputDataBuf, short inputDataStart, } else { boolean verified = ((AEADCipher) cipher).verifyTag(inputDataBuf, (short) (inputDataStart + inputDataLen), macLength, macLength); - if (!verified) + if (!verified) { KMException.throwIt(KMError.VERIFICATION_FAILED); + } } } } finally { diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index 991072e2..08e11436 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -130,11 +130,13 @@ private void padData(byte[] buf, short start, short len, byte[] outBuf, private boolean isValidData(byte[] buf, short start, short len) { if (algorithm == ALG_RSA_SIGN_NOPAD) { - if (len > 256) + if (len > 256) { return false; + } } else { // ALG_RSA_PKCS1_NODIGEST - if (len > 245) + if (len > 245) { return false; + } } return true; } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java index 066d828f..ac099bc5 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java @@ -38,40 +38,41 @@ public KMRsaOAEPEncoding(byte alg) { setDigests(alg); cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); algorithm = alg; - if (null == mgf1Buf) + if (null == mgf1Buf) { mgf1Buf = JCSystem.makeTransientByteArray(MGF1_BUF_SIZE, - JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT); + JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT); + } } private void setDigests(byte alg) { switch (alg) { - case ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1: - hash = MessageDigest.ALG_SHA_256; - mgf1Hash = MessageDigest.ALG_SHA; - break; - case ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA256: - hash = MessageDigest.ALG_SHA_256; - mgf1Hash = MessageDigest.ALG_SHA_256; - break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + case ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1: + hash = MessageDigest.ALG_SHA_256; + mgf1Hash = MessageDigest.ALG_SHA; + break; + case ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA256: + hash = MessageDigest.ALG_SHA_256; + mgf1Hash = MessageDigest.ALG_SHA_256; + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); } } - + private short getDigestLength() { - switch(hash) { - case MessageDigest.ALG_SHA: - return MessageDigest.LENGTH_SHA; - case MessageDigest.ALG_SHA_224: - return MessageDigest.LENGTH_SHA_224; - case MessageDigest.ALG_SHA_256: - return MessageDigest.LENGTH_SHA_256; - case MessageDigest.ALG_SHA_384: - return MessageDigest.LENGTH_SHA_384; - case MessageDigest.ALG_SHA3_512: - return MessageDigest.LENGTH_SHA_512; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + switch (hash) { + case MessageDigest.ALG_SHA: + return MessageDigest.LENGTH_SHA; + case MessageDigest.ALG_SHA_224: + return MessageDigest.LENGTH_SHA_224; + case MessageDigest.ALG_SHA_256: + return MessageDigest.LENGTH_SHA_256; + case MessageDigest.ALG_SHA_384: + return MessageDigest.LENGTH_SHA_384; + case MessageDigest.ALG_SHA3_512: + return MessageDigest.LENGTH_SHA_512; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); } return 0; } @@ -84,7 +85,7 @@ public void init(Key theKey, byte theMode) throws CryptoException { @Override public void init(Key theKey, byte theMode, byte[] bArray, short bOff, - short bLen) throws CryptoException { + short bLen) throws CryptoException { cipher.init(theKey, theMode, bArray, bOff, bLen); } @@ -105,7 +106,7 @@ public byte getPaddingAlgorithm() { @Override public short doFinal(byte[] inBuff, short inOffset, short inLength, - byte[] outBuff, short outOffset) throws CryptoException { + byte[] outBuff, short outOffset) throws CryptoException { short len = cipher.doFinal(inBuff, inOffset, inLength, outBuff, outOffset); // https://tools.ietf.org/html/rfc8017#section-7.1 @@ -127,18 +128,18 @@ public short doFinal(byte[] inBuff, short inOffset, short inLength, inBuff = outBuff; inOffset = (short) (outOffset + 1); return rsaOAEPDecode(inBuff, inOffset, (short) (len - 1), outBuff, - outOffset); + outOffset); } @Override public short update(byte[] inBuff, short inOffset, short inLength, - byte[] outBuff, short outOffset) throws CryptoException { + byte[] outBuff, short outOffset) throws CryptoException { return cipher.update(inBuff, inOffset, inLength, outBuff, outOffset); } private void maskGenerationFunction1(byte[] input, short inputOffset, - short inputLen, short expectedOutLen, byte[] outBuf, short outOffset) { + short inputLen, short expectedOutLen, byte[] outBuf, short outOffset) { short counter = 0; MessageDigest.OneShot md = null; try { @@ -149,21 +150,22 @@ private void maskGenerationFunction1(byte[] input, short inputOffset, while (counter < (short) (expectedOutLen / digestLen)) { I2OS(counter, mgf1Buf, (short) inputLen); md.doFinal(mgf1Buf, (short) 0, (short) (4 + inputLen), outBuf, - (short) (outOffset + (counter * digestLen))); + (short) (outOffset + (counter * digestLen))); counter++; } if ((short) (counter * digestLen) < expectedOutLen) { I2OS(counter, mgf1Buf, (short) inputLen); md.doFinal(mgf1Buf, (short) 0, (short) (4 + inputLen), outBuf, - (short) (outOffset + (counter * digestLen))); + (short) (outOffset + (counter * digestLen))); } } finally { - if (md != null) + if (md != null) { md.close(); + } Util.arrayFillNonAtomic(mgf1Buf, (short) 0, (short) MGF1_BUF_SIZE, - (byte) 0); + (byte) 0); } } @@ -175,14 +177,14 @@ private void I2OS(short i, byte[] out, short offset) { } private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, - short encodedMsgLen, byte[] msg, short offset) { + short encodedMsgLen, byte[] msg, short offset) { MessageDigest.OneShot md = null; byte[] tmpArray = KMAndroidSEProvider.getInstance().tmpArray; try { short hLen = getDigestLength(); - if (encodedMsgLen < (short)(2 * hLen + 1)) { + if (encodedMsgLen < (short) (2 * hLen + 1)) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } // encodedMsg will be in the format of maskedSeed||maskedDB. @@ -191,7 +193,7 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, // of the seedMask is hLen. // seedMask = MGF(maskedDB, hLen) maskGenerationFunction1(encodedMsg, (short) (encodedMsgOff + hLen), - (short) (encodedMsgLen - hLen), hLen, tmpArray, (short) 0); + (short) (encodedMsgLen - hLen), hLen, tmpArray, (short) 0); // Get the seed by doing XOR of (maskedSeed ^ seedMask). // seed = (maskedSeed ^ seedMask) @@ -203,7 +205,7 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, // Now get the dbMask by calling MGF(seed , (emLen-hLen)). // dbMask = MGF(seed , (emLen-hLen)). maskGenerationFunction1(encodedMsg, (short) encodedMsgOff, hLen, - (short) (encodedMsgLen - hLen), tmpArray, (short) 0); + (short) (encodedMsgLen - hLen), tmpArray, (short) 0); // Get the DB value. DB = (maskedDB ^ dbMask) // DB = Hash(P)||00||01||Msg, where P is encoding parameters. (P = NULL) @@ -217,7 +219,7 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, Util.arrayFillNonAtomic(tmpArray, (short) 0, (short) 256, (byte) 0); md.doFinal(tmpArray, (short) 0, (short) 0, tmpArray, (short) 0); if (0 != Util.arrayCompare(encodedMsg, (short) (encodedMsgOff + hLen), - tmpArray, (short) 0, hLen)) { + tmpArray, (short) 0, hLen)) { // Verification failed. CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } @@ -231,7 +233,8 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, // starting of the block and a variable length of 0's are // appended to the end of the hash till the 0x01 byte. short start = 0; - for (short i = (short) (encodedMsgOff + 2 * hLen); i < (short) (encodedMsgOff + encodedMsgLen); i++) { + for (short i = (short) (encodedMsgOff + 2 * hLen); + i < (short) (encodedMsgOff + encodedMsgLen); i++) { if (i == (short) ((encodedMsgOff + encodedMsgLen) - 1)) { // Bad Padding. CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -243,14 +246,15 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, } // Copy the message Util.arrayCopyNonAtomic(encodedMsg, (short) (start + 1), msg, offset, - (short) (encodedMsgLen - ((start - encodedMsgOff) + 1))); + (short) (encodedMsgLen - ((start - encodedMsgOff) + 1))); return (short) (encodedMsgLen - ((start - encodedMsgOff) + 1)); } finally { - if (md != null) + if (md != null) { md.close(); + } Util.arrayFillNonAtomic(tmpArray, (short) 0, - KMAndroidSEProvider.TMP_ARRAY_SIZE, (byte) 0); + KMAndroidSEProvider.TMP_ARRAY_SIZE, (byte) 0); } } } \ No newline at end of file diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index 2e72ae6d..c2b5c7f3 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -18,43 +18,44 @@ import javacard.framework.Util; public class KMUtils { + // 64 bit unsigned calculations for time public static final byte[] oneSecMsec = { - 0, 0, 0, 0, 0, 0, 0x03, (byte) 0xE8 }; // 1000 msec + 0, 0, 0, 0, 0, 0, 0x03, (byte) 0xE8}; // 1000 msec public static final byte[] oneMinMsec = { - 0, 0, 0, 0, 0, 0, (byte) 0xEA, 0x60 }; // 60000 msec + 0, 0, 0, 0, 0, 0, (byte) 0xEA, 0x60}; // 60000 msec public static final byte[] oneHourMsec = { - 0, 0, 0, 0, 0, 0x36, (byte) 0xEE, (byte) 0x80 }; // 3600000 msec + 0, 0, 0, 0, 0, 0x36, (byte) 0xEE, (byte) 0x80}; // 3600000 msec public static final byte[] oneDayMsec = { - 0, 0, 0, 0, 0x05, 0x26, 0x5C, 0x00 }; // 86400000 msec + 0, 0, 0, 0, 0x05, 0x26, 0x5C, 0x00}; // 86400000 msec public static final byte[] oneMonthMsec = { - 0, 0, 0, 0, (byte) 0x9C,(byte) 0xBE, (byte) 0xBD, 0x50}; // 2629746000 msec - public static final byte[] leapYearMsec = { - 0, 0, 0, 0x07, (byte) 0x5C, (byte) 0xD7, (byte) 0x88, 0x00}; //31622400000; + 0, 0, 0, 0, (byte) 0x9C, (byte) 0xBE, (byte) 0xBD, 0x50}; // 2629746000 msec + public static final byte[] leapYearMsec = { + 0, 0, 0, 0x07, (byte) 0x5C, (byte) 0xD7, (byte) 0x88, 0x00}; //31622400000; public static final byte[] yearMsec = { - 0, 0, 0, 0x07, 0x57, (byte) 0xB1, 0x2C, 0x00}; //31536000000 + 0, 0, 0, 0x07, 0x57, (byte) 0xB1, 0x2C, 0x00}; //31536000000 //Leap year(366) + 3 * 365 public static final byte[] fourYrsMsec = { - 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 + 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 public static final byte[] firstJan2020 = { - 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte)0xE8, 0x00 }; // 1577836800000 msec + 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte) 0xE8, 0x00}; // 1577836800000 msec public static final byte[] firstJan2051 = { - 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00 }; // 2556144000000 - // msec + 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00}; // 2556144000000 + // msec public static final byte[] febMonthLeapMSec = { - 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00 }; //2505600000 + 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00}; //2505600000 public static final byte[] febMonthMsec = { - 0, 0, 0, 0, (byte) 0x90, 0x32, 0x10, 0x00 }; //2419200000 + 0, 0, 0, 0, (byte) 0x90, 0x32, 0x10, 0x00}; //2419200000 public static final byte[] ThirtyOneDaysMonthMsec = { - 0, 0, 0, 0, (byte) 0x9F, (byte) 0xA5, 0x24, 0x00 };//2678400000 + 0, 0, 0, 0, (byte) 0x9F, (byte) 0xA5, 0x24, 0x00};//2678400000 public static final byte[] ThirtDaysMonthMsec = { - 0, 0, 0, 0, (byte) 0x9A, 0x7E, (byte) 0xC8, 0x00 };//2592000000 + 0, 0, 0, 0, (byte) 0x9A, 0x7E, (byte) 0xC8, 0x00};//2592000000 public static final short year2051 = 2051; public static final short year2020 = 2020; // -------------------------------------- public static short convertToDate(short time, byte[] scratchPad, - boolean utcFlag) { + boolean utcFlag) { short yrsCount = 0; short monthCount = 1; @@ -66,48 +67,48 @@ public static short convertToDate(short time, byte[] scratchPad, boolean from2020 = true; Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); Util.arrayCopyNonAtomic(KMInteger.cast(time).getBuffer(), - KMInteger.cast(time).getStartOff(), scratchPad, - (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) - .length()); + KMInteger.cast(time).getStartOff(), scratchPad, + (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) + .length()); // If the time is less then 1 Jan 2020 then it is an error if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, - (short) 8) < 0) { + (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, - (short) 0, (short) 8) >= 0) { + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, - (short) 8) < 0) { + (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } else { from2020 = false; Util.arrayCopyNonAtomic(firstJan2051, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with four yrs msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); yrsCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); // quotient - // is - // multiple - // of 4 + // is + // multiple + // of 4 yrsCount = (short) (yrsCount * 4); // number of yrs. // copy reminder as new dividend Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } //Get the leap year index starting from the (base Year + yrsCount) Year. @@ -116,29 +117,33 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || - ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger + .unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) + >= 0)) || + ((leapYrIdx != 0) && + (KMInteger + .unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) + >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { Util.arrayCopyNonAtomic(leapYearMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } else { Util.arrayCopyNonAtomic(yearMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); } subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); if (((short) (i + 1) == leapYrIdx)) { if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, - (short) 0, (short) 8) < 0) { + (short) 0, (short) 8) < 0) { break; } } else { if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, - (short) 0, (short) 8) < 0) { + (short) 0, (short) 8) < 0) { break; } } @@ -146,40 +151,41 @@ public static short convertToDate(short time, byte[] scratchPad, } // total yrs from 1970 - if (from2020) + if (from2020) { yrsCount = (short) (year2020 + yrsCount); - else + } else { yrsCount = (short) (year2051 + yrsCount); + } // divide the given time with one month msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { // Feb month if (isLeapYear(yrsCount)) { // Leap year 29 days Util.arrayCopyNonAtomic(febMonthLeapMSec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } else { // 28 days Util.arrayCopyNonAtomic(febMonthMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } } else if (((i <= 6) && ((i % 2 == 0))) || ((i > 6) && ((i % 2 == 1)))) { Util.arrayCopyNonAtomic(ThirtyOneDaysMonthMsec, (short) 0, - scratchPad, (short) 8, (short) 8); + scratchPad, (short) 8, (short) 8); } else { // 30 Days Util.arrayCopyNonAtomic(ThirtDaysMonthMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, - (short) 8) >= 0) { + (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } else { break; } @@ -189,43 +195,43 @@ public static short convertToDate(short time, byte[] scratchPad, // divide the given time with one day msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); dayCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); dayCount++; Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one hour msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); hhCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one minute msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); mmCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one second msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); ssCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // Now convert to ascii string YYMMDDhhmmssZ or YYYYMMDDhhmmssZ @@ -238,19 +244,21 @@ public static short convertToDate(short time, byte[] scratchPad, len += numberToString(ssCount, scratchPad, len); scratchPad[len] = Z; len++; - if (utcFlag) + if (utcFlag) { return KMByteBlob.instance(scratchPad, (short) 2, (short) (len - 2)); // YY - else + } else { return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY + } } public static short numberToString(short number, byte[] scratchPad, - short offset) { + short offset) { byte zero = 0x30; byte len = 2; byte digit; - if (number > 999) + if (number > 999) { len = 4; + } byte index = len; while (index > 0) { digit = (byte) (number % 10); @@ -265,7 +273,7 @@ public static short numberToString(short number, byte[] scratchPad, // i.e. dividend - quotient*divisor = remainder where remainder < divisor. // so this is division by subtraction until remainder remains. public static short divide(byte[] buf, short dividend, short divisor, - short remainder) { + short remainder) { short expCnt = 1; short q = 0; // first increase divisor so that it becomes greater then dividend. @@ -303,10 +311,11 @@ public static void shiftLeft(byte[] buf, short start) { tmp = buf[(short) (start + index)]; buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] << 1); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] + carry); - if (tmp < 0) + if (tmp < 0) { carry = 1; - else + } else { carry = 0; + } index--; } } @@ -320,10 +329,11 @@ public static void shiftRight(byte[] buf, short start) { buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] >> 1); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] & 0x7F); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] | carry); - if (tmp == 1) + if (tmp == 1) { carry = (byte) 0x80; - else + } else { carry = 0; + } index++; } } @@ -335,8 +345,9 @@ public static void add(byte[] buf, short op1, short op2, short result) { while (index >= 0) { tmp = (short) (buf[(short) (op1 + index)] + buf[(short) (op2 + index)] + carry); carry = 0; - if (tmp > 255) + if (tmp > 255) { carry = 1; // max unsigned byte value is 255 + } buf[(short) (result + index)] = (byte) (tmp & (byte) 0xFF); index--; } @@ -362,25 +373,25 @@ public static void subtract(byte[] buf, short op1, short op2, short result) { index--; } } - + public static short countTemporalCount(byte[] bufTime, short timeOff, - short timeLen, byte[] scratchPad, short offset) { + short timeLen, byte[] scratchPad, short offset) { Util.arrayFillNonAtomic(scratchPad, (short) offset, (short) 24, (byte) 0); Util.arrayCopyNonAtomic( - bufTime, - timeOff, - scratchPad, - (short) (offset + 8 - timeLen), - timeLen); + bufTime, + timeOff, + scratchPad, + (short) (offset + 8 - timeLen), + timeLen); Util.arrayCopyNonAtomic(oneMonthMsec, (short) 0, scratchPad, (short) (offset + 8), - (short) 8); + (short) 8); return divide(scratchPad, (short) 0, (short) 8, (short) 16); } public static boolean isLeapYear(short year) { - if ((short)(year%4) == (short) 0) { - if (((short)(year % 100) == (short) 0) && - ((short) (year % 400)) != (short) 0) { + if ((short) (year % 4) == (short) 0) { + if (((short) (year % 100) == (short) 0) && + ((short) (year % 400)) != (short) 0) { return false; } return true; @@ -390,8 +401,8 @@ public static boolean isLeapYear(short year) { public static short getLeapYrIndex(boolean from2020, short yrsCount) { short newBaseYr = (short) (from2020 ? (year2020 + yrsCount) : (year2051 + yrsCount)); - for(short i = 0; i < 4; i++) { - if(isLeapYear((short)(newBaseYr + i))) { + for (short i = 0; i < 4; i++) { + if (isLeapYear((short) (newBaseYr + i))) { return i; } } diff --git a/Applet/JCardSimProvider/build.xml b/Applet/JCardSimProvider/build.xml index 58343402..3d06a8fd 100644 --- a/Applet/JCardSimProvider/build.xml +++ b/Applet/JCardSimProvider/build.xml @@ -1,21 +1,23 @@ - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -23,9 +25,10 @@ - + - + @@ -34,7 +37,8 @@ - + @@ -52,5 +56,5 @@ - + \ No newline at end of file diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAESKey.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAESKey.java index 489d4f77..258dc461 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAESKey.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAESKey.java @@ -18,6 +18,7 @@ import javacard.security.AESKey; public class KMAESKey implements KMMasterKey { + private AESKey aesKey; public KMAESKey(AESKey key) { @@ -31,7 +32,7 @@ public void setKey(byte[] keyData, short kOff) { public byte getKey(byte[] keyData, short kOff) { return aesKey.getKey(keyData, kOff); } - + public short getKeySizeBits() { return aesKey.getSize(); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 18e67e72..37e67d1c 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -25,50 +25,53 @@ // The certificate is assembled with leafs first and then the sequences. public class KMAttestationCertImpl implements KMAttestationCert { + private static final byte MAX_PARAMS = 30; // DER encoded object identifiers required by the cert. // rsaEncryption - 1.2.840.113549.1.1.1 private static final byte[] rsaEncryption = { - 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01 + 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01 }; // ecPublicKey - 1.2.840.10045.2.1 private static final byte[] eccPubKey = { - 0x06, 0x07, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x02, 0x01 + 0x06, 0x07, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x02, 0x01 }; // prime256v1 curve - 1.2.840.10045.3.1.7 private static final byte[] prime256v1 = { - 0x06, 0x08, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x03, 0x01, 0x07 + 0x06, 0x08, 0x2A, (byte) 0x86, 0x48, (byte) 0xCE, 0x3D, 0x03, 0x01, 0x07 }; // Key Usage Extn - 2.5.29.15 private static final byte[] keyUsageExtn = {0x06, 0x03, 0x55, 0x1D, 0x0F}; // Android Extn - 1.3.6.1.4.1.11129.2.1.17 private static final byte[] androidExtn = { - 0x06, 0x0A, 0X2B, 0X06, 0X01, 0X04, 0X01, (byte) 0XD6, 0X79, 0X02, 0X01, 0X11 + 0x06, 0x0A, 0X2B, 0X06, 0X01, 0X04, 0X01, (byte) 0XD6, 0X79, 0X02, 0X01, 0X11 }; private static final short ECDSA_MAX_SIG_LEN = 72; //Signature algorithm identifier - always ecdsaWithSha256 - 1.2.840.10045.4.3.2 //SEQUENCE of alg OBJ ID and parameters = NULL. private static final byte[] X509SignAlgIdentifier = { - 0x30, - 0x0A, - 0x06, - 0x08, - 0x2A, - (byte) 0x86, - 0x48, - (byte) 0xCE, - (byte) 0x3D, - 0x04, - 0x03, - 0x02 + 0x30, + 0x0A, + 0x06, + 0x08, + 0x2A, + (byte) 0x86, + 0x48, + (byte) 0xCE, + (byte) 0x3D, + 0x04, + 0x03, + 0x02 }; // Validity is not fixed field // Subject is a fixed field with only CN= Android Keystore Key - same for all the keys private static final byte[] X509Subject = { - 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x41, 0x6e, 0x64, - 0x72, 0x6f, 0x69, 0x64, 0x20, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x4B, 0x65, - 0x79 + 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x41, 0x6e, + 0x64, + 0x72, 0x6f, 0x69, 0x64, 0x20, 0x4B, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x4B, + 0x65, + 0x79 }; private static final byte keyUsageSign = (byte) 0x80; // 0 bit @@ -111,10 +114,13 @@ public class KMAttestationCertImpl implements KMAttestationCert { private static short issuer; private static short signPriv; - private KMAttestationCertImpl() {} + private KMAttestationCertImpl() { + } public static KMAttestationCert instance(boolean rsaCert) { - if (inst == null) inst = new KMAttestationCertImpl(); + if (inst == null) { + inst = new KMAttestationCertImpl(); + } init(); KMAttestationCertImpl.rsaCert = rsaCert; return inst; @@ -184,18 +190,19 @@ public KMAttestationCert notBefore(short obj, byte[] scratchpad) { @Override public KMAttestationCert notAfter(short usageExpiryTimeObj, - short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { + short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { if (usageExpiryTimeObj != KMType.INVALID_VALUE) { // compare if the expiry time is greater then 2051 then use generalized // time format else use utc time format. usageExpiryTimeObj = KMIntegerTag.cast(usageExpiryTimeObj).getValue(); tmpVar = KMInteger.uint_64(KMUtils.firstJan2051, (short) 0); - if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) + if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) { usageExpiryTimeObj = KMUtils.convertToDate(usageExpiryTimeObj, scratchPad, - false); - else + false); + } else { usageExpiryTimeObj = KMUtils - .convertToDate(usageExpiryTimeObj, scratchPad, true); + .convertToDate(usageExpiryTimeObj, scratchPad, true); + } notAfter = usageExpiryTimeObj; } else { notAfter = certExpirtyTimeObj; @@ -205,8 +212,11 @@ public KMAttestationCert notAfter(short usageExpiryTimeObj, @Override public KMAttestationCert deviceLocked(boolean val) { - if (val) deviceLocked = (byte) 0xFF; - else deviceLocked = 0; + if (val) { + deviceLocked = (byte) 0xFF; + } else { + deviceLocked = 0; + } return this; } @@ -296,7 +306,9 @@ private static void pushTbsCert(boolean rsaCert) { private static void pushExtensions() { short last = stackPtr; - if (keyUsage != 0) pushKeyUsage(keyUsage, unusedBits); + if (keyUsage != 0) { + pushKeyUsage(keyUsage, unusedBits); + } pushKeyDescription(); pushSequenceHeader((short) (last - stackPtr)); // Extensions have explicit tag of [3] @@ -360,6 +372,7 @@ private static void pushRsaSubjectKeyInfo() { pushRsaEncryption(); pushSequenceHeader((short) (last - stackPtr)); } + // SEQUENCE{SEQUENCE{ecPubKey, prime256v1}, bitString{pubKey}} private static void pushEccSubjectKeyInfo() { short last = stackPtr; @@ -385,6 +398,7 @@ private static void pushRsaEncryption() { pushBytes(rsaEncryption, (short) 0, (short) rsaEncryption.length); pushSequenceHeader((short) (last - stackPtr)); } + // KeyDescription ::= SEQUENCE { // attestationVersion INTEGER, # Value 3 // attestationSecurityLevel SecurityLevel, # See below @@ -427,9 +441,9 @@ private static void pushSWParams() { short last = stackPtr; // Below are the allowed softwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { - KMType.ATTESTATION_APPLICATION_ID, KMType.CREATION_DATETIME, - KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, - KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED }; + KMType.ATTESTATION_APPLICATION_ID, KMType.CREATION_DATETIME, + KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, + KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED}; byte index = 0; do { pushParams(swParams, swParamsIndex, tagIds[index]); @@ -441,15 +455,15 @@ private static void pushHWParams() { short last = stackPtr; // Below are the allowed hardwareEnforced Authorization tags inside the attestation certificate's extension. short[] tagIds = { - KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, - KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.APPLICATION_ID, - KMType.TRUSTED_CONFIRMATION_REQUIRED, - KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, - KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, - KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, - KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, - KMType.ALGORITHM, KMType.PURPOSE }; + KMType.BOOT_PATCH_LEVEL, KMType.VENDOR_PATCH_LEVEL, + KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, + KMType.ORIGIN, KMType.APPLICATION_ID, + KMType.TRUSTED_CONFIRMATION_REQUIRED, + KMType.TRUSTED_USER_PRESENCE_REQUIRED, KMType.ALLOW_WHILE_ON_BODY, + KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, + KMType.ROLLBACK_RESISTANCE, KMType.RSA_PUBLIC_EXPONENT, + KMType.ECCURVE, KMType.PADDING, KMType.DIGEST, KMType.KEYSIZE, + KMType.ALGORITHM, KMType.PURPOSE}; byte index = 0; do { @@ -457,7 +471,9 @@ private static void pushHWParams() { pushRoT(); continue; } - if (pushParams(hwParams, hwParamsIndex, tagIds[index])) continue; + if (pushParams(hwParams, hwParamsIndex, tagIds[index])) { + continue; + } } while (++index < tagIds.length); pushSequenceHeader((short) (last - stackPtr)); } @@ -525,6 +541,7 @@ private static void pushTag(short tag) { break; } } + // RootOfTrust ::= SEQUENCE { // verifiedBootKey OCTET_STRING, // deviceLocked BOOLEAN, @@ -588,6 +605,7 @@ private static void pushEnumArrayTag(short tagId, byte[] buf, short start, short pushSetHeader((short) (last - stackPtr)); pushTagIdHeader(tagId, (short) (last - stackPtr)); } + // Only SET of INTEGERS supported are padding, digest, purpose and blockmode // All of these are enum array tags i.e. byte long values private static void pushIntegerArrayTag(short tagId, short arr) { @@ -647,13 +665,16 @@ private static void pushIntegerTag(short tagId, byte[] buf, short start, short l // pushIntegerHeader((short) (last - stackPtr)); pushTagIdHeader(tagId, (short) (last - stackPtr)); } + // Ignore leading zeros. Only Unsigned Integers are required hence if MSB is set then add 0x00 // as most significant byte. private static void pushInteger(byte[] buf, short start, short len) { short last = stackPtr; byte index = 0; while (index < (byte) len) { - if (buf[(short) (start + index)] != 0) break; + if (buf[(short) (start + index)] != 0) { + break; + } index++; } if (index == (byte) len) { @@ -666,6 +687,7 @@ private static void pushInteger(byte[] buf, short start, short len) { } pushIntegerHeader((short) (last - stackPtr)); } + // Bytes Tag is a octet string and tag id is added explicitly private static void pushBytesTag(short tagId, byte[] buf, short start, short len) { short last = stackPtr; @@ -691,6 +713,7 @@ private static void pushTagIdHeader(short tagId, short len) { pushByte((byte) (0xA0 | (byte) tagId)); } } + // SEQUENCE {ObjId, OCTET STRING{BIT STRING{keyUsage}}} private static void pushKeyUsage(byte keyUsage, byte unusedBits) { short last = stackPtr; @@ -757,7 +780,9 @@ private static void pushBytes(byte[] buf, short start, short len) { private static void decrementStackPtr(short cnt) { stackPtr = (short) (stackPtr - cnt); - if (start > stackPtr) KMException.throwIt(KMError.UNKNOWN_ERROR); + if (start > stackPtr) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } } @Override @@ -800,39 +825,39 @@ public void build() { KMJCardSimulator provider = KMJCardSimulator.getInstance(); short sigLen = provider .ecSign256( - provider.getAttestationKey(), - stack, - tbsOffset, - tbsLength, - stack, - signatureOffset); - if(sigLen != ECDSA_MAX_SIG_LEN) { + provider.getAttestationKey(), + stack, + tbsOffset, + tbsLength, + stack, + signatureOffset); + if (sigLen != ECDSA_MAX_SIG_LEN) { // Update the lengths appropriately. - stackPtr = (short)(signatureOffset - 1); - pushLength((short)(sigLen + 1)); + stackPtr = (short) (signatureOffset - 1); + pushLength((short) (sigLen + 1)); stackPtr = tbsOffset; - last -= (short)(ECDSA_MAX_SIG_LEN - sigLen); - pushLength((short)(last - stackPtr)); - length -= (short)(ECDSA_MAX_SIG_LEN - sigLen); + last -= (short) (ECDSA_MAX_SIG_LEN - sigLen); + pushLength((short) (last - stackPtr)); + length -= (short) (ECDSA_MAX_SIG_LEN - sigLen); } } @Override public KMAttestationCert makeUniqueId(byte[] scratchPad, short scratchPadOff, - byte[] creationTime, short timeOffset, short creationTimeLen, - byte[] attestAppId, short appIdOff, short attestAppIdLen, - byte resetSinceIdRotation, KMMasterKey masterKey) { + byte[] creationTime, short timeOffset, short creationTimeLen, + byte[] attestAppId, short appIdOff, short attestAppIdLen, + byte resetSinceIdRotation, KMMasterKey masterKey) { // Concatenate T||C||R // temporal count T short temp = KMUtils.countTemporalCount(creationTime, timeOffset, - creationTimeLen, scratchPad, scratchPadOff); + creationTimeLen, scratchPad, scratchPadOff); Util.setShort(scratchPad, (short) scratchPadOff, temp); temp = scratchPadOff; scratchPadOff += 2; // Application Id C Util.arrayCopyNonAtomic(attestAppId, appIdOff, scratchPad, scratchPadOff, - attestAppIdLen); + attestAppIdLen); scratchPadOff += attestAppIdLen; // Reset After Rotation R @@ -841,20 +866,20 @@ public KMAttestationCert makeUniqueId(byte[] scratchPad, short scratchPadOff, //Get the key data from the master key KMAESKey aesKey = (KMAESKey) masterKey; - short mKeyData = KMByteBlob.instance((short) (aesKey.getKeySizeBits() / 8)); + short mKeyData = KMByteBlob.instance((short) (aesKey.getKeySizeBits() / 8)); aesKey.getKey( - KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ - KMByteBlob.cast(mKeyData).getStartOff()); /* Key start*/ + KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ + KMByteBlob.cast(mKeyData).getStartOff()); /* Key start*/ timeOffset = KMByteBlob.instance((short) 32); appIdOff = KMJCardSimulator.getInstance().hmacSign( - KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ - KMByteBlob.cast(mKeyData).getStartOff(), /* Key start*/ - KMByteBlob.cast(mKeyData).length(), /* Key length*/ - scratchPad, /* data */ - temp, /* data start */ - scratchPadOff, /* data length */ - KMByteBlob.cast(timeOffset).getBuffer(), /* signature buffer */ - KMByteBlob.cast(timeOffset).getStartOff()); /* signature start */ + KMByteBlob.cast(mKeyData).getBuffer(), /* Key */ + KMByteBlob.cast(mKeyData).getStartOff(), /* Key start*/ + KMByteBlob.cast(mKeyData).length(), /* Key length*/ + scratchPad, /* data */ + temp, /* data start */ + scratchPadOff, /* data length */ + KMByteBlob.cast(timeOffset).getBuffer(), /* signature buffer */ + KMByteBlob.cast(timeOffset).getStartOff()); /* signature start */ if (appIdOff != 32) { KMException.throwIt(KMError.UNKNOWN_ERROR); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java index 3e67ed5e..420a775c 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipher.java @@ -16,11 +16,14 @@ package com.android.javacard.keymaster; public abstract class KMCipher { + public static final short SUN_JCE = 0xE9; - public abstract short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i); + public abstract short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, + short i); - public abstract short update(byte[] buffer, short startOff, short length, byte[] scratchPad, short i); + public abstract short update(byte[] buffer, short startOff, short length, byte[] scratchPad, + short i); public abstract void updateAAD(byte[] buffer, short startOff, short length); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java index 95e5cb83..c4162b12 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMCipherImpl.java @@ -24,25 +24,28 @@ import javax.crypto.ShortBufferException; -public class KMCipherImpl extends KMCipher{ +public class KMCipherImpl extends KMCipher { + private Cipher cipher; private javax.crypto.Cipher sunCipher; private short cipherAlg; private short padding; private short mode; private short blockMode; - KMCipherImpl(Cipher c){ + + KMCipherImpl(Cipher c) { cipher = c; } - KMCipherImpl(javax.crypto.Cipher c){ + + KMCipherImpl(javax.crypto.Cipher c) { sunCipher = c; } @Override - public short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i){ - if(cipherAlg == KMType.RSA && padding == KMType.RSA_OAEP){ + public short doFinal(byte[] buffer, short startOff, short length, byte[] scratchPad, short i) { + if (cipherAlg == KMType.RSA && padding == KMType.RSA_OAEP) { try { - return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i); + return (short) sunCipher.doFinal(buffer, startOff, length, scratchPad, i); } catch (ShortBufferException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -53,9 +56,9 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - }else if(cipherAlg == KMType.AES && blockMode == KMType.GCM){ + } else if (cipherAlg == KMType.AES && blockMode == KMType.GCM) { try { - return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i); + return (short) sunCipher.doFinal(buffer, startOff, length, scratchPad, i); } catch (AEADBadTagException e) { e.printStackTrace(); KMException.throwIt(KMError.VERIFICATION_FAILED); @@ -67,9 +70,9 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch } catch (BadPaddingException e) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - } else if(cipherAlg == KMType.AES && blockMode == KMType.CTR){ + } else if (cipherAlg == KMType.AES && blockMode == KMType.CTR) { try { - return (short)sunCipher.doFinal(buffer,startOff,length,scratchPad,i); + return (short) sunCipher.doFinal(buffer, startOff, length, scratchPad, i); } catch (ShortBufferException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -80,53 +83,64 @@ public short doFinal(byte[] buffer, short startOff, short length, byte[] scratch e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - } else{ - if((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding ==KMType.PKCS7 && mode == KMType.ENCRYPT){ - byte blkSize = 16; - byte paddingBytes; - short len = length; - if (cipherAlg == KMType.DES) blkSize = 8; - // padding bytes - if (len % blkSize == 0) paddingBytes = blkSize; - else paddingBytes = (byte) (blkSize - (len % blkSize)); - // final len with padding - len = (short) (len + paddingBytes); - // intermediate buffer to copy input data+padding - byte[] tmp = new byte[len]; - // fill in the padding - Util.arrayFillNonAtomic(tmp, (short) 0, len, paddingBytes); - // copy the input data - Util.arrayCopyNonAtomic(buffer,startOff,tmp,(short)0,length); - buffer = tmp; - length = len; - startOff = 0; + } else { + if ((cipherAlg == KMType.DES || cipherAlg == KMType.AES) && padding == KMType.PKCS7 + && mode == KMType.ENCRYPT) { + byte blkSize = 16; + byte paddingBytes; + short len = length; + if (cipherAlg == KMType.DES) { + blkSize = 8; + } + // padding bytes + if (len % blkSize == 0) { + paddingBytes = blkSize; + } else { + paddingBytes = (byte) (blkSize - (len % blkSize)); + } + // final len with padding + len = (short) (len + paddingBytes); + // intermediate buffer to copy input data+padding + byte[] tmp = new byte[len]; + // fill in the padding + Util.arrayFillNonAtomic(tmp, (short) 0, len, paddingBytes); + // copy the input data + Util.arrayCopyNonAtomic(buffer, startOff, tmp, (short) 0, length); + buffer = tmp; + length = len; + startOff = 0; } short len = cipher.doFinal(buffer, startOff, length, scratchPad, i); // JCard Sim removes leading zeros during decryption in case of no padding - so add that back. - if (cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.DECRYPT && len < 256) { + if (cipherAlg == KMType.RSA && padding == KMType.PADDING_NONE && mode == KMType.DECRYPT + && len < 256) { byte[] tempBuf = new byte[256]; Util.arrayFillNonAtomic(tempBuf, (short) 0, (short) 256, (byte) 0); Util.arrayCopyNonAtomic(scratchPad, (short) 0, tempBuf, (short) (i + 256 - len), len); Util.arrayCopyNonAtomic(tempBuf, (short) 0, scratchPad, i, (short) 256); len = 256; - }else if((cipherAlg == KMType.AES || cipherAlg == KMType.DES) // PKCS7 - && padding == KMType.PKCS7 - && mode == KMType.DECRYPT){ + } else if ((cipherAlg == KMType.AES || cipherAlg == KMType.DES) // PKCS7 + && padding == KMType.PKCS7 + && mode == KMType.DECRYPT) { byte blkSize = 16; - if (cipherAlg == KMType.DES) blkSize = 8; - if(len >0) { + if (cipherAlg == KMType.DES) { + blkSize = 8; + } + if (len > 0) { //verify if padding is corrupted. - byte paddingByte = scratchPad[i+len -1]; + byte paddingByte = scratchPad[i + len - 1]; //padding byte always should be <= block size - if((short)paddingByte > blkSize || - (short)paddingByte <= 0) KMException.throwIt(KMError.INVALID_ARGUMENT); + if ((short) paddingByte > blkSize || + (short) paddingByte <= 0) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } - for(short j = 1; j <= paddingByte; ++j) { - if (scratchPad[i+len -j] != paddingByte) { + for (short j = 1; j <= paddingByte; ++j) { + if (scratchPad[i + len - j] != paddingByte) { KMException.throwIt(KMError.INVALID_ARGUMENT); } } - len = (short)(len - (short)paddingByte);// remove the padding bytes + len = (short) (len - (short) paddingByte);// remove the padding bytes } } return len; @@ -146,17 +160,17 @@ public void setCipherAlgorithm(short alg) { @Override public short update(byte[] buffer, short startOff, short length, byte[] scratchPad, short i) { - if(cipherAlg == KMType.AES && (blockMode == KMType.GCM || blockMode == KMType.CTR)){ + if (cipherAlg == KMType.AES && (blockMode == KMType.GCM || blockMode == KMType.CTR)) { try { - return (short)sunCipher.update(buffer,startOff,length,scratchPad,i); + return (short) sunCipher.update(buffer, startOff, length, scratchPad, i); } catch (ShortBufferException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } catch (IllegalStateException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - } else{ + } else { return cipher.update(buffer, startOff, length, scratchPad, i); } return KMType.INVALID_VALUE; @@ -164,16 +178,16 @@ public short update(byte[] buffer, short startOff, short length, byte[] scratchP @Override public void updateAAD(byte[] buffer, short startOff, short length) { - try { - sunCipher.updateAAD(buffer,startOff,length); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (IllegalStateException e) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } catch (UnsupportedOperationException e) { - CryptoException.throwIt(CryptoException.ILLEGAL_USE); - } + try { + sunCipher.updateAAD(buffer, startOff, length); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (IllegalStateException e) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } catch (UnsupportedOperationException e) { + CryptoException.throwIt(CryptoException.ILLEGAL_USE); + } } @Override @@ -187,12 +201,12 @@ public void setPaddingAlgorithm(short alg) { } @Override - public void setBlockMode(short mode){ - blockMode = mode; + public void setBlockMode(short mode) { + blockMode = mode; } @Override - public short getBlockMode(){ + public short getBlockMode() { return blockMode; } @@ -206,7 +220,7 @@ public void setMode(short mode) { @Override public short getCipherProvider() { - return KMCipher.SUN_JCE; + return KMCipher.SUN_JCE; } @Override diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java index 65c069d1..62b26cce 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMECPrivateKey.java @@ -30,7 +30,7 @@ public void setS(byte[] buffer, short offset, short length) { ECPrivateKey ecPriv = (ECPrivateKey) ecKeyPair.getPrivate(); ecPriv.setS(buffer, offset, length); } - + public ECPrivateKey getPrivateKey() { return (ECPrivateKey) ecKeyPair.getPrivate(); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java index 904353b1..c382f3cb 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMEcdsa256NoDigestSignature.java @@ -42,60 +42,61 @@ public class KMEcdsa256NoDigestSignature extends Signature { + private java.security.Signature sunSigner; - public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short keyLength){ - KeyFactory kf; - try { - sunSigner = java.security.Signature.getInstance("NONEwithECDSA", "SunEC"); - kf = KeyFactory.getInstance("EC"); - AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", "SunEC"); - //Supported curve secp256r1 - parameters.init(new ECGenParameterSpec("secp256r1")); - ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class); - if(mode == Signature.MODE_SIGN) { - byte[] privKey = new byte[keyLength]; - for(short i =0; i< keyLength; i++) { - privKey[i] = key[keyStart+i]; - } - BigInteger bI = new BigInteger(privKey); - ECPrivateKeySpec prikeyspec = new ECPrivateKeySpec(bI, ecParameters); - ECPrivateKey privkey = (ECPrivateKey) kf.generatePrivate(prikeyspec); - sunSigner.initSign(privkey); - } else { - //Check if the first byte is 04 and remove it. - if(key[keyStart] == 0x04) { - //uncompressed format. - keyStart++; - keyLength--; - } - short i = 0; - byte[] pubx = new byte[keyLength/2]; - for(;i < keyLength/2; i++ ) { - pubx[i] = key[keyStart+i]; - } - byte[] puby = new byte[keyLength/2]; - for(i = 0;i < keyLength/2; i++ ) { - puby[i] = key[keyStart+keyLength/2+i]; - } - BigInteger bIX = new BigInteger(pubx); - BigInteger bIY = new BigInteger(puby); - ECPoint point = new ECPoint(bIX, bIY); - ECPublicKeySpec pubkeyspec = new ECPublicKeySpec(point, ecParameters); - ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec); - sunSigner.initVerify(pubkey); - } - } catch (NoSuchAlgorithmException e) { - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch (NoSuchProviderException e) { - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - } catch(InvalidParameterSpecException e) { - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch(InvalidKeySpecException e) { - CryptoException.throwIt(CryptoException.INVALID_INIT); - } catch(InvalidKeyException e) { - CryptoException.throwIt(CryptoException.INVALID_INIT); - } + public KMEcdsa256NoDigestSignature(byte mode, byte[] key, short keyStart, short keyLength) { + KeyFactory kf; + try { + sunSigner = java.security.Signature.getInstance("NONEwithECDSA", "SunEC"); + kf = KeyFactory.getInstance("EC"); + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", "SunEC"); + //Supported curve secp256r1 + parameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class); + if (mode == Signature.MODE_SIGN) { + byte[] privKey = new byte[keyLength]; + for (short i = 0; i < keyLength; i++) { + privKey[i] = key[keyStart + i]; + } + BigInteger bI = new BigInteger(privKey); + ECPrivateKeySpec prikeyspec = new ECPrivateKeySpec(bI, ecParameters); + ECPrivateKey privkey = (ECPrivateKey) kf.generatePrivate(prikeyspec); + sunSigner.initSign(privkey); + } else { + //Check if the first byte is 04 and remove it. + if (key[keyStart] == 0x04) { + //uncompressed format. + keyStart++; + keyLength--; + } + short i = 0; + byte[] pubx = new byte[keyLength / 2]; + for (; i < keyLength / 2; i++) { + pubx[i] = key[keyStart + i]; + } + byte[] puby = new byte[keyLength / 2]; + for (i = 0; i < keyLength / 2; i++) { + puby[i] = key[keyStart + keyLength / 2 + i]; + } + BigInteger bIX = new BigInteger(pubx); + BigInteger bIY = new BigInteger(puby); + ECPoint point = new ECPoint(bIX, bIY); + ECPublicKeySpec pubkeyspec = new ECPublicKeySpec(point, ecParameters); + ECPublicKey pubkey = (ECPublicKey) kf.generatePublic(pubkeyspec); + sunSigner.initVerify(pubkey); + } + } catch (NoSuchAlgorithmException e) { + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } catch (NoSuchProviderException e) { + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + } catch (InvalidParameterSpecException e) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidKeySpecException e) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } catch (InvalidKeyException e) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } } @Override @@ -109,7 +110,8 @@ public void init(Key key, byte b, byte[] bytes, short i, short i1) throws Crypto } @Override - public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) + throws CryptoException { } @@ -140,45 +142,50 @@ public short getLength() throws CryptoException { @Override public void update(byte[] message, short msgStart, short messageLength) throws CryptoException { - byte[] msgBytes = new byte[messageLength]; - for(int i =0; i< messageLength; i++) { - msgBytes[i] = message[msgStart+i]; - } - try { - if(messageLength > 0) - sunSigner.update(msgBytes); - } catch (SignatureException e) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + byte[] msgBytes = new byte[messageLength]; + for (int i = 0; i < messageLength; i++) { + msgBytes[i] = message[msgStart + i]; + } + try { + if (messageLength > 0) { + sunSigner.update(msgBytes); + } + } catch (SignatureException e) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } } @Override - public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException { + public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) + throws CryptoException { short len = 0; try { - update(bytes, i , i1); - byte[] sig = sunSigner.sign(); - Util.arrayCopyNonAtomic(sig, (short)0, bytes1, i2, (short)sig.length); - return (short)sig.length; - } catch (SignatureException e) { - CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - } + update(bytes, i, i1); + byte[] sig = sunSigner.sign(); + Util.arrayCopyNonAtomic(sig, (short) 0, bytes1, i2, (short) sig.length); + return (short) sig.length; + } catch (SignatureException e) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } return len; } @Override - public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException { + public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2) + throws CryptoException { return 0; } @Override - public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) + throws CryptoException { // Public key operations not handled here. return false; } @Override - public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, + short i3) throws CryptoException { return false; } } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMHmacKey.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMHmacKey.java index 8b75827a..65f1d02a 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMHmacKey.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMHmacKey.java @@ -18,6 +18,7 @@ import javacard.security.HMACKey; public class KMHmacKey implements KMPreSharedKey { + private HMACKey hmacKey; public KMHmacKey(HMACKey key) { diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java index fd6dd910..a97377ea 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java @@ -17,9 +17,10 @@ public class KMJCardSimApplet extends KMKeymasterApplet { - KMJCardSimApplet(){ + KMJCardSimApplet() { super(new KMJCardSimulator()); } + /** * Installs this applet. * @@ -28,7 +29,7 @@ public class KMJCardSimApplet extends KMKeymasterApplet { * @param bLength the length in bytes of the parameter data in bArray */ public static void install(byte[] bArray, short bOffset, byte bLength) { - new KMJCardSimApplet().register(); + new KMJCardSimApplet().register(); } } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java index 0dad8f77..20de91c8 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimulator.java @@ -66,6 +66,7 @@ * creates its own RNG using PRNG. */ public class KMJCardSimulator implements KMSEProvider { + public static final short AES_GCM_TAG_LENGTH = 16; public static final short AES_GCM_NONCE_LENGTH = 12; public static final short MAX_RND_NUM_SIZE = 64; @@ -117,16 +118,16 @@ public KMJCardSimulator() { jCardSimulator = this; } - + public KeyPair createRsaKeyPair() { KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); rsaKeyPair.genKeyPair(); return rsaKeyPair; } - + public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLength, - byte[] privBuffer, short privOff, short privLength) { + byte[] privBuffer, short privOff, short privLength) { KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); RSAPrivateKey privKey = (RSAPrivateKey) rsaKeyPair.getPrivate(); privKey.setExponent(privBuffer, privOff, privLength); @@ -135,88 +136,89 @@ public RSAPrivateKey createRsaKey(byte[] modBuffer, short modOff, short modLengt } - + public KeyPair createECKeyPair() { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); ecKeyPair.genKeyPair(); return ecKeyPair; } - + public ECPrivateKey createEcKey(byte[] privBuffer, short privOff, short privLength) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); ECPrivateKey privKey = (ECPrivateKey) ecKeyPair.getPrivate(); - privKey.setS(privBuffer,privOff, privLength); + privKey.setS(privBuffer, privOff, privLength); return privKey; } - + public AESKey createAESKey(short keysize) { - byte[] rndNum = new byte[(short) (keysize/8)]; - return createAESKey(rndNum, (short)0, (short)rndNum.length); + byte[] rndNum = new byte[(short) (keysize / 8)]; + return createAESKey(rndNum, (short) 0, (short) rndNum.length); } public AESKey createAESKey(byte[] buf, short startOff, short length) { AESKey key = null; - short keysize = (short)(length * 8); + short keysize = (short) (length * 8); if (keysize == 128) { key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false); key.setKey(buf, (short) startOff); - }else if (keysize == 256){ + } else if (keysize == 256) { key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); key.setKey(buf, (short) startOff); } return key; } - + public DESKey createTDESKey() { byte[] rndNum = new byte[24]; - newRandomNumber(rndNum, (short) 0, (short)rndNum.length); - return createTDESKey(rndNum, (short)0, (short)rndNum.length); + newRandomNumber(rndNum, (short) 0, (short) rndNum.length); + return createTDESKey(rndNum, (short) 0, (short) rndNum.length); } - + public DESKey createTDESKey(byte[] secretBuffer, short secretOff, short secretLength) { DESKey triDesKey = - (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); + (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false); triDesKey.setKey(secretBuffer, secretOff); return triDesKey; } - + public HMACKey createHMACKey(short keysize) { - if((keysize % 8 != 0) || !(keysize >= 64 && keysize <= 512)){ + if ((keysize % 8 != 0) || !(keysize >= 64 && keysize <= 512)) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - byte[] rndNum = new byte[(short) (keysize/8)]; - newRandomNumber(rndNum, (short) 0, (short)(keysize/8)); - return createHMACKey(rndNum, (short)0, (short)rndNum.length); + byte[] rndNum = new byte[(short) (keysize / 8)]; + newRandomNumber(rndNum, (short) 0, (short) (keysize / 8)); + return createHMACKey(rndNum, (short) 0, (short) rndNum.length); } @Override public short createSymmetricKey(byte alg, short keysize, byte[] buf, short startOff) { - switch(alg){ + switch (alg) { case KMType.AES: AESKey aesKey = createAESKey(keysize); - return aesKey.getKey(buf,startOff); + return aesKey.getKey(buf, startOff); case KMType.DES: DESKey desKey = createTDESKey(); - return desKey.getKey(buf,startOff); + return desKey.getKey(buf, startOff); case KMType.HMAC: HMACKey hmacKey = createHMACKey(keysize); - return hmacKey.getKey(buf,startOff); - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + return hmacKey.getKey(buf, startOff); + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } return 0; } @Override - public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, - byte[] pubModBuf, short pubModStart, short pubModLength, short[] lengths){ - switch (alg){ + public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, + short privKeyLength, + byte[] pubModBuf, short pubModStart, short pubModLength, short[] lengths) { + switch (alg) { case KMType.RSA: if (RSA_KEY_SIZE != privKeyLength || RSA_KEY_SIZE != pubModLength) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -225,48 +227,51 @@ public void createAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, RSAPrivateKey privKey = (RSAPrivateKey) rsaKey.getPrivate(); //Copy exponent. byte[] exp = new byte[RSA_KEY_SIZE]; - lengths[0] = privKey.getExponent(exp, (short)0); - if (lengths[0] > privKeyLength) + lengths[0] = privKey.getExponent(exp, (short) 0); + if (lengths[0] > privKeyLength) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte)0); - Util.arrayCopyNonAtomic(exp, (short)0, - privKeyBuf, (short)(privKeyStart + privKeyLength - lengths[0]), lengths[0]); + } + Util.arrayFillNonAtomic(privKeyBuf, privKeyStart, privKeyLength, (byte) 0); + Util.arrayCopyNonAtomic(exp, (short) 0, + privKeyBuf, (short) (privKeyStart + privKeyLength - lengths[0]), lengths[0]); //Copy modulus byte[] mod = new byte[RSA_KEY_SIZE]; - lengths[1] = privKey.getModulus(mod, (short)0); - if (lengths[1] > pubModLength) + lengths[1] = privKey.getModulus(mod, (short) 0); + if (lengths[1] > pubModLength) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte)0); - Util.arrayCopyNonAtomic(mod, (short)0, - pubModBuf, (short)(pubModStart + pubModLength - lengths[1]), lengths[1]); + } + Util.arrayFillNonAtomic(pubModBuf, pubModStart, pubModLength, (byte) 0); + Util.arrayCopyNonAtomic(mod, (short) 0, + pubModBuf, (short) (pubModStart + pubModLength - lengths[1]), lengths[1]); break; case KMType.EC: KeyPair ecKey = createECKeyPair(); ECPublicKey ecPubKey = (ECPublicKey) ecKey.getPublic(); ECPrivateKey ecPrivKey = (ECPrivateKey) ecKey.getPrivate(); - lengths[0] = ecPrivKey.getS(privKeyBuf,privKeyStart); - lengths[1] = ecPubKey.getW(pubModBuf,pubModStart); - if(lengths[0] > privKeyLength || lengths[1] > pubModLength){ + lengths[0] = ecPrivKey.getS(privKeyBuf, privKeyStart); + lengths[1] = ecPubKey.getW(pubModBuf, pubModStart); + if (lengths[0] > privKeyLength || lengths[1] > pubModLength) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } break; - default: - CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); - break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; } } @Override - public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, short length) { - switch(alg){ + public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short startOff, + short length) { + switch (alg) { case KMType.AES: - AESKey aesKey = createAESKey(buf,startOff,length); + AESKey aesKey = createAESKey(buf, startOff, length); break; case KMType.DES: - DESKey desKey = createTDESKey(buf,startOff,length); + DESKey desKey = createTDESKey(buf, startOff, length); break; case KMType.HMAC: - HMACKey hmacKey = createHMACKey(buf,startOff,length); + HMACKey hmacKey = createHMACKey(buf, startOff, length); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -276,13 +281,15 @@ public boolean importSymmetricKey(byte alg, short keysize, byte[] buf, short sta } @Override - public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { - switch (alg){ + public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeyStart, + short privKeyLength, byte[] pubModBuf, short pubModStart, short pubModLength) { + switch (alg) { case KMType.RSA: - RSAPrivateKey rsaKey = createRsaKey(pubModBuf,pubModStart,pubModLength,privKeyBuf,privKeyStart,privKeyLength); + RSAPrivateKey rsaKey = createRsaKey(pubModBuf, pubModStart, pubModLength, privKeyBuf, + privKeyStart, privKeyLength); break; case KMType.EC: - ECPrivateKey ecPrivKey = createEcKey(privKeyBuf,privKeyStart,privKeyLength); + ECPrivateKey ecPrivKey = createEcKey(privKeyBuf, privKeyStart, privKeyLength); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -291,12 +298,12 @@ public boolean importAsymmetricKey(byte alg, byte[] privKeyBuf, short privKeySta return true; } - + public HMACKey createHMACKey(byte[] secretBuffer, short secretOff, short secretLength) { HMACKey key = null; key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, - KeyBuilder.LENGTH_HMAC_SHA_256_BLOCK_64, false); - key.setKey(secretBuffer,secretOff,secretLength); + KeyBuilder.LENGTH_HMAC_SHA_256_BLOCK_64, false); + key.setKey(secretBuffer, secretOff, secretLength); return key; } @@ -320,10 +327,10 @@ public short aesGCMEncrypt( short authTagStart, short authTagLen) { //Create the sun jce compliant aes key - if(keyLen != 32 && keyLen != 16){ + if (keyLen != 32 && keyLen != 16) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - java.security.Key aesKey = new SecretKeySpec(keyBuf,keyStart,keyLen, "AES"); + java.security.Key aesKey = new SecretKeySpec(keyBuf, keyStart, keyLen, "AES"); // Create the cipher javax.crypto.Cipher cipher = null; try { @@ -339,13 +346,14 @@ public short aesGCMEncrypt( CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } // Copy nonce - if(nonceLen != AES_GCM_NONCE_LENGTH){ + if (nonceLen != AES_GCM_NONCE_LENGTH) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } byte[] iv = new byte[AES_GCM_NONCE_LENGTH]; - Util.arrayCopyNonAtomic(nonce,nonceStart,iv,(short)0,AES_GCM_NONCE_LENGTH); + Util.arrayCopyNonAtomic(nonce, nonceStart, iv, (short) 0, AES_GCM_NONCE_LENGTH); // Init Cipher - GCMParameterSpec spec = new GCMParameterSpec(AES_GCM_TAG_LENGTH * 8, nonce,nonceStart,AES_GCM_NONCE_LENGTH); + GCMParameterSpec spec = new GCMParameterSpec(AES_GCM_TAG_LENGTH * 8, nonce, nonceStart, + AES_GCM_NONCE_LENGTH); try { cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, aesKey, spec); } catch (InvalidKeyException e) { @@ -357,13 +365,13 @@ public short aesGCMEncrypt( } // Create auth data byte[] aad = new byte[authDataLen]; - Util.arrayCopyNonAtomic(authData,authDataStart,aad,(short)0,authDataLen); + Util.arrayCopyNonAtomic(authData, authDataStart, aad, (short) 0, authDataLen); cipher.updateAAD(aad); // Encrypt secret short len = 0; byte[] outputBuf = new byte[cipher.getOutputSize(secretLen)]; try { - len = (short)(cipher.doFinal(secret,secretStart,secretLen,outputBuf,(short)0)); + len = (short) (cipher.doFinal(secret, secretStart, secretLen, outputBuf, (short) 0)); } catch (ShortBufferException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); @@ -375,10 +383,12 @@ public short aesGCMEncrypt( CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } // Extract Tag appended at the end. - Util.arrayCopyNonAtomic(outputBuf, (short)(len - AES_GCM_TAG_LENGTH),authTag,authTagStart,AES_GCM_TAG_LENGTH); + Util.arrayCopyNonAtomic(outputBuf, (short) (len - AES_GCM_TAG_LENGTH), authTag, authTagStart, + AES_GCM_TAG_LENGTH); //Copy the encrypted data - Util.arrayCopyNonAtomic(outputBuf, (short)0,encSecret,encSecretStart,(short)(len - AES_GCM_TAG_LENGTH)); - return (short)(len - AES_GCM_TAG_LENGTH); + Util.arrayCopyNonAtomic(outputBuf, (short) 0, encSecret, encSecretStart, + (short) (len - AES_GCM_TAG_LENGTH)); + return (short) (len - AES_GCM_TAG_LENGTH); } public boolean aesGCMDecrypt( @@ -398,13 +408,13 @@ public boolean aesGCMDecrypt( short authDataLen, byte[] authTag, short authTagStart, - short authTagLen) { + short authTagLen) { // Create the sun jce compliant aes key if (keyLen != 32 && keyLen != 16) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } java.security.Key aesKey = new SecretKeySpec(keyBuf, keyStart, keyLen, - "AES"); + "AES"); // Create the cipher javax.crypto.Cipher cipher = null; try { @@ -425,10 +435,10 @@ public boolean aesGCMDecrypt( } byte[] iv = new byte[AES_GCM_NONCE_LENGTH]; Util.arrayCopyNonAtomic(nonce, nonceStart, iv, (short) 0, - AES_GCM_NONCE_LENGTH); + AES_GCM_NONCE_LENGTH); // Init Cipher GCMParameterSpec spec = new GCMParameterSpec(authTagLen * 8, nonce, - nonceStart, AES_GCM_NONCE_LENGTH); + nonceStart, AES_GCM_NONCE_LENGTH); try { cipher.init(javax.crypto.Cipher.DECRYPT_MODE, aesKey, spec); } catch (InvalidKeyException e) { @@ -441,20 +451,20 @@ public boolean aesGCMDecrypt( // Create auth data byte[] aad = new byte[authDataLen]; Util.arrayCopyNonAtomic(authData, authDataStart, aad, (short) 0, - authDataLen); + authDataLen); cipher.updateAAD(aad); // Append the auth tag at the end of data byte[] inputBuf = new byte[(short) (encSecretLen + authTagLen)]; Util.arrayCopyNonAtomic(encSecret, encSecretStart, inputBuf, (short) 0, - encSecretLen); + encSecretLen); Util.arrayCopyNonAtomic(authTag, authTagStart, inputBuf, encSecretLen, - authTagLen); + authTagLen); // Decrypt short len = 0; byte[] outputBuf = new byte[cipher.getOutputSize((short) inputBuf.length)]; try { len = (short) (cipher.doFinal(inputBuf, (short) 0, - (short) inputBuf.length, outputBuf, (short) 0)); + (short) inputBuf.length, outputBuf, (short) 0)); } catch (AEADBadTagException e) { e.printStackTrace(); return false; @@ -475,22 +485,25 @@ public boolean aesGCMDecrypt( @Override public void getTrueRandomNumber(byte[] buf, short start, short length) { - Util.arrayCopy(entropyPool,(short)0,buf,start,length); + Util.arrayCopy(entropyPool, (short) 0, buf, start, length); } - - public HMACKey cmacKdf(byte[] keyMaterial, short keyMaterialStart, short keyMaterialLen, byte[] label, - short labelStart, short labelLen, byte[] context, short contextStart, short contextLength) { + + public HMACKey cmacKdf(byte[] keyMaterial, short keyMaterialStart, short keyMaterialLen, + byte[] label, + short labelStart, short labelLen, byte[] context, short contextStart, short contextLength) { // This is hardcoded to requirement - 32 byte output with two concatenated 16 bytes K1 and K2. final byte n = 2; // hardcoded - final byte[] L = {0,0,1,0}; // [L] 256 bits - hardcoded 32 bits as per reference impl in keymaster. + final byte[] L = {0, 0, 1, + 0}; // [L] 256 bits - hardcoded 32 bits as per reference impl in keymaster. final byte[] zero = {0}; // byte - byte[] iBuf = new byte[]{0,0,0,0}; // [i] counter - 32 bits - byte[] keyOut = new byte[(short)(n*16)]; + byte[] iBuf = new byte[]{0, 0, 0, 0}; // [i] counter - 32 bits + byte[] keyOut = new byte[(short) (n * 16)]; Signature prf = Signature.getInstance(Signature.ALG_AES_CMAC_128, false); - AESKey key = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); + AESKey key = (AESKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false); key.setKey(keyMaterial, keyMaterialStart); prf.init(key, Signature.MODE_SIGN); - byte i =1; + byte i = 1; short pos = 0; while (i <= n) { iBuf[3] = i; @@ -501,85 +514,95 @@ public HMACKey cmacKdf(byte[] keyMaterial, short keyMaterialStart, short keyMate pos = prf.sign(L, (short) 0, (short) 4, keyOut, pos); // 4 bytes of L - signature of 16 bytes i++; } - return createHMACKey(keyOut, (short)0, (short)keyOut.length); + return createHMACKey(keyOut, (short) 0, (short) keyOut.length); } @Override public short cmacKDF(KMPreSharedKey pSharedKey, byte[] label, - short labelStart, short labelLen, byte[] context, short contextStart, short contextLength, byte[] keyBuf, short keyStart) { + short labelStart, short labelLen, byte[] context, short contextStart, short contextLength, + byte[] keyBuf, short keyStart) { KMHmacKey key = (KMHmacKey) pSharedKey; short keyMaterialLen = key.getKeySizeBits(); keyMaterialLen = (short) (keyMaterialLen / 8); short keyMaterialStart = 0; byte[] keyMaterial = new byte[keyMaterialLen]; key.getKey(keyMaterial, keyMaterialStart); - HMACKey hmacKey = cmacKdf(keyMaterial,keyMaterialStart, keyMaterialLen, label, labelStart, labelLen,context,contextStart,contextLength); - return hmacKey.getKey(keyBuf,keyStart); + HMACKey hmacKey = cmacKdf(keyMaterial, keyMaterialStart, keyMaterialLen, label, labelStart, + labelLen, context, contextStart, contextLength); + return hmacKey.getKey(keyBuf, keyStart); } - - public short hmacSign(HMACKey key, byte[] data, short dataStart, short dataLength, byte[] mac, short macStart) { + + public short hmacSign(HMACKey key, byte[] data, short dataStart, short dataLength, byte[] mac, + short macStart) { hmacSignature.init(key, Signature.MODE_SIGN); return hmacSignature.sign(data, dataStart, dataLength, mac, macStart); } public boolean hmacVerify(HMACKey key, byte[] data, short dataStart, short dataLength, - byte[] mac, short macStart, short macLength) { + byte[] mac, short macStart, short macLength) { hmacSignature.init(key, Signature.MODE_VERIFY); return hmacSignature.verify(data, dataStart, dataLength, mac, macStart, macLength); } @Override public short hmacKDF(KMMasterKey masterkey, byte[] data, short dataStart, - short dataLength, byte[] signature, short signatureStart) { + short dataLength, byte[] signature, short signatureStart) { KMAESKey aesKey = (KMAESKey) masterkey; short keyLen = (short) (aesKey.getKeySizeBits() / 8); byte[] keyData = new byte[keyLen]; aesKey.getKey(keyData, (short) 0); return hmacSign(keyData, (short) 0, keyLen, data, dataStart, dataLength, - signature, signatureStart); + signature, signatureStart); } @Override - public short hmacSign(byte[] keyBuf, short keyStart, short keyLength, byte[] data, short dataStart, short dataLength, byte[] mac, short macStart) { - HMACKey key = createHMACKey(keyBuf,keyStart,keyLength); - return hmacSign(key,data,dataStart,dataLength,mac,macStart); + public short hmacSign(byte[] keyBuf, short keyStart, short keyLength, byte[] data, + short dataStart, short dataLength, byte[] mac, short macStart) { + HMACKey key = createHMACKey(keyBuf, keyStart, keyLength); + return hmacSign(key, data, dataStart, dataLength, mac, macStart); } @Override - public boolean hmacVerify(byte[] keyBuf, short keyStart, short keyLength, byte[] data, short dataStart, short dataLength, byte[] mac, short macStart, short macLength) { - HMACKey key = createHMACKey(keyBuf,keyStart,keyLength); - return hmacVerify(key,data,dataStart,dataLength,mac,macStart,macLength); + public boolean hmacVerify(byte[] keyBuf, short keyStart, short keyLength, byte[] data, + short dataStart, short dataLength, byte[] mac, short macStart, short macLength) { + HMACKey key = createHMACKey(keyBuf, keyStart, keyLength); + return hmacVerify(key, data, dataStart, dataLength, mac, macStart, macLength); } @Override public short rsaDecipherOAEP256(byte[] secret, short secretStart, short secretLength, - byte[] modBuffer, short modOff, short modLength, - byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] outputDataBuf, short outputDataStart) { + byte[] modBuffer, short modOff, short modLength, + byte[] inputDataBuf, short inputDataStart, short inputDataLength, + byte[] outputDataBuf, short outputDataStart) { KMCipher cipher = createRsaDecipher( - KMType.RSA_OAEP, KMType.SHA2_256, secret, secretStart, secretLength, modBuffer, modOff, modLength); + KMType.RSA_OAEP, KMType.SHA2_256, secret, secretStart, secretLength, modBuffer, modOff, + modLength); return cipher.doFinal( inputDataBuf, inputDataStart, inputDataLength, outputDataBuf, outputDataStart); } @Override - public KMOperation initSymmetricOperation(byte purpose, byte alg, byte digest, byte padding, byte blockMode, - byte[] keyBuf, short keyStart, short keyLength, - byte[] ivBuf, short ivStart, short ivLength, short macLength) { - switch (alg){ + public KMOperation initSymmetricOperation(byte purpose, byte alg, byte digest, byte padding, + byte blockMode, + byte[] keyBuf, short keyStart, short keyLength, + byte[] ivBuf, short ivStart, short ivLength, short macLength) { + switch (alg) { case KMType.AES: case KMType.DES: - if(blockMode != KMType.GCM){ - KMCipher cipher = createSymmetricCipher(alg,purpose, blockMode, padding,keyBuf,keyStart,keyLength, - ivBuf,ivStart,ivLength); - return new KMOperationImpl(cipher); - }else { - KMCipher aesGcm = createAesGcmCipher(purpose,macLength,keyBuf,keyStart,keyLength,ivBuf,ivStart,ivLength); + if (blockMode != KMType.GCM) { + KMCipher cipher = createSymmetricCipher(alg, purpose, blockMode, padding, keyBuf, + keyStart, keyLength, + ivBuf, ivStart, ivLength); + return new KMOperationImpl(cipher); + } else { + KMCipher aesGcm = createAesGcmCipher(purpose, macLength, keyBuf, keyStart, keyLength, + ivBuf, ivStart, ivLength); return new KMOperationImpl(aesGcm); } case KMType.HMAC: - Signature signerVerifier = createHmacSignerVerifier(purpose,digest,keyBuf,keyStart,keyLength); + Signature signerVerifier = createHmacSignerVerifier(purpose, digest, keyBuf, keyStart, + keyLength); return new KMOperationImpl(signerVerifier); default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -589,8 +612,8 @@ public KMOperation initSymmetricOperation(byte purpose, byte alg, byte digest, b @Override public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, byte digest, - byte[] privKeyBuf, short privKeyStart, short privKeyLength, - byte[] pubModBuf, short pubModStart, short pubModLength) { + byte[] privKeyBuf, short privKeyStart, short privKeyLength, + byte[] pubModBuf, short pubModStart, short pubModLength) { if (alg == KMType.RSA) { switch (purpose) { case KMType.SIGN: @@ -608,16 +631,17 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, case KMType.DECRYPT: KMCipher decipher = createRsaDecipher( - padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, pubModLength); + padding, digest, privKeyBuf, privKeyStart, privKeyLength, pubModBuf, pubModStart, + pubModLength); return new KMOperationImpl(decipher); default: KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } - }else if(alg == KMType.EC){ - switch(purpose){ + } else if (alg == KMType.EC) { + switch (purpose) { case KMType.SIGN: Signature signer = - createEcSigner(digest,privKeyBuf,privKeyStart,privKeyLength); + createEcSigner(digest, privKeyBuf, privKeyStart, privKeyLength); return new KMOperationImpl(signer); default: KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); @@ -628,16 +652,18 @@ public KMOperation initAsymmetricOperation(byte purpose, byte alg, byte padding, } public KMCipher createRsaDecipher(short padding, short digest, byte[] secret, short secretStart, - short secretLength, byte[] modBuffer, short modOff, short modLength) { - byte cipherAlg = mapCipherAlg(KMType.RSA, (byte)padding, (byte)0); + short secretLength, byte[] modBuffer, short modOff, short modLength) { + byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0); if (cipherAlg == Cipher.ALG_RSA_PKCS1_OAEP) { - return createRsaOAEP256Cipher(KMType.DECRYPT,(byte)digest,secret,secretStart,secretLength,modBuffer,modOff,modLength); + return createRsaOAEP256Cipher(KMType.DECRYPT, (byte) digest, secret, secretStart, + secretLength, modBuffer, modOff, modLength); } - Cipher rsaCipher = Cipher.getInstance(cipherAlg,false); - RSAPrivateKey key = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048, false); - key.setExponent(secret,secretStart,secretLength); + Cipher rsaCipher = Cipher.getInstance(cipherAlg, false); + RSAPrivateKey key = (RSAPrivateKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048, false); + key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key,Cipher.MODE_DECRYPT); + rsaCipher.init(key, Cipher.MODE_DECRYPT); KMCipherImpl inst = new KMCipherImpl(rsaCipher); inst.setCipherAlgorithm(KMType.RSA); inst.setMode(KMType.DECRYPT); @@ -645,43 +671,45 @@ public KMCipher createRsaDecipher(short padding, short digest, byte[] secret, sh return inst; } - private KMCipher createRsaOAEP256Cipher(byte mode,byte digest, - byte[] secret, short secretStart, short secretLen, - byte[] modBuffer, short modOff, short modLength) { + private KMCipher createRsaOAEP256Cipher(byte mode, byte digest, + byte[] secret, short secretStart, short secretLen, + byte[] modBuffer, short modOff, short modLength) { // Convert byte arrays into keys byte[] exp = null; byte[] mod = new byte[modLength]; if (secret != null) { exp = new byte[secretLen]; Util.arrayCopyNonAtomic(secret, secretStart, exp, (short) 0, secretLen); - }else{ - exp = new byte[]{0x01,0x00,0x01}; + } else { + exp = new byte[]{0x01, 0x00, 0x01}; } - Util.arrayCopyNonAtomic(modBuffer,modOff,mod,(short)0,modLength); + Util.arrayCopyNonAtomic(modBuffer, modOff, mod, (short) 0, modLength); String modString = toHexString(mod); String expString = toHexString(exp); - BigInteger modInt = new BigInteger(modString,16); - BigInteger expInt = new BigInteger(expString,16); + BigInteger modInt = new BigInteger(modString, 16); + BigInteger expInt = new BigInteger(expString, 16); javax.crypto.Cipher rsaCipher = null; - try{ + try { KeyFactory kf = KeyFactory.getInstance("RSA"); // Create cipher with oaep padding OAEPParameterSpec oaepSpec = null; - if(digest == KMType.SHA2_256){ - oaepSpec= new OAEPParameterSpec("SHA-256", "MGF1", - MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); - }else{ - oaepSpec= new OAEPParameterSpec("SHA1", "MGF1", - MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + if (digest == KMType.SHA2_256) { + oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + } else { + oaepSpec = new OAEPParameterSpec("SHA1", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); } rsaCipher = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPPadding", "SunJCE"); - if (mode == KMType.ENCRYPT){ + if (mode == KMType.ENCRYPT) { RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modInt, expInt); - java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf.generatePublic(pubSpec); + java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf + .generatePublic(pubSpec); rsaCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, pubKey, oaepSpec); } else { RSAPrivateKeySpec privSpec = new RSAPrivateKeySpec(modInt, expInt); - java.security.interfaces.RSAPrivateKey privKey = (java.security.interfaces.RSAPrivateKey) kf.generatePrivate(privSpec); + java.security.interfaces.RSAPrivateKey privKey = (java.security.interfaces.RSAPrivateKey) kf + .generatePrivate(privSpec); rsaCipher.init(javax.crypto.Cipher.DECRYPT_MODE, privKey, oaepSpec); } } catch (NoSuchAlgorithmException e) { @@ -709,70 +737,78 @@ private KMCipher createRsaOAEP256Cipher(byte mode,byte digest, ret.setMode(mode); return ret; } - private String toHexString(byte[] num){ + + private String toHexString(byte[] num) { StringBuilder sb = new StringBuilder(); - for(int i = 0; i < num.length; i++){ - sb.append(String.format("%02X", num[i])) ; - } + for (int i = 0; i < num.length; i++) { + sb.append(String.format("%02X", num[i])); + } return sb.toString(); } - + public Signature createRsaSigner(short digest, short padding, byte[] secret, - short secretStart, short secretLength, byte[] modBuffer, - short modOff, short modLength) { - short alg = mapSignature256Alg(KMType.RSA, (byte)padding); + short secretStart, short secretLength, byte[] modBuffer, + short modOff, short modLength) { + short alg = mapSignature256Alg(KMType.RSA, (byte) padding); if (padding == KMType.PADDING_NONE || - (padding == KMType.RSA_PKCS1_1_5_SIGN && digest == KMType.DIGEST_NONE)) { - return createNoDigestSigner(padding,secret, secretStart, secretLength, - modBuffer, modOff, modLength); + (padding == KMType.RSA_PKCS1_1_5_SIGN && digest == KMType.DIGEST_NONE)) { + return createNoDigestSigner(padding, secret, secretStart, secretLength, + modBuffer, modOff, modLength); } - Signature rsaSigner = Signature.getInstance((byte)alg, false); - RSAPrivateKey key = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048, false); - key.setExponent(secret,secretStart,secretLength); + Signature rsaSigner = Signature.getInstance((byte) alg, false); + RSAPrivateKey key = (RSAPrivateKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_RSA_PRIVATE, KeyBuilder.LENGTH_RSA_2048, false); + key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); - rsaSigner.init(key,Signature.MODE_SIGN); + rsaSigner.init(key, Signature.MODE_SIGN); return rsaSigner; } private Signature createNoDigestSigner(short padding, - byte[] secret, short secretStart, short secretLength, - byte[] modBuffer, short modOff, short modLength) { - Cipher rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD,false); + byte[] secret, short secretStart, short secretLength, + byte[] modBuffer, short modOff, short modLength) { + Cipher rsaCipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false); RSAPrivateKey key = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE, - KeyBuilder.LENGTH_RSA_2048, false); - key.setExponent(secret,secretStart,secretLength); + KeyBuilder.LENGTH_RSA_2048, false); + key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); - rsaCipher.init(key,Cipher.MODE_DECRYPT); - KMRsa2048NoDigestSignature inst = new KMRsa2048NoDigestSignature(rsaCipher,(byte)padding, - modBuffer,modOff,modLength); + rsaCipher.init(key, Cipher.MODE_DECRYPT); + KMRsa2048NoDigestSignature inst = new KMRsa2048NoDigestSignature(rsaCipher, (byte) padding, + modBuffer, modOff, modLength); return inst; } - - public Signature createEcSigner(short digest, byte[] secret, short secretStart, short secretLength) { - short alg = mapSignature256Alg(KMType.EC,(byte)0); - Signature ecSigner; - if(digest == KMType.DIGEST_NONE) { - ecSigner = new KMEcdsa256NoDigestSignature(Signature.MODE_SIGN, secret, secretStart, secretLength); - } else { - ECPrivateKey key = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false); - key.setS(secret,secretStart,secretLength); - ecSigner = Signature.getInstance((byte)alg,false); - ecSigner.init(key,Signature.MODE_SIGN); - } + + public Signature createEcSigner(short digest, byte[] secret, short secretStart, + short secretLength) { + short alg = mapSignature256Alg(KMType.EC, (byte) 0); + Signature ecSigner; + if (digest == KMType.DIGEST_NONE) { + ecSigner = new KMEcdsa256NoDigestSignature(Signature.MODE_SIGN, secret, secretStart, + secretLength); + } else { + ECPrivateKey key = (ECPrivateKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, KeyBuilder.LENGTH_EC_FP_256, false); + key.setS(secret, secretStart, secretLength); + ecSigner = Signature.getInstance((byte) alg, false); + ecSigner.init(key, Signature.MODE_SIGN); + } return ecSigner; } - + public KMCipher createSymmetricCipher( - short cipherAlg, short mode, short blockMode, short padding, byte[] secret, short secretStart, short secretLength) { - return createSymmetricCipher(cipherAlg, mode, blockMode, padding, secret,secretStart,secretLength,null,(short)0,(short)0); + short cipherAlg, short mode, short blockMode, short padding, byte[] secret, short secretStart, + short secretLength) { + return createSymmetricCipher(cipherAlg, mode, blockMode, padding, secret, secretStart, + secretLength, null, (short) 0, (short) 0); } - - public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, short padding, byte[] secret, - short secretStart, short secretLength, - byte[] ivBuffer, short ivStart, short ivLength) { + + public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, short padding, + byte[] secret, + short secretStart, short secretLength, + byte[] ivBuffer, short ivStart, short ivLength) { Key key = null; Cipher symmCipher = null; short len = 0; @@ -790,35 +826,36 @@ public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); break; } - short cipherAlg = mapCipherAlg((byte)alg,(byte)padding,(byte)blockMode); - switch(cipherAlg){ + short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode); + switch (cipherAlg) { case Cipher.ALG_AES_BLOCK_128_CBC_NOPAD: - key = KeyBuilder.buildKey(KeyBuilder.TYPE_AES,len,false); - ((AESKey) key).setKey(secret,secretStart); - symmCipher = Cipher.getInstance((byte)cipherAlg, false); + key = KeyBuilder.buildKey(KeyBuilder.TYPE_AES, len, false); + ((AESKey) key).setKey(secret, secretStart); + symmCipher = Cipher.getInstance((byte) cipherAlg, false); symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, ivLength); break; case Cipher.ALG_AES_BLOCK_128_ECB_NOPAD: - key = KeyBuilder.buildKey(KeyBuilder.TYPE_AES,len,false); - ((AESKey) key).setKey(secret,secretStart); - symmCipher = Cipher.getInstance((byte)cipherAlg, false); + key = KeyBuilder.buildKey(KeyBuilder.TYPE_AES, len, false); + ((AESKey) key).setKey(secret, secretStart); + symmCipher = Cipher.getInstance((byte) cipherAlg, false); symmCipher.init(key, mapPurpose(purpose)); break; case Cipher.ALG_DES_CBC_NOPAD: - key = KeyBuilder.buildKey(KeyBuilder.TYPE_DES,len,false); - ((DESKey) key).setKey(secret,secretStart); - symmCipher = Cipher.getInstance((byte)cipherAlg, false); + key = KeyBuilder.buildKey(KeyBuilder.TYPE_DES, len, false); + ((DESKey) key).setKey(secret, secretStart); + symmCipher = Cipher.getInstance((byte) cipherAlg, false); //While sending back the iv send only 8 bytes. - symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, (short)8); + symmCipher.init(key, mapPurpose(purpose), ivBuffer, ivStart, (short) 8); break; case Cipher.ALG_DES_ECB_NOPAD: - key = KeyBuilder.buildKey(KeyBuilder.TYPE_DES,len,false); - ((DESKey) key).setKey(secret,secretStart); - symmCipher = Cipher.getInstance((byte)cipherAlg, false); + key = KeyBuilder.buildKey(KeyBuilder.TYPE_DES, len, false); + ((DESKey) key).setKey(secret, secretStart); + symmCipher = Cipher.getInstance((byte) cipherAlg, false); symmCipher.init(key, mapPurpose(purpose)); break; case Cipher.ALG_AES_CTR: // uses SUNJCE - return createAesCtrCipherNoPad(purpose, secret,secretStart,secretLength,ivBuffer,ivStart,ivLength); + return createAesCtrCipherNoPad(purpose, secret, secretStart, secretLength, ivBuffer, + ivStart, ivLength); default://This should never happen CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); break; @@ -830,26 +867,27 @@ public KMCipher createSymmetricCipher(short alg, short purpose, short blockMode, cipher.setBlockMode(blockMode); return cipher; } - private byte mapPurpose(short purpose){ - switch(purpose){ + + private byte mapPurpose(short purpose) { + switch (purpose) { case KMType.ENCRYPT: return Cipher.MODE_ENCRYPT; case KMType.DECRYPT: return Cipher.MODE_DECRYPT; case KMType.SIGN: - return Signature.MODE_SIGN; + return Signature.MODE_SIGN; case KMType.VERIFY: return Signature.MODE_VERIFY; } return -1; } - private byte mapSignature256Alg(byte alg, byte padding){ - switch(alg){ + private byte mapSignature256Alg(byte alg, byte padding) { + switch (alg) { case KMType.RSA: - switch(padding){ + switch (padding) { case KMType.RSA_PKCS1_1_5_SIGN: - return Signature.ALG_RSA_SHA_256_PKCS1; + return Signature.ALG_RSA_SHA_256_PKCS1; case KMType.RSA_PSS: return Signature.ALG_RSA_SHA_256_PKCS1_PSS; } @@ -862,12 +900,12 @@ private byte mapSignature256Alg(byte alg, byte padding){ return -1; } - private byte mapCipherAlg(byte alg, byte padding, byte blockmode){ - switch(alg){ + private byte mapCipherAlg(byte alg, byte padding, byte blockmode) { + switch (alg) { case KMType.AES: - switch(blockmode){ + switch (blockmode) { case KMType.ECB: - return Cipher.ALG_AES_BLOCK_128_ECB_NOPAD; + return Cipher.ALG_AES_BLOCK_128_ECB_NOPAD; case KMType.CBC: return Cipher.ALG_AES_BLOCK_128_CBC_NOPAD; case KMType.CTR: @@ -877,7 +915,7 @@ private byte mapCipherAlg(byte alg, byte padding, byte blockmode){ } break; case KMType.DES: - switch(blockmode){ + switch (blockmode) { case KMType.ECB: return Cipher.ALG_DES_ECB_NOPAD; case KMType.CBC: @@ -885,7 +923,7 @@ private byte mapCipherAlg(byte alg, byte padding, byte blockmode){ } break; case KMType.RSA: - switch(padding){ + switch (padding) { case KMType.PADDING_NONE: return Cipher.ALG_RSA_NOPAD; case KMType.RSA_PKCS1_1_5_ENCRYPT: @@ -898,20 +936,21 @@ private byte mapCipherAlg(byte alg, byte padding, byte blockmode){ return -1; } - private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secretStart, short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { - if(secretLength != 16 && secretLength != 32){ + private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secretStart, + short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { + if (secretLength != 16 && secretLength != 32) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - if(ivLength != 16){ + if (ivLength != 16) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - if(mode != KMType.ENCRYPT && mode != KMType.DECRYPT){ + if (mode != KMType.ENCRYPT && mode != KMType.DECRYPT) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } //Create the sun jce compliant aes key byte[] keyMaterial = new byte[secretLength]; - Util.arrayCopyNonAtomic(secret,secretStart,keyMaterial,(short)0,secretLength); - java.security.Key aesKey = new SecretKeySpec(keyMaterial,(short)0,keyMaterial.length, "AES"); + Util.arrayCopyNonAtomic(secret, secretStart, keyMaterial, (short) 0, secretLength); + java.security.Key aesKey = new SecretKeySpec(keyMaterial, (short) 0, keyMaterial.length, "AES"); // Create the cipher javax.crypto.Cipher cipher = null; try { @@ -928,12 +967,15 @@ private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secret } // Copy nonce byte[] iv = new byte[ivLength]; - Util.arrayCopyNonAtomic(ivBuffer,ivStart,iv,(short)0,ivLength); + Util.arrayCopyNonAtomic(ivBuffer, ivStart, iv, (short) 0, ivLength); // Init Cipher IvParameterSpec ivSpec = new IvParameterSpec(iv); try { - if(mode == KMType.ENCRYPT) cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, aesKey, ivSpec); - else cipher.init(javax.crypto.Cipher.DECRYPT_MODE, aesKey, ivSpec); + if (mode == KMType.ENCRYPT) { + cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, aesKey, ivSpec); + } else { + cipher.init(javax.crypto.Cipher.DECRYPT_MODE, aesKey, ivSpec); + } } catch (InvalidKeyException e) { e.printStackTrace(); CryptoException.throwIt(CryptoException.INVALID_INIT); @@ -944,38 +986,43 @@ private KMCipher createAesCtrCipherNoPad(short mode, byte[] secret, short secret KMCipherImpl ret = new KMCipherImpl(cipher); ret.setCipherAlgorithm(KMType.AES); ret.setMode(mode); - ret.setPaddingAlgorithm((short)0); + ret.setPaddingAlgorithm((short) 0); ret.setBlockMode(KMType.CTR); return ret; } - - public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, short secretStart, short secretLength) { + + public Signature createHmacSignerVerifier(short purpose, short digest, byte[] secret, + short secretStart, short secretLength) { short alg = Signature.ALG_HMAC_SHA_256; - if(digest != KMType.SHA2_256) CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); - Signature hmacSignerVerifier = Signature.getInstance((byte)alg,false); - HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short)(secretLength*8), false); - key.setKey(secret,secretStart,secretLength); - hmacSignerVerifier.init(key,(byte)purpose); + if (digest != KMType.SHA2_256) { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + Signature hmacSignerVerifier = Signature.getInstance((byte) alg, false); + HMACKey key = (HMACKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_HMAC, (short) (secretLength * 8), false); + key.setKey(secret, secretStart, secretLength); + hmacSignerVerifier.init(key, (byte) purpose); return hmacSignerVerifier; } - - public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, short secretStart, short secretLength, - byte[] ivBuffer, short ivStart, short ivLength) { - if(secretLength != 16 && secretLength != 32){ + + public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, short secretStart, + short secretLength, + byte[] ivBuffer, short ivStart, short ivLength) { + if (secretLength != 16 && secretLength != 32) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - if(ivLength != AES_GCM_NONCE_LENGTH){ + if (ivLength != AES_GCM_NONCE_LENGTH) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - if(mode != KMType.ENCRYPT && mode != KMType.DECRYPT){ + if (mode != KMType.ENCRYPT && mode != KMType.DECRYPT) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } //Create the sun jce compliant aes key byte[] keyMaterial = new byte[secretLength]; - Util.arrayCopyNonAtomic(secret,secretStart,keyMaterial,(short)0,secretLength); - java.security.Key aesKey = new SecretKeySpec(keyMaterial,(short)0,keyMaterial.length, "AES"); + Util.arrayCopyNonAtomic(secret, secretStart, keyMaterial, (short) 0, secretLength); + java.security.Key aesKey = new SecretKeySpec(keyMaterial, (short) 0, keyMaterial.length, "AES"); // Create the cipher javax.crypto.Cipher cipher = null; try { @@ -992,12 +1039,15 @@ public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, shor } // Copy nonce byte[] iv = new byte[AES_GCM_NONCE_LENGTH]; - Util.arrayCopyNonAtomic(ivBuffer,ivStart,iv,(short)0,AES_GCM_NONCE_LENGTH); + Util.arrayCopyNonAtomic(ivBuffer, ivStart, iv, (short) 0, AES_GCM_NONCE_LENGTH); // Init Cipher - GCMParameterSpec spec = new GCMParameterSpec(tagLen, iv,(short)0,AES_GCM_NONCE_LENGTH); + GCMParameterSpec spec = new GCMParameterSpec(tagLen, iv, (short) 0, AES_GCM_NONCE_LENGTH); try { - if(mode == KMType.ENCRYPT)mode = javax.crypto.Cipher.ENCRYPT_MODE; - else mode = javax.crypto.Cipher.DECRYPT_MODE; + if (mode == KMType.ENCRYPT) { + mode = javax.crypto.Cipher.ENCRYPT_MODE; + } else { + mode = javax.crypto.Cipher.DECRYPT_MODE; + } cipher.init(mode, aesKey, spec); } catch (InvalidKeyException e) { e.printStackTrace(); @@ -1009,7 +1059,7 @@ public KMCipher createAesGcmCipher(short mode, short tagLen, byte[] secret, shor KMCipherImpl ret = new KMCipherImpl(cipher); ret.setCipherAlgorithm(KMType.AES); ret.setMode(mode); - ret.setPaddingAlgorithm((short)0); + ret.setPaddingAlgorithm((short) 0); ret.setBlockMode(KMType.GCM); return ret; } @@ -1046,7 +1096,9 @@ public void newRandomNumber(byte[] num, short startOff, short length) { aesRngKey.setKey(entropyPool, (short) 0); aesRngCipher.init(aesRngKey, Cipher.MODE_ENCRYPT, aesICV, (short) 0, (short) 16); while (length > 0) { - if (length < len) len = length; + if (length < len) { + len = length; + } // increment rngCounter by one incrementCounter(); // copy the 8 byte rngCounter into the 16 byte rngCounter buffer. @@ -1071,8 +1123,11 @@ private void incrementCounter() { // then increment the rngCounter rngCounter[index]++; // is the msb still set? i.e. no carry over - if (rngCounter[index] < 0) break; // then break - else index--; // else go to the higher order byte + if (rngCounter[index] < 0) { + break; // then break + } else { + index--; // else go to the higher order byte + } } else { // if msb is not set then increment the rngCounter rngCounter[index]++; @@ -1085,7 +1140,9 @@ private void incrementCounter() { public void addRngEntropy(byte[] num, short offset, short length) { // Maximum length can be 256 bytes. But currently we support max 32 bytes seed. // Get existing entropy pool. - if (length > 32) length = 32; + if (length > 32) { + length = 32; + } // Create new temporary pool. // Populate the new pool with the entropy which is derived from current entropy pool. newRandomNumber(rndNum, (short) 0, (short) entropyPool.length); @@ -1111,14 +1168,14 @@ public KMAttestationCert getAttestationCert(boolean rsaCert) { } public short readCertificateChain(byte[] buf, short offset) { - short len = Util.getShort(certificateChain, (short)0); - Util.arrayCopyNonAtomic(certificateChain, (short)2, buf, offset, len); + short len = Util.getShort(certificateChain, (short) 0); + Util.arrayCopyNonAtomic(certificateChain, (short) 2, buf, offset, len); return len; } @Override public short getCertificateChainLength() { - return Util.getShort(certificateChain, (short)0); + return Util.getShort(certificateChain, (short) 0); } @Override @@ -1126,7 +1183,7 @@ public short ecSign256(KMAttestationKey attestationKey, byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { - ECPrivateKey key = ((KMECPrivateKey)attestationKey).getPrivateKey(); + ECPrivateKey key = ((KMECPrivateKey) attestationKey).getPrivateKey(); Signature signer = Signature .getInstance(Signature.ALG_ECDSA_SHA_256, false); @@ -1138,7 +1195,7 @@ public short ecSign256(KMAttestationKey attestationKey, @Override public void clearCertificateChain() { JCSystem.beginTransaction(); - Util.arrayFillNonAtomic(certificateChain, (short)0, CERT_CHAIN_MAX_SIZE, (byte) 0); + Util.arrayFillNonAtomic(certificateChain, (short) 0, CERT_CHAIN_MAX_SIZE, (byte) 0); JCSystem.commitTransaction(); } @@ -1163,7 +1220,7 @@ public void persistPartialCertificateChain(byte[] buf, short offset, JCSystem.beginTransaction(); Util.setShort(certificateChain, (short) 0, (short) (len + persistedLen)); Util.arrayCopyNonAtomic(buf, offset, certificateChain, - (short) (persistedLen+2), len); + (short) (persistedLen + 2), len); JCSystem.commitTransaction(); } @@ -1208,10 +1265,10 @@ public boolean isUpgrading() { public KMMasterKey createMasterKey(short keySizeBits) { if (masterKey == null) { AESKey key = (AESKey) KeyBuilder.buildKey( - KeyBuilder.TYPE_AES, keySizeBits, false); + KeyBuilder.TYPE_AES, keySizeBits, false); masterKey = new KMAESKey(key); short keyLen = (short) (keySizeBits / 8); - byte[] keyData = new byte[keyLen]; + byte[] keyData = new byte[keyLen]; getTrueRandomNumber(keyData, (short) 0, keyLen); masterKey.setKey(keyData, (short) 0); } @@ -1220,7 +1277,7 @@ public KMMasterKey createMasterKey(short keySizeBits) { @Override public KMAttestationKey createAttestationKey(byte[] keyData, short offset, - short length) { + short length) { if (attestationKey == null) { // Strongbox supports only P-256 curve for EC key. KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -1232,13 +1289,13 @@ public KMAttestationKey createAttestationKey(byte[] keyData, short offset, @Override public KMPreSharedKey createPresharedKey(byte[] keyData, short offset, short length) { - short lengthInBits = (short)(length * 8); + short lengthInBits = (short) (length * 8); if ((lengthInBits % 8 != 0) || !(lengthInBits >= 64 && lengthInBits <= 512)) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } if (preSharedKey == null) { HMACKey key = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, lengthInBits, - false); + false); preSharedKey = new KMHmacKey(key); } preSharedKey.setKey(keyData, offset, length); diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMOperationImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMOperationImpl.java index 78c01302..761b388a 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMOperationImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMOperationImpl.java @@ -18,43 +18,51 @@ import javacard.security.Signature; public class KMOperationImpl implements KMOperation { + private KMCipher cipher; private Signature signature; - public KMOperationImpl(KMCipher cipher){ + public KMOperationImpl(KMCipher cipher) { this.cipher = cipher; this.signature = null; } - public KMOperationImpl(Signature sign){ + public KMOperationImpl(Signature sign) { this.cipher = null; this.signature = sign; } @Override public short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] outputDataBuf, short outputDataStart) { - return cipher.update(inputDataBuf,inputDataStart,inputDataLength,outputDataBuf,outputDataStart); + byte[] outputDataBuf, short outputDataStart) { + return cipher + .update(inputDataBuf, inputDataStart, inputDataLength, outputDataBuf, outputDataStart); } + @Override public short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength) { - signature.update(inputDataBuf,inputDataStart,inputDataLength); - return 0; + signature.update(inputDataBuf, inputDataStart, inputDataLength); + return 0; } @Override - public short finish(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { - return cipher.doFinal(inputDataBuf,inputDataStart,inputDataLength,outputDataBuf,outputDataStart); + public short finish(byte[] inputDataBuf, short inputDataStart, short inputDataLength, + byte[] outputDataBuf, short outputDataStart) { + return cipher + .doFinal(inputDataBuf, inputDataStart, inputDataLength, outputDataBuf, outputDataStart); } @Override - public short sign(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] signBuf, short signStart) { - return signature.sign(inputDataBuf,inputDataStart,inputDataLength,signBuf,signStart); + public short sign(byte[] inputDataBuf, short inputDataStart, short inputDataLength, + byte[] signBuf, short signStart) { + return signature.sign(inputDataBuf, inputDataStart, inputDataLength, signBuf, signStart); } @Override - public boolean verify(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] signBuf, short signStart, short signLength) { - return signature.verify(inputDataBuf,inputDataStart,inputDataLength,signBuf,signStart,signLength); + public boolean verify(byte[] inputDataBuf, short inputDataStart, short inputDataLength, + byte[] signBuf, short signStart, short signLength) { + return signature + .verify(inputDataBuf, inputDataStart, inputDataLength, signBuf, signStart, signLength); } @Override diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java index de97d02c..573be574 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMRsa2048NoDigestSignature.java @@ -22,16 +22,19 @@ import javacardx.crypto.Cipher; public class KMRsa2048NoDigestSignature extends Signature { + private Cipher inst; // ALG_RSA_NOPAD. private byte padding; private byte[] rsaModulus; // to compare with the data value - public KMRsa2048NoDigestSignature(Cipher ciph, byte padding, byte[]mod, short start, short len){ + public KMRsa2048NoDigestSignature(Cipher ciph, byte padding, byte[] mod, short start, short len) { inst = ciph; this.padding = padding; - if(len != 256) CryptoException.throwIt(CryptoException.INVALID_INIT); + if (len != 256) { + CryptoException.throwIt(CryptoException.INVALID_INIT); + } rsaModulus = new byte[256]; - Util.arrayCopyNonAtomic(mod,start,rsaModulus,(short)0,len); + Util.arrayCopyNonAtomic(mod, start, rsaModulus, (short) 0, len); } @Override @@ -44,7 +47,8 @@ public void init(Key key, byte b, byte[] bytes, short i, short i1) throws Crypto } @Override - public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) + throws CryptoException { } @Override @@ -77,30 +81,34 @@ public void update(byte[] bytes, short i, short i1) throws CryptoException { } @Override - public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException { - byte[] inputData = padData(bytes,i,i1); - return inst.doFinal(inputData,(short)0,(short)256,bytes1,i2); + public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2) + throws CryptoException { + byte[] inputData = padData(bytes, i, i1); + return inst.doFinal(inputData, (short) 0, (short) 256, bytes1, i2); } @Override - public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2) throws CryptoException { + public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2) + throws CryptoException { return 0; } @Override - public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) + throws CryptoException { // Public key operations not handled here. return false; } @Override - public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException { + public boolean verifyPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2, + short i3) throws CryptoException { return false; } - private byte[] padData(byte[] buf, short start, short len){ + private byte[] padData(byte[] buf, short start, short len) { byte[] inputData = new byte[256]; - if(!isValidData(buf, start,len)){ + if (!isValidData(buf, start, len)) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } Util.arrayFillNonAtomic(inputData, (short) 0, (short) 256, (byte) 0x00); @@ -108,24 +116,27 @@ private byte[] padData(byte[] buf, short start, short len){ } else if (padding == KMType.RSA_PKCS1_1_5_SIGN) {// 0x00||0x01||PS||0x00 inputData[0] = 0x00; inputData[1] = 0x01; - Util.arrayFillNonAtomic(inputData,(short)2,(short)(256-len-3),(byte)0xFF); - inputData[(short)(256-len-1)] = 0x00; - }else{ + Util.arrayFillNonAtomic(inputData, (short) 2, (short) (256 - len - 3), (byte) 0xFF); + inputData[(short) (256 - len - 1)] = 0x00; + } else { CryptoException.throwIt(CryptoException.ILLEGAL_USE); } - Util.arrayCopyNonAtomic(buf,start,inputData,(short)(256 -len),len); + Util.arrayCopyNonAtomic(buf, start, inputData, (short) (256 - len), len); return inputData; } private boolean isValidData(byte[] buf, short start, short len) { if (padding == KMType.PADDING_NONE) { - if (len > 256) return false; - else if (len == 256) { + if (len > 256) { + return false; + } else if (len == 256) { short v = KMInteger.unsignedByteArrayCompare(buf, start, rsaModulus, (short) 0, len); - if (v > 0) return false; + if (v > 0) { + return false; + } } } else {//pkcs1 no digest - if(len > 245){ + if (len > 245) { return false; } } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index 2e72ae6d..c2b5c7f3 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -18,43 +18,44 @@ import javacard.framework.Util; public class KMUtils { + // 64 bit unsigned calculations for time public static final byte[] oneSecMsec = { - 0, 0, 0, 0, 0, 0, 0x03, (byte) 0xE8 }; // 1000 msec + 0, 0, 0, 0, 0, 0, 0x03, (byte) 0xE8}; // 1000 msec public static final byte[] oneMinMsec = { - 0, 0, 0, 0, 0, 0, (byte) 0xEA, 0x60 }; // 60000 msec + 0, 0, 0, 0, 0, 0, (byte) 0xEA, 0x60}; // 60000 msec public static final byte[] oneHourMsec = { - 0, 0, 0, 0, 0, 0x36, (byte) 0xEE, (byte) 0x80 }; // 3600000 msec + 0, 0, 0, 0, 0, 0x36, (byte) 0xEE, (byte) 0x80}; // 3600000 msec public static final byte[] oneDayMsec = { - 0, 0, 0, 0, 0x05, 0x26, 0x5C, 0x00 }; // 86400000 msec + 0, 0, 0, 0, 0x05, 0x26, 0x5C, 0x00}; // 86400000 msec public static final byte[] oneMonthMsec = { - 0, 0, 0, 0, (byte) 0x9C,(byte) 0xBE, (byte) 0xBD, 0x50}; // 2629746000 msec - public static final byte[] leapYearMsec = { - 0, 0, 0, 0x07, (byte) 0x5C, (byte) 0xD7, (byte) 0x88, 0x00}; //31622400000; + 0, 0, 0, 0, (byte) 0x9C, (byte) 0xBE, (byte) 0xBD, 0x50}; // 2629746000 msec + public static final byte[] leapYearMsec = { + 0, 0, 0, 0x07, (byte) 0x5C, (byte) 0xD7, (byte) 0x88, 0x00}; //31622400000; public static final byte[] yearMsec = { - 0, 0, 0, 0x07, 0x57, (byte) 0xB1, 0x2C, 0x00}; //31536000000 + 0, 0, 0, 0x07, 0x57, (byte) 0xB1, 0x2C, 0x00}; //31536000000 //Leap year(366) + 3 * 365 public static final byte[] fourYrsMsec = { - 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 + 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 public static final byte[] firstJan2020 = { - 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte)0xE8, 0x00 }; // 1577836800000 msec + 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte) 0xE8, 0x00}; // 1577836800000 msec public static final byte[] firstJan2051 = { - 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00 }; // 2556144000000 - // msec + 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00}; // 2556144000000 + // msec public static final byte[] febMonthLeapMSec = { - 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00 }; //2505600000 + 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00}; //2505600000 public static final byte[] febMonthMsec = { - 0, 0, 0, 0, (byte) 0x90, 0x32, 0x10, 0x00 }; //2419200000 + 0, 0, 0, 0, (byte) 0x90, 0x32, 0x10, 0x00}; //2419200000 public static final byte[] ThirtyOneDaysMonthMsec = { - 0, 0, 0, 0, (byte) 0x9F, (byte) 0xA5, 0x24, 0x00 };//2678400000 + 0, 0, 0, 0, (byte) 0x9F, (byte) 0xA5, 0x24, 0x00};//2678400000 public static final byte[] ThirtDaysMonthMsec = { - 0, 0, 0, 0, (byte) 0x9A, 0x7E, (byte) 0xC8, 0x00 };//2592000000 + 0, 0, 0, 0, (byte) 0x9A, 0x7E, (byte) 0xC8, 0x00};//2592000000 public static final short year2051 = 2051; public static final short year2020 = 2020; // -------------------------------------- public static short convertToDate(short time, byte[] scratchPad, - boolean utcFlag) { + boolean utcFlag) { short yrsCount = 0; short monthCount = 1; @@ -66,48 +67,48 @@ public static short convertToDate(short time, byte[] scratchPad, boolean from2020 = true; Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); Util.arrayCopyNonAtomic(KMInteger.cast(time).getBuffer(), - KMInteger.cast(time).getStartOff(), scratchPad, - (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) - .length()); + KMInteger.cast(time).getStartOff(), scratchPad, + (short) (8 - KMInteger.cast(time).length()), KMInteger.cast(time) + .length()); // If the time is less then 1 Jan 2020 then it is an error if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2020, (short) 0, - (short) 8) < 0) { + (short) 8) < 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, - (short) 0, (short) 8) >= 0) { + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, - (short) 8) < 0) { + (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } else { from2020 = false; Util.arrayCopyNonAtomic(firstJan2051, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with four yrs msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, fourYrsMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(fourYrsMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); yrsCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); // quotient - // is - // multiple - // of 4 + // is + // multiple + // of 4 yrsCount = (short) (yrsCount * 4); // number of yrs. // copy reminder as new dividend Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } //Get the leap year index starting from the (base Year + yrsCount) Year. @@ -116,29 +117,33 @@ public static short convertToDate(short time, byte[] scratchPad, // if leap year index is 0, then the number of days for the 1st year will be 366 days. // if leap year index is not 0, then the number of days for the 1st year will be 365 days. if (((leapYrIdx == 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0,(short) 8) >= 0)) || - ((leapYrIdx != 0) && - (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0,(short) 8) >= 0))) { + (KMInteger + .unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, (short) 0, (short) 8) + >= 0)) || + ((leapYrIdx != 0) && + (KMInteger + .unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, (short) 0, (short) 8) + >= 0))) { for (short i = 0; i < 4; i++) { yrsCount++; if (i == leapYrIdx) { Util.arrayCopyNonAtomic(leapYearMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } else { Util.arrayCopyNonAtomic(yearMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); } subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); if (((short) (i + 1) == leapYrIdx)) { if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, leapYearMsec, - (short) 0, (short) 8) < 0) { + (short) 0, (short) 8) < 0) { break; } } else { if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, yearMsec, - (short) 0, (short) 8) < 0) { + (short) 0, (short) 8) < 0) { break; } } @@ -146,40 +151,41 @@ public static short convertToDate(short time, byte[] scratchPad, } // total yrs from 1970 - if (from2020) + if (from2020) { yrsCount = (short) (year2020 + yrsCount); - else + } else { yrsCount = (short) (year2051 + yrsCount); + } // divide the given time with one month msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMonthMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { for (short i = 0; i < 12; i++) { if (i == 1) { // Feb month if (isLeapYear(yrsCount)) { // Leap year 29 days Util.arrayCopyNonAtomic(febMonthLeapMSec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } else { // 28 days Util.arrayCopyNonAtomic(febMonthMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } } else if (((i <= 6) && ((i % 2 == 0))) || ((i > 6) && ((i % 2 == 1)))) { Util.arrayCopyNonAtomic(ThirtyOneDaysMonthMsec, (short) 0, - scratchPad, (short) 8, (short) 8); + scratchPad, (short) 8, (short) 8); } else { // 30 Days Util.arrayCopyNonAtomic(ThirtDaysMonthMsec, (short) 0, scratchPad, - (short) 8, (short) 8); + (short) 8, (short) 8); } if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, scratchPad, (short) 8, - (short) 8) >= 0) { + (short) 8) >= 0) { subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } else { break; } @@ -189,43 +195,43 @@ public static short convertToDate(short time, byte[] scratchPad, // divide the given time with one day msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneDayMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneDayMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); dayCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); dayCount++; Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one hour msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneHourMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneHourMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); hhCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one minute msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneMinMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneMinMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); mmCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // divide the given time with one second msec count if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, oneSecMsec, (short) 0, - (short) 8) >= 0) { + (short) 8) >= 0) { Util.arrayCopyNonAtomic(oneSecMsec, (short) 0, scratchPad, (short) 8, - (short) 8); + (short) 8); ssCount = divide(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, - (short) 8); + (short) 8); } // Now convert to ascii string YYMMDDhhmmssZ or YYYYMMDDhhmmssZ @@ -238,19 +244,21 @@ public static short convertToDate(short time, byte[] scratchPad, len += numberToString(ssCount, scratchPad, len); scratchPad[len] = Z; len++; - if (utcFlag) + if (utcFlag) { return KMByteBlob.instance(scratchPad, (short) 2, (short) (len - 2)); // YY - else + } else { return KMByteBlob.instance(scratchPad, (short) 0, len); // YYYY + } } public static short numberToString(short number, byte[] scratchPad, - short offset) { + short offset) { byte zero = 0x30; byte len = 2; byte digit; - if (number > 999) + if (number > 999) { len = 4; + } byte index = len; while (index > 0) { digit = (byte) (number % 10); @@ -265,7 +273,7 @@ public static short numberToString(short number, byte[] scratchPad, // i.e. dividend - quotient*divisor = remainder where remainder < divisor. // so this is division by subtraction until remainder remains. public static short divide(byte[] buf, short dividend, short divisor, - short remainder) { + short remainder) { short expCnt = 1; short q = 0; // first increase divisor so that it becomes greater then dividend. @@ -303,10 +311,11 @@ public static void shiftLeft(byte[] buf, short start) { tmp = buf[(short) (start + index)]; buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] << 1); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] + carry); - if (tmp < 0) + if (tmp < 0) { carry = 1; - else + } else { carry = 0; + } index--; } } @@ -320,10 +329,11 @@ public static void shiftRight(byte[] buf, short start) { buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] >> 1); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] & 0x7F); buf[(short) (start + index)] = (byte) (buf[(short) (start + index)] | carry); - if (tmp == 1) + if (tmp == 1) { carry = (byte) 0x80; - else + } else { carry = 0; + } index++; } } @@ -335,8 +345,9 @@ public static void add(byte[] buf, short op1, short op2, short result) { while (index >= 0) { tmp = (short) (buf[(short) (op1 + index)] + buf[(short) (op2 + index)] + carry); carry = 0; - if (tmp > 255) + if (tmp > 255) { carry = 1; // max unsigned byte value is 255 + } buf[(short) (result + index)] = (byte) (tmp & (byte) 0xFF); index--; } @@ -362,25 +373,25 @@ public static void subtract(byte[] buf, short op1, short op2, short result) { index--; } } - + public static short countTemporalCount(byte[] bufTime, short timeOff, - short timeLen, byte[] scratchPad, short offset) { + short timeLen, byte[] scratchPad, short offset) { Util.arrayFillNonAtomic(scratchPad, (short) offset, (short) 24, (byte) 0); Util.arrayCopyNonAtomic( - bufTime, - timeOff, - scratchPad, - (short) (offset + 8 - timeLen), - timeLen); + bufTime, + timeOff, + scratchPad, + (short) (offset + 8 - timeLen), + timeLen); Util.arrayCopyNonAtomic(oneMonthMsec, (short) 0, scratchPad, (short) (offset + 8), - (short) 8); + (short) 8); return divide(scratchPad, (short) 0, (short) 8, (short) 16); } public static boolean isLeapYear(short year) { - if ((short)(year%4) == (short) 0) { - if (((short)(year % 100) == (short) 0) && - ((short) (year % 400)) != (short) 0) { + if ((short) (year % 4) == (short) 0) { + if (((short) (year % 100) == (short) 0) && + ((short) (year % 400)) != (short) 0) { return false; } return true; @@ -390,8 +401,8 @@ public static boolean isLeapYear(short year) { public static short getLeapYrIndex(boolean from2020, short yrsCount) { short newBaseYr = (short) (from2020 ? (year2020 + yrsCount) : (year2051 + yrsCount)); - for(short i = 0; i < 4; i++) { - if(isLeapYear((short)(newBaseYr + i))) { + for (short i = 0; i < 4; i++) { + if (isLeapYear((short) (newBaseYr + i))) { return i; } } diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 3e0653eb..2a17d5fa 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -82,6 +82,7 @@ import org.junit.Test; public class KMFunctionalTest { + private static final byte INS_BEGIN_KM_CMD = 0x00; private static final byte INS_PROVISION_ATTESTATION_KEY_CMD = INS_BEGIN_KM_CMD + 1; //0x01 private static final byte INS_PROVISION_ATTESTATION_CERT_CHAIN_CMD = INS_BEGIN_KM_CMD + 2; //0x02 @@ -118,314 +119,314 @@ public class KMFunctionalTest { private static final byte INS_GET_CERT_CHAIN_CMD = INS_END_KM_PROVISION_CMD + 22; //0x36 private static final byte[] kEcPrivKey = { - (byte) 0x21, (byte) 0xe0, (byte) 0x86, (byte) 0x43, (byte) 0x2a, - (byte) 0x15, (byte) 0x19, (byte) 0x84, (byte) 0x59, (byte) 0xcf, - (byte) 0x36, (byte) 0x3a, (byte) 0x50, (byte) 0xfc, (byte) 0x14, - (byte) 0xc9, (byte) 0xda, (byte) 0xad, (byte) 0xf9, (byte) 0x35, - (byte) 0xf5, (byte) 0x27, (byte) 0xc2, (byte) 0xdf, (byte) 0xd7, - (byte) 0x1e, (byte) 0x4d, (byte) 0x6d, (byte) 0xbc, (byte) 0x42, - (byte) 0xe5, (byte) 0x44 }; + (byte) 0x21, (byte) 0xe0, (byte) 0x86, (byte) 0x43, (byte) 0x2a, + (byte) 0x15, (byte) 0x19, (byte) 0x84, (byte) 0x59, (byte) 0xcf, + (byte) 0x36, (byte) 0x3a, (byte) 0x50, (byte) 0xfc, (byte) 0x14, + (byte) 0xc9, (byte) 0xda, (byte) 0xad, (byte) 0xf9, (byte) 0x35, + (byte) 0xf5, (byte) 0x27, (byte) 0xc2, (byte) 0xdf, (byte) 0xd7, + (byte) 0x1e, (byte) 0x4d, (byte) 0x6d, (byte) 0xbc, (byte) 0x42, + (byte) 0xe5, (byte) 0x44}; private static final byte[] kEcPubKey = { - (byte) 0x04, (byte) 0xeb, (byte) 0x9e, (byte) 0x79, (byte) 0xf8, - (byte) 0x42, (byte) 0x63, (byte) 0x59, (byte) 0xac, (byte) 0xcb, - (byte) 0x2a, (byte) 0x91, (byte) 0x4c, (byte) 0x89, (byte) 0x86, - (byte) 0xcc, (byte) 0x70, (byte) 0xad, (byte) 0x90, (byte) 0x66, - (byte) 0x93, (byte) 0x82, (byte) 0xa9, (byte) 0x73, (byte) 0x26, - (byte) 0x13, (byte) 0xfe, (byte) 0xac, (byte) 0xcb, (byte) 0xf8, - (byte) 0x21, (byte) 0x27, (byte) 0x4c, (byte) 0x21, (byte) 0x74, - (byte) 0x97, (byte) 0x4a, (byte) 0x2a, (byte) 0xfe, (byte) 0xa5, - (byte) 0xb9, (byte) 0x4d, (byte) 0x7f, (byte) 0x66, (byte) 0xd4, - (byte) 0xe0, (byte) 0x65, (byte) 0x10, (byte) 0x66, (byte) 0x35, - (byte) 0xbc, (byte) 0x53, (byte) 0xb7, (byte) 0xa0, (byte) 0xa3, - (byte) 0xa6, (byte) 0x71, (byte) 0x58, (byte) 0x3e, (byte) 0xdb, - (byte) 0x3e, (byte) 0x11, (byte) 0xae, (byte) 0x10, (byte) 0x14 }; + (byte) 0x04, (byte) 0xeb, (byte) 0x9e, (byte) 0x79, (byte) 0xf8, + (byte) 0x42, (byte) 0x63, (byte) 0x59, (byte) 0xac, (byte) 0xcb, + (byte) 0x2a, (byte) 0x91, (byte) 0x4c, (byte) 0x89, (byte) 0x86, + (byte) 0xcc, (byte) 0x70, (byte) 0xad, (byte) 0x90, (byte) 0x66, + (byte) 0x93, (byte) 0x82, (byte) 0xa9, (byte) 0x73, (byte) 0x26, + (byte) 0x13, (byte) 0xfe, (byte) 0xac, (byte) 0xcb, (byte) 0xf8, + (byte) 0x21, (byte) 0x27, (byte) 0x4c, (byte) 0x21, (byte) 0x74, + (byte) 0x97, (byte) 0x4a, (byte) 0x2a, (byte) 0xfe, (byte) 0xa5, + (byte) 0xb9, (byte) 0x4d, (byte) 0x7f, (byte) 0x66, (byte) 0xd4, + (byte) 0xe0, (byte) 0x65, (byte) 0x10, (byte) 0x66, (byte) 0x35, + (byte) 0xbc, (byte) 0x53, (byte) 0xb7, (byte) 0xa0, (byte) 0xa3, + (byte) 0xa6, (byte) 0x71, (byte) 0x58, (byte) 0x3e, (byte) 0xdb, + (byte) 0x3e, (byte) 0x11, (byte) 0xae, (byte) 0x10, (byte) 0x14}; private static final byte[] kEcAttestCert = { - 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x30, (byte) 0x82, - (byte) 0x02, (byte) 0x1e, (byte) 0xa0, (byte) 0x03, (byte) 0x02, - (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x10, 0x01, - (byte) 0x30, (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, - (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, - (byte) 0x03, (byte) 0x02, (byte) 0x30, (byte) 0x81, (byte) 0x98, 0x31, - (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, - (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, - (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, 0x11, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, - (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, - (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, 0x69, - (byte) 0x61, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, - (byte) 0x0c, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f, (byte) 0x75, 0x6e, - (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x20, - (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, - (byte) 0x15, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x03, 0x55, - (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, - (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, - (byte) 0x2c, (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, 0x2e, - (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b, (byte) 0x0c, - (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, 0x6f, - (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x33, (byte) 0x30, - (byte) 0x31, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, - (byte) 0x03, (byte) 0x0c, (byte) 0x2a, (byte) 0x41, (byte) 0x6e, 0x64, - (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, - (byte) 0x4b, (byte) 0x65, (byte) 0x79, (byte) 0x73, (byte) 0x74, - (byte) 0x6f, (byte) 0x72, (byte) 0x65, (byte) 0x20, (byte) 0x53, 0x6f, - (byte) 0x66, (byte) 0x74, (byte) 0x77, (byte) 0x61, (byte) 0x72, - (byte) 0x65, (byte) 0x20, (byte) 0x41, (byte) 0x74, (byte) 0x74, - (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x61, (byte) 0x74, 0x69, - (byte) 0x6f, (byte) 0x6e, (byte) 0x20, (byte) 0x52, (byte) 0x6f, - (byte) 0x6f, (byte) 0x74, (byte) 0x30, (byte) 0x1e, (byte) 0x17, - (byte) 0x0d, (byte) 0x31, (byte) 0x36, (byte) 0x30, (byte) 0x31, 0x31, - (byte) 0x31, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x36, - (byte) 0x30, (byte) 0x39, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, - (byte) 0x32, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x30, 0x38, - (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x36, (byte) 0x30, - (byte) 0x39, (byte) 0x5a, (byte) 0x30, (byte) 0x81, (byte) 0x88, - (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, 0x03, - (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, - (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, - (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 0x08, - (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, - (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, - (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x15, (byte) 0x30, 0x13, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, - (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, - (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2c, (byte) 0x20, 0x49, - (byte) 0x6e, (byte) 0x63, (byte) 0x2e, (byte) 0x31, (byte) 0x10, - (byte) 0x30, (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, - (byte) 0x04, (byte) 0x0b, (byte) 0x0c, (byte) 0x07, (byte) 0x41, 0x6e, - (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, - (byte) 0x31, (byte) 0x3b, (byte) 0x30, (byte) 0x39, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c, 0x32, - (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, - (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, - (byte) 0x79, (byte) 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, 0x65, - (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, - (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, - (byte) 0x41, (byte) 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, 0x74, - (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, - (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x74, (byte) 0x65, - (byte) 0x72, (byte) 0x6d, (byte) 0x65, (byte) 0x64, (byte) 0x69, 0x61, - (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x59, (byte) 0x30, - (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a, (byte) 0x86, - (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x02, (byte) 0x01, 0x06, - (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0xce, - (byte) 0x3d, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x03, - (byte) 0x42, (byte) 0x00, (byte) 0x04, (byte) 0xeb, (byte) 0x9e, 0x79, - (byte) 0xf8, (byte) 0x42, (byte) 0x63, (byte) 0x59, (byte) 0xac, - (byte) 0xcb, (byte) 0x2a, (byte) 0x91, (byte) 0x4c, (byte) 0x89, - (byte) 0x86, (byte) 0xcc, (byte) 0x70, (byte) 0xad, (byte) 0x90, 0x66, - (byte) 0x93, (byte) 0x82, (byte) 0xa9, (byte) 0x73, (byte) 0x26, - (byte) 0x13, (byte) 0xfe, (byte) 0xac, (byte) 0xcb, (byte) 0xf8, - (byte) 0x21, (byte) 0x27, (byte) 0x4c, (byte) 0x21, (byte) 0x74, - (byte) 0x97, (byte) 0x4a, (byte) 0x2a, (byte) 0xfe, (byte) 0xa5, - (byte) 0xb9, (byte) 0x4d, (byte) 0x7f, (byte) 0x66, (byte) 0xd4, - (byte) 0xe0, (byte) 0x65, (byte) 0x10, (byte) 0x66, (byte) 0x35, - (byte) 0xbc, 0x53, (byte) 0xb7, (byte) 0xa0, (byte) 0xa3, (byte) 0xa6, - (byte) 0x71, (byte) 0x58, (byte) 0x3e, (byte) 0xdb, (byte) 0x3e, - (byte) 0x11, (byte) 0xae, (byte) 0x10, (byte) 0x14, (byte) 0xa3, - (byte) 0x66, 0x30, (byte) 0x64, (byte) 0x30, (byte) 0x1d, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, - (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x3f, (byte) 0xfc, - (byte) 0xac, (byte) 0xd6, (byte) 0x1a, (byte) 0xb1, (byte) 0x3a, - (byte) 0x9e, (byte) 0x81, (byte) 0x20, (byte) 0xb8, (byte) 0xd5, - (byte) 0x25, (byte) 0x1c, (byte) 0xc5, (byte) 0x65, (byte) 0xbb, - (byte) 0x1e, (byte) 0x91, (byte) 0xa9, (byte) 0x30, (byte) 0x1f, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, - (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, - (byte) 0x14, (byte) 0xc8, (byte) 0xad, (byte) 0xe9, (byte) 0x77, - (byte) 0x4c, (byte) 0x45, (byte) 0xc3, (byte) 0xa3, (byte) 0xcf, - (byte) 0x0d, (byte) 0x16, (byte) 0x10, (byte) 0xe4, (byte) 0x79, - (byte) 0x43, (byte) 0x3a, (byte) 0x21, (byte) 0x5a, 0x30, (byte) 0xcf, - (byte) 0x30, (byte) 0x12, (byte) 0x06, (byte) 0x03, (byte) 0x55, - (byte) 0x1d, (byte) 0x13, (byte) 0x01, (byte) 0x01, (byte) 0xff, - (byte) 0x04, (byte) 0x08, (byte) 0x30, (byte) 0x06, 0x01, (byte) 0x01, - (byte) 0xff, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, - (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, - (byte) 0x0f, (byte) 0x01, (byte) 0x01, (byte) 0xff, 0x04, (byte) 0x04, - (byte) 0x03, (byte) 0x02, (byte) 0x02, (byte) 0x84, (byte) 0x30, - (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x86, - (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, 0x03, (byte) 0x02, - (byte) 0x03, (byte) 0x48, (byte) 0x00, (byte) 0x30, (byte) 0x45, - (byte) 0x02, (byte) 0x20, (byte) 0x4b, (byte) 0x8a, (byte) 0x9b, - (byte) 0x7b, (byte) 0xee, (byte) 0x82, (byte) 0xbc, (byte) 0xc0, - (byte) 0x33, (byte) 0x87, (byte) 0xae, (byte) 0x2f, (byte) 0xc0, - (byte) 0x89, (byte) 0x98, (byte) 0xb4, (byte) 0xdd, (byte) 0xc3, - (byte) 0x8d, (byte) 0xab, (byte) 0x27, (byte) 0x2a, (byte) 0x45, - (byte) 0x9f, (byte) 0x69, (byte) 0x0c, (byte) 0xc7, (byte) 0xc3, - (byte) 0x92, (byte) 0xd4, (byte) 0x0f, (byte) 0x8e, (byte) 0x02, - (byte) 0x21, (byte) 0x00, (byte) 0xee, (byte) 0xda, (byte) 0x01, - (byte) 0x5d, (byte) 0xb6, (byte) 0xf4, (byte) 0x32, (byte) 0xe9, - (byte) 0xd4, (byte) 0x84, (byte) 0x3b, (byte) 0x62, (byte) 0x4c, - (byte) 0x94, (byte) 0x04, (byte) 0xef, (byte) 0x3a, (byte) 0x7c, - (byte) 0xcc, (byte) 0xbd, 0x5e, (byte) 0xfb, (byte) 0x22, (byte) 0xbb, - (byte) 0xe7, (byte) 0xfe, (byte) 0xb9, (byte) 0x77, (byte) 0x3f, - (byte) 0x59, (byte) 0x3f, (byte) 0xfb, }; - - private static final byte[] kEcAttestRootCert = { - 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x8b, (byte) 0x30, - (byte) 0x82, (byte) 0x02, (byte) 0x32, (byte) 0xa0, (byte) 0x03, - (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x09, - (byte) 0x00, (byte) 0xa2, (byte) 0x05, (byte) 0x9e, (byte) 0xd1, - (byte) 0x0e, (byte) 0x43, (byte) 0x5b, (byte) 0x57, (byte) 0x30, - (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x86, - (byte) 0x48, (byte) 0xce, 0x3d, (byte) 0x04, (byte) 0x03, - (byte) 0x02, (byte) 0x30, (byte) 0x81, (byte) 0x98, (byte) 0x31, - (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, - (byte) 0x55, (byte) 0x04, (byte) 0x06, 0x13, (byte) 0x02, - (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, - (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, - (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x43, 0x61, - (byte) 0x6c, (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, - (byte) 0x6e, (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x16, - (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55, - 0x04, (byte) 0x07, (byte) 0x0c, (byte) 0x0d, (byte) 0x4d, - (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, - (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, - (byte) 0x65, 0x77, (byte) 0x31, (byte) 0x15, (byte) 0x30, - (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, - (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, - (byte) 0x6f, (byte) 0x67, 0x6c, (byte) 0x65, (byte) 0x2c, - (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, (byte) 0x2e, - (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, 0x0b, (byte) 0x0c, - (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, - (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x33, - (byte) 0x30, (byte) 0x31, (byte) 0x06, (byte) 0x03, 0x55, - (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x2a, (byte) 0x41, - (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, - (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, (byte) 0x79, - 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, (byte) 0x65, - (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, - (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, - (byte) 0x41, 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, - (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, - (byte) 0x6e, (byte) 0x20, (byte) 0x52, (byte) 0x6f, (byte) 0x6f, - (byte) 0x74, (byte) 0x30, 0x1e, (byte) 0x17, (byte) 0x0d, - (byte) 0x31, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x31, - (byte) 0x31, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x33, - (byte) 0x35, (byte) 0x30, (byte) 0x5a, 0x17, (byte) 0x0d, - (byte) 0x33, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x30, - (byte) 0x36, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x33, - (byte) 0x35, (byte) 0x30, (byte) 0x5a, (byte) 0x30, (byte) 0x81, - (byte) 0x98, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, - (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, - 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, - (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, - (byte) 0x43, (byte) 0x61, (byte) 0x6c, (byte) 0x69, (byte) 0x66, - (byte) 0x6f, 0x72, (byte) 0x6e, (byte) 0x69, (byte) 0x61, - (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x0c, - (byte) 0x0d, (byte) 0x4d, 0x6f, (byte) 0x75, (byte) 0x6e, - (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x20, - (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, - (byte) 0x15, (byte) 0x30, (byte) 0x13, 0x06, (byte) 0x03, - (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, - (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, - (byte) 0x65, (byte) 0x2c, (byte) 0x20, (byte) 0x49, 0x6e, - (byte) 0x63, (byte) 0x2e, (byte) 0x31, (byte) 0x10, (byte) 0x30, - (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, - (byte) 0x0b, (byte) 0x0c, (byte) 0x07, (byte) 0x41, (byte) 0x6e, - 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, - (byte) 0x31, (byte) 0x33, (byte) 0x30, (byte) 0x31, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c, - (byte) 0x2a, 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, - (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x4b, - (byte) 0x65, (byte) 0x79, (byte) 0x73, (byte) 0x74, (byte) 0x6f, - (byte) 0x72, (byte) 0x65, 0x20, (byte) 0x53, (byte) 0x6f, - (byte) 0x66, (byte) 0x74, (byte) 0x77, (byte) 0x61, (byte) 0x72, - (byte) 0x65, (byte) 0x20, (byte) 0x41, (byte) 0x74, (byte) 0x74, - (byte) 0x65, (byte) 0x73, (byte) 0x74, 0x61, (byte) 0x74, - (byte) 0x69, (byte) 0x6f, (byte) 0x6e, 0x77, (byte) 0x1f, - (byte) 0x44, (byte) 0x22, (byte) 0x6d, (byte) 0xbd, (byte) 0xb1, - (byte) 0xaf, (byte) 0xfa, (byte) 0x16, (byte) 0xcb, (byte) 0xc7, - (byte) 0xad, (byte) 0xc5, (byte) 0x77, (byte) 0xd2, (byte) 0x20, - (byte) 0x52, (byte) 0x6f, (byte) 0x6f, (byte) 0x74, (byte) 0x30, - (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, - 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, - (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x08, (byte) 0x2a, - (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x03, - (byte) 0x01, 0x07, (byte) 0x03, (byte) 0x42, (byte) 0x00, - (byte) 0x04, (byte) 0xee, (byte) 0x5d, (byte) 0x5e, (byte) 0xc7, - (byte) 0xe1, (byte) 0xc0, (byte) 0xdb, (byte) 0x6d, (byte) 0x03, - (byte) 0xa6, (byte) 0x7e, (byte) 0xe6, (byte) 0xb6, (byte) 0x1b, - (byte) 0xec, (byte) 0x4d, (byte) 0x6a, (byte) 0x5d, (byte) 0x6a, - (byte) 0x68, (byte) 0x2e, (byte) 0x0f, (byte) 0xff, (byte) 0x7f, - (byte) 0x49, (byte) 0x0e, (byte) 0x7d, 0x56, (byte) 0x9c, - (byte) 0xaa, (byte) 0xb7, (byte) 0xb0, (byte) 0x2d, (byte) 0x54, - (byte) 0x01, (byte) 0x5d, (byte) 0x3e, (byte) 0x43, (byte) 0x2b, - (byte) 0x2a, (byte) 0x8e, (byte) 0xd7, (byte) 0x4e, (byte) 0xec, - (byte) 0x48, (byte) 0x75, (byte) 0x41, (byte) 0xa4, (byte) 0xa3, - (byte) 0x63, (byte) 0x30, (byte) 0x61, (byte) 0x30, (byte) 0x1d, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, - 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0xc8, - (byte) 0xad, (byte) 0xe9, (byte) 0x77, (byte) 0x4c, (byte) 0x45, - (byte) 0xc3, (byte) 0xa3, (byte) 0xcf, (byte) 0x0d, (byte) 0x16, - (byte) 0x10, (byte) 0xe4, (byte) 0x79, (byte) 0x43, (byte) 0x3a, - (byte) 0x21, (byte) 0x5a, (byte) 0x30, (byte) 0xcf, (byte) 0x30, - (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, - (byte) 0x23, (byte) 0x04, 0x18, (byte) 0x30, (byte) 0x16, - (byte) 0x80, (byte) 0x14, (byte) 0xc8, (byte) 0xad, (byte) 0xe9, - (byte) 0x77, (byte) 0x4c, (byte) 0x45, (byte) 0xc3, (byte) 0xa3, - (byte) 0xcf, (byte) 0x0d, (byte) 0x16, 0x10, (byte) 0xe4, - (byte) 0x79, (byte) 0x43, (byte) 0x3a, (byte) 0x21, (byte) 0x5a, - (byte) 0x30, (byte) 0xcf, (byte) 0x30, (byte) 0x0f, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, 0x01, - (byte) 0x01, (byte) 0xff, (byte) 0x04, (byte) 0x05, (byte) 0x30, - (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30, - (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, - 0x0f, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x04, - (byte) 0x04, (byte) 0x03, (byte) 0x02, (byte) 0x02, (byte) 0x84, - (byte) 0x30, (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, - (byte) 0x86, 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, - (byte) 0x03, (byte) 0x02, (byte) 0x03, (byte) 0x47, (byte) 0x00, - (byte) 0x30, (byte) 0x44, (byte) 0x02, (byte) 0x20, (byte) 0x35, - (byte) 0x21, (byte) 0xa3, (byte) 0xef, (byte) 0x8b, (byte) 0x34, - (byte) 0x46, (byte) 0x1e, (byte) 0x9c, (byte) 0xd5, (byte) 0x60, - (byte) 0xf3, (byte) 0x1d, (byte) 0x58, (byte) 0x89, (byte) 0x20, - (byte) 0x6a, (byte) 0xdc, (byte) 0xa3, 0x65, (byte) 0x41, - (byte) 0xf6, (byte) 0x0d, (byte) 0x9e, (byte) 0xce, (byte) 0x8a, - (byte) 0x19, (byte) 0x8c, (byte) 0x66, (byte) 0x48, (byte) 0x60, - (byte) 0x7b, (byte) 0x02, (byte) 0x20, (byte) 0x4d, 0x0b, - (byte) 0xf3, (byte) 0x51, (byte) 0xd9, (byte) 0x30, (byte) 0x7c, - (byte) 0x7d, (byte) 0x5b, (byte) 0xda, (byte) 0x35, (byte) 0x34, - (byte) 0x1d, (byte) 0xa8, (byte) 0x47, (byte) 0x1b, (byte) 0x63, - (byte) 0xa5, (byte) 0x85, (byte) 0x65, (byte) 0x3c, (byte) 0xad, - (byte) 0x4f, (byte) 0x24, (byte) 0xa7, (byte) 0xe7, (byte) 0x4d, - (byte) 0xaf, (byte) 0x41, (byte) 0x7d, (byte) 0xf1, - (byte) 0xbf, }; - - private static final byte[] X509Issuer = { - (byte) 0x30, (byte) 0x81, (byte) 0x88, (byte) 0x31, (byte) 0x0b, - (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, - (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, - (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11, - (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, - (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, - (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, - (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x15, (byte) 0x30, - (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, - (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, - (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2c, - (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, (byte) 0x2e, - (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, - (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b, (byte) 0x0c, - (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, - (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x3b, - (byte) 0x30, (byte) 0x39, (byte) 0x06, (byte) 0x03, (byte) 0x55, - (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x32, (byte) 0x41, - (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, - (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, (byte) 0x79, - (byte) 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, (byte) 0x65, - (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, - (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, - (byte) 0x41, (byte) 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, - (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, - (byte) 0x6e, (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x74, - (byte) 0x65, (byte) 0x72, (byte) 0x6d, (byte) 0x65, (byte) 0x64, - (byte) 0x69, (byte) 0x61, (byte) 0x74, (byte) 0x65 }; + 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x30, (byte) 0x82, + (byte) 0x02, (byte) 0x1e, (byte) 0xa0, (byte) 0x03, (byte) 0x02, + (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x10, 0x01, + (byte) 0x30, (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, + (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, + (byte) 0x03, (byte) 0x02, (byte) 0x30, (byte) 0x81, (byte) 0x98, 0x31, + (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, + (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, + (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, 0x11, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, + (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, + (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, 0x69, + (byte) 0x61, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, + (byte) 0x0c, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f, (byte) 0x75, 0x6e, + (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x20, + (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, + (byte) 0x15, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x03, 0x55, + (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, + (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, + (byte) 0x2c, (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, 0x2e, + (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b, (byte) 0x0c, + (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, 0x6f, + (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x33, (byte) 0x30, + (byte) 0x31, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x03, (byte) 0x0c, (byte) 0x2a, (byte) 0x41, (byte) 0x6e, 0x64, + (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, + (byte) 0x4b, (byte) 0x65, (byte) 0x79, (byte) 0x73, (byte) 0x74, + (byte) 0x6f, (byte) 0x72, (byte) 0x65, (byte) 0x20, (byte) 0x53, 0x6f, + (byte) 0x66, (byte) 0x74, (byte) 0x77, (byte) 0x61, (byte) 0x72, + (byte) 0x65, (byte) 0x20, (byte) 0x41, (byte) 0x74, (byte) 0x74, + (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x61, (byte) 0x74, 0x69, + (byte) 0x6f, (byte) 0x6e, (byte) 0x20, (byte) 0x52, (byte) 0x6f, + (byte) 0x6f, (byte) 0x74, (byte) 0x30, (byte) 0x1e, (byte) 0x17, + (byte) 0x0d, (byte) 0x31, (byte) 0x36, (byte) 0x30, (byte) 0x31, 0x31, + (byte) 0x31, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x36, + (byte) 0x30, (byte) 0x39, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, + (byte) 0x32, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x30, 0x38, + (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x36, (byte) 0x30, + (byte) 0x39, (byte) 0x5a, (byte) 0x30, (byte) 0x81, (byte) 0x88, + (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, 0x03, + (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, + (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, + (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, 0x08, + (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, + (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, + (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x15, (byte) 0x30, 0x13, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, + (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, (byte) 0x6f, + (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2c, (byte) 0x20, 0x49, + (byte) 0x6e, (byte) 0x63, (byte) 0x2e, (byte) 0x31, (byte) 0x10, + (byte) 0x30, (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, + (byte) 0x04, (byte) 0x0b, (byte) 0x0c, (byte) 0x07, (byte) 0x41, 0x6e, + (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, + (byte) 0x31, (byte) 0x3b, (byte) 0x30, (byte) 0x39, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c, 0x32, + (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, + (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, + (byte) 0x79, (byte) 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, 0x65, + (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, + (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, + (byte) 0x41, (byte) 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, 0x74, + (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, + (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x74, (byte) 0x65, + (byte) 0x72, (byte) 0x6d, (byte) 0x65, (byte) 0x64, (byte) 0x69, 0x61, + (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x59, (byte) 0x30, + (byte) 0x13, (byte) 0x06, (byte) 0x07, (byte) 0x2a, (byte) 0x86, + (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x02, (byte) 0x01, 0x06, + (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0xce, + (byte) 0x3d, (byte) 0x03, (byte) 0x01, (byte) 0x07, (byte) 0x03, + (byte) 0x42, (byte) 0x00, (byte) 0x04, (byte) 0xeb, (byte) 0x9e, 0x79, + (byte) 0xf8, (byte) 0x42, (byte) 0x63, (byte) 0x59, (byte) 0xac, + (byte) 0xcb, (byte) 0x2a, (byte) 0x91, (byte) 0x4c, (byte) 0x89, + (byte) 0x86, (byte) 0xcc, (byte) 0x70, (byte) 0xad, (byte) 0x90, 0x66, + (byte) 0x93, (byte) 0x82, (byte) 0xa9, (byte) 0x73, (byte) 0x26, + (byte) 0x13, (byte) 0xfe, (byte) 0xac, (byte) 0xcb, (byte) 0xf8, + (byte) 0x21, (byte) 0x27, (byte) 0x4c, (byte) 0x21, (byte) 0x74, + (byte) 0x97, (byte) 0x4a, (byte) 0x2a, (byte) 0xfe, (byte) 0xa5, + (byte) 0xb9, (byte) 0x4d, (byte) 0x7f, (byte) 0x66, (byte) 0xd4, + (byte) 0xe0, (byte) 0x65, (byte) 0x10, (byte) 0x66, (byte) 0x35, + (byte) 0xbc, 0x53, (byte) 0xb7, (byte) 0xa0, (byte) 0xa3, (byte) 0xa6, + (byte) 0x71, (byte) 0x58, (byte) 0x3e, (byte) 0xdb, (byte) 0x3e, + (byte) 0x11, (byte) 0xae, (byte) 0x10, (byte) 0x14, (byte) 0xa3, + (byte) 0x66, 0x30, (byte) 0x64, (byte) 0x30, (byte) 0x1d, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, + (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x3f, (byte) 0xfc, + (byte) 0xac, (byte) 0xd6, (byte) 0x1a, (byte) 0xb1, (byte) 0x3a, + (byte) 0x9e, (byte) 0x81, (byte) 0x20, (byte) 0xb8, (byte) 0xd5, + (byte) 0x25, (byte) 0x1c, (byte) 0xc5, (byte) 0x65, (byte) 0xbb, + (byte) 0x1e, (byte) 0x91, (byte) 0xa9, (byte) 0x30, (byte) 0x1f, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, + (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, + (byte) 0x14, (byte) 0xc8, (byte) 0xad, (byte) 0xe9, (byte) 0x77, + (byte) 0x4c, (byte) 0x45, (byte) 0xc3, (byte) 0xa3, (byte) 0xcf, + (byte) 0x0d, (byte) 0x16, (byte) 0x10, (byte) 0xe4, (byte) 0x79, + (byte) 0x43, (byte) 0x3a, (byte) 0x21, (byte) 0x5a, 0x30, (byte) 0xcf, + (byte) 0x30, (byte) 0x12, (byte) 0x06, (byte) 0x03, (byte) 0x55, + (byte) 0x1d, (byte) 0x13, (byte) 0x01, (byte) 0x01, (byte) 0xff, + (byte) 0x04, (byte) 0x08, (byte) 0x30, (byte) 0x06, 0x01, (byte) 0x01, + (byte) 0xff, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x30, + (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, + (byte) 0x0f, (byte) 0x01, (byte) 0x01, (byte) 0xff, 0x04, (byte) 0x04, + (byte) 0x03, (byte) 0x02, (byte) 0x02, (byte) 0x84, (byte) 0x30, + (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x86, + (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, 0x03, (byte) 0x02, + (byte) 0x03, (byte) 0x48, (byte) 0x00, (byte) 0x30, (byte) 0x45, + (byte) 0x02, (byte) 0x20, (byte) 0x4b, (byte) 0x8a, (byte) 0x9b, + (byte) 0x7b, (byte) 0xee, (byte) 0x82, (byte) 0xbc, (byte) 0xc0, + (byte) 0x33, (byte) 0x87, (byte) 0xae, (byte) 0x2f, (byte) 0xc0, + (byte) 0x89, (byte) 0x98, (byte) 0xb4, (byte) 0xdd, (byte) 0xc3, + (byte) 0x8d, (byte) 0xab, (byte) 0x27, (byte) 0x2a, (byte) 0x45, + (byte) 0x9f, (byte) 0x69, (byte) 0x0c, (byte) 0xc7, (byte) 0xc3, + (byte) 0x92, (byte) 0xd4, (byte) 0x0f, (byte) 0x8e, (byte) 0x02, + (byte) 0x21, (byte) 0x00, (byte) 0xee, (byte) 0xda, (byte) 0x01, + (byte) 0x5d, (byte) 0xb6, (byte) 0xf4, (byte) 0x32, (byte) 0xe9, + (byte) 0xd4, (byte) 0x84, (byte) 0x3b, (byte) 0x62, (byte) 0x4c, + (byte) 0x94, (byte) 0x04, (byte) 0xef, (byte) 0x3a, (byte) 0x7c, + (byte) 0xcc, (byte) 0xbd, 0x5e, (byte) 0xfb, (byte) 0x22, (byte) 0xbb, + (byte) 0xe7, (byte) 0xfe, (byte) 0xb9, (byte) 0x77, (byte) 0x3f, + (byte) 0x59, (byte) 0x3f, (byte) 0xfb,}; + + private static final byte[] kEcAttestRootCert = { + 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x8b, (byte) 0x30, + (byte) 0x82, (byte) 0x02, (byte) 0x32, (byte) 0xa0, (byte) 0x03, + (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x09, + (byte) 0x00, (byte) 0xa2, (byte) 0x05, (byte) 0x9e, (byte) 0xd1, + (byte) 0x0e, (byte) 0x43, (byte) 0x5b, (byte) 0x57, (byte) 0x30, + (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, (byte) 0x86, + (byte) 0x48, (byte) 0xce, 0x3d, (byte) 0x04, (byte) 0x03, + (byte) 0x02, (byte) 0x30, (byte) 0x81, (byte) 0x98, (byte) 0x31, + (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, + (byte) 0x55, (byte) 0x04, (byte) 0x06, 0x13, (byte) 0x02, + (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, + (byte) 0x11, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x43, 0x61, + (byte) 0x6c, (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, + (byte) 0x6e, (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x16, + (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55, + 0x04, (byte) 0x07, (byte) 0x0c, (byte) 0x0d, (byte) 0x4d, + (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, + (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, + (byte) 0x65, 0x77, (byte) 0x31, (byte) 0x15, (byte) 0x30, + (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, + (byte) 0x6f, (byte) 0x67, 0x6c, (byte) 0x65, (byte) 0x2c, + (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, (byte) 0x2e, + (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, 0x0b, (byte) 0x0c, + (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, + (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x33, + (byte) 0x30, (byte) 0x31, (byte) 0x06, (byte) 0x03, 0x55, + (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x2a, (byte) 0x41, + (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, + (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, (byte) 0x79, + 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, (byte) 0x65, + (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, + (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, + (byte) 0x41, 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, + (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, + (byte) 0x6e, (byte) 0x20, (byte) 0x52, (byte) 0x6f, (byte) 0x6f, + (byte) 0x74, (byte) 0x30, 0x1e, (byte) 0x17, (byte) 0x0d, + (byte) 0x31, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x31, + (byte) 0x31, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x33, + (byte) 0x35, (byte) 0x30, (byte) 0x5a, 0x17, (byte) 0x0d, + (byte) 0x33, (byte) 0x36, (byte) 0x30, (byte) 0x31, (byte) 0x30, + (byte) 0x36, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x33, + (byte) 0x35, (byte) 0x30, (byte) 0x5a, (byte) 0x30, (byte) 0x81, + (byte) 0x98, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, + (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, + 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03, + (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, + (byte) 0x43, (byte) 0x61, (byte) 0x6c, (byte) 0x69, (byte) 0x66, + (byte) 0x6f, 0x72, (byte) 0x6e, (byte) 0x69, (byte) 0x61, + (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x0c, + (byte) 0x0d, (byte) 0x4d, 0x6f, (byte) 0x75, (byte) 0x6e, + (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e, (byte) 0x20, + (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31, + (byte) 0x15, (byte) 0x30, (byte) 0x13, 0x06, (byte) 0x03, + (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, + (byte) 0x47, (byte) 0x6f, (byte) 0x6f, (byte) 0x67, (byte) 0x6c, + (byte) 0x65, (byte) 0x2c, (byte) 0x20, (byte) 0x49, 0x6e, + (byte) 0x63, (byte) 0x2e, (byte) 0x31, (byte) 0x10, (byte) 0x30, + (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x0b, (byte) 0x0c, (byte) 0x07, (byte) 0x41, (byte) 0x6e, + 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, + (byte) 0x31, (byte) 0x33, (byte) 0x30, (byte) 0x31, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c, + (byte) 0x2a, 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, + (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x4b, + (byte) 0x65, (byte) 0x79, (byte) 0x73, (byte) 0x74, (byte) 0x6f, + (byte) 0x72, (byte) 0x65, 0x20, (byte) 0x53, (byte) 0x6f, + (byte) 0x66, (byte) 0x74, (byte) 0x77, (byte) 0x61, (byte) 0x72, + (byte) 0x65, (byte) 0x20, (byte) 0x41, (byte) 0x74, (byte) 0x74, + (byte) 0x65, (byte) 0x73, (byte) 0x74, 0x61, (byte) 0x74, + (byte) 0x69, (byte) 0x6f, (byte) 0x6e, 0x77, (byte) 0x1f, + (byte) 0x44, (byte) 0x22, (byte) 0x6d, (byte) 0xbd, (byte) 0xb1, + (byte) 0xaf, (byte) 0xfa, (byte) 0x16, (byte) 0xcb, (byte) 0xc7, + (byte) 0xad, (byte) 0xc5, (byte) 0x77, (byte) 0xd2, (byte) 0x20, + (byte) 0x52, (byte) 0x6f, (byte) 0x6f, (byte) 0x74, (byte) 0x30, + (byte) 0x59, (byte) 0x30, (byte) 0x13, (byte) 0x06, (byte) 0x07, + 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, + (byte) 0x02, (byte) 0x01, (byte) 0x06, (byte) 0x08, (byte) 0x2a, + (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x03, + (byte) 0x01, 0x07, (byte) 0x03, (byte) 0x42, (byte) 0x00, + (byte) 0x04, (byte) 0xee, (byte) 0x5d, (byte) 0x5e, (byte) 0xc7, + (byte) 0xe1, (byte) 0xc0, (byte) 0xdb, (byte) 0x6d, (byte) 0x03, + (byte) 0xa6, (byte) 0x7e, (byte) 0xe6, (byte) 0xb6, (byte) 0x1b, + (byte) 0xec, (byte) 0x4d, (byte) 0x6a, (byte) 0x5d, (byte) 0x6a, + (byte) 0x68, (byte) 0x2e, (byte) 0x0f, (byte) 0xff, (byte) 0x7f, + (byte) 0x49, (byte) 0x0e, (byte) 0x7d, 0x56, (byte) 0x9c, + (byte) 0xaa, (byte) 0xb7, (byte) 0xb0, (byte) 0x2d, (byte) 0x54, + (byte) 0x01, (byte) 0x5d, (byte) 0x3e, (byte) 0x43, (byte) 0x2b, + (byte) 0x2a, (byte) 0x8e, (byte) 0xd7, (byte) 0x4e, (byte) 0xec, + (byte) 0x48, (byte) 0x75, (byte) 0x41, (byte) 0xa4, (byte) 0xa3, + (byte) 0x63, (byte) 0x30, (byte) 0x61, (byte) 0x30, (byte) 0x1d, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, + 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0xc8, + (byte) 0xad, (byte) 0xe9, (byte) 0x77, (byte) 0x4c, (byte) 0x45, + (byte) 0xc3, (byte) 0xa3, (byte) 0xcf, (byte) 0x0d, (byte) 0x16, + (byte) 0x10, (byte) 0xe4, (byte) 0x79, (byte) 0x43, (byte) 0x3a, + (byte) 0x21, (byte) 0x5a, (byte) 0x30, (byte) 0xcf, (byte) 0x30, + (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, + (byte) 0x23, (byte) 0x04, 0x18, (byte) 0x30, (byte) 0x16, + (byte) 0x80, (byte) 0x14, (byte) 0xc8, (byte) 0xad, (byte) 0xe9, + (byte) 0x77, (byte) 0x4c, (byte) 0x45, (byte) 0xc3, (byte) 0xa3, + (byte) 0xcf, (byte) 0x0d, (byte) 0x16, 0x10, (byte) 0xe4, + (byte) 0x79, (byte) 0x43, (byte) 0x3a, (byte) 0x21, (byte) 0x5a, + (byte) 0x30, (byte) 0xcf, (byte) 0x30, (byte) 0x0f, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, 0x01, + (byte) 0x01, (byte) 0xff, (byte) 0x04, (byte) 0x05, (byte) 0x30, + (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30, + (byte) 0x0e, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, + 0x0f, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x04, + (byte) 0x04, (byte) 0x03, (byte) 0x02, (byte) 0x02, (byte) 0x84, + (byte) 0x30, (byte) 0x0a, (byte) 0x06, (byte) 0x08, (byte) 0x2a, + (byte) 0x86, 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x04, + (byte) 0x03, (byte) 0x02, (byte) 0x03, (byte) 0x47, (byte) 0x00, + (byte) 0x30, (byte) 0x44, (byte) 0x02, (byte) 0x20, (byte) 0x35, + (byte) 0x21, (byte) 0xa3, (byte) 0xef, (byte) 0x8b, (byte) 0x34, + (byte) 0x46, (byte) 0x1e, (byte) 0x9c, (byte) 0xd5, (byte) 0x60, + (byte) 0xf3, (byte) 0x1d, (byte) 0x58, (byte) 0x89, (byte) 0x20, + (byte) 0x6a, (byte) 0xdc, (byte) 0xa3, 0x65, (byte) 0x41, + (byte) 0xf6, (byte) 0x0d, (byte) 0x9e, (byte) 0xce, (byte) 0x8a, + (byte) 0x19, (byte) 0x8c, (byte) 0x66, (byte) 0x48, (byte) 0x60, + (byte) 0x7b, (byte) 0x02, (byte) 0x20, (byte) 0x4d, 0x0b, + (byte) 0xf3, (byte) 0x51, (byte) 0xd9, (byte) 0x30, (byte) 0x7c, + (byte) 0x7d, (byte) 0x5b, (byte) 0xda, (byte) 0x35, (byte) 0x34, + (byte) 0x1d, (byte) 0xa8, (byte) 0x47, (byte) 0x1b, (byte) 0x63, + (byte) 0xa5, (byte) 0x85, (byte) 0x65, (byte) 0x3c, (byte) 0xad, + (byte) 0x4f, (byte) 0x24, (byte) 0xa7, (byte) 0xe7, (byte) 0x4d, + (byte) 0xaf, (byte) 0x41, (byte) 0x7d, (byte) 0xf1, + (byte) 0xbf,}; + + private static final byte[] X509Issuer = { + (byte) 0x30, (byte) 0x81, (byte) 0x88, (byte) 0x31, (byte) 0x0b, + (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, + (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, + (byte) 0x53, (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11, + (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, + (byte) 0x0c, (byte) 0x0a, (byte) 0x43, (byte) 0x61, (byte) 0x6c, + (byte) 0x69, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x6e, + (byte) 0x69, (byte) 0x61, (byte) 0x31, (byte) 0x15, (byte) 0x30, + (byte) 0x13, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, + (byte) 0x0a, (byte) 0x0c, (byte) 0x0c, (byte) 0x47, (byte) 0x6f, + (byte) 0x6f, (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x2c, + (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x63, (byte) 0x2e, + (byte) 0x31, (byte) 0x10, (byte) 0x30, (byte) 0x0e, (byte) 0x06, + (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0b, (byte) 0x0c, + (byte) 0x07, (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, + (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x31, (byte) 0x3b, + (byte) 0x30, (byte) 0x39, (byte) 0x06, (byte) 0x03, (byte) 0x55, + (byte) 0x04, (byte) 0x03, (byte) 0x0c, (byte) 0x32, (byte) 0x41, + (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, + (byte) 0x64, (byte) 0x20, (byte) 0x4b, (byte) 0x65, (byte) 0x79, + (byte) 0x73, (byte) 0x74, (byte) 0x6f, (byte) 0x72, (byte) 0x65, + (byte) 0x20, (byte) 0x53, (byte) 0x6f, (byte) 0x66, (byte) 0x74, + (byte) 0x77, (byte) 0x61, (byte) 0x72, (byte) 0x65, (byte) 0x20, + (byte) 0x41, (byte) 0x74, (byte) 0x74, (byte) 0x65, (byte) 0x73, + (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x69, (byte) 0x6f, + (byte) 0x6e, (byte) 0x20, (byte) 0x49, (byte) 0x6e, (byte) 0x74, + (byte) 0x65, (byte) 0x72, (byte) 0x6d, (byte) 0x65, (byte) 0x64, + (byte) 0x69, (byte) 0x61, (byte) 0x74, (byte) 0x65}; // AttestationApplicationId ::= SEQUENCE { // * packageInfoRecords SET OF PackageInfoRecord, // * signatureDigests SET OF OCTET_STRING, @@ -436,24 +437,29 @@ public class KMFunctionalTest { // * version INTEGER, // * } private static final byte[] attAppId = {0x30, 0x10, 0x31, 0x0B, 0x30, 0x04, 0x05, 'A', 'B', 'C', - 'D', 'E', 0x02, 0x01, 0x01, 0x31, 0x02, 0x04, 0x00}; - private static final byte[] attChallenge = {'c','h','a','l','l','e','n','g','e'}; - private static final byte[] expiryTime = {(byte)0x32, (byte)0x36, (byte)0x30, (byte)0x31, (byte)0x30, (byte)0x38, (byte)0x30, (byte)0x30, (byte)0x34, (byte)0x36, (byte)0x30, (byte)0x39, (byte)0x5a}; - private static final byte[] authKeyId = { (byte)0x80, (byte)0x14, (byte)0xc8, (byte)0xad, (byte)0xe9, (byte)0x77, (byte)0x4c, (byte)0x45, (byte)0xc3, (byte)0xa3, (byte)0xcf, (byte)0x0d, (byte)0x16, (byte)0x10, (byte)0xe4, (byte)0x79, (byte)0x43, (byte)0x3a, (byte)0x21, (byte)0x5a, (byte)0x30, (byte)0xcf}; + 'D', 'E', 0x02, 0x01, 0x01, 0x31, 0x02, 0x04, 0x00}; + private static final byte[] attChallenge = {'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; + private static final byte[] expiryTime = {(byte) 0x32, (byte) 0x36, (byte) 0x30, (byte) 0x31, + (byte) 0x30, (byte) 0x38, (byte) 0x30, (byte) 0x30, (byte) 0x34, (byte) 0x36, (byte) 0x30, + (byte) 0x39, (byte) 0x5a}; + private static final byte[] authKeyId = {(byte) 0x80, (byte) 0x14, (byte) 0xc8, (byte) 0xad, + (byte) 0xe9, (byte) 0x77, (byte) 0x4c, (byte) 0x45, (byte) 0xc3, (byte) 0xa3, (byte) 0xcf, + (byte) 0x0d, (byte) 0x16, (byte) 0x10, (byte) 0xe4, (byte) 0x79, (byte) 0x43, (byte) 0x3a, + (byte) 0x21, (byte) 0x5a, (byte) 0x30, (byte) 0xcf}; private CardSimulator simulator; private KMEncoder encoder; private KMDecoder decoder; private KMSEProvider cryptoProvider; - public KMFunctionalTest(){ + public KMFunctionalTest() { cryptoProvider = new KMJCardSimulator(); simulator = new CardSimulator(); encoder = new KMEncoder(); decoder = new KMDecoder(); } - private void init(){ + private void init() { // Create simulator AID appletAID = AIDUtil.create("A000000062"); simulator.installApplet(appletAID, KMJCardSimApplet.class); @@ -464,7 +470,7 @@ private void init(){ } private void setBootParams(CardSimulator simulator, short osVersion, - short osPatchLevel, short vendorPatchLevel, short bootPatchLevel) { + short osPatchLevel, short vendorPatchLevel, short bootPatchLevel) { // Argument 1 OS Version short versionPtr = KMInteger.uint_16(osVersion); // short versionTagPtr = KMIntegerTag.instance(KMType.UINT_TAG, @@ -476,16 +482,16 @@ private void setBootParams(CardSimulator simulator, short osVersion, // Argument 3 Verified Boot Key byte[] bootKeyHash = "00011122233344455566677788899900".getBytes(); short bootKeyPtr = KMByteBlob.instance(bootKeyHash, (short) 0, - (short) bootKeyHash.length); + (short) bootKeyHash.length); // Argument 4 Verified Boot Hash short bootHashPtr = KMByteBlob.instance(bootKeyHash, (short) 0, - (short) bootKeyHash.length); + (short) bootKeyHash.length); // Argument 5 Verified Boot State short bootStatePtr = KMEnum.instance(KMType.VERIFIED_BOOT_STATE, - KMType.VERIFIED_BOOT); + KMType.VERIFIED_BOOT); // Argument 6 Device Locked short deviceLockedPtr = KMEnum.instance(KMType.DEVICE_LOCKED, - KMType.DEVICE_LOCKED_FALSE); + KMType.DEVICE_LOCKED_FALSE); // Arguments short arrPtr = KMArray.instance((short) 8); KMArray vals = KMArray.cast(arrPtr); @@ -506,18 +512,18 @@ private void setBootParams(CardSimulator simulator, short osVersion, private void provisionSigningCertificate(CardSimulator simulator) { short byteBlobPtr = KMByteBlob.instance( - (short) (kEcAttestCert.length + kEcAttestRootCert.length)); + (short) (kEcAttestCert.length + kEcAttestRootCert.length)); Util.arrayCopyNonAtomic(kEcAttestCert, (short) 0, - KMByteBlob.cast(byteBlobPtr).getBuffer(), - KMByteBlob.cast(byteBlobPtr).getStartOff(), - (short) kEcAttestCert.length); + KMByteBlob.cast(byteBlobPtr).getBuffer(), + KMByteBlob.cast(byteBlobPtr).getStartOff(), + (short) kEcAttestCert.length); Util.arrayCopyNonAtomic(kEcAttestRootCert, (short) 0, - KMByteBlob.cast(byteBlobPtr).getBuffer(), - (short) (KMByteBlob.cast(byteBlobPtr).getStartOff() - + kEcAttestCert.length), - (short) kEcAttestRootCert.length); + KMByteBlob.cast(byteBlobPtr).getBuffer(), + (short) (KMByteBlob.cast(byteBlobPtr).getStartOff() + + kEcAttestCert.length), + (short) kEcAttestRootCert.length); CommandAPDU apdu = encodeApdu( - (byte) INS_PROVISION_ATTESTATION_CERT_CHAIN_CMD, byteBlobPtr); + (byte) INS_PROVISION_ATTESTATION_CERT_CHAIN_CMD, byteBlobPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); @@ -536,7 +542,7 @@ private void provisionSigningKey(CardSimulator simulator) { KMArray.cast(arrPtr).add((short) 0, ecCurve); KMArray.cast(arrPtr).add((short) 1, digest); KMArray.cast(arrPtr).add((short) 2, - KMEnumTag.instance(KMType.ALGORITHM, KMType.EC)); + KMEnumTag.instance(KMType.ALGORITHM, KMType.EC)); KMArray.cast(arrPtr).add((short) 3, purpose); short keyParams = KMKeyParameters.instance(arrPtr); // Note: VTS uses PKCS8 KeyFormat RAW @@ -545,9 +551,9 @@ private void provisionSigningKey(CardSimulator simulator) { // Key short signKeyPtr = KMArray.instance((short) 2); KMArray.cast(signKeyPtr).add((short) 0, KMByteBlob.instance(kEcPrivKey, - (short) 0, (short) kEcPrivKey.length)); + (short) 0, (short) kEcPrivKey.length)); KMArray.cast(signKeyPtr).add((short) 1, KMByteBlob.instance(kEcPubKey, - (short) 0, (short) kEcPubKey.length)); + (short) 0, (short) kEcPubKey.length)); byte[] keyBuf = new byte[120]; short len = encoder.encode(signKeyPtr, keyBuf, (short) 0); short signKeyBstr = KMByteBlob.instance(keyBuf, (short) 0, len); @@ -558,7 +564,7 @@ private void provisionSigningKey(CardSimulator simulator) { KMArray.cast(finalArrayPtr).add((short) 2, signKeyBstr); CommandAPDU apdu = encodeApdu((byte) INS_PROVISION_ATTESTATION_KEY_CMD, - finalArrayPtr); + finalArrayPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); @@ -568,14 +574,14 @@ private void provisionCertificateParams(CardSimulator simulator) { short arrPtr = KMArray.instance((short) 2); short byteBlob1 = KMByteBlob.instance(X509Issuer, (short) 0, - (short) X509Issuer.length); + (short) X509Issuer.length); KMArray.cast(arrPtr).add((short) 0, byteBlob1); short byteBlob2 = KMByteBlob.instance(expiryTime, (short) 0, - (short) expiryTime.length); + (short) expiryTime.length); KMArray.cast(arrPtr).add((short) 1, byteBlob2); CommandAPDU apdu = encodeApdu( - (byte) INS_PROVISION_ATTESTATION_CERT_PARAMS_CMD, arrPtr); + (byte) INS_PROVISION_ATTESTATION_CERT_PARAMS_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); @@ -583,15 +589,15 @@ private void provisionCertificateParams(CardSimulator simulator) { private void provisionSharedSecret(CardSimulator simulator) { byte[] sharedKeySecret = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0}; short arrPtr = KMArray.instance((short) 1); short byteBlob = KMByteBlob.instance(sharedKeySecret, (short) 0, - (short) sharedKeySecret.length); + (short) sharedKeySecret.length); KMArray.cast(arrPtr).add((short) 0, byteBlob); CommandAPDU apdu = encodeApdu((byte) INS_PROVISION_PRESHARED_SECRET_CMD, - arrPtr); + arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); @@ -603,34 +609,34 @@ private void provisionAttestIds(CardSimulator simulator) { byte[] buf = "Attestation Id".getBytes(); KMArray.cast(arrPtr).add((short) 0, - KMByteTag.instance(KMType.ATTESTATION_ID_BRAND, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_BRAND, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 1, - KMByteTag.instance(KMType.ATTESTATION_ID_PRODUCT, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_PRODUCT, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 2, - KMByteTag.instance(KMType.ATTESTATION_ID_DEVICE, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_DEVICE, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 3, - KMByteTag.instance(KMType.ATTESTATION_ID_MODEL, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_MODEL, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 4, - KMByteTag.instance(KMType.ATTESTATION_ID_IMEI, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_IMEI, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 5, - KMByteTag.instance(KMType.ATTESTATION_ID_MEID, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_MEID, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 6, - KMByteTag.instance(KMType.ATTESTATION_ID_MANUFACTURER, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_MANUFACTURER, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); KMArray.cast(arrPtr).add((short) 7, - KMByteTag.instance(KMType.ATTESTATION_ID_SERIAL, - KMByteBlob.instance(buf, (short) 0, (short) buf.length))); + KMByteTag.instance(KMType.ATTESTATION_ID_SERIAL, + KMByteBlob.instance(buf, (short) 0, (short) buf.length))); short keyParams = KMKeyParameters.instance(arrPtr); short outerArrPtr = KMArray.instance((short) 1); KMArray.cast(outerArrPtr).add((short) 0, keyParams); CommandAPDU apdu = encodeApdu((byte) INS_PROVISION_ATTEST_IDS_CMD, - outerArrPtr); + outerArrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); @@ -638,7 +644,7 @@ private void provisionAttestIds(CardSimulator simulator) { private void provisionLocked(CardSimulator simulator) { CommandAPDU commandAPDU = new CommandAPDU(0x80, INS_LOCK_PROVISIONING_CMD, - 0x40, 0x00); + 0x40, 0x00); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(commandAPDU); Assert.assertEquals(0x9000, response.getSW()); @@ -651,28 +657,28 @@ private void provisionCmd(CardSimulator simulator) { provisionSharedSecret(simulator); provisionAttestIds(simulator); // set bootup parameters - setBootParams(simulator,(short)1,(short)1, (short)0, (short)0); + setBootParams(simulator, (short) 1, (short) 1, (short) 0, (short) 0); provisionLocked(simulator); } - private void cleanUp(){ + private void cleanUp() { AID appletAID = AIDUtil.create("A000000062"); // Delete i.e. uninstall applet simulator.deleteApplet(appletAID); } - private CommandAPDU encodeApdu(byte ins, short cmd){ + private CommandAPDU encodeApdu(byte ins, short cmd) { byte[] buf = new byte[2500]; - buf[0] = (byte)0x80; + buf[0] = (byte) 0x80; buf[1] = ins; - buf[2] = (byte)0x40; - buf[3] = (byte)0x00; + buf[2] = (byte) 0x40; + buf[3] = (byte) 0x00; buf[4] = 0; short len = encoder.encode(cmd, buf, (short) 7); - Util.setShort(buf, (short)5, len); - byte[] apdu = new byte[7+len]; - Util.arrayCopyNonAtomic(buf,(short)0,apdu,(short)0,(short)(7+len)); + Util.setShort(buf, (short) 5, len); + byte[] apdu = new byte[7 + len]; + Util.arrayCopyNonAtomic(buf, (short) 0, apdu, (short) 0, (short) (7 + len)); //CommandAPDU commandAPDU = new CommandAPDU(0x80, 0x10, 0x40, 0x00, buf, 0, actualLen); return new CommandAPDU(apdu); } @@ -680,53 +686,54 @@ private CommandAPDU encodeApdu(byte ins, short cmd){ @Test public void testAesImportKeySuccess() { init(); - byte[] aesKeySecret = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - short arrPtr = KMArray.instance((short)5); + byte[] aesKeySecret = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + short arrPtr = KMArray.instance((short) 5); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)128)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ECB); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 128)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ECB); short blockMode = KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.PKCS7); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.PKCS7); short paddingMode = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - KMArray.cast(arrPtr).add((short)0, boolTag); - KMArray.cast(arrPtr).add((short)1, keySize); - KMArray.cast(arrPtr).add((short)2, blockMode); - KMArray.cast(arrPtr).add((short)3, paddingMode); - KMArray.cast(arrPtr).add((short)4, KMEnumTag.instance(KMType.ALGORITHM, KMType.AES)); + KMArray.cast(arrPtr).add((short) 0, boolTag); + KMArray.cast(arrPtr).add((short) 1, keySize); + KMArray.cast(arrPtr).add((short) 2, blockMode); + KMArray.cast(arrPtr).add((short) 3, paddingMode); + KMArray.cast(arrPtr).add((short) 4, KMEnumTag.instance(KMType.ALGORITHM, KMType.AES)); short keyParams = KMKeyParameters.instance(arrPtr); short keyFormatPtr = KMEnum.instance(KMType.KEY_FORMAT, KMType.RAW); - short keyBlob = KMArray.instance((short)1); - KMArray.cast(keyBlob).add((short)0, KMByteBlob.instance(aesKeySecret,(short)0,(short)16)); + short keyBlob = KMArray.instance((short) 1); + KMArray.cast(keyBlob).add((short) 0, KMByteBlob.instance(aesKeySecret, (short) 0, (short) 16)); byte[] blob = new byte[256]; - short len = encoder.encode(keyBlob,blob,(short)0); - keyBlob = KMByteBlob.instance(blob, (short)0, len); - arrPtr = KMArray.instance((short)3); + short len = encoder.encode(keyBlob, blob, (short) 0); + keyBlob = KMByteBlob.instance(blob, (short) 0, len); + arrPtr = KMArray.instance((short) 3); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - arg.add((short)1, keyFormatPtr); - arg.add((short)2, keyBlob); - CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_KEY_CMD, arrPtr); + arg.add((short) 1, keyFormatPtr); + arg.add((short) 2, keyBlob); + CommandAPDU apdu = encodeApdu((byte) INS_IMPORT_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); short tag = KMKeyParameters.findTag(KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, hwParams); - Assert.assertEquals(KMBoolTag.cast(tag).getVal(),0x01); + Assert.assertEquals(KMBoolTag.cast(tag).getVal(), 0x01); tag = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.KEYSIZE, hwParams); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 128); tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, hwParams); @@ -743,51 +750,53 @@ public void testAesImportKeySuccess() { @Test public void testHmacImportKeySuccess() { init(); - byte[] hmacKeySecret = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - short arrPtr = KMArray.instance((short)5); + byte[] hmacKeySecret = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + short arrPtr = KMArray.instance((short) 5); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)128)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SHA2_256); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 128)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SHA2_256); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - short minMacLength = KMIntegerTag.instance(KMType.UINT_TAG,KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short)256)); - KMArray.cast(arrPtr).add((short)0, boolTag); - KMArray.cast(arrPtr).add((short)1, keySize); - KMArray.cast(arrPtr).add((short)2, digest); - KMArray.cast(arrPtr).add((short)3, minMacLength); - KMArray.cast(arrPtr).add((short)4, KMEnumTag.instance(KMType.ALGORITHM, KMType.HMAC)); + short minMacLength = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short) 256)); + KMArray.cast(arrPtr).add((short) 0, boolTag); + KMArray.cast(arrPtr).add((short) 1, keySize); + KMArray.cast(arrPtr).add((short) 2, digest); + KMArray.cast(arrPtr).add((short) 3, minMacLength); + KMArray.cast(arrPtr).add((short) 4, KMEnumTag.instance(KMType.ALGORITHM, KMType.HMAC)); short keyParams = KMKeyParameters.instance(arrPtr); short keyFormatPtr = KMEnum.instance(KMType.KEY_FORMAT, KMType.RAW); - short keyBlob = KMArray.instance((short)1); - KMArray.cast(keyBlob).add((short)0, KMByteBlob.instance(hmacKeySecret,(short)0,(short)16)); + short keyBlob = KMArray.instance((short) 1); + KMArray.cast(keyBlob).add((short) 0, KMByteBlob.instance(hmacKeySecret, (short) 0, (short) 16)); byte[] blob = new byte[256]; - short len = encoder.encode(keyBlob,blob,(short)0); - keyBlob = KMByteBlob.instance(blob, (short)0, len); - arrPtr = KMArray.instance((short)3); + short len = encoder.encode(keyBlob, blob, (short) 0); + keyBlob = KMByteBlob.instance(blob, (short) 0, len); + arrPtr = KMArray.instance((short) 3); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - arg.add((short)1, keyFormatPtr); - arg.add((short)2, keyBlob); - CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_KEY_CMD, arrPtr); + arg.add((short) 1, keyFormatPtr); + arg.add((short) 2, keyBlob); + CommandAPDU apdu = encodeApdu((byte) INS_IMPORT_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); short tag = KMKeyParameters.findTag(KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, hwParams); - Assert.assertEquals(KMBoolTag.cast(tag).getVal(),0x01); + Assert.assertEquals(KMBoolTag.cast(tag).getVal(), 0x01); tag = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.KEYSIZE, hwParams); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 128); tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.DIGEST, hwParams); @@ -804,61 +813,64 @@ public void testHmacImportKeySuccess() { @Test public void testRsaImportKeySuccess() { init(); - byte[] pub = new byte[]{0x00,0x01,0x00,0x01}; + byte[] pub = new byte[]{0x00, 0x01, 0x00, 0x01}; byte[] mod = new byte[256]; byte[] priv = new byte[256]; short[] lengths = new short[2]; - cryptoProvider.createAsymmetricKey(KMType.RSA,priv,(short)0,(short)256,mod,(short)0, (short)256,lengths); - short arrPtr = KMArray.instance((short)6); + cryptoProvider + .createAsymmetricKey(KMType.RSA, priv, (short) 0, (short) 256, mod, (short) 0, (short) 256, + lengths); + short arrPtr = KMArray.instance((short) 6); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)2048)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SHA2_256); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 2048)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SHA2_256); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - short rsaPubExpTag = KMIntegerTag.instance(KMType.ULONG_TAG,KMType.RSA_PUBLIC_EXPONENT, - KMInteger.uint_32(pub, (short)0)); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.RSA_PSS); + short rsaPubExpTag = KMIntegerTag.instance(KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, + KMInteger.uint_32(pub, (short) 0)); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.RSA_PSS); short padding = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - KMArray.cast(arrPtr).add((short)0, boolTag); - KMArray.cast(arrPtr).add((short)1, keySize); - KMArray.cast(arrPtr).add((short)2, digest); - KMArray.cast(arrPtr).add((short)3, rsaPubExpTag); - KMArray.cast(arrPtr).add((short)4, KMEnumTag.instance(KMType.ALGORITHM, KMType.RSA)); - KMArray.cast(arrPtr).add((short)5, padding); + KMArray.cast(arrPtr).add((short) 0, boolTag); + KMArray.cast(arrPtr).add((short) 1, keySize); + KMArray.cast(arrPtr).add((short) 2, digest); + KMArray.cast(arrPtr).add((short) 3, rsaPubExpTag); + KMArray.cast(arrPtr).add((short) 4, KMEnumTag.instance(KMType.ALGORITHM, KMType.RSA)); + KMArray.cast(arrPtr).add((short) 5, padding); short keyParams = KMKeyParameters.instance(arrPtr); short keyFormatPtr = KMEnum.instance(KMType.KEY_FORMAT, KMType.RAW);// Note: VTS uses PKCS8 - short keyBlob = KMArray.instance((short)2); - KMArray.cast(keyBlob).add((short)0, KMByteBlob.instance(priv,(short)0,(short)256)); - KMArray.cast(keyBlob).add((short)1, KMByteBlob.instance(mod,(short)0,(short)256)); + short keyBlob = KMArray.instance((short) 2); + KMArray.cast(keyBlob).add((short) 0, KMByteBlob.instance(priv, (short) 0, (short) 256)); + KMArray.cast(keyBlob).add((short) 1, KMByteBlob.instance(mod, (short) 0, (short) 256)); byte[] blob = new byte[620]; - short len = encoder.encode(keyBlob,blob,(short)0); - keyBlob = KMByteBlob.instance(blob, (short)0, len); - arrPtr = KMArray.instance((short)3); + short len = encoder.encode(keyBlob, blob, (short) 0); + keyBlob = KMByteBlob.instance(blob, (short) 0, len); + arrPtr = KMArray.instance((short) 3); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - arg.add((short)1, keyFormatPtr); - arg.add((short)2, keyBlob); - CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_KEY_CMD, arrPtr); + arg.add((short) 1, keyFormatPtr); + arg.add((short) 2, keyBlob); + CommandAPDU apdu = encodeApdu((byte) INS_IMPORT_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); short tag = KMKeyParameters.findTag(KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, hwParams); - Assert.assertEquals(KMBoolTag.cast(tag).getVal(),0x01); + Assert.assertEquals(KMBoolTag.cast(tag).getVal(), 0x01); tag = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.KEYSIZE, hwParams); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 2048); tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.DIGEST, hwParams); @@ -866,7 +878,8 @@ public void testRsaImportKeySuccess() { tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, hwParams); Assert.assertTrue(KMEnumArrayTag.cast(tag).contains(KMType.RSA_PSS)); tag = KMKeyParameters.findTag(KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, hwParams); - Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getSignificantShort(), 0x01); + Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getSignificantShort(), + 0x01); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 0x01); tag = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, hwParams); Assert.assertEquals(KMEnumTag.cast(tag).getValue(), KMType.RSA); @@ -876,58 +889,61 @@ public void testRsaImportKeySuccess() { } @Test - public void testDeviceLocked(){ + public void testDeviceLocked() { init(); byte[] hmacKey = new byte[32]; - cryptoProvider.newRandomNumber(hmacKey,(short)0,(short)32); - KMRepository.instance().initComputedHmac(hmacKey,(short)0,(short)32); + cryptoProvider.newRandomNumber(hmacKey, (short) 0, (short) 32); + KMRepository.instance().initComputedHmac(hmacKey, (short) 0, (short) 32); // generate aes key with unlocked_device_required - short aesKey = generateAesDesKey(KMType.AES,(short)128,null,null, true); - short keyBlobPtr = KMArray.cast(aesKey).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; + short aesKey = generateAesDesKey(KMType.AES, (short) 128, null, null, true); + short keyBlobPtr = KMArray.cast(aesKey).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); // encrypt something short inParams = getAesDesParams(KMType.AES, KMType.ECB, KMType.PKCS7, null); - byte[] plainData= "Hello World 123!".getBytes(); + byte[] plainData = "Hello World 123!".getBytes(); short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false, false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.ENCRYPT, + KMKeyParameters.instance(inParams), + (short) 0, null, false, false ); - keyBlobPtr = KMArray.cast(ret).get((short)2); + keyBlobPtr = KMArray.cast(ret).get((short) 2); byte[] cipherData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - cipherData,(short)0, (short)cipherData.length); + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + cipherData, (short) 0, (short) cipherData.length); // create verification token short verToken = KMVerificationToken.instance(); - KMVerificationToken.cast(verToken).setTimestamp(KMInteger.uint_16((short)1)); + KMVerificationToken.cast(verToken).setTimestamp(KMInteger.uint_16((short) 1)); verToken = signVerificationToken(verToken); // device locked request deviceLock(verToken); // decrypt should fail inParams = getAesDesParams(KMType.AES, KMType.ECB, KMType.PKCS7, null); short beginResp = begin(KMType.DECRYPT, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), KMKeyParameters.instance(inParams), (short)0); - Assert.assertEquals(beginResp,KMError.DEVICE_LOCKED); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(inParams), (short) 0); + Assert.assertEquals(beginResp, KMError.DEVICE_LOCKED); short hwToken = KMHardwareAuthToken.instance(); - KMHardwareAuthToken.cast(hwToken).setTimestamp(KMInteger.uint_16((byte)2)); - KMHardwareAuthToken.cast(hwToken).setHwAuthenticatorType(KMEnum.instance(KMType.USER_AUTH_TYPE, (byte)KMType.PASSWORD)); + KMHardwareAuthToken.cast(hwToken).setTimestamp(KMInteger.uint_16((byte) 2)); + KMHardwareAuthToken.cast(hwToken) + .setHwAuthenticatorType(KMEnum.instance(KMType.USER_AUTH_TYPE, (byte) KMType.PASSWORD)); inParams = getAesDesParams(KMType.AES, KMType.ECB, KMType.PKCS7, null); hwToken = signHwToken(hwToken); - ret = processMessage(cipherData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.DECRYPT, - KMKeyParameters.instance(inParams),hwToken,null,false, false + ret = processMessage(cipherData, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.DECRYPT, + KMKeyParameters.instance(inParams), hwToken, null, false, false ); - ret = KMArray.cast(ret).get((short)0); + ret = KMArray.cast(ret).get((short) 0); Assert.assertEquals(KMInteger.cast(ret).getShort(), KMError.OK); - cleanUp(); + cleanUp(); } - private short signHwToken(short hwToken){ + private short signHwToken(short hwToken) { short len = 0; byte[] scratchPad = new byte[256]; // add 0 @@ -936,17 +952,17 @@ private short signHwToken(short hwToken){ // concatenate challenge - 8 bytes short ptr = KMHardwareAuthToken.cast(hwToken).getChallenge(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // concatenate user id - 8 bytes ptr = KMHardwareAuthToken.cast(hwToken).getUserId(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // concatenate authenticator id - 8 bytes ptr = KMHardwareAuthToken.cast(hwToken).getAuthenticatorId(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // concatenate authenticator type - 4 bytes ptr = KMHardwareAuthToken.cast(hwToken).getHwAuthenticatorType(); @@ -955,7 +971,7 @@ private short signHwToken(short hwToken){ // concatenate timestamp -8 bytes ptr = KMHardwareAuthToken.cast(hwToken).getTimestamp(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // hmac the data /* HMACKey key = @@ -973,26 +989,28 @@ private short signHwToken(short hwToken){ (short)0); */ short key = KMRepository.instance().getComputedHmacKey(); - cryptoProvider.hmacSign( + cryptoProvider.hmacSign( KMByteBlob.cast(key).getBuffer(), KMByteBlob.cast(key).getStartOff(), KMByteBlob.cast(key).length(), scratchPad, (short) 0, len, mac, - (short)0); - KMHardwareAuthToken.cast(hwToken).setMac(KMByteBlob.instance(mac,(short)0,(short)mac.length)); + (short) 0); + KMHardwareAuthToken.cast(hwToken) + .setMac(KMByteBlob.instance(mac, (short) 0, (short) mac.length)); return hwToken; } + private void deviceLock(short verToken) { - short req = KMArray.instance((short)2); - KMArray.cast(req).add((short)0, KMInteger.uint_8((byte)1)); - KMArray.cast(req).add((short)1, verToken); - CommandAPDU apdu = encodeApdu((byte)INS_DEVICE_LOCKED_CMD,req); + short req = KMArray.instance((short) 2); + KMArray.cast(req).add((short) 0, KMInteger.uint_8((byte) 1)); + KMArray.cast(req).add((short) 1, verToken); + CommandAPDU apdu = encodeApdu((byte) INS_DEVICE_LOCKED_CMD, req); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 1); KMArray.cast(ret).add((short) 0, KMInteger.exp()); byte[] respBuf = response.getBytes(); - Assert.assertEquals(respBuf[0],KMError.OK); + Assert.assertEquals(respBuf[0], KMError.OK); } private short signVerificationToken(short verToken) { @@ -1003,17 +1021,17 @@ private short signVerificationToken(short verToken) { Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); short params = KMVerificationToken.cast(verToken).getParametersVerified(); // Add "Auth Verification" - 17 bytes. - Util.arrayCopy(authVer,(short)0, scratchPad, (short)0, (short)authVer.length); - short len = (short)authVer.length; + Util.arrayCopy(authVer, (short) 0, scratchPad, (short) 0, (short) authVer.length); + short len = (short) authVer.length; // concatenate challenge - 8 bytes short ptr = KMVerificationToken.cast(verToken).getChallenge(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // concatenate timestamp -8 bytes ptr = KMVerificationToken.cast(verToken).getTimestamp(); KMInteger.cast(ptr) - .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); + .value(scratchPad, (short) (len + (short) (8 - KMInteger.cast(ptr).length()))); len += 8; // concatenate security level - 4 bytes ptr = KMVerificationToken.cast(verToken).getSecurityLevel(); @@ -1040,13 +1058,14 @@ private short signVerificationToken(short verToken) { (short)0); */ short key = KMRepository.instance().getComputedHmacKey(); - cryptoProvider.hmacSign(KMByteBlob.cast(key).getBuffer(), + cryptoProvider.hmacSign(KMByteBlob.cast(key).getBuffer(), KMByteBlob.cast(key).getStartOff(), KMByteBlob.cast(key).length(), scratchPad, (short) 0, len, mac, - (short)0); - KMVerificationToken.cast(verToken).setMac(KMByteBlob.instance(mac,(short)0,(short)mac.length)); + (short) 0); + KMVerificationToken.cast(verToken) + .setMac(KMByteBlob.instance(mac, (short) 0, (short) mac.length)); return verToken; } @@ -1056,55 +1075,58 @@ public void testEcImportKeySuccess() { byte[] pub = new byte[128]; byte[] priv = new byte[128]; short[] lengths = new short[2]; - cryptoProvider.createAsymmetricKey(KMType.EC,priv,(short)0,(short)128,pub,(short)0, (short)128,lengths); - short pubBlob = KMByteBlob.instance(pub,(short)0,lengths[1]); - short privBlob = KMByteBlob.instance(priv,(short)0,lengths[0]); - short arrPtr = KMArray.instance((short)5); + cryptoProvider + .createAsymmetricKey(KMType.EC, priv, (short) 0, (short) 128, pub, (short) 0, (short) 128, + lengths); + short pubBlob = KMByteBlob.instance(pub, (short) 0, lengths[1]); + short privBlob = KMByteBlob.instance(priv, (short) 0, lengths[0]); + short arrPtr = KMArray.instance((short) 5); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)256)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SHA2_256); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 256)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SHA2_256); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); short ecCurve = KMEnumTag.instance(KMType.ECCURVE, KMType.P_256); - KMArray.cast(arrPtr).add((short)0, boolTag); - KMArray.cast(arrPtr).add((short)1, keySize); - KMArray.cast(arrPtr).add((short)2, digest); - KMArray.cast(arrPtr).add((short)3, ecCurve); - KMArray.cast(arrPtr).add((short)4, KMEnumTag.instance(KMType.ALGORITHM, KMType.EC)); + KMArray.cast(arrPtr).add((short) 0, boolTag); + KMArray.cast(arrPtr).add((short) 1, keySize); + KMArray.cast(arrPtr).add((short) 2, digest); + KMArray.cast(arrPtr).add((short) 3, ecCurve); + KMArray.cast(arrPtr).add((short) 4, KMEnumTag.instance(KMType.ALGORITHM, KMType.EC)); short keyParams = KMKeyParameters.instance(arrPtr); short keyFormatPtr = KMEnum.instance(KMType.KEY_FORMAT, KMType.RAW);// Note: VTS uses PKCS8 - short keyBlob = KMArray.instance((short)2); - KMArray.cast(keyBlob).add((short)0, privBlob); - KMArray.cast(keyBlob).add((short)1, pubBlob); + short keyBlob = KMArray.instance((short) 2); + KMArray.cast(keyBlob).add((short) 0, privBlob); + KMArray.cast(keyBlob).add((short) 1, pubBlob); byte[] blob = new byte[128]; - short len = encoder.encode(keyBlob,blob,(short)0); - keyBlob = KMByteBlob.instance(blob, (short)0, len); - arrPtr = KMArray.instance((short)3); + short len = encoder.encode(keyBlob, blob, (short) 0); + keyBlob = KMByteBlob.instance(blob, (short) 0, len); + arrPtr = KMArray.instance((short) 3); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - arg.add((short)1, keyFormatPtr); - arg.add((short)2, keyBlob); - CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_KEY_CMD, arrPtr); + arg.add((short) 1, keyFormatPtr); + arg.add((short) 2, keyBlob); + CommandAPDU apdu = encodeApdu((byte) INS_IMPORT_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short blobArr = extractKeyBlobArray(KMArray.cast(ret).get((short)1)); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short blobArr = extractKeyBlobArray(KMArray.cast(ret).get((short) 1)); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); short tag = KMKeyParameters.findTag(KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, hwParams); - Assert.assertEquals(KMBoolTag.cast(tag).getVal(),0x01); + Assert.assertEquals(KMBoolTag.cast(tag).getVal(), 0x01); tag = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.KEYSIZE, hwParams); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 256); tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.DIGEST, hwParams); @@ -1127,27 +1149,27 @@ private short extractKeyBlobArray(byte[] buf, short off, short buflen) { KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_KEYCHAR, ptr); KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, KMByteBlob.exp()); ret = - decoder.decodeArray( - ret, - buf, off, buflen); + decoder.decodeArray( + ret, + buf, off, buflen); short len = KMArray.cast(ret).length(); - ptr = KMArray.cast(ret).get((short)4); + ptr = KMArray.cast(ret).get((short) 4); // print(KMByteBlob.cast(ptr).getBuffer(),KMByteBlob.cast(ptr).getStartOff(),KMByteBlob.cast(ptr).length()); return ret; } private short extractKeyBlobArray(short keyBlob) { return extractKeyBlobArray(KMByteBlob.cast(keyBlob).getBuffer(), KMByteBlob - .cast(keyBlob).getStartOff(), KMByteBlob.cast(keyBlob).length()); + .cast(keyBlob).getStartOff(), KMByteBlob.cast(keyBlob).length()); } @Test public void testRsaGenerateKeySuccess() { init(); short ret = generateRsaKey(null, null); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(error, KMError.OK); @@ -1158,7 +1180,8 @@ public void testRsaGenerateKeySuccess() { tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, hwParams); Assert.assertTrue(KMEnumArrayTag.cast(tag).contains(KMType.RSA_PKCS1_1_5_ENCRYPT)); tag = KMKeyParameters.findTag(KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, hwParams); - Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getSignificantShort(), 0x01); + Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getSignificantShort(), + 0x01); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 0x01); tag = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, hwParams); Assert.assertEquals(KMEnumTag.cast(tag).getValue(), KMType.RSA); @@ -1167,34 +1190,40 @@ public void testRsaGenerateKeySuccess() { cleanUp(); } - private short generateRsaKey(byte[] clientId, byte[] appData){ - byte[] activeAndCreationDateTime = {0,0,0x01,0x73,0x51,0x7C,(byte)0xCC,0x00}; + private short generateRsaKey(byte[] clientId, byte[] appData) { + byte[] activeAndCreationDateTime = {0, 0, 0x01, 0x73, 0x51, 0x7C, (byte) 0xCC, 0x00}; short tagCount = 11; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } short arrPtr = KMArray.instance(tagCount); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)2048)); - short byteBlob = KMByteBlob.instance((short)3); - KMByteBlob.cast(byteBlob).add((short)0, KMType.DIGEST_NONE); - KMByteBlob.cast(byteBlob).add((short)1, KMType.SHA2_256); - KMByteBlob.cast(byteBlob).add((short)2, KMType.SHA1); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 2048)); + short byteBlob = KMByteBlob.instance((short) 3); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.DIGEST_NONE); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.SHA2_256); + KMByteBlob.cast(byteBlob).add((short) 2, KMType.SHA1); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - byteBlob = KMByteBlob.instance((short)5); - KMByteBlob.cast(byteBlob).add((short)0, KMType.RSA_PKCS1_1_5_ENCRYPT); - KMByteBlob.cast(byteBlob).add((short)1, KMType.RSA_PKCS1_1_5_SIGN); - KMByteBlob.cast(byteBlob).add((short)2, KMType.RSA_OAEP); - KMByteBlob.cast(byteBlob).add((short)3, KMType.RSA_PSS); - KMByteBlob.cast(byteBlob).add((short)4, KMType.PADDING_NONE); + byteBlob = KMByteBlob.instance((short) 5); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.RSA_PKCS1_1_5_ENCRYPT); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.RSA_PKCS1_1_5_SIGN); + KMByteBlob.cast(byteBlob).add((short) 2, KMType.RSA_OAEP); + KMByteBlob.cast(byteBlob).add((short) 3, KMType.RSA_PSS); + KMByteBlob.cast(byteBlob).add((short) 4, KMType.PADDING_NONE); short padding = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - byteBlob = KMByteBlob.instance((short)5); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SIGN); - KMByteBlob.cast(byteBlob).add((short)1, KMType.VERIFY); - KMByteBlob.cast(byteBlob).add((short)2, KMType.ENCRYPT); - KMByteBlob.cast(byteBlob).add((short)3, KMType.DECRYPT); - KMByteBlob.cast(byteBlob).add((short)4, KMType.WRAP_KEY); + byteBlob = KMByteBlob.instance((short) 5); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SIGN); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.VERIFY); + KMByteBlob.cast(byteBlob).add((short) 2, KMType.ENCRYPT); + KMByteBlob.cast(byteBlob).add((short) 3, KMType.DECRYPT); + KMByteBlob.cast(byteBlob).add((short) 4, KMType.WRAP_KEY); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); - byte[] pub = {0,1,0,1}; - short rsaPubExpTag = KMIntegerTag.instance(KMType.ULONG_TAG,KMType.RSA_PUBLIC_EXPONENT, KMInteger.uint_32(pub, (short)0)); + byte[] pub = {0, 1, 0, 1}; + short rsaPubExpTag = KMIntegerTag + .instance(KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, KMInteger.uint_32(pub, (short) 0)); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, purpose); @@ -1206,25 +1235,33 @@ private short generateRsaKey(byte[] clientId, byte[] appData){ KMArray.cast(arrPtr).add(tagIndex++, rsaPubExpTag); KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, KMType.RSA)); KMArray.cast(arrPtr).add(tagIndex++, padding); - short dateTag = KMInteger.uint_64(activeAndCreationDateTime,(short)0); - KMArray.cast(arrPtr).add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG,KMType.ACTIVE_DATETIME,dateTag)); - KMArray.cast(arrPtr).add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG,KMType.CREATION_DATETIME,dateTag)); - - if(clientId != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + short dateTag = KMInteger.uint_64(activeAndCreationDateTime, (short) 0); + KMArray.cast(arrPtr) + .add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG, KMType.ACTIVE_DATETIME, dateTag)); + KMArray.cast(arrPtr) + .add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG, KMType.CREATION_DATETIME, dateTag)); + + if (clientId != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); @@ -1233,25 +1270,27 @@ private short generateRsaKey(byte[] clientId, byte[] appData){ return ret; } - private short generateAttestationKey(){ + private short generateAttestationKey() { // 15th July 2020 00.00.00 - byte[] activeAndCreationDateTime = {0,0,0x01,0x73,0x51,0x7C,(byte)0xCC,0x00}; + byte[] activeAndCreationDateTime = {0, 0, 0x01, 0x73, 0x51, 0x7C, (byte) 0xCC, 0x00}; short tagCount = 11; short arrPtr = KMArray.instance(tagCount); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)2048)); - short byteBlob = KMByteBlob.instance((short)3); - KMByteBlob.cast(byteBlob).add((short)0, KMType.DIGEST_NONE); - KMByteBlob.cast(byteBlob).add((short)1, KMType.SHA2_256); - KMByteBlob.cast(byteBlob).add((short)2, KMType.SHA1); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 2048)); + short byteBlob = KMByteBlob.instance((short) 3); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.DIGEST_NONE); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.SHA2_256); + KMByteBlob.cast(byteBlob).add((short) 2, KMType.SHA1); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.RSA_PKCS1_1_5_SIGN); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.RSA_PKCS1_1_5_SIGN); short padding = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ATTEST_KEY); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ATTEST_KEY); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); - byte[] pub = {0,1,0,1}; - short rsaPubExpTag = KMIntegerTag.instance(KMType.ULONG_TAG,KMType.RSA_PUBLIC_EXPONENT, KMInteger.uint_32(pub, (short)0)); + byte[] pub = {0, 1, 0, 1}; + short rsaPubExpTag = KMIntegerTag + .instance(KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, KMInteger.uint_32(pub, (short) 0)); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, purpose); @@ -1264,20 +1303,22 @@ private short generateAttestationKey(){ KMArray.cast(arrPtr).add(tagIndex++, rsaPubExpTag); KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, KMType.RSA)); KMArray.cast(arrPtr).add(tagIndex++, padding); - short dateTag = KMInteger.uint_64(activeAndCreationDateTime,(short)0); - KMArray.cast(arrPtr).add(tagIndex++, KMIntegerTag.instance(KMType.ULONG_TAG,KMType.ACTIVE_DATETIME,dateTag)); - KMArray.cast(arrPtr).add(tagIndex++, KMIntegerTag.instance(KMType.ULONG_TAG,KMType.CREATION_DATETIME,dateTag)); + short dateTag = KMInteger.uint_64(activeAndCreationDateTime, (short) 0); + KMArray.cast(arrPtr) + .add(tagIndex++, KMIntegerTag.instance(KMType.ULONG_TAG, KMType.ACTIVE_DATETIME, dateTag)); + KMArray.cast(arrPtr).add(tagIndex++, + KMIntegerTag.instance(KMType.ULONG_TAG, KMType.CREATION_DATETIME, dateTag)); short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); @@ -1290,9 +1331,9 @@ private short generateAttestationKey(){ public void testEcGenerateKeySuccess() { init(); short ret = generateEcKey(null, null); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(error, KMError.OK); @@ -1306,20 +1347,26 @@ public void testEcGenerateKeySuccess() { Assert.assertEquals(KMEnumTag.cast(tag).getValue(), KMType.GENERATED); cleanUp(); } + public short generateEcKey(byte[] clientId, byte[] appData) { - byte[] activeAndCreationDateTime = {0,0,0x01,0x73,0x51,0x7C,(byte)0xCC,0x00}; + byte[] activeAndCreationDateTime = {0, 0, 0x01, 0x73, 0x51, 0x7C, (byte) 0xCC, 0x00}; short tagCount = 6; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } short arrPtr = KMArray.instance(tagCount); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)256)); - short byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.DIGEST_NONE); - KMByteBlob.cast(byteBlob).add((short)1, KMType.SHA2_256); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 256)); + short byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.DIGEST_NONE); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.SHA2_256); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SIGN); - KMByteBlob.cast(byteBlob).add((short)1, KMType.VERIFY); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SIGN); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.VERIFY); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); short tagIndex = 0; @@ -1328,23 +1375,30 @@ public short generateEcKey(byte[] clientId, byte[] appData) { KMArray.cast(arrPtr).add(tagIndex++, keySize); KMArray.cast(arrPtr).add(tagIndex++, digest); KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, KMType.EC)); - short dateTag = KMInteger.uint_64(activeAndCreationDateTime,(short)0); - KMArray.cast(arrPtr).add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG,KMType.CREATION_DATETIME,dateTag)); - if(clientId != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + short dateTag = KMInteger.uint_64(activeAndCreationDateTime, (short) 0); + KMArray.cast(arrPtr) + .add(tagIndex++, KMIntegerTag.instance(KMType.DATE_TAG, KMType.CREATION_DATETIME, dateTag)); + if (clientId != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); @@ -1357,9 +1411,9 @@ public short generateEcKey(byte[] clientId, byte[] appData) { public void testHmacGenerateKeySuccess() { init(); short ret = generateHmacKey(null, null); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(error, KMError.OK); @@ -1375,21 +1429,28 @@ public void testHmacGenerateKeySuccess() { Assert.assertEquals(KMEnumTag.cast(tag).getValue(), KMType.GENERATED); cleanUp(); } - public short generateHmacKey(byte[] clientId, byte[] appData){ + + public short generateHmacKey(byte[] clientId, byte[] appData) { short tagCount = 6; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } short arrPtr = KMArray.instance(tagCount); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)128)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SHA2_256); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 128)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SHA2_256); short digest = KMEnumArrayTag.instance(KMType.DIGEST, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.SIGN); - KMByteBlob.cast(byteBlob).add((short)1, KMType.VERIFY); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.SIGN); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.VERIFY); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short minMacLen = KMIntegerTag.instance(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short)/*256*/160)); + short minMacLen = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short)/*256*/160)); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, minMacLen); KMArray.cast(arrPtr).add(tagIndex++, purpose); @@ -1397,50 +1458,65 @@ public short generateHmacKey(byte[] clientId, byte[] appData){ KMArray.cast(arrPtr).add(tagIndex++, keySize); KMArray.cast(arrPtr).add(tagIndex++, digest); KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, KMType.HMAC)); - if(clientId != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + if (clientId != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); return ret; } - public short generateAesDesKey(byte alg, short keysize, byte[] clientId, byte[] appData, boolean unlockReqd) { + + public short generateAesDesKey(byte alg, short keysize, byte[] clientId, byte[] appData, + boolean unlockReqd) { short tagCount = 7; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; - if(unlockReqd)tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } + if (unlockReqd) { + tagCount++; + } short arrPtr = KMArray.instance(tagCount); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16(keysize)); - short byteBlob = KMByteBlob.instance((short)3); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ECB); - KMByteBlob.cast(byteBlob).add((short)1, KMType.CBC); - KMByteBlob.cast(byteBlob).add((short)2, KMType.CTR); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16(keysize)); + short byteBlob = KMByteBlob.instance((short) 3); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ECB); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.CBC); + KMByteBlob.cast(byteBlob).add((short) 2, KMType.CTR); short blockModeTag = KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.PKCS7); - KMByteBlob.cast(byteBlob).add((short)1, KMType.PADDING_NONE); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.PKCS7); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.PADDING_NONE); short paddingMode = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ENCRYPT); - KMByteBlob.cast(byteBlob).add((short)1, KMType.DECRYPT); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ENCRYPT); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.DECRYPT); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, boolTag); @@ -1450,48 +1526,63 @@ public short generateAesDesKey(byte alg, short keysize, byte[] clientId, byte[] KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, alg)); KMArray.cast(arrPtr).add(tagIndex++, purpose); KMArray.cast(arrPtr).add(tagIndex++, KMBoolTag.instance(KMType.CALLER_NONCE)); - if(unlockReqd)KMArray.cast(arrPtr).add(tagIndex++, KMBoolTag.instance(KMType.UNLOCKED_DEVICE_REQUIRED)); - if(clientId != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + if (unlockReqd) { + KMArray.cast(arrPtr).add(tagIndex++, KMBoolTag.instance(KMType.UNLOCKED_DEVICE_REQUIRED)); + } + if (clientId != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); return ret; } + public short generateAesGcmKey(short keysize, byte[] clientId, byte[] appData) { short tagCount = 8; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } short arrPtr = KMArray.instance(tagCount); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16(keysize)); - short macLength = KMIntegerTag.instance(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short)96)); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.GCM); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16(keysize)); + short macLength = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, KMInteger.uint_16((short) 96)); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.GCM); short blockModeTag = KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, KMType.PADDING_NONE); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.PADDING_NONE); short paddingMode = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ENCRYPT); - KMByteBlob.cast(byteBlob).add((short)1, KMType.DECRYPT); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ENCRYPT); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.DECRYPT); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, boolTag); @@ -1502,83 +1593,90 @@ public short generateAesGcmKey(short keysize, byte[] clientId, byte[] appData) { KMArray.cast(arrPtr).add(tagIndex++, KMEnumTag.instance(KMType.ALGORITHM, KMType.AES)); KMArray.cast(arrPtr).add(tagIndex++, purpose); KMArray.cast(arrPtr).add(tagIndex++, KMBoolTag.instance(KMType.CALLER_NONCE)); - if(clientId != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(arrPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + if (clientId != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(arrPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } short keyParams = KMKeyParameters.instance(arrPtr); - arrPtr = KMArray.instance((short)1); + arrPtr = KMArray.instance((short) 1); KMArray arg = KMArray.cast(arrPtr); arg.add((short) 0, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_GENERATE_KEY_CMD, arrPtr); + CommandAPDU apdu = encodeApdu((byte) INS_GENERATE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); return ret; } @Test - public void testComputeHmacParams(){ + public void testComputeHmacParams() { init(); // Get Hmac parameters short ret = getHmacSharingParams(); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - KMHmacSharingParameters params = KMHmacSharingParameters.cast(KMArray.cast(ret).get((short)1)); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + KMHmacSharingParameters params = KMHmacSharingParameters.cast(KMArray.cast(ret).get((short) 1)); short seed = params.getSeed(); short nonce = params.getNonce(); short params1 = KMHmacSharingParameters.instance(); - KMHmacSharingParameters.cast(params1).setSeed(KMByteBlob.instance((short)0)); - short num = KMByteBlob.instance((short)32); + KMHmacSharingParameters.cast(params1).setSeed(KMByteBlob.instance((short) 0)); + short num = KMByteBlob.instance((short) 32); Util.arrayCopyNonAtomic( - KMByteBlob.cast(nonce).getBuffer(), - KMByteBlob.cast(nonce).getStartOff(), - KMByteBlob.cast(num).getBuffer(), - KMByteBlob.cast(num).getStartOff(), - KMByteBlob.cast(num).length()); + KMByteBlob.cast(nonce).getBuffer(), + KMByteBlob.cast(nonce).getStartOff(), + KMByteBlob.cast(num).getBuffer(), + KMByteBlob.cast(num).getStartOff(), + KMByteBlob.cast(num).length()); KMHmacSharingParameters.cast(params1).setNonce(num); short params2 = KMHmacSharingParameters.instance(); - KMHmacSharingParameters.cast(params2).setSeed(KMByteBlob.instance((short)0)); - num = KMByteBlob.instance((short)32); + KMHmacSharingParameters.cast(params2).setSeed(KMByteBlob.instance((short) 0)); + num = KMByteBlob.instance((short) 32); cryptoProvider.newRandomNumber( - KMByteBlob.cast(num).getBuffer(), - KMByteBlob.cast(num).getStartOff(), - KMByteBlob.cast(num).length()); + KMByteBlob.cast(num).getBuffer(), + KMByteBlob.cast(num).getStartOff(), + KMByteBlob.cast(num).length()); KMHmacSharingParameters.cast(params2).setNonce(num); - short arr = KMArray.instance((short)2); - KMArray.cast(arr).add((short)0, params1); - KMArray.cast(arr).add((short)1,params2); - short arrPtr = KMArray.instance((short)1); - KMArray.cast(arrPtr).add((short)0,arr); - CommandAPDU apdu = encodeApdu((byte)INS_COMPUTE_SHARED_HMAC_CMD, arrPtr); + short arr = KMArray.instance((short) 2); + KMArray.cast(arr).add((short) 0, params1); + KMArray.cast(arr).add((short) 1, params2); + short arrPtr = KMArray.instance((short) 1); + KMArray.cast(arrPtr).add((short) 0, arr); + CommandAPDU apdu = encodeApdu((byte) INS_COMPUTE_SHARED_HMAC_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); Assert.assertEquals(0x9000, response.getSW()); - ret = KMArray.instance((short) 2); + ret = KMArray.instance((short) 2); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); cleanUp(); } + @Test - public void testGetHmacSharingParams(){ + public void testGetHmacSharingParams() { init(); CommandAPDU commandAPDU = new CommandAPDU(0x80, INS_GET_HMAC_SHARING_PARAM_CMD, 0x40, 0x00); //print(commandAPDU.getBytes()); @@ -1591,8 +1689,8 @@ public void testGetHmacSharingParams(){ byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - KMHmacSharingParameters params = KMHmacSharingParameters.cast(KMArray.cast(ret).get((short)1)); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + KMHmacSharingParameters params = KMHmacSharingParameters.cast(KMArray.cast(ret).get((short) 1)); short seed = params.getSeed(); short nonce = params.getNonce(); Assert.assertTrue(KMByteBlob.cast(seed).length() == 0); @@ -1602,7 +1700,8 @@ public void testGetHmacSharingParams(){ Assert.assertEquals(error, KMError.OK); cleanUp(); } - public short getHmacSharingParams(){ + + public short getHmacSharingParams() { CommandAPDU commandAPDU = new CommandAPDU(0x80, INS_GET_HMAC_SHARING_PARAM_CMD, 0x40, 0x00); //print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(commandAPDU); @@ -1618,58 +1717,60 @@ public short getHmacSharingParams(){ } @Test - public void testImportWrappedKey(){ + public void testImportWrappedKey() { init(); byte[] wrappedKey = new byte[16]; - cryptoProvider.newRandomNumber(wrappedKey,(short)0,(short)16); + cryptoProvider.newRandomNumber(wrappedKey, (short) 0, (short) 16); byte[] encWrappedKey = new byte[16]; byte[] transportKeyMaterial = new byte[32]; - cryptoProvider.newRandomNumber(transportKeyMaterial,(short)0,(short)32); + cryptoProvider.newRandomNumber(transportKeyMaterial, (short) 0, (short) 32); byte[] nonce = new byte[12]; - cryptoProvider.newRandomNumber(nonce,(short)0,(short)12); + cryptoProvider.newRandomNumber(nonce, (short) 0, (short) 12); byte[] authData = "Auth Data".getBytes(); byte[] authTag = new byte[16]; - cryptoProvider.aesGCMEncrypt(transportKeyMaterial,(short)0,(short)32,wrappedKey, - (short)0,(short)16,encWrappedKey,(short)0, - nonce,(short)0, (short)12,authData,(short)0,(short)authData.length, - authTag, (short)0, (short)16); - byte[] maskingKey = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}; + cryptoProvider.aesGCMEncrypt(transportKeyMaterial, (short) 0, (short) 32, wrappedKey, + (short) 0, (short) 16, encWrappedKey, (short) 0, + nonce, (short) 0, (short) 12, authData, (short) 0, (short) authData.length, + authTag, (short) 0, (short) 16); + byte[] maskingKey = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0}; byte[] maskedTransportKey = new byte[32]; - for(int i=0; i< maskingKey.length;i++){ - maskedTransportKey[i] = (byte)(transportKeyMaterial[i] ^ maskingKey[i]); + for (int i = 0; i < maskingKey.length; i++) { + maskedTransportKey[i] = (byte) (transportKeyMaterial[i] ^ maskingKey[i]); } - short rsaKeyArr = generateRsaKey(null,null); - short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short)1); - byte[] wrappingKeyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; + short rsaKeyArr = generateRsaKey(null, null); + short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short) 1); + byte[] wrappingKeyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length); + KMByteBlob.cast(keyBlobPtr).getStartOff(), + wrappingKeyBlob, (short) 0, (short) wrappingKeyBlob.length); byte[] output = new byte[256]; short outlen = rsaOaepEncryptMessage(wrappingKeyBlob, KMType.SHA2_256, - maskedTransportKey, (short)0, (short)maskedTransportKey.length, - output, (short)0); + maskedTransportKey, (short) 0, (short) maskedTransportKey.length, + output, (short) 0); Assert.assertTrue((outlen == 256)); byte[] encTransportKey = new byte[outlen]; - Util.arrayCopyNonAtomic(output, (short)0, encTransportKey, (short)0, - outlen); + Util.arrayCopyNonAtomic(output, (short) 0, encTransportKey, (short) 0, + outlen); //Clean the heap. KMRepository.instance().clean(); short tagCount = 7; short arrPtr = KMArray.instance(tagCount); short boolTag = KMBoolTag.instance(KMType.NO_AUTH_REQUIRED); - short keySize = KMIntegerTag.instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short)128)); - short byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ECB); - KMByteBlob.cast(byteBlob).add((short)1, KMType.CBC); + short keySize = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.KEYSIZE, KMInteger.uint_16((short) 128)); + short byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ECB); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.CBC); short blockModeTag = KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.PKCS7); - KMByteBlob.cast(byteBlob).add((short)1, KMType.PADDING_NONE); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.PKCS7); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.PADDING_NONE); short paddingMode = KMEnumArrayTag.instance(KMType.PADDING, byteBlob); - byteBlob = KMByteBlob.instance((short)2); - KMByteBlob.cast(byteBlob).add((short)0, KMType.ENCRYPT); - KMByteBlob.cast(byteBlob).add((short)1, KMType.DECRYPT); + byteBlob = KMByteBlob.instance((short) 2); + KMByteBlob.cast(byteBlob).add((short) 0, KMType.ENCRYPT); + KMByteBlob.cast(byteBlob).add((short) 1, KMType.DECRYPT); short purpose = KMEnumArrayTag.instance(KMType.PURPOSE, byteBlob); short tagIndex = 0; KMArray.cast(arrPtr).add(tagIndex++, boolTag); @@ -1680,41 +1781,48 @@ public void testImportWrappedKey(){ KMArray.cast(arrPtr).add(tagIndex++, purpose); KMArray.cast(arrPtr).add(tagIndex++, KMBoolTag.instance(KMType.CALLER_NONCE)); short keyParams = KMKeyParameters.instance(arrPtr); - short nullParams = KMArray.instance((short)0); + short nullParams = KMArray.instance((short) 0); nullParams = KMKeyParameters.instance(nullParams); - short arr = KMArray.instance((short)12); + short arr = KMArray.instance((short) 12); KMArray.cast(arr).add((short) 0, keyParams); // Key Params of wrapped key - KMArray.cast(arr).add((short) 1, KMEnum.instance(KMType.KEY_FORMAT,KMType.RAW)); // Key Format - KMArray.cast(arr).add((short) 2, KMByteBlob.instance(encWrappedKey,(short)0,(short)encWrappedKey.length)); // Wrapped Import Key Blob - KMArray.cast(arr).add((short) 3, KMByteBlob.instance(authTag,(short)0,(short)authTag.length)); // Auth Tag - KMArray.cast(arr).add((short) 4, KMByteBlob.instance(nonce,(short)0,(short)nonce.length)); // IV - Nonce - KMArray.cast(arr).add((short) 5, KMByteBlob.instance(encTransportKey,(short)0,(short)encTransportKey.length)); // Encrypted Transport Key - KMArray.cast(arr).add((short) 6, KMByteBlob.instance(wrappingKeyBlob,(short)0, (short)wrappingKeyBlob.length)); // Wrapping Key KeyBlob - KMArray.cast(arr).add((short) 7, KMByteBlob.instance(maskingKey,(short)0,(short)maskingKey.length)); // Masking Key + KMArray.cast(arr).add((short) 1, KMEnum.instance(KMType.KEY_FORMAT, KMType.RAW)); // Key Format + KMArray.cast(arr).add((short) 2, KMByteBlob.instance(encWrappedKey, (short) 0, + (short) encWrappedKey.length)); // Wrapped Import Key Blob + KMArray.cast(arr).add((short) 3, + KMByteBlob.instance(authTag, (short) 0, (short) authTag.length)); // Auth Tag + KMArray.cast(arr) + .add((short) 4, KMByteBlob.instance(nonce, (short) 0, (short) nonce.length)); // IV - Nonce + KMArray.cast(arr).add((short) 5, KMByteBlob.instance(encTransportKey, (short) 0, + (short) encTransportKey.length)); // Encrypted Transport Key + KMArray.cast(arr).add((short) 6, KMByteBlob.instance(wrappingKeyBlob, (short) 0, + (short) wrappingKeyBlob.length)); // Wrapping Key KeyBlob + KMArray.cast(arr).add((short) 7, + KMByteBlob.instance(maskingKey, (short) 0, (short) maskingKey.length)); // Masking Key KMArray.cast(arr).add((short) 8, nullParams); // Un-wrapping Params - KMArray.cast(arr).add((short) 9, KMByteBlob.instance(authData,(short)0,(short)authData.length)); // Wrapped Key ASSOCIATED AUTH DATA - KMArray.cast(arr).add((short) 10, KMInteger.uint_8((byte)0)); // Password Sid - KMArray.cast(arr).add((short) 11, KMInteger.uint_8((byte)0)); // Biometric Sid - CommandAPDU apdu = encodeApdu((byte)INS_IMPORT_WRAPPED_KEY_CMD, arr); + KMArray.cast(arr).add((short) 9, KMByteBlob.instance(authData, (short) 0, + (short) authData.length)); // Wrapped Key ASSOCIATED AUTH DATA + KMArray.cast(arr).add((short) 10, KMInteger.uint_8((byte) 0)); // Password Sid + KMArray.cast(arr).add((short) 11, KMInteger.uint_8((byte) 0)); // Biometric Sid + CommandAPDU apdu = encodeApdu((byte) INS_IMPORT_WRAPPED_KEY_CMD, arr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); short inst = KMKeyCharacteristics.exp(); KMArray.cast(ret).add((short) 2, inst); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short)1)).length(); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + short keyBlobLength = KMByteBlob.cast(KMArray.cast(ret).get((short) 1)).length(); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); Assert.assertEquals(0x9000, response.getSW()); Assert.assertEquals(error, KMError.OK); short tag = KMKeyParameters.findTag(KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, hwParams); - Assert.assertEquals(KMBoolTag.cast(tag).getVal(),0x01); + Assert.assertEquals(KMBoolTag.cast(tag).getVal(), 0x01); tag = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.KEYSIZE, hwParams); Assert.assertEquals(KMInteger.cast(KMIntegerTag.cast(tag).getValue()).getShort(), 128); tag = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, hwParams); @@ -1733,16 +1841,18 @@ public void testGetKeyCharacteristicsWithIdDataSuccess() { init(); byte[] clientId = "clientId".getBytes(); byte[] appData = "appData".getBytes(); - short ret = generateRsaKey(clientId,appData); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short ret = generateRsaKey(clientId, appData); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); - short keyBlob = KMArray.cast(ret).get((short)1); - - short arrPtr = KMArray.instance((short)3); - KMArray.cast(arrPtr).add((short)0, keyBlob); - KMArray.cast(arrPtr).add((short)1, KMByteBlob.instance(clientId,(short)0, (short)clientId.length)); - KMArray.cast(arrPtr).add((short)2, KMByteBlob.instance(appData,(short)0, (short)appData.length)); - CommandAPDU apdu = encodeApdu((byte)INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); + short keyBlob = KMArray.cast(ret).get((short) 1); + + short arrPtr = KMArray.instance((short) 3); + KMArray.cast(arrPtr).add((short) 0, keyBlob); + KMArray.cast(arrPtr) + .add((short) 1, KMByteBlob.instance(clientId, (short) 0, (short) clientId.length)); + KMArray.cast(arrPtr) + .add((short) 2, KMByteBlob.instance(appData, (short) 0, (short) appData.length)); + CommandAPDU apdu = encodeApdu((byte) INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); ret = KMArray.instance((short) 2); @@ -1752,7 +1862,7 @@ public void testGetKeyCharacteristicsWithIdDataSuccess() { byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); cleanUp(); } @@ -1761,15 +1871,15 @@ public void testGetKeyCharacteristicsWithIdDataSuccess() { public void testGetKeyCharacteristicsSuccess() { init(); short ret = generateRsaKey(null, null); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); - short keyBlob = KMArray.cast(ret).get((short)1); + short keyBlob = KMArray.cast(ret).get((short) 1); - short arrPtr = KMArray.instance((short)3); - KMArray.cast(arrPtr).add((short)0, keyBlob); - KMArray.cast(arrPtr).add((short)1, KMByteBlob.instance((short)0)); - KMArray.cast(arrPtr).add((short)2, KMByteBlob.instance((short)0)); - CommandAPDU apdu = encodeApdu((byte)INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); + short arrPtr = KMArray.instance((short) 3); + KMArray.cast(arrPtr).add((short) 0, keyBlob); + KMArray.cast(arrPtr).add((short) 1, KMByteBlob.instance((short) 0)); + KMArray.cast(arrPtr).add((short) 2, KMByteBlob.instance((short) 0)); + CommandAPDU apdu = encodeApdu((byte) INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); ret = KMArray.instance((short) 2); @@ -1779,7 +1889,7 @@ public void testGetKeyCharacteristicsSuccess() { byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); cleanUp(); } @@ -1788,13 +1898,13 @@ public void testGetKeyCharacteristicsSuccess() { public void testDeleteKeySuccess() { init(); short ret = generateRsaKey(null, null); - short keyBlobPtr = KMArray.cast(ret).get((short)1); + short keyBlobPtr = KMArray.cast(ret).get((short) 1); byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - short len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob, (short)0); + short len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob, (short) 0); ret = getKeyCharacteristics(keyBlobPtr); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); - ret = deleteKey(KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); + ret = deleteKey(KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length)); Assert.assertEquals(ret, KMError.OK); cleanUp(); } @@ -1803,13 +1913,13 @@ public void testDeleteKeySuccess() { public void testDeleteAllKeySuccess() { init(); short ret1 = generateRsaKey(null, null); - short keyBlobPtr = KMArray.cast(ret1).get((short)1); + short keyBlobPtr = KMArray.cast(ret1).get((short) 1); byte[] keyBlob1 = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - short len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob1, (short)0); + short len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob1, (short) 0); short ret2 = generateRsaKey(null, null); - keyBlobPtr = KMArray.cast(ret2).get((short)1); + keyBlobPtr = KMArray.cast(ret2).get((short) 1); byte[] keyBlob2 = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob2, (short)0); + len = KMByteBlob.cast(keyBlobPtr).getValues(keyBlob2, (short) 0); CommandAPDU apdu = new CommandAPDU(0x80, INS_DELETE_ALL_KEYS_CMD, 0x40, 0x00); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); @@ -1819,9 +1929,9 @@ public void testDeleteAllKeySuccess() { } private short deleteKey(short keyBlob) { - short arrPtr = KMArray.instance((short)1); - KMArray.cast(arrPtr).add((short)0, keyBlob); - CommandAPDU apdu = encodeApdu((byte)INS_DELETE_KEY_CMD, arrPtr); + short arrPtr = KMArray.instance((short) 1); + KMArray.cast(arrPtr).add((short) 0, keyBlob); + CommandAPDU apdu = encodeApdu((byte) INS_DELETE_KEY_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); byte[] respBuf = response.getBytes(); @@ -1829,21 +1939,21 @@ private short deleteKey(short keyBlob) { } private short abort(short opHandle) { - short arrPtr = KMArray.instance((short)1); - KMArray.cast(arrPtr).add((short)0, opHandle); - CommandAPDU apdu = encodeApdu((byte)INS_ABORT_OPERATION_CMD, arrPtr); + short arrPtr = KMArray.instance((short) 1); + KMArray.cast(arrPtr).add((short) 0, opHandle); + CommandAPDU apdu = encodeApdu((byte) INS_ABORT_OPERATION_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); byte[] respBuf = response.getBytes(); return respBuf[0]; } - public short getKeyCharacteristics(short keyBlob){ - short arrPtr = KMArray.instance((short)3); - KMArray.cast(arrPtr).add((short)0, keyBlob); - KMArray.cast(arrPtr).add((short)1, KMByteBlob.instance((short)0)); - KMArray.cast(arrPtr).add((short)2, KMByteBlob.instance((short)0)); - CommandAPDU apdu = encodeApdu((byte)INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); + public short getKeyCharacteristics(short keyBlob) { + short arrPtr = KMArray.instance((short) 3); + KMArray.cast(arrPtr).add((short) 0, keyBlob); + KMArray.cast(arrPtr).add((short) 1, KMByteBlob.instance((short) 0)); + KMArray.cast(arrPtr).add((short) 2, KMByteBlob.instance((short) 0)); + CommandAPDU apdu = encodeApdu((byte) INS_GET_KEY_CHARACTERISTICS_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 2); @@ -1852,157 +1962,170 @@ public short getKeyCharacteristics(short keyBlob){ KMArray.cast(ret).add((short) 1, inst); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; - if( len > 5) + if (len > 5) { ret = decoder.decode(ret, respBuf, (short) 0, len); - else - ret = KMByteBlob.instance(respBuf, (short)0, len); + } else { + ret = KMByteBlob.instance(respBuf, (short) 0, len); + } return ret; } @Test - public void testWithAesGcmWithUpdate(){ + public void testWithAesGcmWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.GCM, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.GCM, KMType.PADDING_NONE, true); cleanUp(); } + @Test - public void testWithAesEcbPkcs7WithUpdate(){ + public void testWithAesEcbPkcs7WithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PKCS7,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PKCS7, true); cleanUp(); } @Test - public void testWithAesCtrNoPadWithUpdate(){ + public void testWithAesCtrNoPadWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CTR, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CTR, KMType.PADDING_NONE, true); cleanUp(); } @Test - public void testWithAesCtrNoPad(){ + public void testWithAesCtrNoPad() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CTR, KMType.PADDING_NONE,false); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CTR, KMType.PADDING_NONE, false); cleanUp(); } @Test - public void testWithAesEcbNoPadWithUpdate(){ + public void testWithAesEcbNoPadWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PADDING_NONE, true); cleanUp(); } + @Test - public void testWithDesEcbPkcs7WithUpdate(){ + public void testWithDesEcbPkcs7WithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PKCS7,true); + testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PKCS7, true); cleanUp(); } + @Test - public void testWithDesEcbNoPadWithUpdate(){ + public void testWithDesEcbNoPadWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PADDING_NONE, true); cleanUp(); } + @Test - public void testWithAesCbcPkcs7WithUpdate(){ + public void testWithAesCbcPkcs7WithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PKCS7,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PKCS7, true); cleanUp(); } + @Test - public void testWithAesCbcNoPadWithUpdate(){ + public void testWithAesCbcNoPadWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PADDING_NONE, true); cleanUp(); } + @Test - public void testWithDesCbcPkcs7WithUpdate(){ + public void testWithDesCbcPkcs7WithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PKCS7,true); + testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PKCS7, true); cleanUp(); } + @Test - public void testWithDesCbcNoPadWithUpdate(){ + public void testWithDesCbcNoPadWithUpdate() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PADDING_NONE,true); + testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PADDING_NONE, true); cleanUp(); } @Test - public void testWithAesEcbPkcs7(){ + public void testWithAesEcbPkcs7() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PKCS7,false); + testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PKCS7, false); cleanUp(); } + @Test - public void testWithAesCbcPkcs7(){ + public void testWithAesCbcPkcs7() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PKCS7,false); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PKCS7, false); cleanUp(); } + @Test - public void testWithAesEcbNoPad(){ + public void testWithAesEcbNoPad() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PADDING_NONE,false); + testEncryptDecryptWithAesDes(KMType.AES, KMType.ECB, KMType.PADDING_NONE, false); cleanUp(); } @Test - public void testWithAesCbcNoPad(){ + public void testWithAesCbcNoPad() { init(); - testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PADDING_NONE,false); + testEncryptDecryptWithAesDes(KMType.AES, KMType.CBC, KMType.PADDING_NONE, false); cleanUp(); } @Test - public void testWithDesCbcPkcs7(){ + public void testWithDesCbcPkcs7() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PKCS7,false); + testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PKCS7, false); cleanUp(); } @Test - public void testWithDesCbcNoPad(){ + public void testWithDesCbcNoPad() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PADDING_NONE,false); + testEncryptDecryptWithAesDes(KMType.DES, KMType.CBC, KMType.PADDING_NONE, false); cleanUp(); } + @Test - public void testWithDesEcbNoPad(){ + public void testWithDesEcbNoPad() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PADDING_NONE,false); + testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PADDING_NONE, false); cleanUp(); } + @Test - public void testWithDesEcbPkcs7(){ + public void testWithDesEcbPkcs7() { init(); - testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PKCS7,false); + testEncryptDecryptWithAesDes(KMType.DES, KMType.ECB, KMType.PKCS7, false); cleanUp(); } @Test - public void testWithRsa256Oaep(){ + public void testWithRsa256Oaep() { init(); testEncryptDecryptWithRsa(KMType.SHA2_256, KMType.RSA_OAEP); cleanUp(); } + @Test - public void testWithRsaSha1Oaep(){ + public void testWithRsaSha1Oaep() { init(); testEncryptDecryptWithRsa(KMType.SHA1, KMType.RSA_OAEP); cleanUp(); } @Test - public void testWithRsaNonePkcs1(){ + public void testWithRsaNonePkcs1() { init(); testEncryptDecryptWithRsa(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_ENCRYPT); cleanUp(); } @Test - public void testWithRsaNoneNoPad(){ + public void testWithRsaNoneNoPad() { init(); testEncryptDecryptWithRsa(KMType.DIGEST_NONE, KMType.PADDING_NONE); cleanUp(); @@ -2010,62 +2133,64 @@ public void testWithRsaNoneNoPad(){ // TODO Signing with no digest is not supported by crypto provider or javacard @Test - public void testSignWithRsaNoneNoPad(){ + public void testSignWithRsaNoneNoPad() { init(); - testSignVerifyWithRsa(KMType.DIGEST_NONE, KMType.PADDING_NONE,false, false); + testSignVerifyWithRsa(KMType.DIGEST_NONE, KMType.PADDING_NONE, false, false); cleanUp(); } @Test - public void testSignWithRsaNonePkcs1(){ + public void testSignWithRsaNonePkcs1() { init(); - testSignVerifyWithRsa(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_SIGN,false, false); + testSignVerifyWithRsa(KMType.DIGEST_NONE, KMType.RSA_PKCS1_1_5_SIGN, false, false); cleanUp(); } public short getPublicKey(byte[] keyBlob, short off, short len, - byte[] pubKey, short pubKeyOff) { + byte[] pubKey, short pubKeyOff) { short keyBlobPtr = extractKeyBlobArray(keyBlob, off, len); short arrayLen = KMArray.cast(keyBlobPtr).length(); if (arrayLen < 5) { return 0; } short pubKeyPtr = KMArray.cast(keyBlobPtr).get( - KMKeymasterApplet.KEY_BLOB_PUB_KEY); + KMKeymasterApplet.KEY_BLOB_PUB_KEY); Util.arrayCopy(KMByteBlob.cast(pubKeyPtr).getBuffer(), - KMByteBlob.cast(pubKeyPtr).getStartOff(), pubKey, pubKeyOff, - KMByteBlob.cast(pubKeyPtr).length()); + KMByteBlob.cast(pubKeyPtr).getStartOff(), pubKey, pubKeyOff, + KMByteBlob.cast(pubKeyPtr).length()); return KMByteBlob.cast(pubKeyPtr).length(); } - private String toHexString(byte[] num){ + private String toHexString(byte[] num) { StringBuilder sb = new StringBuilder(); - for(int i = 0; i < num.length; i++){ - sb.append(String.format("%02X", num[i])) ; - } + for (int i = 0; i < num.length; i++) { + sb.append(String.format("%02X", num[i])); + } return sb.toString(); } - public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte[] input, short inputOff, short inputlen, - byte[] output, short outputOff) { + public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte[] input, + short inputOff, short inputlen, + byte[] output, short outputOff) { byte alg = Cipher.ALG_RSA_PKCS1; byte[] tmp = null; short inLen = inputlen; if (padding == KMType.PADDING_NONE) { alg = Cipher.ALG_RSA_NOPAD; // Length cannot be greater then key size according to JcardSim - if(inLen >= 256) + if (inLen >= 256) { return 0; + } // make input equal to 255 bytes tmp = new byte[255]; - Util.arrayFillNonAtomic(tmp,(short)0,(short)255, (byte)0); + Util.arrayFillNonAtomic(tmp, (short) 0, (short) 255, (byte) 0); Util.arrayCopyNonAtomic( - input, - inputOff, - tmp, (short)(255 - inLen),inLen); + input, + inputOff, + tmp, (short) (255 - inLen), inLen); inLen = 255; inputOff = 0; - } else if(padding == KMType.RSA_PKCS1_1_5_ENCRYPT) { + } else if (padding == KMType.RSA_PKCS1_1_5_ENCRYPT) { tmp = input; } else { /*Fail */ @@ -2074,10 +2199,11 @@ public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte byte[] pubKey = new byte[256]; KeyPair rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyPair.getPublic(); - if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + if (0 == getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, pubKey, (short) 0)) { return 0; + } - byte[] exponent = new byte[]{0x01,0x00,0x01}; + byte[] exponent = new byte[]{0x01, 0x00, 0x01}; rsaPubKey.setModulus(pubKey, (short) 0, (short) pubKey.length); rsaPubKey.setExponent(exponent, (short) 0, (short) exponent.length); @@ -2086,38 +2212,41 @@ public short rsaEncryptMessage(byte[] keyBlob, short padding, short digest, byte return rsaCipher.doFinal(tmp, inputOff, inLen, output, outputOff); } - public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, short inputOff, short inputlen, - byte[] output, short outputOff) { + public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, short inputOff, + short inputlen, + byte[] output, short outputOff) { byte[] mod = new byte[256]; - if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, mod, (short)0)) + if (0 == getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, mod, (short) 0)) { return 0; - byte[] exponent = new byte[]{0x01,0x00,0x01}; + } + byte[] exponent = new byte[]{0x01, 0x00, 0x01}; // Convert byte arrays into keys String modString = toHexString(mod); String expString = toHexString(exponent); - BigInteger modInt = new BigInteger(modString,16); - BigInteger expInt = new BigInteger(expString,16); + BigInteger modInt = new BigInteger(modString, 16); + BigInteger expInt = new BigInteger(expString, 16); javax.crypto.Cipher rsaCipher = null; - try{ + try { KeyFactory kf = KeyFactory.getInstance("RSA"); // Create cipher with oaep padding OAEPParameterSpec oaepSpec = null; - if(digest == KMType.SHA2_256){ - oaepSpec= new OAEPParameterSpec("SHA-256", "MGF1", - MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); - }else{ - oaepSpec= new OAEPParameterSpec("SHA1", "MGF1", - MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + if (digest == KMType.SHA2_256) { + oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); + } else { + oaepSpec = new OAEPParameterSpec("SHA1", "MGF1", + MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT); } rsaCipher = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPPadding", "SunJCE"); RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modInt, expInt); - java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf.generatePublic(pubSpec); + java.security.interfaces.RSAPublicKey pubKey = (java.security.interfaces.RSAPublicKey) kf + .generatePublic(pubSpec); rsaCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, pubKey, oaepSpec); byte[] cipherOut = rsaCipher.doFinal(input, inputOff, inputlen); - if(cipherOut != null) { + if (cipherOut != null) { Util.arrayCopyNonAtomic(cipherOut, (short) 0, output, outputOff, (short) cipherOut.length); } return (short) cipherOut.length; @@ -2142,25 +2271,26 @@ public short rsaOaepEncryptMessage(byte[] keyBlob, short digest, byte[] input, s } public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, - short inputlen, byte[] sign, short signOff, short signLen, - byte[] keyBlob) { + short inputlen, byte[] sign, short signOff, short signLen, + byte[] keyBlob) { KeyFactory kf; byte[] pubKey = new byte[128]; short keyStart = 0; short keyLength = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, - pubKey, (short) 0); - if (keyLength == 0) + pubKey, (short) 0); + if (keyLength == 0) { return false; + } try { java.security.Signature sunSigner = java.security.Signature.getInstance( - "NONEwithECDSA", "SunEC"); + "NONEwithECDSA", "SunEC"); kf = KeyFactory.getInstance("EC"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC", - "SunEC"); + "SunEC"); // Supported curve secp256r1 parameters.init(new ECGenParameterSpec("secp256r1")); ECParameterSpec ecParameters = parameters - .getParameterSpec(ECParameterSpec.class); + .getParameterSpec(ECParameterSpec.class); // Check if the first byte is 04 and remove it. if (pubKey[keyStart] == 0x04) { @@ -2182,7 +2312,7 @@ public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, ECPoint point = new ECPoint(bIX, bIY); ECPublicKeySpec pubkeyspec = new ECPublicKeySpec(point, ecParameters); java.security.interfaces.ECPublicKey ecPubkey = (java.security.interfaces.ECPublicKey) kf - .generatePublic(pubkeyspec); + .generatePublic(pubkeyspec); sunSigner.initVerify(ecPubkey); sunSigner.update(input, inputOff, inputlen); return sunSigner.verify(sign, signOff, signLen); @@ -2203,87 +2333,92 @@ public boolean ecNoDigestVerifyMessage(byte[] input, short inputOff, } public boolean ecVerifyMessage(byte[] input, short inputOff, short inputlen, - byte[] sign, short signOff, short signLen, byte[] keyBlob) { + byte[] sign, short signOff, short signLen, byte[] keyBlob) { Signature ecVerifier; byte[] pubKey = new byte[128]; short len = getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, - pubKey, (short) 0); + pubKey, (short) 0); if (len == 0) { return false; } ECPublicKey key = (ECPublicKey) KeyBuilder.buildKey( - KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); + KeyBuilder.TYPE_EC_FP_PUBLIC, KeyBuilder.LENGTH_EC_FP_256, false); key.setW(pubKey, (short) 0, len); ecVerifier = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false); ecVerifier.init(key, Signature.MODE_VERIFY); return ecVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); } - public boolean rsaVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] sign, short signOff, short signLen, - short digest,short padding, byte[] keyBlob) { - if(digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) + public boolean rsaVerifyMessage(byte[] input, short inputOff, short inputlen, byte[] sign, + short signOff, short signLen, + short digest, short padding, byte[] keyBlob) { + if (digest == KMType.DIGEST_NONE || padding == KMType.PADDING_NONE) { return false; + } byte[] pubKey = new byte[256]; - if (0 == getPublicKey(keyBlob, (short)0, (short)keyBlob.length, pubKey, (short)0)) + if (0 == getPublicKey(keyBlob, (short) 0, (short) keyBlob.length, pubKey, (short) 0)) { return false; + } short alg = Signature.ALG_RSA_SHA_256_PKCS1_PSS; - if (padding == KMType.RSA_PKCS1_1_5_SIGN) + if (padding == KMType.RSA_PKCS1_1_5_SIGN) { alg = Signature.ALG_RSA_SHA_256_PKCS1; + } - Signature rsaVerifier = Signature.getInstance((byte)alg, false); - RSAPublicKey key = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); - byte[] exponent = new byte[]{0x01,0x00,0x01}; - key.setExponent(exponent,(short)0,(short)exponent.length); - key.setModulus(pubKey, (short)0, (short)pubKey.length); - rsaVerifier.init(key,Signature.MODE_VERIFY); + Signature rsaVerifier = Signature.getInstance((byte) alg, false); + RSAPublicKey key = (RSAPublicKey) KeyBuilder + .buildKey(KeyBuilder.TYPE_RSA_PUBLIC, KeyBuilder.LENGTH_RSA_2048, false); + byte[] exponent = new byte[]{0x01, 0x00, 0x01}; + key.setExponent(exponent, (short) 0, (short) exponent.length); + key.setModulus(pubKey, (short) 0, (short) pubKey.length); + rsaVerifier.init(key, Signature.MODE_VERIFY); return rsaVerifier.verify(input, inputOff, inputlen, sign, signOff, signLen); } public byte[] EncryptMessage(byte[] input, short params, byte[] keyBlob) { short ret = begin(KMType.ENCRYPT, - KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - KMKeyParameters.instance(params), (short) 0); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(params), (short) 0); // Get the operation handle. short opHandle = KMArray.cast(ret).get((short) 2); byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, - (short) opHandleBuf.length); + (short) opHandleBuf.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); ret = finish(opHandle, - KMByteBlob.instance(input, (short) 0, (short) input.length), null, - (short) 0, (short) 0, (short) 0, KMError.OK); + KMByteBlob.instance(input, (short) 0, (short) input.length), null, + (short) 0, (short) 0, (short) 0, KMError.OK); short dataPtr = KMArray.cast(ret).get((short) 2); byte[] output = new byte[KMByteBlob.cast(dataPtr).length()]; if (KMByteBlob.cast(dataPtr).length() > 0) { Util.arrayCopyNonAtomic(KMByteBlob.cast(dataPtr).getBuffer(), KMByteBlob .cast(dataPtr).getStartOff(), output, (short) 0, - KMByteBlob.cast(dataPtr).length()); + KMByteBlob.cast(dataPtr).length()); } return output; } public byte[] DecryptMessage(byte[] input, short params, byte[] keyBlob) { short ret = begin(KMType.DECRYPT, - KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - KMKeyParameters.instance(params), (short) 0); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(params), (short) 0); // Get the operation handle. short opHandle = KMArray.cast(ret).get((short) 2); byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, - (short) opHandleBuf.length); + (short) opHandleBuf.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); ret = finish(opHandle, - KMByteBlob.instance(input, (short) 0, (short) input.length), null, - (short) 0, (short) 0, (short) 0, KMError.OK); + KMByteBlob.instance(input, (short) 0, (short) input.length), null, + (short) 0, (short) 0, (short) 0, KMError.OK); short dataPtr = KMArray.cast(ret).get((short) 2); byte[] output = new byte[KMByteBlob.cast(dataPtr).length()]; if (KMByteBlob.cast(dataPtr).length() > 0) { Util.arrayCopyNonAtomic(KMByteBlob.cast(dataPtr).getBuffer(), KMByteBlob .cast(dataPtr).getStartOff(), output, (short) 0, - KMByteBlob.cast(dataPtr).length()); + KMByteBlob.cast(dataPtr).length()); } return output; } @@ -2302,12 +2437,12 @@ public void testDesEcbPkcs7PaddingCorrupted() { byte[] keyBlob = new byte[KMByteBlob.cast(desKeyPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(desKeyPtr).getBuffer(), KMByteBlob .cast(desKeyPtr).getStartOff(), keyBlob, (short) 0, - (short) keyBlob.length); + (short) keyBlob.length); byte[] message = { - 0x61 }; + 0x61}; short desPkcs7Params = getAesDesParams(KMType.DES, KMType.ECB, - KMType.PKCS7, null); + KMType.PKCS7, null); byte[] cipherText1 = EncryptMessage(message, desPkcs7Params, keyBlob); Assert.assertEquals(8, cipherText1.length); Assert.assertFalse(Arrays.equals(message, cipherText1)); @@ -2320,21 +2455,21 @@ public void testDesEcbPkcs7PaddingCorrupted() { desPkcs7Params = getAesDesParams(KMType.DES, KMType.ECB, KMType.PKCS7, null); short ret = begin(KMType.DECRYPT, - KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - KMKeyParameters.instance(desPkcs7Params), (short) 0); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(desPkcs7Params), (short) 0); // Get the operation handle. short opHandle = KMArray.cast(ret).get((short) 2); byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, - (short) opHandleBuf.length); + (short) opHandleBuf.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); // Finish short dataPtr = KMByteBlob.instance(cipherText1, (short) 0, - (short) cipherText1.length); + (short) cipherText1.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, - KMError.INVALID_ARGUMENT); + KMError.INVALID_ARGUMENT); cleanUp(); } @@ -2342,37 +2477,39 @@ public void testDesEcbPkcs7PaddingCorrupted() { public void testVtsRsaPkcs1Success() { init(); byte[] message = { - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, - 0x21 }; // "Hello World!"; + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, + 0x21}; // "Hello World!"; for (int i = 0; i < 250; i++) { short key = generateRsaKey(null, null); short rsaKeyPtr = KMArray.cast(key).get((short) 1); byte[] keyBlob = new byte[KMByteBlob.cast(rsaKeyPtr).length()]; Util.arrayCopyNonAtomic(KMByteBlob.cast(rsaKeyPtr).getBuffer(), - KMByteBlob.cast(rsaKeyPtr).getStartOff(), keyBlob, (short) 0, - (short) keyBlob.length); + KMByteBlob.cast(rsaKeyPtr).getStartOff(), keyBlob, (short) 0, + (short) keyBlob.length); short pkcs1Params = getRsaParams(KMType.DIGEST_NONE, - KMType.RSA_PKCS1_1_5_ENCRYPT); + KMType.RSA_PKCS1_1_5_ENCRYPT); byte[] cipherText1 = new byte[256]; - short cipherText1Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, - message, (short)0, (short)message.length, - cipherText1, (short)0); + short cipherText1Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, + KMType.DIGEST_NONE, + message, (short) 0, (short) message.length, + cipherText1, (short) 0); Assert.assertEquals((2048 / 8), cipherText1Len); pkcs1Params = getRsaParams(KMType.DIGEST_NONE, - KMType.RSA_PKCS1_1_5_ENCRYPT); + KMType.RSA_PKCS1_1_5_ENCRYPT); byte[] cipherText2 = new byte[256]; - short cipherText2Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, KMType.DIGEST_NONE, - message, (short)0, (short)message.length, - cipherText2, (short)0); + short cipherText2Len = rsaEncryptMessage(keyBlob, KMType.RSA_PKCS1_1_5_ENCRYPT, + KMType.DIGEST_NONE, + message, (short) 0, (short) message.length, + cipherText2, (short) 0); Assert.assertEquals((2048 / 8), cipherText2Len); // PKCS1 v1.5 randomizes padding so every result should be different. Assert.assertFalse(Arrays.equals(cipherText1, cipherText2)); pkcs1Params = getRsaParams(KMType.DIGEST_NONE, - KMType.RSA_PKCS1_1_5_ENCRYPT); + KMType.RSA_PKCS1_1_5_ENCRYPT); byte[] plainText = DecryptMessage(cipherText1, pkcs1Params, keyBlob); Assert.assertTrue(Arrays.equals(message, plainText)); @@ -2386,76 +2523,79 @@ public void testVtsRsaPkcs1Success() { cipherText1[offset_to_corrupt] = corrupt_byte; pkcs1Params = getRsaParams(KMType.DIGEST_NONE, - KMType.RSA_PKCS1_1_5_ENCRYPT); + KMType.RSA_PKCS1_1_5_ENCRYPT); // Do Begin operation. short ret = begin(KMType.DECRYPT, - KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - KMKeyParameters.instance(pkcs1Params), (short) 0); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(pkcs1Params), (short) 0); // Get the operation handle. short opHandle = KMArray.cast(ret).get((short) 2); byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, - (short) opHandleBuf.length); + (short) opHandleBuf.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); short dataPtr = KMByteBlob.instance(cipherText1, (short) 0, - (short) cipherText1.length); + (short) cipherText1.length); // Finish should return UNKNOWN_ERROR. ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, - KMError.UNKNOWN_ERROR); + KMError.UNKNOWN_ERROR); } cleanUp(); } @Test - public void testSignVerifyWithHmacSHA256WithUpdate(){ + public void testSignVerifyWithHmacSHA256WithUpdate() { init(); testSignVerifyWithHmac(KMType.SHA2_256, true); cleanUp(); } @Test - public void testSignVerifyWithHmacSHA256(){ + public void testSignVerifyWithHmacSHA256() { init(); testSignVerifyWithHmac(KMType.SHA2_256, false); cleanUp(); } @Test - public void testSignVerifyWithEcdsaSHA256WithUpdate(){ + public void testSignVerifyWithEcdsaSHA256WithUpdate() { init(); testSignVerifyWithEcdsa(KMType.SHA2_256, true); cleanUp(); } + @Test - public void testSignVerifyWithEcdsaSHA256(){ + public void testSignVerifyWithEcdsaSHA256() { init(); testSignVerifyWithEcdsa(KMType.SHA2_256, false); cleanUp(); } + @Test - public void testSignVerifyWithRsaSHA256Pkcs1(){ + public void testSignVerifyWithRsaSHA256Pkcs1() { init(); - testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PKCS1_1_5_SIGN,false, true); + testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PKCS1_1_5_SIGN, false, true); cleanUp(); } + @Test - public void testSignVerifyWithRsaSHA256Pss(){ + public void testSignVerifyWithRsaSHA256Pss() { init(); - testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PSS,false, true); + testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PSS, false, true); cleanUp(); } @Test - public void testSignVerifyWithRsaSHA256Pkcs1WithUpdate(){ + public void testSignVerifyWithRsaSHA256Pkcs1WithUpdate() { init(); - testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PKCS1_1_5_SIGN,true, true); + testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PKCS1_1_5_SIGN, true, true); cleanUp(); } @Test - public void testProvisionSuccess(){ + public void testProvisionSuccess() { AID appletAID1 = AIDUtil.create("A000000062"); simulator.installApplet(appletAID1, KMJCardSimApplet.class); // Select applet @@ -2466,88 +2606,90 @@ public void testProvisionSuccess(){ } @Test - public void testAttestRsaKey(){ + public void testAttestRsaKey() { init(); - short key = generateRsaKey(null,null); - short keyBlobPtr = KMArray.cast(key).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; + short key = generateRsaKey(null, null); + short keyBlobPtr = KMArray.cast(key).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic( - KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); testAttestKey(keyBlob); cleanUp(); } @Test - public void testAttestEcKey(){ + public void testAttestEcKey() { init(); - short key = generateEcKey(null,null); - short keyBlobPtr = KMArray.cast(key).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; + short key = generateEcKey(null, null); + short keyBlobPtr = KMArray.cast(key).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; Util.arrayCopyNonAtomic( - KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); testAttestKey(keyBlob); cleanUp(); } - public void testAttestKey(byte[] keyBlob){ - short arrPtr = KMArray.instance((short)2); - KMArray.cast(arrPtr).add((short)0, KMByteTag.instance(KMType.ATTESTATION_APPLICATION_ID, - KMByteBlob.instance(attAppId,(short)0,(short)attAppId.length))); - KMArray.cast(arrPtr).add((short)1, KMByteTag.instance(KMType.ATTESTATION_CHALLENGE, - KMByteBlob.instance(attChallenge,(short)0,(short)attChallenge.length))); + public void testAttestKey(byte[] keyBlob) { + short arrPtr = KMArray.instance((short) 2); + KMArray.cast(arrPtr).add((short) 0, KMByteTag.instance(KMType.ATTESTATION_APPLICATION_ID, + KMByteBlob.instance(attAppId, (short) 0, (short) attAppId.length))); + KMArray.cast(arrPtr).add((short) 1, KMByteTag.instance(KMType.ATTESTATION_CHALLENGE, + KMByteBlob.instance(attChallenge, (short) 0, (short) attChallenge.length))); short keyParams = KMKeyParameters.instance(arrPtr); - short args = KMArray.instance((short)2); - KMArray.cast(args).add((short)0, KMByteBlob.instance(keyBlob,(short)0,(short)keyBlob.length)); - KMArray.cast(args).add((short)1, keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_ATTEST_KEY_CMD, args); + short args = KMArray.instance((short) 2); + KMArray.cast(args) + .add((short) 0, KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length)); + KMArray.cast(args).add((short) 1, keyParams); + CommandAPDU apdu = encodeApdu((byte) INS_ATTEST_KEY_CMD, args); //print(apdu.getBytes(),(short)0,(short)apdu.getBytes().length); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 2); - short arrBlobs = KMArray.instance((short)1); - KMArray.cast(arrBlobs).add((short)0, KMByteBlob.exp()); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, arrBlobs); + short arrBlobs = KMArray.instance((short) 1); + KMArray.cast(arrBlobs).add((short) 0, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 0, KMInteger.exp()); + KMArray.cast(ret).add((short) 1, arrBlobs); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; - //(respBuf,(short)0,(short)respBuf.length); + //(respBuf,(short)0,(short)respBuf.length); ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); - arrBlobs = KMArray.cast(ret).get((short)1); - short cert = KMArray.cast(arrBlobs).get((short)0); + arrBlobs = KMArray.cast(ret).get((short) 1); + short cert = KMArray.cast(arrBlobs).get((short) 0); //printCert(KMByteBlob.cast(cert).getBuffer(),KMByteBlob.cast(cert).getStartOff(),KMByteBlob.cast(cert).length()); } @Test - public void testUpgradeKey(){ + public void testUpgradeKey() { init(); short ret = generateHmacKey(null, null); - short keyBlobPtr = KMArray.cast(ret).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); - short keyCharacteristics = KMArray.cast(ret).get((short)2); + short keyBlobPtr = KMArray.cast(ret).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); + short keyCharacteristics = KMArray.cast(ret).get((short) 2); short hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); short swParams = KMKeyCharacteristics.cast(keyCharacteristics).getSoftwareEnforced(); - short osVersion = KMKeyParameters.findTag(KMType.UINT_TAG,KMType.OS_VERSION,hwParams); + short osVersion = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.OS_VERSION, hwParams); osVersion = KMIntegerTag.cast(osVersion).getValue(); - short osPatch = KMKeyParameters.findTag(KMType.UINT_TAG,KMType.OS_PATCH_LEVEL,hwParams); + short osPatch = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.OS_PATCH_LEVEL, hwParams); osPatch = KMIntegerTag.cast(osPatch).getValue(); Assert.assertEquals(KMInteger.cast(osVersion).getShort(), 1); Assert.assertEquals(KMInteger.cast(osPatch).getShort(), 1); - setBootParams(simulator,(short) 2,(short)2, (short)1, (short)1); - ret = upgradeKey(KMByteBlob.instance(keyBlob, (short)0, (short)keyBlob.length),null, null); - keyBlobPtr = KMArray.cast(ret).get((short)1); + setBootParams(simulator, (short) 2, (short) 2, (short) 1, (short) 1); + ret = upgradeKey(KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), null, null); + keyBlobPtr = KMArray.cast(ret).get((short) 1); ret = getKeyCharacteristics(keyBlobPtr); - keyCharacteristics = KMArray.cast(ret).get((short)1); + keyCharacteristics = KMArray.cast(ret).get((short) 1); hwParams = KMKeyCharacteristics.cast(keyCharacteristics).getHardwareEnforced(); - osVersion = KMKeyParameters.findTag(KMType.UINT_TAG,KMType.OS_VERSION,hwParams); + osVersion = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.OS_VERSION, hwParams); osVersion = KMIntegerTag.cast(osVersion).getValue(); - osPatch = KMKeyParameters.findTag(KMType.UINT_TAG,KMType.OS_PATCH_LEVEL,hwParams); + osPatch = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.OS_PATCH_LEVEL, hwParams); osPatch = KMIntegerTag.cast(osPatch).getValue(); Assert.assertEquals(KMInteger.cast(osVersion).getShort(), 2); Assert.assertEquals(KMInteger.cast(osPatch).getShort(), 2); @@ -2555,7 +2697,7 @@ public void testUpgradeKey(){ } @Test - public void testDestroyAttIds(){ + public void testDestroyAttIds() { init(); CommandAPDU commandAPDU = new CommandAPDU(0x80, INS_DESTROY_ATT_IDS_CMD, 0x40, 0x00); ResponseAPDU response = simulator.transmitCommand(commandAPDU); @@ -2564,54 +2706,70 @@ public void testDestroyAttIds(){ cleanUp(); } - private short upgradeKey(short keyBlobPtr, byte[] clientId, byte[] appData){ + private short upgradeKey(short keyBlobPtr, byte[] clientId, byte[] appData) { short tagCount = 0; short clientIdTag = 0; short appDataTag = 0; - if(clientId != null) tagCount++; - if(appData != null) tagCount++; + if (clientId != null) { + tagCount++; + } + if (appData != null) { + tagCount++; + } short keyParams = KMArray.instance(tagCount); - short tagIndex=0; - if(clientId != null)KMArray.cast(keyBlobPtr).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_ID, KMByteBlob.instance(clientId,(short)0,(short)clientId.length))); - if(appData != null)KMArray.cast(keyParams).add(tagIndex++, - KMByteTag.instance(KMType.APPLICATION_DATA, KMByteBlob.instance(appData,(short)0,(short)appData.length))); + short tagIndex = 0; + if (clientId != null) { + KMArray.cast(keyBlobPtr).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_ID, + KMByteBlob.instance(clientId, (short) 0, (short) clientId.length))); + } + if (appData != null) { + KMArray.cast(keyParams).add(tagIndex++, + KMByteTag.instance(KMType.APPLICATION_DATA, + KMByteBlob.instance(appData, (short) 0, (short) appData.length))); + } keyParams = KMKeyParameters.instance(keyParams); - short arr = KMArray.instance((short)2); - KMArray.cast(arr).add((short)0,keyBlobPtr); - KMArray.cast(arr).add((short)1,keyParams); - CommandAPDU apdu = encodeApdu((byte)INS_UPGRADE_KEY_CMD, arr); + short arr = KMArray.instance((short) 2); + KMArray.cast(arr).add((short) 0, keyBlobPtr); + KMArray.cast(arr).add((short) 1, keyParams); + CommandAPDU apdu = encodeApdu((byte) INS_UPGRADE_KEY_CMD, arr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 2); KMArray.cast(ret).add((short) 0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 1, KMByteBlob.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); return ret; } + @Test - public void testSignVerifyWithRsaSHA256PssWithUpdate(){ + public void testSignVerifyWithRsaSHA256PssWithUpdate() { init(); - testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PSS,true, true); + testSignVerifyWithRsa(KMType.SHA2_256, KMType.RSA_PSS, true, true); cleanUp(); } + @Test - public void testAbortOperation(){ + public void testAbortOperation() { init(); - short aesDesKeyArr = generateAesDesKey(KMType.AES, (short)128,null, null, false);; - short keyBlobPtr = KMArray.cast(aesDesKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + short aesDesKeyArr = generateAesDesKey(KMType.AES, (short) 128, null, null, false); + ; + short keyBlobPtr = KMArray.cast(aesDesKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); byte[] nonce = new byte[16]; - cryptoProvider.newRandomNumber(nonce,(short)0,(short)16); - short inParams = getAesDesParams(KMType.AES,KMType.ECB, KMType.PKCS7, nonce); - byte[] plainData= "Hello World 123!".getBytes(); - short ret = begin(KMType.ENCRYPT, KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), KMKeyParameters.instance(inParams), (short)0); + cryptoProvider.newRandomNumber(nonce, (short) 0, (short) 16); + short inParams = getAesDesParams(KMType.AES, KMType.ECB, KMType.PKCS7, nonce); + byte[] plainData = "Hello World 123!".getBytes(); + short ret = begin(KMType.ENCRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(inParams), (short) 0); short opHandle = KMArray.cast(ret).get((short) 2); byte[] opHandleBuf = new byte[KMRepository.OPERATION_HANDLE_SIZE]; KMInteger.cast(opHandle).getValue(opHandleBuf, (short) 0, (short) opHandleBuf.length); @@ -2620,65 +2778,70 @@ public void testAbortOperation(){ short dataPtr = KMByteBlob.instance(plainData, (short) 0, (short) plainData.length); opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); ret = update(opHandle, dataPtr, (short) 0, (short) 0, (short) 0); - Assert.assertEquals(KMError.INVALID_OPERATION_HANDLE,ret); + Assert.assertEquals(KMError.INVALID_OPERATION_HANDLE, ret); cleanUp(); } - public void testEncryptDecryptWithAesDes(byte alg, byte blockMode, byte padding, boolean update){ + public void testEncryptDecryptWithAesDes(byte alg, byte blockMode, byte padding, boolean update) { short aesDesKeyArr; boolean aesGcmFlag = false; - if(alg == KMType.AES){ - if(blockMode == KMType.GCM){ - aesDesKeyArr = generateAesGcmKey((short)128,null,null); + if (alg == KMType.AES) { + if (blockMode == KMType.GCM) { + aesDesKeyArr = generateAesGcmKey((short) 128, null, null); aesGcmFlag = true; } else { aesDesKeyArr = generateAesDesKey(alg, (short) 128, null, null, false); } - } else{ - aesDesKeyArr = generateAesDesKey(alg, (short)168,null, null, false); + } else { + aesDesKeyArr = generateAesDesKey(alg, (short) 168, null, null, false); } - short keyBlobPtr = KMArray.cast(aesDesKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + short keyBlobPtr = KMArray.cast(aesDesKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); byte[] nonce = new byte[16]; - cryptoProvider.newRandomNumber(nonce,(short)0,(short)16); - short inParams = getAesDesParams(alg,blockMode, padding, nonce); - byte[] plainData= "Hello World 123!".getBytes(); - if(update) plainData= "Hello World 123! Hip Hip Hoorah!".getBytes(); + cryptoProvider.newRandomNumber(nonce, (short) 0, (short) 16); + short inParams = getAesDesParams(alg, blockMode, padding, nonce); + byte[] plainData = "Hello World 123!".getBytes(); + if (update) { + plainData = "Hello World 123! Hip Hip Hoorah!".getBytes(); + } //Encrypt short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.ENCRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,update, aesGcmFlag - ); - inParams = getAesDesParams(alg,blockMode, padding, nonce); - keyBlobPtr = KMArray.cast(ret).get((short)2); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.ENCRYPT, + KMKeyParameters.instance(inParams), + (short) 0, null, update, aesGcmFlag + ); + inParams = getAesDesParams(alg, blockMode, padding, nonce); + keyBlobPtr = KMArray.cast(ret).get((short) 2); //print(keyBlobPtr); byte[] cipherData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - cipherData,(short)0, (short)cipherData.length); + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + cipherData, (short) 0, (short) cipherData.length); ret = processMessage(cipherData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.DECRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,update, aesGcmFlag + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.DECRYPT, + KMKeyParameters.instance(inParams), + (short) 0, null, update, aesGcmFlag ); - keyBlobPtr = KMArray.cast(ret).get((short)2); + keyBlobPtr = KMArray.cast(ret).get((short) 2); //print(plainData,(short)0,(short)plainData.length); //print(keyBlobPtr); - short equal = Util.arrayCompare(plainData,(short)0,KMByteBlob.cast(keyBlobPtr).getBuffer(), - KMByteBlob.cast(keyBlobPtr).getStartOff(),(short)plainData.length); + short equal = Util.arrayCompare(plainData, (short) 0, KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), (short) plainData.length); Assert.assertTrue(equal == 0); } - public void testEncryptDecryptWithRsa(byte digest, byte padding){ + public void testEncryptDecryptWithRsa(byte digest, byte padding) { short rsaKeyArr = generateRsaKey(null, null); - short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); short inParams = getRsaParams(digest, padding); byte[] plainData = "Hello World 123!".getBytes(); byte[] cipherData = new byte[256]; @@ -2686,193 +2849,211 @@ public void testEncryptDecryptWithRsa(byte digest, byte padding){ //Encrypt if (padding == KMType.RSA_OAEP) { cipherDataLen = rsaOaepEncryptMessage(keyBlob, digest, plainData, - (short) 0, (short) plainData.length, cipherData, (short) 0); + (short) 0, (short) plainData.length, cipherData, (short) 0); } else { cipherDataLen = rsaEncryptMessage(keyBlob, padding, digest, plainData, - (short) 0, (short) plainData.length, cipherData, (short) 0); + (short) 0, (short) plainData.length, cipherData, (short) 0); } Assert.assertTrue((cipherDataLen == 256)); inParams = getRsaParams(digest, padding); short ret = processMessage(cipherData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.DECRYPT, - KMKeyParameters.instance(inParams), - (short)0,null,false,false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.DECRYPT, + KMKeyParameters.instance(inParams), + (short) 0, null, false, false ); - keyBlobPtr = KMArray.cast(ret).get((short)2); + keyBlobPtr = KMArray.cast(ret).get((short) 2); short len = KMByteBlob.cast(keyBlobPtr).length(); short start = KMByteBlob.cast(keyBlobPtr).getStartOff(); - short equal = Util.arrayCompare(plainData,(short)0,KMByteBlob.cast(keyBlobPtr).getBuffer(), - (short)(start+len-plainData.length),(short)plainData.length); + short equal = Util.arrayCompare(plainData, (short) 0, KMByteBlob.cast(keyBlobPtr).getBuffer(), + (short) (start + len - plainData.length), (short) plainData.length); Assert.assertTrue(equal == 0); } - public void testSignVerifyWithRsa(byte digest, byte padding, boolean update, boolean verifyFlag){ + public void testSignVerifyWithRsa(byte digest, byte padding, boolean update, boolean verifyFlag) { short rsaKeyArr = generateRsaKey(null, null); - short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + short keyBlobPtr = KMArray.cast(rsaKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); short inParams = getRsaParams(digest, padding); byte[] plainData = "Hello World 123!".getBytes(); - if(update) plainData= "Hello World 123! Hip Hip Hoorah!".getBytes(); + if (update) { + plainData = "Hello World 123! Hip Hip Hoorah!".getBytes(); + } //Sign short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.SIGN, - KMKeyParameters.instance(inParams), - (short)0,null,update,false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.SIGN, + KMKeyParameters.instance(inParams), + (short) 0, null, update, false ); inParams = getRsaParams(digest, padding); - keyBlobPtr = KMArray.cast(ret).get((short)2); + keyBlobPtr = KMArray.cast(ret).get((short) 2); byte[] signatureData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - signatureData,(short)0, (short)signatureData.length); - if(verifyFlag == false) { - Assert.assertEquals(signatureData.length,256); + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + signatureData, (short) 0, (short) signatureData.length); + if (verifyFlag == false) { + Assert.assertEquals(signatureData.length, 256); return; } - boolean verify = rsaVerifyMessage(plainData, (short)0, (short)plainData.length, - signatureData, (short)0, (short)signatureData.length, - digest, padding, keyBlob); + boolean verify = rsaVerifyMessage(plainData, (short) 0, (short) plainData.length, + signatureData, (short) 0, (short) signatureData.length, + digest, padding, keyBlob); Assert.assertTrue(verify); } - public void testSignVerifyWithEcdsa(byte digest, boolean update){ + public void testSignVerifyWithEcdsa(byte digest, boolean update) { short ecKeyArr = generateEcKey(null, null); - short keyBlobPtr = KMArray.cast(ecKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); + short keyBlobPtr = KMArray.cast(ecKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); short inParams = getEcParams(digest); byte[] plainData = "Hello World 123!".getBytes(); - if(update) plainData= "Hello World 123! Hip Hip Hoorah!".getBytes(); + if (update) { + plainData = "Hello World 123! Hip Hip Hoorah!".getBytes(); + } //Sign short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.SIGN, - KMKeyParameters.instance(inParams), - (short)0,null,update,false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.SIGN, + KMKeyParameters.instance(inParams), + (short) 0, null, update, false ); inParams = getEcParams(digest); - keyBlobPtr = KMArray.cast(ret).get((short)2); + keyBlobPtr = KMArray.cast(ret).get((short) 2); byte[] signatureData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - signatureData,(short)0, (short)signatureData.length); + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + signatureData, (short) 0, (short) signatureData.length); boolean verify = false; if (digest == KMType.DIGEST_NONE) { - verify = ecNoDigestVerifyMessage(plainData, (short)0, (short)plainData.length, - signatureData, (short)0, (short)signatureData.length, - keyBlob); + verify = ecNoDigestVerifyMessage(plainData, (short) 0, (short) plainData.length, + signatureData, (short) 0, (short) signatureData.length, + keyBlob); } else { - verify = ecVerifyMessage(plainData, (short)0, (short)plainData.length, - signatureData, (short)0, (short)signatureData.length, - keyBlob); + verify = ecVerifyMessage(plainData, (short) 0, (short) plainData.length, + signatureData, (short) 0, (short) signatureData.length, + keyBlob); } Assert.assertTrue(verify); } - public void testSignVerifyWithHmac(byte digest, boolean update){ + + public void testSignVerifyWithHmac(byte digest, boolean update) { short hmacKeyArr = generateHmacKey(null, null); - short keyBlobPtr = KMArray.cast(hmacKeyArr).get((short)1); - byte[] keyBlob= new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - keyBlob,(short)0, (short)keyBlob.length); - short inParams = getHmacParams(digest,true); + short keyBlobPtr = KMArray.cast(hmacKeyArr).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(keyBlobPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + keyBlob, (short) 0, (short) keyBlob.length); + short inParams = getHmacParams(digest, true); byte[] plainData = "Hello World 123!".getBytes(); - if(update) plainData= "Hello World 123! Hip Hip Hoorah!".getBytes(); + if (update) { + plainData = "Hello World 123! Hip Hip Hoorah!".getBytes(); + } //Sign short ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.SIGN, - KMKeyParameters.instance(inParams), - (short)0,null,update,false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.SIGN, + KMKeyParameters.instance(inParams), + (short) 0, null, update, false ); - inParams = getHmacParams(digest,false); - keyBlobPtr = KMArray.cast(ret).get((short)2); + inParams = getHmacParams(digest, false); + keyBlobPtr = KMArray.cast(ret).get((short) 2); byte[] signatureData = new byte[KMByteBlob.cast(keyBlobPtr).length()]; - Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), KMByteBlob.cast(keyBlobPtr).getStartOff(), - signatureData,(short)0, (short)signatureData.length); + Util.arrayCopyNonAtomic(KMByteBlob.cast(keyBlobPtr).getBuffer(), + KMByteBlob.cast(keyBlobPtr).getStartOff(), + signatureData, (short) 0, (short) signatureData.length); ret = processMessage(plainData, - KMByteBlob.instance(keyBlob,(short)0, (short)keyBlob.length), - KMType.VERIFY, - KMKeyParameters.instance(inParams), - (short)0,signatureData,update,false + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMType.VERIFY, + KMKeyParameters.instance(inParams), + (short) 0, signatureData, update, false ); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); } private short getAesDesParams(byte alg, byte blockMode, byte padding, byte[] nonce) { short inParams; - if(blockMode == KMType.GCM){ - inParams = KMArray.instance((short)5); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, blockMode); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, padding); - KMArray.cast(inParams).add((short)1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); + if (blockMode == KMType.GCM) { + inParams = KMArray.instance((short) 5); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, blockMode); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, padding); + KMArray.cast(inParams).add((short) 1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); short nonceLen = 12; - byteBlob = KMByteBlob.instance(nonce,(short)0, nonceLen); - KMArray.cast(inParams).add((short)2, KMByteTag.instance(KMType.NONCE, byteBlob)); - short macLen = KMInteger.uint_16((short)128); - macLen = KMIntegerTag.instance(KMType.UINT_TAG,KMType.MAC_LENGTH,macLen); - KMArray.cast(inParams).add((short)3, macLen); + byteBlob = KMByteBlob.instance(nonce, (short) 0, nonceLen); + KMArray.cast(inParams).add((short) 2, KMByteTag.instance(KMType.NONCE, byteBlob)); + short macLen = KMInteger.uint_16((short) 128); + macLen = KMIntegerTag.instance(KMType.UINT_TAG, KMType.MAC_LENGTH, macLen); + KMArray.cast(inParams).add((short) 3, macLen); byte[] authData = "AuthData".getBytes(); - short associatedData = KMByteBlob.instance(authData,(short)0,(short)authData.length); - associatedData = KMByteTag.instance(KMType.ASSOCIATED_DATA,associatedData); - KMArray.cast(inParams).add((short)4, associatedData); - }else if(blockMode == KMType.ECB){ - inParams = KMArray.instance((short)2); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, blockMode); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, padding); - KMArray.cast(inParams).add((short)1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); - }else{ - inParams = KMArray.instance((short)3); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, blockMode); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, padding); - KMArray.cast(inParams).add((short)1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); + short associatedData = KMByteBlob.instance(authData, (short) 0, (short) authData.length); + associatedData = KMByteTag.instance(KMType.ASSOCIATED_DATA, associatedData); + KMArray.cast(inParams).add((short) 4, associatedData); + } else if (blockMode == KMType.ECB) { + inParams = KMArray.instance((short) 2); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, blockMode); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, padding); + KMArray.cast(inParams).add((short) 1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); + } else { + inParams = KMArray.instance((short) 3); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, blockMode); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.BLOCK_MODE, byteBlob)); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, padding); + KMArray.cast(inParams).add((short) 1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); short nonceLen = 16; - if(alg == KMType.DES) nonceLen = 8; - byteBlob = KMByteBlob.instance(nonce,(short)0, nonceLen); - KMArray.cast(inParams).add((short)2, KMByteTag.instance(KMType.NONCE, byteBlob)); + if (alg == KMType.DES) { + nonceLen = 8; + } + byteBlob = KMByteBlob.instance(nonce, (short) 0, nonceLen); + KMArray.cast(inParams).add((short) 2, KMByteTag.instance(KMType.NONCE, byteBlob)); } return inParams; } private short getRsaParams(byte digest, byte padding) { - short inParams = KMArray.instance((short)2); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, digest); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); - byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, padding); - KMArray.cast(inParams).add((short)1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); + short inParams = KMArray.instance((short) 2); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, digest); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); + byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, padding); + KMArray.cast(inParams).add((short) 1, KMEnumArrayTag.instance(KMType.PADDING, byteBlob)); return inParams; } private short getEcParams(byte digest) { - short inParams = KMArray.instance((short)1); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, digest); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); + short inParams = KMArray.instance((short) 1); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, digest); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); return inParams; } + private short getHmacParams(byte digest, boolean sign) { - short paramsize = (short) (sign ? 2 : 1); - short inParams = KMArray.instance((short)paramsize); - short byteBlob = KMByteBlob.instance((short)1); - KMByteBlob.cast(byteBlob).add((short)0, digest); - KMArray.cast(inParams).add((short)0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); - short macLength = KMIntegerTag.instance(KMType.UINT_TAG,KMType.MAC_LENGTH, KMInteger.uint_16((short)/*256*/160)); - if(sign) - KMArray.cast(inParams).add((short)1, macLength); + short paramsize = (short) (sign ? 2 : 1); + short inParams = KMArray.instance((short) paramsize); + short byteBlob = KMByteBlob.instance((short) 1); + KMByteBlob.cast(byteBlob).add((short) 0, digest); + KMArray.cast(inParams).add((short) 0, KMEnumArrayTag.instance(KMType.DIGEST, byteBlob)); + short macLength = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.MAC_LENGTH, KMInteger.uint_16((short)/*256*/160)); + if (sign) { + KMArray.cast(inParams).add((short) 1, macLength); + } return inParams; } @@ -2892,24 +3073,24 @@ public short processMessage( short dataPtr = KMByteBlob.instance(data, (short) 0, (short) data.length); short ret = KMType.INVALID_VALUE; byte[] outputData = new byte[128]; - short len=0; + short len = 0; inParams = 0; //Test - short firstDataLen =16; + short firstDataLen = 16; if (keyPurpose == KMType.DECRYPT) { - firstDataLen = 32; + firstDataLen = 32; } //Test if (updateFlag) { dataPtr = KMByteBlob.instance(data, (short) 0, (short) /*16*/firstDataLen); - if(aesGcmFlag){ + if (aesGcmFlag) { byte[] authData = "AuthData".getBytes(); - short associatedData = KMByteBlob.instance(authData,(short)0,(short)authData.length); - associatedData = KMByteTag.instance(KMType.ASSOCIATED_DATA,associatedData); - inParams = KMArray.instance((short)1); - KMArray.cast(inParams).add((short)0, associatedData); + short associatedData = KMByteBlob.instance(authData, (short) 0, (short) authData.length); + associatedData = KMByteTag.instance(KMType.ASSOCIATED_DATA, associatedData); + inParams = KMArray.instance((short) 1); + KMArray.cast(inParams).add((short) 0, associatedData); inParams = KMKeyParameters.instance(inParams); } opHandle = KMInteger.uint_64(opHandleBuf, (short) 0); @@ -2924,8 +3105,9 @@ public short processMessage( KMByteBlob.cast(dataPtr).length()); len = KMByteBlob.cast(dataPtr).length(); dataPtr = KMByteBlob.instance(data, len, (short) (data.length - len)); - }else{ - dataPtr = KMByteBlob.instance(data, (short)/*16*/firstDataLen, (short) (data.length - /*16*/firstDataLen)); + } else { + dataPtr = KMByteBlob + .instance(data, (short)/*16*/firstDataLen, (short) (data.length - /*16*/firstDataLen)); } } @@ -2935,49 +3117,54 @@ public short processMessage( } else { ret = finish(opHandle, dataPtr, null, (short) 0, (short) 0, (short) 0, KMError.OK); } - if(len >0){ - dataPtr = KMArray.cast(ret).get((short)2); - if(KMByteBlob.cast(dataPtr).length() >0){ + if (len > 0) { + dataPtr = KMArray.cast(ret).get((short) 2); + if (KMByteBlob.cast(dataPtr).length() > 0) { Util.arrayCopyNonAtomic( - KMByteBlob.cast(dataPtr).getBuffer(), - KMByteBlob.cast(dataPtr).getStartOff(), - outputData, - len, - KMByteBlob.cast(dataPtr).length()); - len = (short)(len + KMByteBlob.cast(dataPtr).length()); + KMByteBlob.cast(dataPtr).getBuffer(), + KMByteBlob.cast(dataPtr).getStartOff(), + outputData, + len, + KMByteBlob.cast(dataPtr).length()); + len = (short) (len + KMByteBlob.cast(dataPtr).length()); } - KMArray.cast(ret).add((short)2, KMByteBlob.instance(outputData,(short)0,len)); + KMArray.cast(ret).add((short) 2, KMByteBlob.instance(outputData, (short) 0, len)); } return ret; } public short begin(byte keyPurpose, short keyBlob, short keyParmas, short hwToken) { - short arrPtr = KMArray.instance((short)4); - KMArray.cast(arrPtr).add((short)0, KMEnum.instance(KMType.PURPOSE, keyPurpose)); - KMArray.cast(arrPtr).add((short)1, keyBlob); - KMArray.cast(arrPtr).add((short)2, keyParmas); - if(hwToken == 0) { + short arrPtr = KMArray.instance((short) 4); + KMArray.cast(arrPtr).add((short) 0, KMEnum.instance(KMType.PURPOSE, keyPurpose)); + KMArray.cast(arrPtr).add((short) 1, keyBlob); + KMArray.cast(arrPtr).add((short) 2, keyParmas); + if (hwToken == 0) { hwToken = KMHardwareAuthToken.instance(); } - KMArray.cast(arrPtr).add((short)3, hwToken); - CommandAPDU apdu = encodeApdu((byte)INS_BEGIN_OPERATION_CMD, arrPtr); + KMArray.cast(arrPtr).add((short) 3, hwToken); + CommandAPDU apdu = encodeApdu((byte) INS_BEGIN_OPERATION_CMD, arrPtr); //print(apdu.getBytes(),(short)0,(short)apdu.getBytes().length); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); short outParams = KMKeyParameters.exp(); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, outParams); - KMArray.cast(ret).add((short)2, KMInteger.exp()); + KMArray.cast(ret).add((short) 0, KMInteger.exp()); + KMArray.cast(ret).add((short) 1, outParams); + KMArray.cast(ret).add((short) 2, KMInteger.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; - if(len > 5){ - ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); - return ret;}else{ - if(len == 3) return respBuf[0]; - if(len == 4) return respBuf[1]; - return Util.getShort(respBuf,(short)0); + if (len > 5) { + ret = decoder.decode(ret, respBuf, (short) 0, len); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + Assert.assertEquals(error, KMError.OK); + return ret; + } else { + if (len == 3) { + return respBuf[0]; + } + if (len == 4) { + return respBuf[1]; + } + return Util.getShort(respBuf, (short) 0); } } @@ -3008,31 +3195,32 @@ public short translateExtendedErrorCodes(short err) { return err; } - public short finish(short operationHandle, short data, byte[] signature, short inParams, short hwToken, short verToken, short expectedErr) { - if(hwToken == 0) { + public short finish(short operationHandle, short data, byte[] signature, short inParams, + short hwToken, short verToken, short expectedErr) { + if (hwToken == 0) { hwToken = KMHardwareAuthToken.instance(); } - if(verToken == 0){ + if (verToken == 0) { verToken = KMVerificationToken.instance(); } short signatureTag; - if(signature == null){ - signatureTag = KMByteBlob.instance((short)0); - }else{ - signatureTag = KMByteBlob.instance(signature,(short)0,(short)signature.length); + if (signature == null) { + signatureTag = KMByteBlob.instance((short) 0); + } else { + signatureTag = KMByteBlob.instance(signature, (short) 0, (short) signature.length); } - if(inParams == 0){ - short arr = KMArray.instance((short)0); + if (inParams == 0) { + short arr = KMArray.instance((short) 0); inParams = KMKeyParameters.instance(arr); } - short arrPtr = KMArray.instance((short)6); - KMArray.cast(arrPtr).add((short)0, operationHandle); - KMArray.cast(arrPtr).add((short)1, inParams); - KMArray.cast(arrPtr).add((short)2, data); - KMArray.cast(arrPtr).add((short)3, signatureTag); - KMArray.cast(arrPtr).add((short)4, hwToken); - KMArray.cast(arrPtr).add((short)5, verToken); - CommandAPDU apdu = encodeApdu((byte)INS_FINISH_OPERATION_CMD, arrPtr); + short arrPtr = KMArray.instance((short) 6); + KMArray.cast(arrPtr).add((short) 0, operationHandle); + KMArray.cast(arrPtr).add((short) 1, inParams); + KMArray.cast(arrPtr).add((short) 2, data); + KMArray.cast(arrPtr).add((short) 3, signatureTag); + KMArray.cast(arrPtr).add((short) 4, hwToken); + KMArray.cast(arrPtr).add((short) 5, verToken); + CommandAPDU apdu = encodeApdu((byte) INS_FINISH_OPERATION_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); byte[] respBuf = response.getBytes(); @@ -3042,15 +3230,15 @@ public short finish(short operationHandle, short data, byte[] signature, short i if (expectedErr == KMError.OK) { ret = KMArray.instance((short) 3); short outParams = KMKeyParameters.exp(); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, outParams); - KMArray.cast(ret).add((short)2, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 0, KMInteger.exp()); + KMArray.cast(ret).add((short) 1, outParams); + KMArray.cast(ret).add((short) 2, KMByteBlob.exp()); } else { ret = KMInteger.exp(); } ret = decoder.decode(ret, respBuf, (short) 0, len); if (expectedErr == KMError.OK) { - error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); + error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); } else { error = KMInteger.cast(ret).getShort(); error = translateExtendedErrorCodes(error); @@ -3058,58 +3246,63 @@ public short finish(short operationHandle, short data, byte[] signature, short i Assert.assertEquals(error, expectedErr); return ret; } - public short update(short operationHandle, short data, short inParams, short hwToken, short verToken) { - if(hwToken == 0) { + + public short update(short operationHandle, short data, short inParams, short hwToken, + short verToken) { + if (hwToken == 0) { hwToken = KMHardwareAuthToken.instance(); } - if(verToken == 0){ + if (verToken == 0) { verToken = KMVerificationToken.instance(); } - if(inParams == 0){ - short arr = KMArray.instance((short)0); + if (inParams == 0) { + short arr = KMArray.instance((short) 0); inParams = KMKeyParameters.instance(arr); } - short arrPtr = KMArray.instance((short)5); - KMArray.cast(arrPtr).add((short)0, operationHandle); - KMArray.cast(arrPtr).add((short)1, inParams); - KMArray.cast(arrPtr).add((short)2, data); - KMArray.cast(arrPtr).add((short)3, hwToken); - KMArray.cast(arrPtr).add((short)4, verToken); - CommandAPDU apdu = encodeApdu((byte)INS_UPDATE_OPERATION_CMD, arrPtr); + short arrPtr = KMArray.instance((short) 5); + KMArray.cast(arrPtr).add((short) 0, operationHandle); + KMArray.cast(arrPtr).add((short) 1, inParams); + KMArray.cast(arrPtr).add((short) 2, data); + KMArray.cast(arrPtr).add((short) 3, hwToken); + KMArray.cast(arrPtr).add((short) 4, verToken); + CommandAPDU apdu = encodeApdu((byte) INS_UPDATE_OPERATION_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 4); short outParams = KMKeyParameters.exp(); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, KMInteger.exp()); - KMArray.cast(ret).add((short)2, outParams); - KMArray.cast(ret).add((short)3, KMByteBlob.exp()); + KMArray.cast(ret).add((short) 0, KMInteger.exp()); + KMArray.cast(ret).add((short) 1, KMInteger.exp()); + KMArray.cast(ret).add((short) 2, outParams); + KMArray.cast(ret).add((short) 3, KMByteBlob.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; if (len > 5) { ret = decoder.decode(ret, respBuf, (short) 0, len); short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); Assert.assertEquals(error, KMError.OK); - }else{ + } else { ret = respBuf[1]; } return ret; } - private void print(short blob){ - print(KMByteBlob.cast(blob).getBuffer(),KMByteBlob.cast(blob).getStartOff(),KMByteBlob.cast(blob).length()); + private void print(short blob) { + print(KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff(), + KMByteBlob.cast(blob).length()); } - private void print(byte[] buf, short start, short length){ + + private void print(byte[] buf, short start, short length) { StringBuilder sb = new StringBuilder(); - for(int i = start; i < (start+length); i++){ - sb.append(String.format(" 0x%02X", buf[i])) ; + for (int i = start; i < (start + length); i++) { + sb.append(String.format(" 0x%02X", buf[i])); } System.out.println(sb.toString()); } - private void printCert(byte[] buf, short start, short length){ + + private void printCert(byte[] buf, short start, short length) { StringBuilder sb = new StringBuilder(); - for(int i = start; i < (start+length); i++){ - sb.append(String.format("%02X", buf[i])) ; + for (int i = start; i < (start + length); i++) { + sb.append(String.format("%02X", buf[i])); } System.out.println(sb.toString()); } diff --git a/Applet/build.xml b/Applet/build.xml index c08e095f..4a14664e 100644 --- a/Applet/build.xml +++ b/Applet/build.xml @@ -1,26 +1,26 @@ - + - - - - - - - + + + + + + + - + - + - + - + - + \ No newline at end of file diff --git a/Applet/src/com/android/javacard/keymaster/KMArray.java b/Applet/src/com/android/javacard/keymaster/KMArray.java index 61139e23..f2206474 100644 --- a/Applet/src/com/android/javacard/keymaster/KMArray.java +++ b/Applet/src/com/android/javacard/keymaster/KMArray.java @@ -22,24 +22,29 @@ /** * KMArray represents an array of KMTypes. Array is the sequence of elements of one or more sub - * types of KMType. It also acts as a vector of one subtype of KMTypes on the lines of class KMArray + * types of KMType. It also acts as a vector of one subtype of KMTypes on the lines of class + * KMArray * , where subType is subclass of KMType. Vector is the sequence of elements of one sub * type e.g. KMType.BYTE_BLOB_TYPE. The KMArray instance maps to the CBOR type array. KMArray is a * KMType and it further extends the value field in TLV_HEADER as ARRAY_HEADER struct{short subType; - * short length;} followed by sequence of short pointers to KMType instances. The subType can be - * 0 if this is an array or subType is short KMType value e.g. KMType.BYTE_BLOB_TYPE if this is a + * short length;} followed by sequence of short pointers to KMType instances. The subType can be 0 + * if this is an array or subType is short KMType value e.g. KMType.BYTE_BLOB_TYPE if this is a * vector of that sub type. */ public class KMArray extends KMType { + public static final short ANY_ARRAY_LENGTH = 0x1000; private static final short ARRAY_HEADER_SIZE = 4; private static KMArray prototype; private static short instPtr; - private KMArray() {} + private KMArray() { + } private static KMArray proto(short ptr) { - if (prototype == null) prototype = new KMArray(); + if (prototype == null) { + prototype = new KMArray(); + } instPtr = ptr; return prototype; } @@ -72,13 +77,17 @@ public static short instance(short length, byte type) { } public static KMArray cast(short ptr) { - if (heap[ptr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } public void add(short index, short objPtr) { short len = length(); - if (index >= len) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + if (index >= len) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } Util.setShort( heap, (short) (instPtr + TLV_HEADER_SIZE + ARRAY_HEADER_SIZE + (short) (index * 2)), @@ -87,7 +96,9 @@ public void add(short index, short objPtr) { public short get(short index) { short len = length(); - if (index >= len) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + if (index >= len) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } return Util.getShort( heap, (short) (instPtr + TLV_HEADER_SIZE + ARRAY_HEADER_SIZE + (short) (index * 2))); } diff --git a/Applet/src/com/android/javacard/keymaster/KMAttestationCert.java b/Applet/src/com/android/javacard/keymaster/KMAttestationCert.java index a472ff27..487dccc7 100644 --- a/Applet/src/com/android/javacard/keymaster/KMAttestationCert.java +++ b/Applet/src/com/android/javacard/keymaster/KMAttestationCert.java @@ -23,6 +23,7 @@ * instance of cert. */ public interface KMAttestationCert { + /** * Set verified boot hash. * @@ -63,12 +64,13 @@ public interface KMAttestationCert { * @return instance of KMAttestationCert. */ KMAttestationCert makeUniqueId(byte[] scratchpad, short scratchPadOff, byte[] creationTime, - short creationTimeOff, short creationTimeLen, byte[] attestAppId, - short attestAppIdOff, short attestAppIdLen, byte resetSinceIdRotation, - KMMasterKey masterKey); + short creationTimeOff, short creationTimeLen, byte[] attestAppId, + short attestAppIdOff, short attestAppIdLen, byte resetSinceIdRotation, + KMMasterKey masterKey); /** - * Set start time received from creation/activation time tag. Used for certificate's valid period. + * Set start time received from creation/activation time tag. Used for certificate's valid + * period. * * @param obj This is a KMByteBlob object containing start time. * @param scratchpad Buffer to store intermediate results. @@ -78,17 +80,18 @@ KMAttestationCert makeUniqueId(byte[] scratchpad, short scratchPadOff, byte[] cr /** - * Set expiry time received from expiry time tag or ca certificates expiry time. - * Used for certificate's valid period. + * Set expiry time received from expiry time tag or ca certificates expiry time. Used for + * certificate's valid period. * * @param usageExpiryTimeObj This is a KMByteBlob containing expiry time. - * @param certExpirtyTimeObj This is a KMByteblob containing expirty time extracted from certificate. + * @param certExpirtyTimeObj This is a KMByteblob containing expirty time extracted from + * certificate. * @param scratchpad Buffer to store intermediate results. * @param offset Variable used to store intermediate results. * @return instance of KMAttestationCert */ KMAttestationCert notAfter(short usageExpiryTimeObj, - short certExpirtyTimeObj, byte[] scratchPad, short offset); + short certExpirtyTimeObj, byte[] scratchPad, short offset); /** * Set device lock status received during booting time or due to device lock command. @@ -115,12 +118,12 @@ KMAttestationCert notAfter(short usageExpiryTimeObj, KMAttestationCert attestationChallenge(short obj); /** - * Set extension tag received from key characteristics which needs to be added to android extension. - * This method will called once for each tag. + * Set extension tag received from key characteristics which needs to be added to android + * extension. This method will called once for each tag. * * @param tag is the KMByteBlob containing KMTag. - * @param hwEnforced is true if the tag has to be added to hw enforced list or - * else added to sw enforced list. + * @param hwEnforced is true if the tag has to be added to hw enforced list or else added to sw + * enforced list. * @return instance of KMAttestationCert */ KMAttestationCert extensionTag(short tag, boolean hwEnforced); @@ -166,7 +169,6 @@ KMAttestationCert notAfter(short usageExpiryTimeObj, /** * Build the certificate. After this method the certificate is ready. - * */ void build(); } diff --git a/Applet/src/com/android/javacard/keymaster/KMAttestationKey.java b/Applet/src/com/android/javacard/keymaster/KMAttestationKey.java index 8582d2b2..3d626bbf 100644 --- a/Applet/src/com/android/javacard/keymaster/KMAttestationKey.java +++ b/Applet/src/com/android/javacard/keymaster/KMAttestationKey.java @@ -16,10 +16,9 @@ package com.android.javacard.keymaster; /** - * KMAttestationKey is a marker interface and the SE Provider has to implement - * this interface. Internally attestation key is stored as a Javacard EC - * key pair object, which will provide additional security. - * The attestation key is maintained by the SEProvider. + * KMAttestationKey is a marker interface and the SE Provider has to implement this interface. + * Internally attestation key is stored as a Javacard EC key pair object, which will provide + * additional security. The attestation key is maintained by the SEProvider. */ public interface KMAttestationKey { diff --git a/Applet/src/com/android/javacard/keymaster/KMBoolTag.java b/Applet/src/com/android/javacard/keymaster/KMBoolTag.java index 4396470b..173e6269 100644 --- a/Applet/src/com/android/javacard/keymaster/KMBoolTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMBoolTag.java @@ -21,43 +21,48 @@ import javacard.framework.Util; /** - * KMBoolTag represents BOOL TAG type from the android keymaster hal specifications. If it is present in the key parameter list then its value is always true. A KMTag always requires - * a value because it is a key value pair. The bool tag always has 0x01 as its value. - * struct{byte TAG_TYPE; short length; struct{short BOOL_TAG; short tagKey; byte value 1}} + * KMBoolTag represents BOOL TAG type from the android keymaster hal specifications. If it is + * present in the key parameter list then its value is always true. A KMTag always requires a value + * because it is a key value pair. The bool tag always has 0x01 as its value. struct{byte TAG_TYPE; + * short length; struct{short BOOL_TAG; short tagKey; byte value 1}} */ public class KMBoolTag extends KMTag { + private static KMBoolTag prototype; private static short instPtr; // The allowed tag keys of type bool tag. private static final short[] tags = { - CALLER_NONCE, - INCLUDE_UNIQUE_ID, - BOOTLOADER_ONLY, - ROLLBACK_RESISTANCE, - NO_AUTH_REQUIRED, - ALLOW_WHILE_ON_BODY, - TRUSTED_USER_PRESENCE_REQUIRED, - TRUSTED_CONFIRMATION_REQUIRED, - UNLOCKED_DEVICE_REQUIRED, - RESET_SINCE_ID_ROTATION, - EARLY_BOOT_ONLY, - DEVICE_UNIQUE_ATTESTATION + CALLER_NONCE, + INCLUDE_UNIQUE_ID, + BOOTLOADER_ONLY, + ROLLBACK_RESISTANCE, + NO_AUTH_REQUIRED, + ALLOW_WHILE_ON_BODY, + TRUSTED_USER_PRESENCE_REQUIRED, + TRUSTED_CONFIRMATION_REQUIRED, + UNLOCKED_DEVICE_REQUIRED, + RESET_SINCE_ID_ROTATION, + EARLY_BOOT_ONLY, + DEVICE_UNIQUE_ATTESTATION }; - private KMBoolTag() {} + private KMBoolTag() { + } private static KMBoolTag proto(short ptr) { - if (prototype == null) prototype = new KMBoolTag(); + if (prototype == null) { + prototype = new KMBoolTag(); + } instPtr = ptr; return prototype; } // pointer to an empty instance used as expression public static short exp() { - short ptr = instance(TAG_TYPE, (short)2); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), BOOL_TAG); + short ptr = instance(TAG_TYPE, (short) 2); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), BOOL_TAG); return ptr; } @@ -65,16 +70,18 @@ public static short instance(short key) { if (!validateKey(key)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = KMType.instance(TAG_TYPE, (short)5); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), BOOL_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), key); + short ptr = KMType.instance(TAG_TYPE, (short) 5); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), BOOL_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); // Value is always 1. - heap[(short)(ptr+TLV_HEADER_SIZE+4)] = 0x01; + heap[(short) (ptr + TLV_HEADER_SIZE + 4)] = 0x01; return ptr; } public static KMBoolTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)) != BOOL_TAG) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -82,7 +89,7 @@ public static KMBoolTag cast(short ptr) { } public short getKey() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+2)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 2)); } public short getTagType() { @@ -90,7 +97,7 @@ public short getTagType() { } public byte getVal() { - return heap[(short)(instPtr+TLV_HEADER_SIZE+4)]; + return heap[(short) (instPtr + TLV_HEADER_SIZE + 4)]; } // validate the tag key. @@ -104,7 +111,7 @@ private static boolean validateKey(short key) { return false; } - public static short[] getTags(){ + public static short[] getTags() { return tags; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java index 28b916db..001bab01 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteBlob.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteBlob.java @@ -22,17 +22,21 @@ /** * KMByteBlob represents contiguous block of bytes. It corresponds to CBOR type of Byte String. It - * extends KMType by specifying value field as zero or more sequence of bytes. - * struct{byte BYTE_BLOB_TYPE; short length; sequence of bytes} + * extends KMType by specifying value field as zero or more sequence of bytes. struct{byte + * BYTE_BLOB_TYPE; short length; sequence of bytes} */ public class KMByteBlob extends KMType { + private static KMByteBlob prototype; private static short instPtr; - private KMByteBlob() {} + private KMByteBlob() { + } private static KMByteBlob proto(short ptr) { - if (prototype == null) prototype = new KMByteBlob(); + if (prototype == null) { + prototype = new KMByteBlob(); + } instPtr = ptr; return prototype; } @@ -56,7 +60,9 @@ public static short instance(byte[] buf, short startOff, short length) { // cast the ptr to KMByteBlob public static KMByteBlob cast(short ptr) { - if (heap[ptr] != BYTE_BLOB_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != BYTE_BLOB_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + 1)) == INVALID_VALUE) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -66,14 +72,18 @@ public static KMByteBlob cast(short ptr) { // Add the byte public void add(short index, byte val) { short len = length(); - if (index >= len) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + if (index >= len) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } heap[(short) (instPtr + TLV_HEADER_SIZE + index)] = val; } // Get the byte public byte get(short index) { short len = length(); - if (index >= len) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + if (index >= len) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } return heap[(short) (instPtr + TLV_HEADER_SIZE + index)]; } diff --git a/Applet/src/com/android/javacard/keymaster/KMByteTag.java b/Applet/src/com/android/javacard/keymaster/KMByteTag.java index 7310bb8a..4384891d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteTag.java @@ -21,42 +21,46 @@ import javacard.framework.Util; /** - * KMByteTag represents BYTES Tag Type from android keymaster hal specifications. The tag value of this tag - * is the KMByteBlob pointer i.e. offset of KMByteBlob in memory heap. - * struct{byte TAG_TYPE; short length; struct{short BYTES_TAG; short tagKey; short blobPtr}} + * KMByteTag represents BYTES Tag Type from android keymaster hal specifications. The tag value of + * this tag is the KMByteBlob pointer i.e. offset of KMByteBlob in memory heap. struct{byte + * TAG_TYPE; short length; struct{short BYTES_TAG; short tagKey; short blobPtr}} */ public class KMByteTag extends KMTag { + private static KMByteTag prototype; private static short instPtr; // The allowed tag keys of type bool tag private static final short[] tags = { - APPLICATION_ID, - APPLICATION_DATA, - ROOT_OF_TRUST, - UNIQUE_ID, - ATTESTATION_CHALLENGE, - ATTESTATION_APPLICATION_ID, - ATTESTATION_ID_BRAND, - ATTESTATION_ID_DEVICE, - ATTESTATION_ID_PRODUCT, - ATTESTATION_ID_SERIAL, - ATTESTATION_ID_IMEI, - ATTESTATION_ID_MEID, - ATTESTATION_ID_MANUFACTURER, - ATTESTATION_ID_MODEL, - ASSOCIATED_DATA, - NONCE, - CONFIRMATION_TOKEN, - VERIFIED_BOOT_KEY, - VERIFIED_BOOT_HASH + APPLICATION_ID, + APPLICATION_DATA, + ROOT_OF_TRUST, + UNIQUE_ID, + ATTESTATION_CHALLENGE, + ATTESTATION_APPLICATION_ID, + ATTESTATION_ID_BRAND, + ATTESTATION_ID_DEVICE, + ATTESTATION_ID_PRODUCT, + ATTESTATION_ID_SERIAL, + ATTESTATION_ID_IMEI, + ATTESTATION_ID_MEID, + ATTESTATION_ID_MANUFACTURER, + ATTESTATION_ID_MODEL, + ASSOCIATED_DATA, + NONCE, + CONFIRMATION_TOKEN, + VERIFIED_BOOT_KEY, + VERIFIED_BOOT_HASH }; - private KMByteTag() {} + private KMByteTag() { + } private static KMByteTag proto(short ptr) { - if (prototype == null) prototype = new KMByteTag(); + if (prototype == null) { + prototype = new KMByteTag(); + } instPtr = ptr; return prototype; } @@ -64,10 +68,10 @@ private static KMByteTag proto(short ptr) { // pointer to an empty instance used as expression public static short exp() { short blobPtr = KMByteBlob.exp(); - short ptr = instance(TAG_TYPE, (short)6); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), BYTES_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), INVALID_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+4), blobPtr); + short ptr = instance(TAG_TYPE, (short) 6); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), BYTES_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), INVALID_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 4), blobPtr); return ptr; } @@ -82,18 +86,20 @@ public static short instance(short key, short byteBlob) { if (!validateKey(key)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - if(heap[byteBlob] != BYTE_BLOB_TYPE) { + if (heap[byteBlob] != BYTE_BLOB_TYPE) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = instance(TAG_TYPE, (short)6); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), BYTES_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), key); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+4), byteBlob); + short ptr = instance(TAG_TYPE, (short) 6); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), BYTES_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 4), byteBlob); return ptr; } public static KMByteTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)) != BYTES_TAG) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -101,7 +107,7 @@ public static KMByteTag cast(short ptr) { } public short getKey() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+2)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 2)); } public short getTagType() { @@ -109,11 +115,11 @@ public short getTagType() { } public short getValue() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+4)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 4)); } public short length() { - short blobPtr = Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+4)); + short blobPtr = Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 4)); return KMByteBlob.cast(blobPtr).length(); } diff --git a/Applet/src/com/android/javacard/keymaster/KMDecoder.java b/Applet/src/com/android/javacard/keymaster/KMDecoder.java index d74e35d0..520ffb7c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMDecoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMDecoder.java @@ -21,21 +21,22 @@ import javacard.framework.Util; public class KMDecoder { + // major types private static final short UINT_TYPE = 0x00; private static final short BYTES_TYPE = 0x40; private static final short ARRAY_TYPE = 0x80; - private static final short MAP_TYPE = 0xA0; + private static final short MAP_TYPE = 0xA0; // masks private static final short ADDITIONAL_MASK = 0x1F; private static final short MAJOR_TYPE_MASK = 0xE0; // value length - private static final short UINT8_LENGTH = 0x18; - private static final short UINT16_LENGTH = 0x19; + private static final short UINT8_LENGTH = 0x18; + private static final short UINT16_LENGTH = 0x19; private static final short UINT32_LENGTH = 0x1A; - private static final short UINT64_LENGTH = 0x1B; + private static final short UINT64_LENGTH = 0x1B; private byte[] buffer; private short startOff; @@ -52,16 +53,17 @@ public KMDecoder() { public short decode(short expression, byte[] buffer, short startOff, short length) { this.buffer = buffer; this.startOff = startOff; - this.length = (short)(startOff+length); + this.length = (short) (startOff + length); return decode(expression); } - public short decodeArray(short exp, byte[] buffer, short startOff, short length){ + + public short decodeArray(short exp, byte[] buffer, short startOff, short length) { this.buffer = buffer; this.startOff = startOff; - this.length = (short)(startOff+length); + this.length = (short) (startOff + length); short payloadLength = readMajorTypeWithPayloadLength(ARRAY_TYPE); short expLength = KMArray.cast(exp).length(); - if(payloadLength > expLength){ + if (payloadLength > expLength) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } short index = 0; @@ -76,9 +78,10 @@ public short decodeArray(short exp, byte[] buffer, short startOff, short length) } return arrPtr; } - private short decode(short exp){ + + private short decode(short exp) { byte type = KMType.getType(exp); - switch(type){ + switch (type) { case KMType.BYTE_BLOB_TYPE: return decodeByteBlob(exp); case KMType.INTEGER_TYPE: @@ -105,8 +108,9 @@ private short decode(short exp){ return 0; } } - private short decodeTag(short tagType, short exp){ - switch(tagType){ + + private short decodeTag(short tagType, short exp) { + switch (tagType) { case KMType.BYTES_TAG: return decodeBytesTag(exp); case KMType.BOOL_TAG: @@ -174,16 +178,15 @@ private short decodeKeyParam(short exp) { if (tagType == allowedType) { // then decodeByteBlob and add that to the array. obj = decode(tagClass); - KMArray.cast(vals).add(index,obj); + KMArray.cast(vals).add(index, obj); tagFound = true; break; } tagInd++; } - if(!tagFound){ + if (!tagFound) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); - } - else { + } else { index++; } } @@ -199,14 +202,14 @@ private short decodeIntegerArrayTag(short exp) { readTagKey(KMIntegerArrayTag.cast(exp).getTagType()); // the values are array of integers. return KMIntegerArrayTag.instance(KMIntegerArrayTag.cast(exp).getTagType(), - this.tagKey, decode(KMIntegerArrayTag.cast(exp).getValues())); + this.tagKey, decode(KMIntegerArrayTag.cast(exp).getValues())); } private short decodeIntegerTag(short exp) { readTagKey(KMIntegerTag.cast(exp).getTagType()); // the value is an integer return KMIntegerTag.instance(KMIntegerTag.cast(exp).getTagType(), - this.tagKey, decode(KMIntegerTag.cast(exp).getValue())); + this.tagKey, decode(KMIntegerTag.cast(exp).getValue())); } private short decodeBytesTag(short exp) { @@ -222,7 +225,7 @@ private short decodeArray(short exp) { short type; short obj; // check whether array contains one type of objects or multiple types - if( KMArray.cast(exp).containedType() == 0){// multiple types specified by expression. + if (KMArray.cast(exp).containedType() == 0) {// multiple types specified by expression. if (KMArray.cast(exp).length() != KMArray.ANY_ARRAY_LENGTH) { if (KMArray.cast(exp).length() != payloadLength) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); @@ -234,9 +237,9 @@ private short decodeArray(short exp) { KMArray.cast(arrPtr).add(index, obj); index++; } - }else{ // Array is a Vector containing objects of one type + } else { // Array is a Vector containing objects of one type type = KMArray.cast(exp).containedType(); - while(index < payloadLength){ + while (index < payloadLength) { obj = decode(type); KMArray.cast(arrPtr).add(index, obj); index++; @@ -257,7 +260,7 @@ private short decodeEnumTag(short exp) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (len < UINT8_LENGTH) { - enumVal = (byte)(len & ADDITIONAL_MASK); + enumVal = (byte) (len & ADDITIONAL_MASK); incrementStartOff((short) 1); } else if (len == UINT8_LENGTH) { incrementStartOff((short) 1); @@ -291,7 +294,7 @@ private short decodeEnum(short exp) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } if (len < UINT8_LENGTH) { - enumVal = (byte)(len & ADDITIONAL_MASK); + enumVal = (byte) (len & ADDITIONAL_MASK); incrementStartOff((short) 1); } else { incrementStartOff((short) 1); @@ -307,12 +310,12 @@ private short decodeInteger(short exp) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short len = (short) (buffer[startOff] & ADDITIONAL_MASK); - if(len > UINT64_LENGTH){ + if (len > UINT64_LENGTH) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } incrementStartOff((short) 1); if (len < UINT8_LENGTH) { - inst = KMInteger.uint_8((byte)(len & ADDITIONAL_MASK)); + inst = KMInteger.uint_8((byte) (len & ADDITIONAL_MASK)); } else if (len == UINT8_LENGTH) { inst = KMInteger.instance(buffer, startOff, (short) 1); incrementStartOff((short) 1); @@ -377,8 +380,8 @@ private short readMajorTypeWithPayloadLength(short majorType) { } if (lenType < UINT8_LENGTH) { payloadLength = lenType; - }else if (lenType == UINT8_LENGTH) { - payloadLength = (short)(readByte() & 0xFF); + } else if (lenType == UINT8_LENGTH) { + payloadLength = (short) (readByte() & 0xFF); } else { payloadLength = readShort(); } @@ -405,12 +408,12 @@ private void incrementStartOff(short inc) { } public short readCertificateChainLengthAndHeaderLen(byte[] buf, short bufOffset, - short bufLen) { + short bufLen) { this.buffer = buf; this.startOff = bufOffset; this.length = (short) (bufOffset + bufLen); short totalLen = readMajorTypeWithPayloadLength(BYTES_TYPE); - totalLen += (short)( startOff - bufOffset); + totalLen += (short) (startOff - bufOffset); return totalLen; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 431d84e3..61163c00 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -22,6 +22,7 @@ import javacard.framework.Util; public class KMEncoder { + // major types private static final byte UINT_TYPE = 0x00; private static final byte BYTES_TYPE = 0x40; @@ -37,7 +38,7 @@ public class KMEncoder { private static final byte UINT32_LENGTH = (byte) 0x1A; private static final byte UINT64_LENGTH = (byte) 0x1B; private static final short TINY_PAYLOAD = 0x17; - private static final short SHORT_PAYLOAD = 0x100; + private static final short SHORT_PAYLOAD = 0x100; private byte[] buffer; private short startOff; private short length; @@ -48,41 +49,44 @@ public KMEncoder() { buffer = null; startOff = 0; length = 0; - stack = JCSystem.makeTransientShortArray((short)50, JCSystem.CLEAR_ON_RESET); + stack = JCSystem.makeTransientShortArray((short) 50, JCSystem.CLEAR_ON_RESET); } - private static void push (short objPtr){ + private static void push(short objPtr) { stack[stackPtr] = objPtr; stackPtr++; } - private static short pop(){ + + private static short pop() { stackPtr--; return stack[stackPtr]; } - private void encode(short obj){ + + private void encode(short obj) { push(obj); } + public short encode(short object, byte[] buffer, short startOff) { stackPtr = 0; this.buffer = buffer; this.startOff = startOff; short len = (short) buffer.length; - if((len <0) || (len > KMKeymasterApplet.MAX_LENGTH)){ + if ((len < 0) || (len > KMKeymasterApplet.MAX_LENGTH)) { this.length = KMKeymasterApplet.MAX_LENGTH; - }else{ - this.length = (short)buffer.length; + } else { + this.length = (short) buffer.length; } //this.length = (short)(startOff + length); push(object); encode(); - return (short)(this.startOff - startOff); + return (short) (this.startOff - startOff); } // array{KMError.OK,Array{KMByteBlobs}} public void encodeCertChain(byte[] buffer, short offset, short length) { this.buffer = buffer; this.startOff = offset; - this.length = (short)(offset+3); + this.length = (short) (offset + 3); writeMajorTypeWithLength(ARRAY_TYPE, (short) 2); // Array of 2 elements writeByte(UINT_TYPE); // Error.OK @@ -92,7 +96,7 @@ public void encodeCertChain(byte[] buffer, short offset, short length) { public short encodeCert(byte[] certBuffer, short bufferStart, short certStart, short certLength) { this.buffer = certBuffer; this.startOff = certStart; - this.length = (short)(certStart+1); + this.length = (short) (certStart + 1); //Array header - 2 elements i.e. 1 byte this.startOff--; // Error.Ok - 1 byte @@ -101,14 +105,16 @@ public short encodeCert(byte[] certBuffer, short bufferStart, short certStart, s this.startOff--; // Cert Byte blob - typically 2 bytes length i.e. 3 bytes header this.startOff -= 2; - if(certLength >= SHORT_PAYLOAD) { - this.startOff--; + if (certLength >= SHORT_PAYLOAD) { + this.startOff--; } bufferStart = startOff; - if(this.startOff < bufferStart) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - writeMajorTypeWithLength(ARRAY_TYPE,(short)2); // Array of 2 elements + if (this.startOff < bufferStart) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + writeMajorTypeWithLength(ARRAY_TYPE, (short) 2); // Array of 2 elements writeByte(UINT_TYPE); // Error.OK - writeMajorTypeWithLength(ARRAY_TYPE,(short)1); // Array of 1 element + writeMajorTypeWithLength(ARRAY_TYPE, (short) 1); // Array of 1 element writeMajorTypeWithLength(BYTES_TYPE, certLength); // Cert Byte Blob of length return bufferStart; } @@ -116,21 +122,21 @@ public short encodeCert(byte[] certBuffer, short bufferStart, short certStart, s public short encodeError(short err, byte[] buffer, short startOff, short length) { this.buffer = buffer; this.startOff = startOff; - this.length = (short)(startOff + length); + this.length = (short) (startOff + length); // encode the err as UINT with value in err - should not be greater then 5 bytes. - if(err < UINT8_LENGTH){ - writeByte((byte)(UINT_TYPE | err )); - }else if(err < 0x100){ - writeByte((byte)(UINT_TYPE | UINT8_LENGTH)); - writeByte((byte)err); - }else { - writeByte((byte)(UINT_TYPE | UINT16_LENGTH)); + if (err < UINT8_LENGTH) { + writeByte((byte) (UINT_TYPE | err)); + } else if (err < 0x100) { + writeByte((byte) (UINT_TYPE | UINT8_LENGTH)); + writeByte((byte) err); + } else { + writeByte((byte) (UINT_TYPE | UINT16_LENGTH)); writeShort(err); } - return (short)(this.startOff - startOff); + return (short) (this.startOff - startOff); } - private void encode(){ + private void encode() { while (stackPtr > 0) { short exp = pop(); byte type = KMType.getType(exp); @@ -171,8 +177,9 @@ private void encode(){ } } } - private void encodeTag(short tagType, short exp){ - switch(tagType){ + + private void encodeTag(short tagType, short exp) { + switch (tagType) { case KMType.BYTES_TAG: encodeBytesTag(exp); return; @@ -202,6 +209,7 @@ private void encodeTag(short tagType, short exp){ private void encodeKeyParam(short obj) { encodeAsMap(KMKeyParameters.cast(obj).getVals()); } + private void encodeKeyChar(short obj) { encode(KMKeyCharacteristics.cast(obj).getVals()); } @@ -221,19 +229,19 @@ private void encodeHmacSharingParam(short obj) { private void encodeArray(short obj) { writeMajorTypeWithLength(ARRAY_TYPE, KMArray.cast(obj).length()); short len = KMArray.cast(obj).length(); - short index = (short)(len-1); - while(index >= 0){ + short index = (short) (len - 1); + while (index >= 0) { encode(KMArray.cast(obj).get(index)); index--; } } - private void encodeAsMap(short obj){ + private void encodeAsMap(short obj) { writeMajorTypeWithLength(MAP_TYPE, KMArray.cast(obj).length()); short len = KMArray.cast(obj).length(); - short index = (short)(len-1); + short index = (short) (len - 1); short inst; - while(index >= 0){ + while (index >= 0) { inst = KMArray.cast(obj).get(index); encode(inst); index--; @@ -251,8 +259,8 @@ private void encodeEnumArrayTag(short obj) { } private void encodeIntegerTag(short obj) { - writeTag(KMIntegerTag .cast(obj).getTagType(), KMIntegerTag .cast(obj).getKey()); - encode(KMIntegerTag .cast(obj).getValue()); + writeTag(KMIntegerTag.cast(obj).getTagType(), KMIntegerTag.cast(obj).getKey()); + encode(KMIntegerTag.cast(obj).getValue()); } private void encodeBytesTag(short obj) { @@ -269,6 +277,7 @@ private void encodeEnumTag(short obj) { writeTag(KMEnumTag.cast(obj).getTagType(), KMEnumTag.cast(obj).getKey()); writeByteValue(KMEnumTag.cast(obj).getValue()); } + private void encodeEnum(short obj) { writeByteValue(KMEnum.cast(obj).getVal()); } @@ -277,86 +286,89 @@ private void encodeInteger(short obj) { byte[] val = KMInteger.cast(obj).getBuffer(); short len = KMInteger.cast(obj).length(); short startOff = KMInteger.cast(obj).getStartOff(); - byte index =0; + byte index = 0; // find out the most significant byte - while(index < len){ - if(val[(short)(startOff + index)] > 0){ + while (index < len) { + if (val[(short) (startOff + index)] > 0) { break; - }else if(val[(short)(startOff + index)] < 0){ + } else if (val[(short) (startOff + index)] < 0) { break; } index++; // index will be equal to len if value is 0. } // find the difference between most significant byte and len - short diff = (short)(len - index); - if(diff == 0){ - writeByte((byte)(UINT_TYPE | 0)); - }else if((diff == 1) && (val[(short)(startOff + index)] < UINT8_LENGTH) - &&(val[(short)(startOff + index)] >= 0)){ - writeByte((byte)(UINT_TYPE | val[(short)(startOff + index)])); - }else if (diff == 1){ - writeByte((byte)(UINT_TYPE | UINT8_LENGTH)); - writeByte(val[(short)(startOff + index)]); - }else if(diff == 2){ - writeByte((byte)(UINT_TYPE | UINT16_LENGTH)); - writeBytes(val, (short)(startOff + index), (short)2); - }else if(diff <= 4){ - writeByte((byte)(UINT_TYPE | UINT32_LENGTH)); - writeBytes(val, (short)(startOff + len - 4), (short)4); - }else { - writeByte((byte)(UINT_TYPE | UINT64_LENGTH)); - writeBytes(val, startOff, (short)8); + short diff = (short) (len - index); + if (diff == 0) { + writeByte((byte) (UINT_TYPE | 0)); + } else if ((diff == 1) && (val[(short) (startOff + index)] < UINT8_LENGTH) + && (val[(short) (startOff + index)] >= 0)) { + writeByte((byte) (UINT_TYPE | val[(short) (startOff + index)])); + } else if (diff == 1) { + writeByte((byte) (UINT_TYPE | UINT8_LENGTH)); + writeByte(val[(short) (startOff + index)]); + } else if (diff == 2) { + writeByte((byte) (UINT_TYPE | UINT16_LENGTH)); + writeBytes(val, (short) (startOff + index), (short) 2); + } else if (diff <= 4) { + writeByte((byte) (UINT_TYPE | UINT32_LENGTH)); + writeBytes(val, (short) (startOff + len - 4), (short) 4); + } else { + writeByte((byte) (UINT_TYPE | UINT64_LENGTH)); + writeBytes(val, startOff, (short) 8); } } private void encodeByteBlob(short obj) { writeMajorTypeWithLength(BYTES_TYPE, KMByteBlob.cast(obj).length()); writeBytes(KMByteBlob.cast(obj).getBuffer(), KMByteBlob.cast(obj).getStartOff(), - KMByteBlob.cast(obj).length()); + KMByteBlob.cast(obj).length()); } - private void writeByteValue(byte val){ - if((val < UINT8_LENGTH) && (val >=0)){ - writeByte((byte)(UINT_TYPE | val)); - }else{ - writeByte((byte)(UINT_TYPE | UINT8_LENGTH)); - writeByte((byte)val); + private void writeByteValue(byte val) { + if ((val < UINT8_LENGTH) && (val >= 0)) { + writeByte((byte) (UINT_TYPE | val)); + } else { + writeByte((byte) (UINT_TYPE | UINT8_LENGTH)); + writeByte((byte) val); } } - private void writeTag(short tagType, short tagKey){ - writeByte((byte)(UINT_TYPE | UINT32_LENGTH)); + private void writeTag(short tagType, short tagKey) { + writeByte((byte) (UINT_TYPE | UINT32_LENGTH)); writeShort(tagType); writeShort(tagKey); } + private void writeMajorTypeWithLength(byte majorType, short len) { - if(len <= TINY_PAYLOAD){ - writeByte((byte)(majorType | (byte) (len & ADDITIONAL_MASK))); - }else if(len < SHORT_PAYLOAD){ - writeByte((byte)(majorType | UINT8_LENGTH )); - writeByte((byte)(len & 0xFF)); - }else { - writeByte((byte)(majorType | UINT16_LENGTH )); + if (len <= TINY_PAYLOAD) { + writeByte((byte) (majorType | (byte) (len & ADDITIONAL_MASK))); + } else if (len < SHORT_PAYLOAD) { + writeByte((byte) (majorType | UINT8_LENGTH)); + writeByte((byte) (len & 0xFF)); + } else { + writeByte((byte) (majorType | UINT16_LENGTH)); writeShort(len); } } - private void writeBytes(byte[] buf, short start, short len){ + private void writeBytes(byte[] buf, short start, short len) { Util.arrayCopyNonAtomic(buf, start, buffer, startOff, len); incrementStartOff(len); } - private void writeShort(short val){ - buffer[startOff] = (byte)((val >> 8) & 0xFF); - incrementStartOff((short)1); - buffer[startOff] = (byte)((val & 0xFF)); - incrementStartOff((short)1); + + private void writeShort(short val) { + buffer[startOff] = (byte) ((val >> 8) & 0xFF); + incrementStartOff((short) 1); + buffer[startOff] = (byte) ((val & 0xFF)); + incrementStartOff((short) 1); } - private void writeByte(byte val){ + + private void writeByte(byte val) { buffer[startOff] = val; - incrementStartOff((short)1); + incrementStartOff((short) 1); } - private void incrementStartOff(short inc){ + private void incrementStartOff(short inc) { startOff += inc; if (startOff >= this.length) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); diff --git a/Applet/src/com/android/javacard/keymaster/KMEnum.java b/Applet/src/com/android/javacard/keymaster/KMEnum.java index d25c5f8e..6dbdf7ce 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnum.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnum.java @@ -26,27 +26,31 @@ * struct{short enumType; byte val}} */ public class KMEnum extends KMType { + private static KMEnum prototype; private static short instPtr; // The allowed enum types. private static short[] types = { - HARDWARE_TYPE, - KEY_FORMAT, - KEY_DERIVATION_FUNCTION, - VERIFIED_BOOT_STATE, - DEVICE_LOCKED, - USER_AUTH_TYPE, - PURPOSE, - ECCURVE + HARDWARE_TYPE, + KEY_FORMAT, + KEY_DERIVATION_FUNCTION, + VERIFIED_BOOT_STATE, + DEVICE_LOCKED, + USER_AUTH_TYPE, + PURPOSE, + ECCURVE }; private static Object[] enums = null; - private KMEnum() {} + private KMEnum() { + } private static KMEnum proto(short ptr) { - if (prototype == null) prototype = new KMEnum(); + if (prototype == null) { + prototype = new KMEnum(); + } instPtr = ptr; return prototype; } @@ -61,7 +65,9 @@ public short length() { } public static KMEnum cast(short ptr) { - if (heap[ptr] != ENUM_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != ENUM_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + 1)) == INVALID_VALUE) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -91,22 +97,22 @@ private static void create() { // The allowed enum values to corresponding enum types in the types array. if (enums == null) { enums = - new Object[] { - new byte[] {SOFTWARE, TRUSTED_ENVIRONMENT, STRONGBOX}, - new byte[] {X509, PKCS8, RAW}, - new byte[] { - DERIVATION_NONE, - RFC5869_SHA256, - ISO18033_2_KDF1_SHA1, - ISO18033_2_KDF1_SHA256, - ISO18033_2_KDF2_SHA1, - ISO18033_2_KDF2_SHA256 - }, - new byte[] {SELF_SIGNED_BOOT, VERIFIED_BOOT, UNVERIFIED_BOOT, FAILED_BOOT}, - new byte[] {DEVICE_LOCKED_TRUE, DEVICE_LOCKED_FALSE}, - new byte[] {USER_AUTH_NONE, PASSWORD, FINGERPRINT, BOTH}, - new byte[] {ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP_KEY, ATTEST_KEY}, - new byte[] {P_224, P_256, P_384, P_521} + new Object[]{ + new byte[]{SOFTWARE, TRUSTED_ENVIRONMENT, STRONGBOX}, + new byte[]{X509, PKCS8, RAW}, + new byte[]{ + DERIVATION_NONE, + RFC5869_SHA256, + ISO18033_2_KDF1_SHA1, + ISO18033_2_KDF1_SHA256, + ISO18033_2_KDF2_SHA1, + ISO18033_2_KDF2_SHA256 + }, + new byte[]{SELF_SIGNED_BOOT, VERIFIED_BOOT, UNVERIFIED_BOOT, FAILED_BOOT}, + new byte[]{DEVICE_LOCKED_TRUE, DEVICE_LOCKED_FALSE}, + new byte[]{USER_AUTH_NONE, PASSWORD, FINGERPRINT, BOTH}, + new byte[]{ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP_KEY, ATTEST_KEY}, + new byte[]{P_224, P_256, P_384, P_521} }; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java index 37e23286..1cc5730d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnumArrayTag.java @@ -35,10 +35,13 @@ public class KMEnumArrayTag extends KMTag { // Tag Values. private static Object[] enums = null; - private KMEnumArrayTag() {} + private KMEnumArrayTag() { + } private static KMEnumArrayTag proto(short ptr) { - if (prototype == null) prototype = new KMEnumArrayTag(); + if (prototype == null) { + prototype = new KMEnumArrayTag(); + } instPtr = ptr; return prototype; } @@ -94,7 +97,9 @@ public static short instance(short key, short byteBlob) { } public static KMEnumArrayTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)) != ENUM_ARRAY_TAG) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -122,13 +127,13 @@ public static void create() { if (enums == null) { // allowed tag values. enums = - new Object[] { - new byte[] {ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP_KEY, ATTEST_KEY}, - new byte[] {ECB, CBC, CTR, GCM}, - new byte[] {DIGEST_NONE, MD5, SHA1, SHA2_224, SHA2_256, SHA2_384, SHA2_512}, - new byte[] { - PADDING_NONE, RSA_OAEP, RSA_PSS, RSA_PKCS1_1_5_ENCRYPT, RSA_PKCS1_1_5_SIGN, PKCS7 - } + new Object[]{ + new byte[]{ENCRYPT, DECRYPT, SIGN, VERIFY, WRAP_KEY, ATTEST_KEY}, + new byte[]{ECB, CBC, CTR, GCM}, + new byte[]{DIGEST_NONE, MD5, SHA1, SHA2_224, SHA2_256, SHA2_384, SHA2_512}, + new byte[]{ + PADDING_NONE, RSA_OAEP, RSA_PSS, RSA_PKCS1_1_5_ENCRYPT, RSA_PKCS1_1_5_SIGN, PKCS7 + } }; } } @@ -198,15 +203,20 @@ public boolean isValidDigests(byte alg) { switch (alg) { case KMType.EC: case KMType.RSA: - if (digest != KMType.DIGEST_NONE && digest != KMType.SHA2_256 && digest != KMType.SHA1) + if (digest != KMType.DIGEST_NONE && digest != KMType.SHA2_256 && digest != KMType.SHA1) { return false; + } break; case KMType.HMAC: - if (digest != KMType.SHA2_256) return false; + if (digest != KMType.SHA2_256) { + return false; + } break; case KMType.AES: case KMType.DES: - if (digest != KMType.DIGEST_NONE) return false; + if (digest != KMType.DIGEST_NONE) { + return false; + } break; default: return false; @@ -270,7 +280,9 @@ public boolean isValidPurpose(byte alg) { } break; case KMType.WRAP_KEY: - if (alg != KMType.RSA) return false; + if (alg != KMType.RSA) { + return false; + } break; default: return false; diff --git a/Applet/src/com/android/javacard/keymaster/KMEnumTag.java b/Applet/src/com/android/javacard/keymaster/KMEnumTag.java index 2c87bb96..485572ed 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEnumTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMEnumTag.java @@ -19,61 +19,68 @@ import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; + /** - * KMEnumTag represents ENUM Tag type specified in android keymaster hal specifications. - * struct{byte TAG_TYPE; short length; struct{short ENUM_TAG; short tagKey; byte value}} + * KMEnumTag represents ENUM Tag type specified in android keymaster hal specifications. struct{byte + * TAG_TYPE; short length; struct{short ENUM_TAG; short tagKey; byte value}} */ public class KMEnumTag extends KMTag { + private static KMEnumTag prototype; private static short instPtr; // The allowed tag keys of type enum tag. private static short[] tags = { - ALGORITHM, ECCURVE, BLOB_USAGE_REQ, USER_AUTH_TYPE, ORIGIN, HARDWARE_TYPE + ALGORITHM, ECCURVE, BLOB_USAGE_REQ, USER_AUTH_TYPE, ORIGIN, HARDWARE_TYPE }; private static Object[] enums = null; - private KMEnumTag() {} + private KMEnumTag() { + } private static KMEnumTag proto(short ptr) { - if (prototype == null) prototype = new KMEnumTag(); + if (prototype == null) { + prototype = new KMEnumTag(); + } instPtr = ptr; return prototype; } // pointer to an empty instance used as expression public static short exp() { - short ptr = instance(TAG_TYPE, (short)2); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), ENUM_TAG); + short ptr = instance(TAG_TYPE, (short) 2); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), ENUM_TAG); return ptr; } public static short instance(short key) { - if(!validateEnum(key, NO_VALUE)){ + if (!validateEnum(key, NO_VALUE)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = KMType.instance(TAG_TYPE, (short)4); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), ENUM_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), key); + short ptr = KMType.instance(TAG_TYPE, (short) 4); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), ENUM_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); return ptr; } public static short instance(short key, byte val) { - if(!validateEnum(key, val)){ + if (!validateEnum(key, val)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = instance(TAG_TYPE, (short)5); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), ENUM_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), key); - heap[(short)(ptr+TLV_HEADER_SIZE+4)]= val; + short ptr = instance(TAG_TYPE, (short) 5); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), ENUM_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); + heap[(short) (ptr + TLV_HEADER_SIZE + 4)] = val; return ptr; } public static KMEnumTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } if (Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)) != ENUM_TAG) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } @@ -81,7 +88,7 @@ public static KMEnumTag cast(short ptr) { } public short getKey() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+2)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 2)); } public short getTagType() { @@ -89,20 +96,21 @@ public short getTagType() { } public byte getValue() { - return heap[(short)(instPtr+TLV_HEADER_SIZE+4)]; + return heap[(short) (instPtr + TLV_HEADER_SIZE + 4)]; } public static void create() { if (enums == null) { // enum tag values. enums = - new Object[] { - new byte[] {RSA, DES, EC, AES, HMAC}, - new byte[] {P_224, P_256, P_384, P_521}, - new byte[] {STANDALONE, REQUIRES_FILE_SYSTEM}, - new byte[] {USER_AUTH_NONE, PASSWORD, FINGERPRINT, (byte)(PASSWORD & FINGERPRINT),ANY}, - new byte[] {GENERATED, DERIVED, IMPORTED, UNKNOWN, SECURELY_IMPORTED}, - new byte[] {SOFTWARE, TRUSTED_ENVIRONMENT, STRONGBOX} + new Object[]{ + new byte[]{RSA, DES, EC, AES, HMAC}, + new byte[]{P_224, P_256, P_384, P_521}, + new byte[]{STANDALONE, REQUIRES_FILE_SYSTEM}, + new byte[]{USER_AUTH_NONE, PASSWORD, FINGERPRINT, (byte) (PASSWORD & FINGERPRINT), + ANY}, + new byte[]{GENERATED, DERIVED, IMPORTED, UNKNOWN, SECURELY_IMPORTED}, + new byte[]{SOFTWARE, TRUSTED_ENVIRONMENT, STRONGBOX} }; } } @@ -138,10 +146,10 @@ private static boolean validateEnum(short key, byte value) { return false; } - public static short getValue(short tagType, short keyParameters){ + public static short getValue(short tagType, short keyParameters) { short tagPtr = KMKeyParameters.findTag(KMType.ENUM_TAG, tagType, keyParameters); - if(tagPtr != KMType.INVALID_VALUE){ - return heap[(short)(tagPtr+TLV_HEADER_SIZE+4)]; + if (tagPtr != KMType.INVALID_VALUE) { + return heap[(short) (tagPtr + TLV_HEADER_SIZE + 4)]; } return KMType.INVALID_VALUE; } diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 76ec8560..bac8cf20 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -20,6 +20,7 @@ * positive unlike negative values in keymaster hal. */ public class KMError { + public static final short OK = 0; public static final short UNSUPPORTED_PURPOSE = 2; public static final short INCOMPATIBLE_PURPOSE = 3; @@ -36,7 +37,9 @@ public class KMError { public static final short UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = 19; - /** For PKCS8 & PKCS12 */ + /** + * For PKCS8 & PKCS12 + */ public static final short INVALID_INPUT_LENGTH = 21; @@ -86,5 +89,5 @@ public class KMError { public static final short CRYPTO_UNINITIALIZED_KEY = 10012; //Generic Unknown error. public static final short GENERIC_UNKNOWN_ERROR = 10013; - + } diff --git a/Applet/src/com/android/javacard/keymaster/KMException.java b/Applet/src/com/android/javacard/keymaster/KMException.java index 08bbd6ed..0f4f6740 100644 --- a/Applet/src/com/android/javacard/keymaster/KMException.java +++ b/Applet/src/com/android/javacard/keymaster/KMException.java @@ -21,20 +21,26 @@ * throw EMError errors. */ public class KMException extends RuntimeException { + public static short reason; public static KMException exception; - private KMException(){ + + private KMException() { } - public static void throwIt(short reason){ + + public static void throwIt(short reason) { KMException.reason = reason; throw instance(); } - public static KMException instance(){ - if(exception == null ) exception = new KMException(); + + public static KMException instance() { + if (exception == null) { + exception = new KMException(); + } return exception; } - public void clear(){ + public void clear() { reason = KMError.UNKNOWN_ERROR; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java b/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java index 6136563b..71e2e8bb 100644 --- a/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java +++ b/Applet/src/com/android/javacard/keymaster/KMHardwareAuthToken.java @@ -21,14 +21,14 @@ import javacard.framework.Util; /** - * KMHardwareAuthToken represents HardwareAuthToken structure from android keymaster hal specifications. - * It corresponds to CBOR array type. - * struct{byte HW_AUTH_TOKEN_TYPE; short length=2; short arrayPtr} where arrayPtr is a pointer to - * ordered array with following elements: - * {KMInteger Challenge; KMInteger UserId; KMInteger AuthenticatorId; UserAuthType HwAuthenticatorId; - * KMInteger TimeStamp; KMByteBlob Mac} + * KMHardwareAuthToken represents HardwareAuthToken structure from android keymaster hal + * specifications. It corresponds to CBOR array type. struct{byte HW_AUTH_TOKEN_TYPE; short + * length=2; short arrayPtr} where arrayPtr is a pointer to ordered array with following elements: + * {KMInteger Challenge; KMInteger UserId; KMInteger AuthenticatorId; UserAuthType + * HwAuthenticatorId; KMInteger TimeStamp; KMByteBlob Mac} */ public class KMHardwareAuthToken extends KMType { + public static final byte CHALLENGE = 0x00; public static final byte USER_ID = 0x01; public static final byte AUTHENTICATOR_ID = 0x02; @@ -39,10 +39,11 @@ public class KMHardwareAuthToken extends KMType { private static KMHardwareAuthToken prototype; private static short instPtr; - private KMHardwareAuthToken() {} + private KMHardwareAuthToken() { + } public static short exp() { - short arrPtr = KMArray.instance((short)6); + short arrPtr = KMArray.instance((short) 6); KMArray arr = KMArray.cast(arrPtr); arr.add(CHALLENGE, KMInteger.exp()); arr.add(USER_ID, KMInteger.exp()); @@ -54,35 +55,43 @@ public static short exp() { } private static KMHardwareAuthToken proto(short ptr) { - if (prototype == null) prototype = new KMHardwareAuthToken(); + if (prototype == null) { + prototype = new KMHardwareAuthToken(); + } instPtr = ptr; return prototype; } public static short instance() { - short arrPtr = KMArray.instance((short)6); + short arrPtr = KMArray.instance((short) 6); KMArray arr = KMArray.cast(arrPtr); - arr.add(CHALLENGE, KMInteger.uint_16((short)0)); - arr.add(USER_ID, KMInteger.uint_16((short)0)); - arr.add(AUTHENTICATOR_ID, KMInteger.uint_16((short)0)); + arr.add(CHALLENGE, KMInteger.uint_16((short) 0)); + arr.add(USER_ID, KMInteger.uint_16((short) 0)); + arr.add(AUTHENTICATOR_ID, KMInteger.uint_16((short) 0)); arr.add(HW_AUTHENTICATOR_TYPE, KMEnum.instance(KMType.USER_AUTH_TYPE, KMType.USER_AUTH_NONE)); - arr.add(TIMESTAMP, KMInteger.uint_16((short)0)); - arr.add(MAC, KMByteBlob.instance((short)0)); + arr.add(TIMESTAMP, KMInteger.uint_16((short) 0)); + arr.add(MAC, KMByteBlob.instance((short) 0)); return instance(arrPtr); } public static short instance(short vals) { KMArray arr = KMArray.cast(vals); - if(arr.length() != 6)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - short ptr = KMType.instance(HW_AUTH_TOKEN_TYPE, (short)2); - Util.setShort(heap, (short)(ptr + TLV_HEADER_SIZE), vals); + if (arr.length() != 6) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + short ptr = KMType.instance(HW_AUTH_TOKEN_TYPE, (short) 2); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), vals); return ptr; } public static KMHardwareAuthToken cast(short ptr) { - if (heap[ptr] != HW_AUTH_TOKEN_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != HW_AUTH_TOKEN_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short arrPtr = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); - if(heap[arrPtr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[arrPtr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } diff --git a/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java b/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java index c05ee29f..81a19bd3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java +++ b/Applet/src/com/android/javacard/keymaster/KMHmacSharingParameters.java @@ -19,24 +19,26 @@ import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; + /** - * KMHmacSharingParameters represents HmacSharingParameters structure from android keymaster hal specifications. - * It corresponds to CBOR array type. - * struct{byte HMAC_SHARING_PARAM_TYPE; short length=2; short arrayPtr} where arrayPtr is a pointer to - * ordered array with following elements: + * KMHmacSharingParameters represents HmacSharingParameters structure from android keymaster hal + * specifications. It corresponds to CBOR array type. struct{byte HMAC_SHARING_PARAM_TYPE; short + * length=2; short arrayPtr} where arrayPtr is a pointer to ordered array with following elements: * {KMByteBlob Seed; KMByteBlob Nonce} */ public class KMHmacSharingParameters extends KMType { + public static final byte SEED = 0x00; public static final byte NONCE = 0x01; private static KMHmacSharingParameters prototype; private static short instPtr; - private KMHmacSharingParameters() {} + private KMHmacSharingParameters() { + } public static short exp() { - short arrPtr = KMArray.instance((short)2); + short arrPtr = KMArray.instance((short) 2); KMArray arr = KMArray.cast(arrPtr); arr.add(SEED, KMByteBlob.exp()); arr.add(NONCE, KMByteBlob.exp()); @@ -44,27 +46,35 @@ public static short exp() { } private static KMHmacSharingParameters proto(short ptr) { - if (prototype == null) prototype = new KMHmacSharingParameters(); + if (prototype == null) { + prototype = new KMHmacSharingParameters(); + } instPtr = ptr; return prototype; } public static short instance() { - short arrPtr = KMArray.instance((short)2); + short arrPtr = KMArray.instance((short) 2); return instance(arrPtr); } public static short instance(short vals) { - short ptr = KMType.instance(HMAC_SHARING_PARAM_TYPE, (short)2); - if(KMArray.cast(vals).length() != 2) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - Util.setShort(heap, (short)(ptr + TLV_HEADER_SIZE), vals); + short ptr = KMType.instance(HMAC_SHARING_PARAM_TYPE, (short) 2); + if (KMArray.cast(vals).length() != 2) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), vals); return ptr; } public static KMHmacSharingParameters cast(short ptr) { - if (heap[ptr] != HMAC_SHARING_PARAM_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != HMAC_SHARING_PARAM_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short arrPtr = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); - if(heap[arrPtr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[arrPtr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } diff --git a/Applet/src/com/android/javacard/keymaster/KMInteger.java b/Applet/src/com/android/javacard/keymaster/KMInteger.java index 541eae8b..1330f85f 100644 --- a/Applet/src/com/android/javacard/keymaster/KMInteger.java +++ b/Applet/src/com/android/javacard/keymaster/KMInteger.java @@ -25,15 +25,19 @@ * struct{byte INTEGER_TYPE; short length; 4 or 8 bytes of value} */ public class KMInteger extends KMType { + public static final short UINT_32 = 4; public static final short UINT_64 = 8; private static KMInteger prototype; private static short instPtr; - private KMInteger() {} + private KMInteger() { + } private static KMInteger proto(short ptr) { - if (prototype == null) prototype = new KMInteger(); + if (prototype == null) { + prototype = new KMInteger(); + } instPtr = ptr; return prototype; } @@ -44,7 +48,9 @@ public static short exp() { // return an empty integer instance public static short instance(short length) { - if ((length <= 0) || (length > 8)) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + if ((length <= 0) || (length > 8)) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } if (length > 4) { length = UINT_64; } else { @@ -70,7 +76,9 @@ public static short instance(byte[] num, short srcOff, short length) { public static KMInteger cast(short ptr) { byte[] heap = repository.getHeap(); - if (heap[ptr] != INTEGER_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + 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); } @@ -120,58 +128,65 @@ public short getStartOff() { return (short) (instPtr + TLV_HEADER_SIZE); } - public void getValue(byte[] dest, short destOff, short length){ - if(length < length()) KMException.throwIt(KMError.UNKNOWN_ERROR); - if(length > length()) { + public void getValue(byte[] dest, short destOff, short length) { + if (length < length()) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } + if (length > length()) { length = length(); - destOff +=length; + destOff += length; } - Util.arrayCopyNonAtomic(heap, (short)(instPtr+TLV_HEADER_SIZE), dest, destOff, length); + Util.arrayCopyNonAtomic(heap, (short) (instPtr + TLV_HEADER_SIZE), dest, destOff, length); } - public void setValue(byte[] src, short srcOff){ - Util.arrayCopyNonAtomic(src, srcOff, heap, (short)(instPtr+TLV_HEADER_SIZE), length()); + + public void setValue(byte[] src, short srcOff) { + Util.arrayCopyNonAtomic(src, srcOff, heap, (short) (instPtr + TLV_HEADER_SIZE), length()); } - public short value(byte[] dest, short destOff){ - Util.arrayCopyNonAtomic(heap, (short)(instPtr+TLV_HEADER_SIZE), dest, destOff, length()); + + public short value(byte[] dest, short destOff) { + Util.arrayCopyNonAtomic(heap, (short) (instPtr + TLV_HEADER_SIZE), dest, destOff, length()); return length(); } public short getShort() { return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 2)); } - public short getSignificantShort(){ + + public short getSignificantShort() { return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE)); } + public byte getByte() { return heap[(short) (instPtr + TLV_HEADER_SIZE + 3)]; } public boolean isZero() { - if(getShort() == 0 && getSignificantShort() == 0){ + if (getShort() == 0 && getSignificantShort() == 0) { return true; } return false; } - 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); + 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); + 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); + KMInteger.cast(num2).getValue(repository.getHeap(), (short) (num2Buf + (short) (8 - len)), len); return KMInteger.unsignedByteArrayCompare( - repository.getHeap(), num1Buf, - repository.getHeap(), num2Buf, - (short)8); + repository.getHeap(), num1Buf, + repository.getHeap(), num2Buf, + (short) 8); } - public static byte unsignedByteArrayCompare(byte[] a1, short offset1, byte[] a2, short offset2, short length) { + 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; + short val1 = (short) 0; + short val2 = (short) 0; for (; count < length; count++) { val1 = (short) (a1[(short) (count + offset1)] & 0x00FF); diff --git a/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java b/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java index 7faa4c00..b97f5fa6 100644 --- a/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMIntegerArrayTag.java @@ -21,20 +21,24 @@ import javacard.framework.Util; /** - * KMIntegerArrayTag represents UINT_REP and ULONG_REP tags specified in keymaster hal specs. struct{byte - * TAG_TYPE; short length; struct{short UINT_TAG/ULONG_TAG; short tagKey; short arrPtr}, where arrPtr - * is the pointer to KMArray of KMInteger instances. + * KMIntegerArrayTag represents UINT_REP and ULONG_REP tags specified in keymaster hal specs. + * struct{byte TAG_TYPE; short length; struct{short UINT_TAG/ULONG_TAG; short tagKey; short arrPtr}, + * where arrPtr is the pointer to KMArray of KMInteger instances. */ public class KMIntegerArrayTag extends KMTag { + private static KMIntegerArrayTag prototype; private static short instPtr; private static final short[] tags = {USER_SECURE_ID}; - private KMIntegerArrayTag() {} + private KMIntegerArrayTag() { + } private static KMIntegerArrayTag proto(short ptr) { - if (prototype == null) prototype = new KMIntegerArrayTag(); + if (prototype == null) { + prototype = new KMIntegerArrayTag(); + } instPtr = ptr; return prototype; } @@ -44,10 +48,10 @@ public static short exp(short tagType) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } short arrPtr = KMArray.exp(KMType.INTEGER_TYPE); - short ptr = instance(TAG_TYPE, (short)6); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), tagType); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), INVALID_TAG); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+4), arrPtr); + short ptr = instance(TAG_TYPE, (short) 6); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), tagType); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), INVALID_TAG); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 4), arrPtr); return ptr; } @@ -69,18 +73,20 @@ public static short instance(short tagType, short key, short arrObj) { if (!validateKey(key)) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - if(heap[arrObj] != ARRAY_TYPE) { + if (heap[arrObj] != ARRAY_TYPE) { ISOException.throwIt(ISO7816.SW_DATA_INVALID); } - short ptr = instance(TAG_TYPE, (short)6); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE), tagType); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+2), key); - Util.setShort(heap, (short)(ptr+TLV_HEADER_SIZE+4), arrObj); + short ptr = instance(TAG_TYPE, (short) 6); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), tagType); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2), key); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE + 4), arrObj); return ptr; } public static KMIntegerArrayTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short tagType = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); if (!validateTagType(tagType)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); @@ -89,15 +95,15 @@ public static KMIntegerArrayTag cast(short ptr) { } public short getTagType() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE)); } public short getKey() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+2)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 2)); } public short getValues() { - return Util.getShort(heap, (short)(instPtr+TLV_HEADER_SIZE+4)); + return Util.getShort(heap, (short) (instPtr + TLV_HEADER_SIZE + 4)); } public short length() { @@ -131,7 +137,7 @@ private static boolean validateTagType(short tagType) { public static boolean contains(short tagId, short tagValue, short params) { short tag = - KMKeyParameters.findTag(KMType.UINT_ARRAY_TAG, tagId, params); + KMKeyParameters.findTag(KMType.UINT_ARRAY_TAG, tagId, params); if (tag != KMType.INVALID_VALUE) { short index = 0; tag = KMIntegerArrayTag.cast(tag).getValues(); diff --git a/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java b/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java index 2700580f..44136ec4 100644 --- a/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMIntegerTag.java @@ -19,40 +19,46 @@ import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; + /** * KMIntegerTag represents UINT, ULONG and DATE tags specified in keymaster hal specs. struct{byte - * TAG_TYPE; short length; struct{short UINT_TAG/ULONG_TAG/DATE_TAG; short tagKey; 4 or 8 byte value}} + * TAG_TYPE; short length; struct{short UINT_TAG/ULONG_TAG/DATE_TAG; short tagKey; 4 or 8 byte + * value}} */ public class KMIntegerTag extends KMTag { + private static KMIntegerTag prototype; private static short instPtr; // Allowed tag keys. private static final short[] tags = { - // UINT - KEYSIZE, - MIN_MAC_LENGTH, - MIN_SEC_BETWEEN_OPS, - MAX_USES_PER_BOOT, - USERID, - AUTH_TIMEOUT, - OS_VERSION, - OS_PATCH_LEVEL, - VENDOR_PATCH_LEVEL, - BOOT_PATCH_LEVEL, - MAC_LENGTH, - // ULONG - RSA_PUBLIC_EXPONENT, - // DATE - ACTIVE_DATETIME, - ORIGINATION_EXPIRE_DATETIME, - USAGE_EXPIRE_DATETIME, - CREATION_DATETIME + // UINT + KEYSIZE, + MIN_MAC_LENGTH, + MIN_SEC_BETWEEN_OPS, + MAX_USES_PER_BOOT, + USERID, + AUTH_TIMEOUT, + OS_VERSION, + OS_PATCH_LEVEL, + VENDOR_PATCH_LEVEL, + BOOT_PATCH_LEVEL, + MAC_LENGTH, + // ULONG + RSA_PUBLIC_EXPONENT, + // DATE + ACTIVE_DATETIME, + ORIGINATION_EXPIRE_DATETIME, + USAGE_EXPIRE_DATETIME, + CREATION_DATETIME }; - private KMIntegerTag() {} + private KMIntegerTag() { + } private static KMIntegerTag proto(short ptr) { - if (prototype == null) prototype = new KMIntegerTag(); + if (prototype == null) { + prototype = new KMIntegerTag(); + } instPtr = ptr; return prototype; } @@ -98,7 +104,9 @@ public static short instance(short tagType, short key, short intObj) { } public static KMIntegerTag cast(short ptr) { - if (heap[ptr] != TAG_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != TAG_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short tagType = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); if (!validateTagType(tagType)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); @@ -172,19 +180,29 @@ public boolean isValidKeySize(byte alg) { val = KMInteger.cast(val).getShort(); switch (alg) { case KMType.RSA: - if (val == 2048) return true; + if (val == 2048) { + return true; + } break; case KMType.AES: - if (val == 128 || val == 256) return true; + if (val == 128 || val == 256) { + return true; + } break; case KMType.DES: - if (val == 192 || val == 168) return true; + if (val == 192 || val == 168) { + return true; + } break; case KMType.EC: - if (val == 256) return true; + if (val == 256) { + return true; + } break; case KMType.HMAC: - if (val % 8 == 0 && val >= 64 && val <= 512) return true; + if (val % 8 == 0 && val >= 64 && val <= 512) { + return true; + } break; default: break; diff --git a/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java b/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java index 2b482b01..2ad16117 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeyCharacteristics.java @@ -19,25 +19,27 @@ import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; + /** - * KMKeyCharacteristics represents KeyCharacteristics structure from android keymaster hal specifications. - * It corresponds to CBOR array type. - * struct{byte KEY_CHAR_TYPE; short length=2; short arrayPtr} where arrayPtr is a pointer to - * ordered array with following elements: + * KMKeyCharacteristics represents KeyCharacteristics structure from android keymaster hal + * specifications. It corresponds to CBOR array type. struct{byte KEY_CHAR_TYPE; short length=2; + * short arrayPtr} where arrayPtr is a pointer to ordered array with following elements: * {KMKeyParameters sofEnf; KMKeyParameters hwEnf} */ public class KMKeyCharacteristics extends KMType { + public static final byte SOFTWARE_ENFORCED = 0x00; public static final byte HARDWARE_ENFORCED = 0x01; private static KMKeyCharacteristics prototype; private static short instPtr; - private KMKeyCharacteristics() {} + private KMKeyCharacteristics() { + } public static short exp() { short softEnf = KMKeyParameters.exp(); short hwEnf = KMKeyParameters.exp(); - short arrPtr = KMArray.instance((short)2); + short arrPtr = KMArray.instance((short) 2); KMArray arr = KMArray.cast(arrPtr); arr.add(SOFTWARE_ENFORCED, softEnf); arr.add(HARDWARE_ENFORCED, hwEnf); @@ -45,27 +47,35 @@ public static short exp() { } private static KMKeyCharacteristics proto(short ptr) { - if (prototype == null) prototype = new KMKeyCharacteristics(); + if (prototype == null) { + prototype = new KMKeyCharacteristics(); + } instPtr = ptr; return prototype; } public static short instance() { - short arrPtr = KMArray.instance((short)2); + short arrPtr = KMArray.instance((short) 2); return instance(arrPtr); } public static short instance(short vals) { - short ptr = KMType.instance(KEY_CHAR_TYPE, (short)2); - if(KMArray.cast(vals).length() != 2) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - Util.setShort(heap, (short)(ptr + TLV_HEADER_SIZE), vals); + short ptr = KMType.instance(KEY_CHAR_TYPE, (short) 2); + if (KMArray.cast(vals).length() != 2) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), vals); return ptr; } public static KMKeyCharacteristics cast(short ptr) { - if (heap[ptr] != KEY_CHAR_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != KEY_CHAR_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short arrPtr = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); - if(heap[arrPtr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[arrPtr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } @@ -80,7 +90,7 @@ public short length() { public short getSoftwareEnforced() { short arrPtr = getVals(); - return KMArray.cast(arrPtr).get(SOFTWARE_ENFORCED); + return KMArray.cast(arrPtr).get(SOFTWARE_ENFORCED); } public short getHardwareEnforced() { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java index f08ee388..cfdd9c30 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java @@ -21,19 +21,22 @@ import javacard.framework.Util; /** - * KMKeyParameters represents KeyParameters structure from android keymaster hal specifications. - * It corresponds to CBOR map type. - * struct{byte KEY_PARAM_TYPE; short length=2; short arrayPtr} where arrayPtr is a pointer to - * array with any KMTag subtype instances. + * KMKeyParameters represents KeyParameters structure from android keymaster hal specifications. It + * corresponds to CBOR map type. struct{byte KEY_PARAM_TYPE; short length=2; short arrayPtr} where + * arrayPtr is a pointer to array with any KMTag subtype instances. */ public class KMKeyParameters extends KMType { + private static KMKeyParameters prototype; private static short instPtr; - private KMKeyParameters() {} + private KMKeyParameters() { + } private static KMKeyParameters proto(short ptr) { - if (prototype == null) prototype = new KMKeyParameters(); + if (prototype == null) { + prototype = new KMKeyParameters(); + } instPtr = ptr; return prototype; } @@ -60,9 +63,13 @@ public static short instance(short vals) { } public static KMKeyParameters cast(short ptr) { - if (heap[ptr] != KEY_PARAM_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != KEY_PARAM_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short arrPtr = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); - if (heap[arrPtr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[arrPtr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } @@ -80,7 +87,7 @@ public static short findTag(short tagType, short tagKey, short keyParam) { return instParam.findTag(tagType, tagKey); } - public short findTag(short tagType, short tagKey){ + public short findTag(short tagType, short tagKey) { KMArray vals = KMArray.cast(getVals()); short index = 0; short length = vals.length(); @@ -100,16 +107,16 @@ public short findTag(short tagType, short tagKey){ } return ret; } - + public static boolean hasUnsupportedTags(short keyParamsPtr) { final short[] tagArr = { - // Unsupported tags. - KMType.BOOL_TAG, KMType.TRUSTED_CONFIRMATION_REQUIRED, - KMType.BOOL_TAG, KMType.TRUSTED_USER_PRESENCE_REQUIRED, - KMType.BOOL_TAG, KMType.ALLOW_WHILE_ON_BODY, - KMType.UINT_TAG, KMType.MIN_SEC_BETWEEN_OPS, - KMType.UINT_TAG, KMType.MAX_USES_PER_BOOT - }; + // Unsupported tags. + KMType.BOOL_TAG, KMType.TRUSTED_CONFIRMATION_REQUIRED, + KMType.BOOL_TAG, KMType.TRUSTED_USER_PRESENCE_REQUIRED, + KMType.BOOL_TAG, KMType.ALLOW_WHILE_ON_BODY, + KMType.UINT_TAG, KMType.MIN_SEC_BETWEEN_OPS, + KMType.UINT_TAG, KMType.MAX_USES_PER_BOOT + }; byte index = 0; short tagInd; short tagPtr; @@ -136,30 +143,30 @@ public static boolean hasUnsupportedTags(short keyParamsPtr) { // KDF, ECIES_SINGLE_HASH_MODE missing from types.hal public static short makeHwEnforced(short keyParamsPtr, byte origin, - short osVersionObjPtr, short osPatchObjPtr, short vendorPatchObjPtr, - short bootPatchObjPtr, byte[] scratchPad) { + short osVersionObjPtr, short osPatchObjPtr, short vendorPatchObjPtr, + short bootPatchObjPtr, byte[] scratchPad) { final short[] hwEnforcedTagArr = { - // HW Enforced - KMType.ENUM_TAG, KMType.ORIGIN, - KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, - KMType.ENUM_TAG, KMType.ALGORITHM, - KMType.UINT_TAG, KMType.KEYSIZE, - KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, - KMType.ENUM_TAG, KMType.BLOB_USAGE_REQ, - KMType.ENUM_ARRAY_TAG, KMType.DIGEST, - KMType.ENUM_ARRAY_TAG, KMType.PADDING, - KMType.ENUM_ARRAY_TAG, KMType.BLOCK_MODE, - KMType.ULONG_ARRAY_TAG, KMType.USER_SECURE_ID, - KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, - KMType.UINT_TAG, KMType.AUTH_TIMEOUT, - KMType.BOOL_TAG, KMType.CALLER_NONCE, - KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, - KMType.ENUM_TAG, KMType.ECCURVE, - KMType.BOOL_TAG, KMType.INCLUDE_UNIQUE_ID, - KMType.BOOL_TAG, KMType.ROLLBACK_RESISTANCE, - KMType.ENUM_TAG, KMType.USER_AUTH_TYPE, - KMType.BOOL_TAG, KMType.UNLOCKED_DEVICE_REQUIRED, - KMType.BOOL_TAG, KMType.RESET_SINCE_ID_ROTATION + // HW Enforced + KMType.ENUM_TAG, KMType.ORIGIN, + KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, + KMType.ENUM_TAG, KMType.ALGORITHM, + KMType.UINT_TAG, KMType.KEYSIZE, + KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, + KMType.ENUM_TAG, KMType.BLOB_USAGE_REQ, + KMType.ENUM_ARRAY_TAG, KMType.DIGEST, + KMType.ENUM_ARRAY_TAG, KMType.PADDING, + KMType.ENUM_ARRAY_TAG, KMType.BLOCK_MODE, + KMType.ULONG_ARRAY_TAG, KMType.USER_SECURE_ID, + KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, + KMType.UINT_TAG, KMType.AUTH_TIMEOUT, + KMType.BOOL_TAG, KMType.CALLER_NONCE, + KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, + KMType.ENUM_TAG, KMType.ECCURVE, + KMType.BOOL_TAG, KMType.INCLUDE_UNIQUE_ID, + KMType.BOOL_TAG, KMType.ROLLBACK_RESISTANCE, + KMType.ENUM_TAG, KMType.USER_AUTH_TYPE, + KMType.BOOL_TAG, KMType.UNLOCKED_DEVICE_REQUIRED, + KMType.BOOL_TAG, KMType.RESET_SINCE_ID_ROTATION }; byte index = 0; short tagInd; @@ -197,10 +204,12 @@ public static short makeHwEnforced(short keyParamsPtr, byte origin, short osPatchTag = KMIntegerTag.instance(KMType.UINT_TAG, KMType.OS_PATCH_LEVEL, osPatchObjPtr); Util.setShort(scratchPad, arrInd, osPatchTag); arrInd += 2; - short vendorPatchTag = KMIntegerTag.instance(KMType.UINT_TAG, KMType.VENDOR_PATCH_LEVEL, vendorPatchObjPtr); + short vendorPatchTag = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.VENDOR_PATCH_LEVEL, vendorPatchObjPtr); Util.setShort(scratchPad, arrInd, vendorPatchTag); arrInd += 2; - short bootPatchTag = KMIntegerTag.instance(KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, bootPatchObjPtr); + short bootPatchTag = KMIntegerTag + .instance(KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, bootPatchObjPtr); Util.setShort(scratchPad, arrInd, bootPatchTag); arrInd += 2; return createKeyParameters(scratchPad, (short) (arrInd / 2)); @@ -209,11 +218,11 @@ public static short makeHwEnforced(short keyParamsPtr, byte origin, // ALL_USERS, EXPORTABLE missing from types.hal public static short makeSwEnforced(short keyParamsPtr, byte[] scratchPad) { final short[] swEnforcedTagsArr = { - KMType.DATE_TAG, KMType.ACTIVE_DATETIME, - KMType.DATE_TAG, KMType.ORIGINATION_EXPIRE_DATETIME, - KMType.DATE_TAG, KMType.USAGE_EXPIRE_DATETIME, - KMType.UINT_TAG, KMType.USERID, - KMType.DATE_TAG, KMType.CREATION_DATETIME + KMType.DATE_TAG, KMType.ACTIVE_DATETIME, + KMType.DATE_TAG, KMType.ORIGINATION_EXPIRE_DATETIME, + KMType.DATE_TAG, KMType.USAGE_EXPIRE_DATETIME, + KMType.UINT_TAG, KMType.USERID, + KMType.DATE_TAG, KMType.CREATION_DATETIME }; byte index = 0; short tagInd; @@ -228,7 +237,7 @@ public static short makeSwEnforced(short keyParamsPtr, byte[] scratchPad) { tagPtr = KMArray.cast(arrPtr).get(index); tagKey = KMTag.getKey(tagPtr); tagType = KMTag.getTagType(tagPtr); - if (!isValidTag(tagType, tagKey)){ + if (!isValidTag(tagType, tagKey)) { KMException.throwIt(KMError.INVALID_KEY_BLOB); } while (tagInd < (short) swEnforcedTagsArr.length) { @@ -250,7 +259,7 @@ public static short makeHidden(short keyParamsPtr, short rootOfTrustBlob, byte[] if (appId != KMTag.INVALID_VALUE) { appId = KMByteTag.cast(appId).getValue(); } - short appData = + short appData = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, keyParamsPtr); if (appData != KMTag.INVALID_VALUE) { appData = KMByteTag.cast(appData).getValue(); @@ -258,7 +267,8 @@ public static short makeHidden(short keyParamsPtr, short rootOfTrustBlob, byte[] return makeHidden(appId, appData, rootOfTrustBlob, scratchPad); } - public static short makeHidden(short appIdBlob, short appDataBlob, short rootOfTrustBlob, byte[] scratchPad){ + public static short makeHidden(short appIdBlob, short appDataBlob, short rootOfTrustBlob, + byte[] scratchPad) { // Order in which the hidden array is created should not change. short index = 0; KMByteBlob.cast(rootOfTrustBlob); @@ -273,16 +283,17 @@ public static short makeHidden(short appIdBlob, short appDataBlob, short rootOfT Util.setShort(scratchPad, index, appDataBlob); index += 2; } - return createKeyParameters(scratchPad, (short)(index/2)); + return createKeyParameters(scratchPad, (short) (index / 2)); } + public static boolean isValidTag(short tagType, short tagKey) { short[] invalidTagsArr = { - KMType.BYTES_TAG, KMType.NONCE, - KMType.BYTES_TAG, KMType.ASSOCIATED_DATA, - KMType.BYTES_TAG, KMType.UNIQUE_ID, - KMType.UINT_TAG, KMType.MAC_LENGTH, - KMType.BOOL_TAG, KMType.BOOTLOADER_ONLY + KMType.BYTES_TAG, KMType.NONCE, + KMType.BYTES_TAG, KMType.ASSOCIATED_DATA, + KMType.BYTES_TAG, KMType.UNIQUE_ID, + KMType.UINT_TAG, KMType.MAC_LENGTH, + KMType.BOOL_TAG, KMType.BOOTLOADER_ONLY }; short index = 0; if (tagKey == KMType.INVALID_TAG) { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 3942a891..b4914308 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -32,6 +32,7 @@ * events. */ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLength { + // Constants. public static final byte AES_BLOCK_SIZE = 16; public static final byte DES_BLOCK_SIZE = 8; @@ -43,23 +44,27 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // "Keymaster HMAC Verification" - used for HMAC key verification. public static final byte[] sharingCheck = { - 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x48, 0x4D, 0x41, 0x43, 0x20, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E + 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x48, 0x4D, 0x41, 0x43, 0x20, + 0x56, + 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E }; // "KeymasterSharedMac" public static final byte[] ckdfLable = { - 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4D, - 0x61, 0x63 + 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, + 0x4D, + 0x61, 0x63 }; // "Auth Verification" public static final byte[] authVerification = { - 0x41, 0x75, 0x74, 0x68, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, - 0x6E + 0x41, 0x75, 0x74, 0x68, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6F, + 0x6E }; // "confirmation token" public static final byte[] confirmationToken = { - 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x74, 0x6F, 0x6B, - 0x65, 0x6E + 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x74, 0x6F, + 0x6B, + 0x65, 0x6E }; // Possible states of the applet. @@ -180,7 +185,9 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe protected byte provisionStatus = NOT_PROVISIONED; protected static final short MAX_CERT_SIZE = 2048; - /** Registers this applet. */ + /** + * Registers this applet. + */ protected KMKeymasterApplet(KMSEProvider seImpl) { seProvider = seImpl; boolean isUpgrading = seImpl.isUpgrading(); @@ -189,7 +196,7 @@ protected KMKeymasterApplet(KMSEProvider seImpl) { data = JCSystem.makeTransientShortArray((short) DATA_ARRAY_SIZE, JCSystem.CLEAR_ON_RESET); tmpVariables = JCSystem.makeTransientShortArray((short) TMP_VARIABLE_ARRAY_SIZE, JCSystem.CLEAR_ON_RESET); - if(!isUpgrading) { + if (!isUpgrading) { keymasterState = KMKeymasterApplet.INIT_STATE; seProvider.createMasterKey((short) (KMRepository.MASTER_KEY_SIZE * 8)); } @@ -212,13 +219,17 @@ public boolean select() { return true; } - /** De-selects this applet. */ + /** + * De-selects this applet. + */ @Override public void deselect() { repository.onDeselect(); } - /** Uninstalls the applet after cleaning the repository. */ + /** + * Uninstalls the applet after cleaning the repository. + */ @Override public void uninstall() { repository.onUninstall(); @@ -245,7 +256,7 @@ private short mapISOErrorToKMError(short reason) { return KMError.UNKNOWN_ERROR; } } - + private short mapCryptoErrorToKMError(short reason) { switch (reason) { case CryptoException.ILLEGAL_USE: @@ -261,7 +272,7 @@ private short mapCryptoErrorToKMError(short reason) { default: return KMError.UNKNOWN_ERROR; } - } + } protected void validateApduHeader(APDU apdu) { // Read the apdu header and buffer. @@ -291,7 +302,7 @@ public void process(APDU apdu) { repository.onProcess(); // Verify whether applet is in correct state. if ((keymasterState == KMKeymasterApplet.INIT_STATE) - || (keymasterState == KMKeymasterApplet.ILLEGAL_STATE)) { + || (keymasterState == KMKeymasterApplet.ILLEGAL_STATE)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } // If this is select applet apdu which is selecting this applet then @@ -358,11 +369,11 @@ public void process(APDU apdu) { } if ((keymasterState == KMKeymasterApplet.ACTIVE_STATE) - || (keymasterState == KMKeymasterApplet.IN_PROVISION_STATE)) { + || (keymasterState == KMKeymasterApplet.IN_PROVISION_STATE)) { switch (apduIns) { case INS_SET_BOOT_PARAMS_CMD: if (seProvider.isBootSignalEventSupported() - && (!seProvider.isDeviceRebooted())) { + && (!seProvider.isDeviceRebooted())) { ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED); } processSetBootParamsCmd(apdu); @@ -378,8 +389,8 @@ public void process(APDU apdu) { } if ((keymasterState == KMKeymasterApplet.ACTIVE_STATE) - || ((keymasterState == KMKeymasterApplet.IN_PROVISION_STATE) - && isProvisioningComplete())) { + || ((keymasterState == KMKeymasterApplet.IN_PROVISION_STATE) + && isProvisioningComplete())) { switch (apduIns) { case INS_GENERATE_KEY_CMD: processGenerateKey(apdu); @@ -479,11 +490,11 @@ private void generateUniqueOperationHandle(byte[] buf, short offset, short len) } private boolean isProvisioningComplete() { - if((0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_KEY)) - && (0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_CERT_CHAIN)) - && (0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_CERT_PARAMS)) - && (0 != (provisionStatus & PROVISION_STATUS_PRESHARED_SECRET)) - && (0 != (provisionStatus & PROVISION_STATUS_BOOT_PARAM))) { + if ((0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_KEY)) + && (0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_CERT_CHAIN)) + && (0 != (provisionStatus & PROVISION_STATUS_ATTESTATION_CERT_PARAMS)) + && (0 != (provisionStatus & PROVISION_STATUS_PRESHARED_SECRET)) + && (0 != (provisionStatus & PROVISION_STATUS_BOOT_PARAM))) { return true; } else { return false; @@ -543,10 +554,13 @@ private void resetData() { index++; } } - /** Sends a response, may be extended response, as requested by the command. */ + + /** + * Sends a response, may be extended response, as requested by the command. + */ public static void sendOutgoing(APDU apdu) { if (((short) (bufferLength + bufferStartOffset)) > ((short) repository - .getHeap().length)) { + .getHeap().length)) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); } // Send data @@ -555,7 +569,9 @@ public static void sendOutgoing(APDU apdu) { apdu.sendBytesLong(buffer, bufferStartOffset, bufferLength); } - /** Receives data, which can be extended data, as requested by the command instance. */ + /** + * Receives data, which can be extended data, as requested by the command instance. + */ public static void receiveIncoming(APDU apdu) { byte[] srcBuffer = apdu.getBuffer(); short recvLen = apdu.setIncomingAndReceive(); @@ -574,8 +590,8 @@ public static void receiveIncoming(APDU apdu) { private void processGetHwInfoCmd(APDU apdu) { // No arguments expected 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, + 0x4A, 0x61, 0x76, 0x61, 0x63, 0x61, 0x72, 0x64, 0x4B, 0x65, 0x79, 0x6D, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, }; final byte[] Google = {0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65}; @@ -674,18 +690,19 @@ private void processProvisionAttestationCertChainCmd(APDU apdu) { bufferStartOffset = repository.alloc(bufferLength); short bytesRead = 0; Util.arrayCopyNonAtomic(srcBuffer, srcOffset, buffer, bufferStartOffset, - recvLen); + recvLen); // tmpVariables[1] holds the total length + Header length. tmpVariables[1] = decoder.readCertificateChainLengthAndHeaderLen(buffer, - bufferStartOffset, recvLen); + bufferStartOffset, recvLen); while (recvLen > 0 && ((short) bytesRead <= bufferLength)) { seProvider.persistPartialCertificateChain(buffer, bufferStartOffset, - recvLen, bufferLength); + recvLen, bufferLength); bytesRead += recvLen; recvLen = apdu.receiveBytes(srcOffset); - if (recvLen > 0) + if (recvLen > 0) { Util.arrayCopyNonAtomic(srcBuffer, srcOffset, buffer, bufferStartOffset, - recvLen); + recvLen); + } } if (tmpVariables[1] != bytesRead) { ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); @@ -730,10 +747,13 @@ private void processProvisionAttestationKey(APDU apdu) { tmpVariables[0] = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.DIGEST, data[KEY_PARAMETERS]); if (tmpVariables[0] != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(tmpVariables[0]).length() != 1) + if (KMEnumArrayTag.cast(tmpVariables[0]).length() != 1) { KMException.throwIt(KMError.INVALID_ARGUMENT); + } tmpVariables[0] = KMEnumArrayTag.cast(tmpVariables[0]).get((short) 0); - if (tmpVariables[0] != KMType.SHA2_256) KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); + if (tmpVariables[0] != KMType.SHA2_256) { + KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); + } } else { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -741,10 +761,13 @@ private void processProvisionAttestationKey(APDU apdu) { tmpVariables[0] = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, data[KEY_PARAMETERS]); if (tmpVariables[0] != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(tmpVariables[0]).length() != 1) + if (KMEnumArrayTag.cast(tmpVariables[0]).length() != 1) { KMException.throwIt(KMError.INVALID_ARGUMENT); + } tmpVariables[0] = KMEnumArrayTag.cast(tmpVariables[0]).get((short) 0); - if (tmpVariables[0] != KMType.ATTEST_KEY) KMException.throwIt(KMError.INCOMPATIBLE_PURPOSE); + if (tmpVariables[0] != KMType.ATTEST_KEY) { + KMException.throwIt(KMError.INCOMPATIBLE_PURPOSE); + } } else { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -753,9 +776,9 @@ private void processProvisionAttestationKey(APDU apdu) { // persist key seProvider.createAttestationKey( - KMByteBlob.cast(data[SECRET]).getBuffer(), - KMByteBlob.cast(data[SECRET]).getStartOff(), - KMByteBlob.cast(data[SECRET]).length()); + KMByteBlob.cast(data[SECRET]).getBuffer(), + KMByteBlob.cast(data[SECRET]).getStartOff(), + KMByteBlob.cast(data[SECRET]).length()); } private void processProvisionAttestIdsCmd(APDU apdu) { @@ -938,9 +961,9 @@ private void processDeleteKeyCmd(APDU apdu) { KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, KMByteBlob.exp()); try { data[KEY_BLOB] = decoder.decodeArray(tmpVariables[1], - KMByteBlob.cast(data[KEY_BLOB]).getBuffer(), - KMByteBlob.cast(data[KEY_BLOB]).getStartOff(), - KMByteBlob.cast(data[KEY_BLOB]).length()); + KMByteBlob.cast(data[KEY_BLOB]).getBuffer(), + KMByteBlob.cast(data[KEY_BLOB]).getStartOff(), + KMByteBlob.cast(data[KEY_BLOB]).length()); } catch (ISOException e) { // As per VTS, deleteKey should return KMError.OK but in case if // input is empty then VTS accepts UNIMPLEMENTED errorCode as well. @@ -1017,11 +1040,11 @@ private void processComputeSharedHmacCmd(APDU apdu) { if (tmpVariables[7] == 1) { if (0 == Util.arrayCompare( - repository.getHeap(), - (short) (tmpVariables[1] + tmpVariables[3]), - KMByteBlob.cast(tmpVariables[9]).getBuffer(), - KMByteBlob.cast(tmpVariables[9]).getStartOff(), - tmpVariables[6])) { + repository.getHeap(), + (short) (tmpVariables[1] + tmpVariables[3]), + KMByteBlob.cast(tmpVariables[9]).getBuffer(), + KMByteBlob.cast(tmpVariables[9]).getStartOff(), + tmpVariables[6])) { tmpVariables[7] = 2; // hmac nonce for this keymaster found. } else { tmpVariables[7] = 0; @@ -1129,7 +1152,7 @@ private void processUpgradeKeyCmd(APDU apdu) { } //Compare vendor patch levels tmpVariables[1] = - KMKeyParameters.findTag(KMType.UINT_TAG, KMType.VENDOR_PATCH_LEVEL, data[HW_PARAMETERS]); + KMKeyParameters.findTag(KMType.UINT_TAG, KMType.VENDOR_PATCH_LEVEL, data[HW_PARAMETERS]); tmpVariables[1] = KMIntegerTag.cast(tmpVariables[1]).getValue(); tmpVariables[2] = repository.getVendorPatchLevel(); if (tmpVariables[1] != KMType.INVALID_VALUE) { @@ -1142,7 +1165,7 @@ private void processUpgradeKeyCmd(APDU apdu) { } //Compare boot patch levels tmpVariables[1] = - KMKeyParameters.findTag(KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, data[HW_PARAMETERS]); + KMKeyParameters.findTag(KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, data[HW_PARAMETERS]); tmpVariables[1] = KMIntegerTag.cast(tmpVariables[1]).getValue(); tmpVariables[2] = repository.getBootPatchLevel(); if (tmpVariables[1] != KMType.INVALID_VALUE) { @@ -1373,7 +1396,9 @@ private void processAttestKeyCmd(APDU apdu) { KMException.throwIt(KMError.INCOMPATIBLE_ALGORITHM); } boolean rsaCert = true; - if (tmpVariables[0] == KMType.EC) rsaCert = false; + if (tmpVariables[0] == KMType.EC) { + rsaCert = false; + } KMAttestationCert cert = seProvider.getAttestationCert(rsaCert); // Save attestation application id - must be present. tmpVariables[0] = @@ -1401,12 +1426,14 @@ private void processAttestKeyCmd(APDU apdu) { // then it is an error. tmpVariables[1] = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.ACTIVE_DATETIME, data[SW_PARAMETERS]); - if (tmpVariables[1] != KMType.INVALID_VALUE) + if (tmpVariables[1] != KMType.INVALID_VALUE) { tmpVariables[1] = KMIntegerTag.cast(tmpVariables[1]).getValue(); - else { + } else { tmpVariables[1] = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CREATION_DATETIME, data[SW_PARAMETERS]); - if (tmpVariables[1] == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_KEY_BLOB); + if (tmpVariables[1] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.INVALID_KEY_BLOB); + } tmpVariables[1] = KMIntegerTag.cast(tmpVariables[1]).getValue(); } // convert milliseconds to UTC date. Start of validity period has to be UTC. @@ -1445,15 +1472,15 @@ private void processAttestKeyCmd(APDU apdu) { // -------------------------------- private void addAttestationIds(KMAttestationCert cert) { final short[] attTags = - new short[] { - KMType.ATTESTATION_ID_BRAND, - KMType.ATTESTATION_ID_DEVICE, - KMType.ATTESTATION_ID_IMEI, - KMType.ATTESTATION_ID_MANUFACTURER, - KMType.ATTESTATION_ID_MEID, - KMType.ATTESTATION_ID_MODEL, - KMType.ATTESTATION_ID_PRODUCT, - KMType.ATTESTATION_ID_SERIAL + new short[]{ + KMType.ATTESTATION_ID_BRAND, + KMType.ATTESTATION_ID_DEVICE, + KMType.ATTESTATION_ID_IMEI, + KMType.ATTESTATION_ID_MANUFACTURER, + KMType.ATTESTATION_ID_MEID, + KMType.ATTESTATION_ID_MODEL, + KMType.ATTESTATION_ID_PRODUCT, + KMType.ATTESTATION_ID_SERIAL }; byte index = 0; short attIdTag; @@ -1481,44 +1508,46 @@ private void addTags(short params, boolean hwEnforced, KMAttestationCert cert) { private void setUniqueId(KMAttestationCert cert, byte[] scratchPad) { tmpVariables[0] = KMKeyParameters.findTag(KMType.BOOL_TAG, - KMType.INCLUDE_UNIQUE_ID, data[HW_PARAMETERS]); + KMType.INCLUDE_UNIQUE_ID, data[HW_PARAMETERS]); if (tmpVariables[0] == KMType.INVALID_VALUE) { return; } // temporal count T tmpVariables[0] = KMKeyParameters.findTag(KMType.DATE_TAG, - KMType.CREATION_DATETIME, data[SW_PARAMETERS]); - if (tmpVariables[0] == KMType.INVALID_VALUE) + KMType.CREATION_DATETIME, data[SW_PARAMETERS]); + if (tmpVariables[0] == KMType.INVALID_VALUE) { KMException.throwIt(KMError.INVALID_TAG); + } tmpVariables[0] = KMIntegerTag.cast(tmpVariables[0]).getValue(); // Application Id C tmpVariables[1] = KMKeyParameters.findTag(KMType.BYTES_TAG, - KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]); - if (tmpVariables[1] == KMType.INVALID_VALUE) + KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]); + if (tmpVariables[1] == KMType.INVALID_VALUE) { KMException.throwIt(KMError.ATTESTATION_APPLICATION_ID_MISSING); + } tmpVariables[1] = KMByteTag.cast(tmpVariables[1]).getValue(); // Reset After Rotation R - it will be part of HW Enforced key // characteristics byte resetAfterRotation = 0; tmpVariables[2] = KMKeyParameters.findTag(KMType.BOOL_TAG, - KMType.RESET_SINCE_ID_ROTATION, data[HW_PARAMETERS]); + KMType.RESET_SINCE_ID_ROTATION, data[HW_PARAMETERS]); if (tmpVariables[2] != KMType.INVALID_VALUE) { resetAfterRotation = 0x01; } cert.makeUniqueId( - scratchPad, - (short) 0, - KMInteger.cast(tmpVariables[0]).getBuffer(), - KMInteger.cast(tmpVariables[0]).getStartOff(), - KMInteger.cast(tmpVariables[0]).length(), - KMByteBlob.cast(tmpVariables[1]).getBuffer(), - KMByteBlob.cast(tmpVariables[1]).getStartOff(), - KMByteBlob.cast(tmpVariables[1]).length(), resetAfterRotation, - seProvider.getMasterKey()); + scratchPad, + (short) 0, + KMInteger.cast(tmpVariables[0]).getBuffer(), + KMInteger.cast(tmpVariables[0]).getStartOff(), + KMInteger.cast(tmpVariables[0]).length(), + KMByteBlob.cast(tmpVariables[1]).getBuffer(), + KMByteBlob.cast(tmpVariables[1]).getStartOff(), + KMByteBlob.cast(tmpVariables[1]).length(), resetAfterRotation, + seProvider.getMasterKey()); } private void processDestroyAttIdsCmd(APDU apdu) { @@ -1662,8 +1691,9 @@ private void finishDecryptOperation(KMOperationState op, byte[] scratchPad) { case KMType.RSA: // Fill the scratch pad with zero Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); - if (op.getPadding() == KMType.PADDING_NONE && len != 256) + if (op.getPadding() == KMType.PADDING_NONE && len != 256) { KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } len = op.getOperation() .finish( @@ -1773,8 +1803,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); } else { - KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } } catch (CryptoException e) { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -1797,8 +1827,8 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch (short) 0); data[OUTPUT_DATA] = KMByteBlob.instance(scratchPad, (short) 0, len); } else { - KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); - } + KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } break; case KMType.HMAC: // As per Keymaster HAL documentation, the length of the Hmac output can @@ -1826,11 +1856,11 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch if (op.getPurpose() == KMType.VERIFY) { if (0 != Util.arrayCompare( - KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[SIGNATURE]).getBuffer(), - KMByteBlob.cast(data[SIGNATURE]).getStartOff(), - (short) (op.getMacLength() / 8))) { + KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), + KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff(), + KMByteBlob.cast(data[SIGNATURE]).getBuffer(), + KMByteBlob.cast(data[SIGNATURE]).getStartOff(), + (short) (op.getMacLength() / 8))) { KMException.throwIt(KMError.VERIFICATION_FAILED); } } @@ -1871,7 +1901,9 @@ private void authorizeDeviceUnlock(short hwToken) { KMType.BOOL_TAG, KMType.UNLOCKED_DEVICE_REQUIRED, data[HW_PARAMETERS]); if (ptr != KMType.INVALID_VALUE && repository.getDeviceLock()) { - if (hwToken == KMType.INVALID_VALUE) KMException.throwIt(KMError.DEVICE_LOCKED); + if (hwToken == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.DEVICE_LOCKED); + } ptr = KMHardwareAuthToken.cast(hwToken).getTimestamp(); // Check if the current auth time stamp is greater then device locked time stamp short ts = repository.getDeviceTimeStamp(); @@ -1992,7 +2024,9 @@ private void processUpdateOperationCmd(APDU apdu) { // Check Operation Handle and get op state // Check Operation Handle KMOperationState op = repository.findOperation(data[OP_HANDLE]); - if (op == null) KMException.throwIt(KMError.INVALID_OPERATION_HANDLE); + if (op == null) { + KMException.throwIt(KMError.INVALID_OPERATION_HANDLE); + } // authorize the update operation authorizeUpdateFinishOperation(op, scratchPad); // If signing without digest then do length validation checks @@ -2132,17 +2166,18 @@ private void processBeginOperationCmd(APDU apdu) { /*Generate a random number for operation handle */ short buf = KMByteBlob.instance(KMRepository.OPERATION_HANDLE_SIZE); generateUniqueOperationHandle( - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); /* opHandle is a KMInteger and is encoded as KMInteger when it is returned back. */ short opHandle = KMInteger.instance( - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); KMOperationState op = repository.reserveOperation(opHandle); - if (op == null) + if (op == null) { KMException.throwIt(KMError.TOO_MANY_OPERATIONS); + } data[OP_HANDLE] = op.getHandle(); op.setPurpose((byte) tmpVariables[0]); op.setKeySize(KMByteBlob.cast(data[SECRET]).length()); @@ -2207,13 +2242,15 @@ private void authorizePurpose(KMOperationState op) { switch (op.getAlgorithm()) { case KMType.AES: case KMType.DES: - if (op.getPurpose() == KMType.SIGN || op.getPurpose() == KMType.VERIFY) + if (op.getPurpose() == KMType.SIGN || op.getPurpose() == KMType.VERIFY) { KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } break; case KMType.EC: case KMType.HMAC: - if (op.getPurpose() == KMType.ENCRYPT || op.getPurpose() == KMType.DECRYPT) + if (op.getPurpose() == KMType.ENCRYPT || op.getPurpose() == KMType.DECRYPT) { KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); + } break; default: break; @@ -2230,17 +2267,21 @@ private void authorizeDigest(KMOperationState op) { short param = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.DIGEST, data[KEY_PARAMETERS]); if (param != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(param).length() != 1) KMException.throwIt(KMError.INVALID_ARGUMENT); + if (KMEnumArrayTag.cast(param).length() != 1) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } param = KMEnumArrayTag.cast(param).get((short) 0); - if (!KMEnumArrayTag.cast(digests).contains(param)) + if (!KMEnumArrayTag.cast(digests).contains(param)) { KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); + } op.setDigest((byte) param); } short paramPadding = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, data[KEY_PARAMETERS]); if (paramPadding != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(paramPadding).length() != 1) + if (KMEnumArrayTag.cast(paramPadding).length() != 1) { KMException.throwIt(KMError.INVALID_ARGUMENT); + } paramPadding = KMEnumArrayTag.cast(paramPadding).get((short) 0); } switch (op.getAlgorithm()) { @@ -2252,7 +2293,9 @@ private void authorizeDigest(KMOperationState op) { break; case KMType.EC: case KMType.HMAC: - if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.UNSUPPORTED_DIGEST); + if (param == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNSUPPORTED_DIGEST); + } break; default: break; @@ -2266,24 +2309,31 @@ private void authorizePadding(KMOperationState op) { short param = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, data[KEY_PARAMETERS]); if (param != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(param).length() != 1) KMException.throwIt(KMError.INVALID_ARGUMENT); + if (KMEnumArrayTag.cast(param).length() != 1) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } param = KMEnumArrayTag.cast(param).get((short) 0); - if (!KMEnumArrayTag.cast(paddings).contains(param)) + if (!KMEnumArrayTag.cast(paddings).contains(param)) { KMException.throwIt(KMError.INCOMPATIBLE_PADDING_MODE); + } } switch (op.getAlgorithm()) { case KMType.RSA: - if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + if (param == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + } if ((op.getPurpose() == KMType.SIGN || op.getPurpose() == KMType.VERIFY) && param != KMType.PADDING_NONE && param != KMType.RSA_PSS - && param != KMType.RSA_PKCS1_1_5_SIGN) + && param != KMType.RSA_PKCS1_1_5_SIGN) { KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + } if ((op.getPurpose() == KMType.ENCRYPT || op.getPurpose() == KMType.DECRYPT) && param != KMType.PADDING_NONE && param != KMType.RSA_OAEP - && param != KMType.RSA_PKCS1_1_5_ENCRYPT) + && param != KMType.RSA_PKCS1_1_5_ENCRYPT) { KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + } if (param == KMType.PADDING_NONE && op.getDigest() != KMType.DIGEST_NONE) { KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); } @@ -2295,7 +2345,9 @@ private void authorizePadding(KMOperationState op) { break; case KMType.DES: case KMType.AES: - if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + if (param == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); + } op.setPadding((byte) param); break; default: @@ -2307,7 +2359,9 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { short param = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.BLOCK_MODE, data[KEY_PARAMETERS]); if (param != KMType.INVALID_VALUE) { - if (KMEnumArrayTag.cast(param).length() != 1) KMException.throwIt(KMError.INVALID_ARGUMENT); + if (KMEnumArrayTag.cast(param).length() != 1) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } param = KMEnumArrayTag.cast(param).get((short) 0); } if (KMType.AES == op.getAlgorithm() || KMType.DES == op.getAlgorithm()) { @@ -2320,7 +2374,7 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { switch (op.getAlgorithm()) { case KMType.AES: //Validate the block mode. - switch(param) { + switch (param) { case KMType.ECB: case KMType.CBC: case KMType.CTR: @@ -2329,7 +2383,9 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { default: KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); } - if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); + if (param == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } if (param == KMType.GCM) { if (op.getPadding() != KMType.PADDING_NONE) { KMException.throwIt(KMError.INCOMPATIBLE_PADDING_MODE); @@ -2340,8 +2396,8 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { if (macLen % 8 != 0 || macLen > 128 || macLen - < KMIntegerTag.getShortValue( - KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { + < KMIntegerTag.getShortValue( + KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { KMException.throwIt(KMError.INVALID_MAC_LENGTH); } op.setMacLength(macLen); @@ -2349,14 +2405,16 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { break; case KMType.DES: //Validate the block mode. - switch(param) { + switch (param) { case KMType.ECB: case KMType.CBC: break; default: KMException.throwIt(KMError.UNSUPPORTED_BLOCK_MODE); } - if (param == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_ARGUMENT); + if (param == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.INVALID_ARGUMENT); + } break; case KMType.HMAC: if (macLen == KMType.INVALID_VALUE) { @@ -2370,11 +2428,11 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) { } if (macLen < KMIntegerTag.getShortValue( - KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { + KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { KMException.throwIt(KMError.INVALID_MAC_LENGTH); } else if (macLen > KMIntegerTag.getShortValue( - KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { + KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) { KMException.throwIt(KMError.UNSUPPORTED_MAC_LENGTH); } op.setMacLength(macLen); @@ -2431,8 +2489,8 @@ private void authorizeAndBeginOperation(KMOperationState op, byte[] scratchPad) // For symmetric decryption iv is required if (op.getPurpose() == KMType.DECRYPT && (op.getBlockMode() == KMType.CBC - || op.getBlockMode() == KMType.GCM - || op.getBlockMode() == KMType.CTR)) { + || op.getBlockMode() == KMType.GCM + || op.getBlockMode() == KMType.CTR)) { KMException.throwIt(KMError.MISSING_NONCE); } else if (op.getBlockMode() == KMType.ECB) { // For ECB we create zero length nonce @@ -2499,10 +2557,11 @@ private void beginCipherOperation(KMOperationState op) { KMByteBlob.cast(data[IV]).length(), op.getMacLength())); } catch (CryptoException exception) { - if (exception.getReason() == CryptoException.ILLEGAL_VALUE) + if (exception.getReason() == CryptoException.ILLEGAL_VALUE) { KMException.throwIt(KMError.INVALID_ARGUMENT); - else if (exception.getReason() == CryptoException.NO_SUCH_ALGORITHM) + } else if (exception.getReason() == CryptoException.NO_SUCH_ALGORITHM) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); + } } } } @@ -2555,17 +2614,17 @@ private void beginSignVerifyOperation(KMOperationState op) { } break; case KMType.HMAC: - // As per Keymaster HAL documentation, the length of the Hmac output can - // be decided by using TAG_MAC_LENGTH in Keyparameters. But there is no - // such provision to control the length of the Hmac output using JavaCard - // crypto APIs and the current implementation always returns 32 bytes - // length of Hmac output. So to provide support to TAG_MAC_LENGTH - // feature, we truncate the output signature to TAG_MAC_LENGTH and return - // the truncated signature back to the caller. At the time of verfication - // we again compute the signature of the plain text input, truncate it to - // TAG_MAC_LENGTH and compare it with the input signature for - // verification. So this is the reason we are using KMType.SIGN directly - // instead of using op.getPurpose(). + // As per Keymaster HAL documentation, the length of the Hmac output can + // be decided by using TAG_MAC_LENGTH in Keyparameters. But there is no + // such provision to control the length of the Hmac output using JavaCard + // crypto APIs and the current implementation always returns 32 bytes + // length of Hmac output. So to provide support to TAG_MAC_LENGTH + // feature, we truncate the output signature to TAG_MAC_LENGTH and return + // the truncated signature back to the caller. At the time of verfication + // we again compute the signature of the plain text input, truncate it to + // TAG_MAC_LENGTH and compare it with the input signature for + // verification. So this is the reason we are using KMType.SIGN directly + // instead of using op.getPurpose(). try { op.setOperation( seProvider.initSymmetricOperation( @@ -2601,7 +2660,9 @@ private void authorizeUserSecureIdAuthTimeout(KMOperationState op) { KMKeyParameters.findTag(KMType.UINT_TAG, KMType.AUTH_TIMEOUT, data[HW_PARAMETERS]); if (tmpVariables[0] != KMType.INVALID_VALUE) { // check if hw token is empty - mac should not be empty. - if (data[HW_TOKEN] == KMType.INVALID_VALUE) KMException.throwIt(KMError.INVALID_MAC_LENGTH); + if (data[HW_TOKEN] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.INVALID_MAC_LENGTH); + } authTime = KMIntegerTag.cast(tmpVariables[0]).getValue(); // authenticate user authenticateUser(); @@ -2740,7 +2801,7 @@ private void importKey(APDU apdu, byte[] scratchPad) { } //Check if the tags are supported. - if(KMKeyParameters.hasUnsupportedTags(data[KEY_PARAMETERS])) { + if (KMKeyParameters.hasUnsupportedTags(data[KEY_PARAMETERS])) { KMException.throwIt(KMError.UNSUPPORTED_TAG); } // Check algorithm and dispatch to appropriate handler. @@ -2802,7 +2863,7 @@ private void importECKeys(byte[] scratchPad) { // As per NIST.SP.800-186 page 9, secret for 256 curve should be between // 256-383 if (((256 <= (short) (KMByteBlob.cast(data[SECRET]).length() * 8)) - && (383 >= (short) (KMByteBlob.cast(data[SECRET]).length() * 8))) + && (383 >= (short) (KMByteBlob.cast(data[SECRET]).length() * 8))) ^ tmpVariables[2] == 256) { KMException.throwIt(KMError.IMPORT_PARAMETER_MISMATCH); } @@ -2822,7 +2883,7 @@ private void importECKeys(byte[] scratchPad) { // As per NIST.SP.800-186 page 9, secret length for 256 curve should be between // 256-383 if (((256 <= (short) (KMByteBlob.cast(data[SECRET]).length() * 8)) - && (383 >= (short) (KMByteBlob.cast(data[SECRET]).length() * 8))) + && (383 >= (short) (KMByteBlob.cast(data[SECRET]).length() * 8))) ^ tmpVariables[3] == KMType.P_256) { KMException.throwIt(KMError.IMPORT_PARAMETER_MISMATCH); } @@ -3148,9 +3209,9 @@ private void processSetBootParamsCmd(APDU apdu) { KMInteger.cast(tmpVariables[2]).length()); repository.setBootPatchLevel( - KMInteger.cast(tmpVariables[3]).getBuffer(), - KMInteger.cast(tmpVariables[3]).getStartOff(), - KMInteger.cast(tmpVariables[3]).length()); + KMInteger.cast(tmpVariables[3]).getBuffer(), + KMInteger.cast(tmpVariables[3]).getStartOff(), + KMInteger.cast(tmpVariables[3]).length()); repository.setVerifiedBootKey( KMByteBlob.cast(tmpVariables[4]).getBuffer(), @@ -3233,10 +3294,10 @@ private static void processGenerateKey(APDU apdu) { } } //Check if the tags are supported. - if(KMKeyParameters.hasUnsupportedTags(data[KEY_PARAMETERS])) { + if (KMKeyParameters.hasUnsupportedTags(data[KEY_PARAMETERS])) { KMException.throwIt(KMError.UNSUPPORTED_TAG); } - + // Check algorithm and dispatch to appropriate handler. switch (tmpVariables[3]) { case KMType.RSA: @@ -3738,9 +3799,9 @@ private static short deriveKey(byte[] scratchPad) { if (DERIVE_KEY_INPUT_SIZE > tmpVariables[2]) { // Copy KeyCharacteristics in the remaining space of DERIVE_KEY_INPUT_SIZE Util.arrayCopyNonAtomic(repository.getHeap(), (short) (data[AUTH_DATA]), - repository.getHeap(), - (short) (tmpVariables[1] + tmpVariables[2]), - (short) (DERIVE_KEY_INPUT_SIZE - tmpVariables[2])); + repository.getHeap(), + (short) (tmpVariables[1] + tmpVariables[2]), + (short) (DERIVE_KEY_INPUT_SIZE - tmpVariables[2])); } // KeyDerivation: // 1. Do HMAC Sign, with below input parameters. @@ -3751,12 +3812,12 @@ private static short deriveKey(byte[] scratchPad) { // Consume only first 16 bytes as derived key. // Hmac sign. tmpVariables[3] = seProvider.hmacKDF( - seProvider.getMasterKey(), - repository.getHeap(), - tmpVariables[1], - DERIVE_KEY_INPUT_SIZE, - scratchPad, - (short) 0); + seProvider.getMasterKey(), + repository.getHeap(), + tmpVariables[1], + DERIVE_KEY_INPUT_SIZE, + scratchPad, + (short) 0); if (tmpVariables[3] < 16) { KMException.throwIt(KMError.UNKNOWN_ERROR); } @@ -3801,8 +3862,9 @@ private void add(byte[] buf, short op1, short op2, short result) { while (index >= 0) { tmp = (short) (buf[(short) (op1 + index)] + buf[(short) (op2 + index)] + carry); carry = 0; - if (tmp > 255) + if (tmp > 255) { carry = 1; // max unsigned byte value is 255 + } buf[(short) (result + index)] = (byte) (tmp & (byte) 0xFF); index--; } diff --git a/Applet/src/com/android/javacard/keymaster/KMMasterKey.java b/Applet/src/com/android/javacard/keymaster/KMMasterKey.java index 0ceb6291..7a88778e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMMasterKey.java +++ b/Applet/src/com/android/javacard/keymaster/KMMasterKey.java @@ -16,10 +16,9 @@ package com.android.javacard.keymaster; /** - * KMMasterKey is a marker interface and the SE Provider has to implement - * this interface. Internally Masterkey is stored as a Javacard AES key object, - * which will provide additional security. The master key is maintained by the - * SEProvider. + * KMMasterKey is a marker interface and the SE Provider has to implement this interface. Internally + * Masterkey is stored as a Javacard AES key object, which will provide additional security. The + * master key is maintained by the SEProvider. */ public interface KMMasterKey { diff --git a/Applet/src/com/android/javacard/keymaster/KMOperation.java b/Applet/src/com/android/javacard/keymaster/KMOperation.java index 8db3312b..3132e4b3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperation.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperation.java @@ -21,23 +21,25 @@ * returned back to KMSEProvider for the reuse when the operation is finished. */ public interface KMOperation { + // Used for cipher operations short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] outputDataBuf, short outputDataStart); + byte[] outputDataBuf, short outputDataStart); + // Used for signature operations short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength); // Used for finishing cipher operations. short finish(byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] outputDataBuf, short outputDataStart); + byte[] outputDataBuf, short outputDataStart); // Used for finishing signing operations. short sign(byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] signBuf, short signStart); + byte[] signBuf, short signStart); // Used for finishing verifying operations. boolean verify(byte[] inputDataBuf, short inputDataStart, short inputDataLength, - byte[] signBuf, short signStart, short signLength); + byte[] signBuf, short signStart, short signLength); // Used for aborting the ongoing operations. void abort(); diff --git a/Applet/src/com/android/javacard/keymaster/KMOperationState.java b/Applet/src/com/android/javacard/keymaster/KMOperationState.java index 6ea96941..f1c65ea4 100644 --- a/Applet/src/com/android/javacard/keymaster/KMOperationState.java +++ b/Applet/src/com/android/javacard/keymaster/KMOperationState.java @@ -20,10 +20,10 @@ import javacard.framework.Util; /** - * KMOperationState is the container of an active operation started by beginOperation function. - * This operation state is persisted by the applet in non volatile memory. However, this state is not - * retained if applet is upgraded. There will be four operation state records maintained i.e. only four - * active operations are supported at any given time. + * KMOperationState is the container of an active operation started by beginOperation function. This + * operation state is persisted by the applet in non volatile memory. However, this state is not + * retained if applet is upgraded. There will be four operation state records maintained i.e. only + * four active operations are supported at any given time. */ public class KMOperationState { @@ -64,7 +64,9 @@ private KMOperationState() { } private static KMOperationState proto() { - if (prototype == null) prototype = new KMOperationState(); + if (prototype == null) { + prototype = new KMOperationState(); + } return prototype; } @@ -88,7 +90,9 @@ public static KMOperationState read(byte[] oprHandle, short off, Object[] slot) } public void persist() { - if (!dFlag) return; + if (!dFlag) { + return; + } KMRepository.instance().persistOperation(data, Util.getShort(data, OP_HANDLE), op); dFlag = false; } @@ -108,13 +112,14 @@ public void reset() { Util.arrayFillNonAtomic( data, (short) 0, (short) data.length, (byte) 0); } - private void dataUpdated(){ + + private void dataUpdated() { dFlag = true; } public void release() { Object[] ops = ((Object[]) slot[REFS]); - ((KMOperation)ops[OPERATION]).abort(); + ((KMOperation) ops[OPERATION]).abort(); JCSystem.beginTransaction(); Util.arrayFillNonAtomic( (byte[]) slot[0], (short) 0, (short) ((byte[]) slot[0]).length, (byte) 0); @@ -168,20 +173,29 @@ public void setAuthTime(byte[] timeBuf, short start) { } public void setOneTimeAuthReqd(boolean flag) { - if (flag) data[FLAGS] = (byte) (data[FLAGS] | SECURE_USER_ID_REQD); - else data[FLAGS] = (byte) (data[FLAGS] & (~SECURE_USER_ID_REQD)); + if (flag) { + data[FLAGS] = (byte) (data[FLAGS] | SECURE_USER_ID_REQD); + } else { + data[FLAGS] = (byte) (data[FLAGS] & (~SECURE_USER_ID_REQD)); + } dataUpdated(); } public void setAuthTimeoutValidated(boolean flag) { - if (flag) data[FLAGS] = (byte) (data[FLAGS] | AUTH_TIMEOUT_VALIDATED); - else data[FLAGS] = (byte) (data[FLAGS] & (~AUTH_TIMEOUT_VALIDATED)); + if (flag) { + data[FLAGS] = (byte) (data[FLAGS] | AUTH_TIMEOUT_VALIDATED); + } else { + data[FLAGS] = (byte) (data[FLAGS] & (~AUTH_TIMEOUT_VALIDATED)); + } dataUpdated(); } public void setAuthPerOperationReqd(boolean flag) { - if (flag) data[FLAGS] = (byte) (data[FLAGS] | AUTH_PER_OP_REQD); - else data[FLAGS] = (byte) (data[FLAGS] & (~AUTH_PER_OP_REQD)); + if (flag) { + data[FLAGS] = (byte) (data[FLAGS] | AUTH_PER_OP_REQD); + } else { + data[FLAGS] = (byte) (data[FLAGS] & (~AUTH_PER_OP_REQD)); + } dataUpdated(); } diff --git a/Applet/src/com/android/javacard/keymaster/KMPreSharedKey.java b/Applet/src/com/android/javacard/keymaster/KMPreSharedKey.java index 71dfcae6..273aeb4a 100644 --- a/Applet/src/com/android/javacard/keymaster/KMPreSharedKey.java +++ b/Applet/src/com/android/javacard/keymaster/KMPreSharedKey.java @@ -16,10 +16,9 @@ package com.android.javacard.keymaster; /** - * KMPreSharedKey is a marker interface and the SE Provider has to implement - * this interface. Internally Preshared key is stored as a Javacard HMac key object, - * which will provide additional security. The pre-shared key is maintained by the - * SEProvider. + * KMPreSharedKey is a marker interface and the SE Provider has to implement this interface. + * Internally Preshared key is stored as a Javacard HMac key object, which will provide additional + * security. The pre-shared key is maintained by the SEProvider. */ public interface KMPreSharedKey { diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index 47ad740a..204fe312 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -24,10 +24,11 @@ import javacard.framework.Util; /** - * KMRepository class manages persistent and volatile memory usage by the applet. Note the repository - * is only used by applet and it is not intended to be used by seProvider. + * KMRepository class manages persistent and volatile memory usage by the applet. Note the + * repository is only used by applet and it is not intended to be used by seProvider. */ public class KMRepository implements KMUpgradable { + // Data table configuration public static final short DATA_INDEX_SIZE = 22; public static final short DATA_INDEX_ENTRY_SIZE = 4; @@ -39,7 +40,8 @@ public class KMRepository implements KMUpgradable { private static final short OPERATION_HANDLE_STATUS_OFFSET = 0; private static final short OPERATION_HANDLE_STATUS_SIZE = 1; private static final short OPERATION_HANDLE_OFFSET = 1; - private static final short OPERATION_HANDLE_ENTRY_SIZE = OPERATION_HANDLE_SIZE + OPERATION_HANDLE_STATUS_SIZE; + private static final short OPERATION_HANDLE_ENTRY_SIZE = + OPERATION_HANDLE_SIZE + OPERATION_HANDLE_STATUS_SIZE; // Data table offsets public static final byte COMPUTED_HMAC_KEY = 8; @@ -106,10 +108,10 @@ public KMRepository(boolean isUpgrading) { //First byte in the operation handle buffer denotes whether the operation is //reserved or unreserved. byte index = 0; - while(index < MAX_OPS){ + while (index < MAX_OPS) { operationStateTable[index] = new Object[]{new byte[OPERATION_HANDLE_ENTRY_SIZE], - new Object[] {new byte[KMOperationState.MAX_DATA], - new Object[KMOperationState.MAX_REFS]}}; + new Object[]{new byte[KMOperationState.MAX_DATA], + new Object[KMOperationState.MAX_REFS]}}; index++; } //Initialize the device locked status @@ -134,7 +136,8 @@ public KMOperationState findOperation(byte[] buf, short off, short len) { opId = ((byte[]) ((Object[]) operationStateTable[index])[0]); if (0 == Util.arrayCompare(buf, off, opId, OPERATION_HANDLE_OFFSET, len)) { return KMOperationState - .read(opId, OPERATION_HANDLE_OFFSET, (Object[]) ((Object[]) operationStateTable[index])[1]); + .read(opId, OPERATION_HANDLE_OFFSET, + (Object[]) ((Object[]) operationStateTable[index])[1]); } index++; } @@ -146,25 +149,26 @@ public KMOperationState findOperation(byte[] buf, short off, short len) { public KMOperationState findOperation(short operationHandle) { short buf = KMByteBlob.instance(OPERATION_HANDLE_SIZE); getOperationHandle( - operationHandle, - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + operationHandle, + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); return findOperation( - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); } /* opHandle is a KMInteger */ - public KMOperationState reserveOperation(short opHandle){ + public KMOperationState reserveOperation(short opHandle) { short index = 0; byte[] opId; - while(index < MAX_OPS){ - opId = (byte[])((Object[])operationStateTable[index])[0]; + while (index < MAX_OPS) { + opId = (byte[]) ((Object[]) operationStateTable[index])[0]; /* Check for unreserved operation state */ if (opId[OPERATION_HANDLE_STATUS_OFFSET] == 0) { - return KMOperationState.instance(opHandle, (Object[])((Object[])operationStateTable[index])[1]); + return KMOperationState + .instance(opHandle, (Object[]) ((Object[]) operationStateTable[index])[1]); } index++; } @@ -172,28 +176,28 @@ public KMOperationState reserveOperation(short opHandle){ } public void persistOperation(byte[] data, short opHandle, KMOperation op) { - short index = 0; + short index = 0; byte[] opId; short buf = KMByteBlob.instance(OPERATION_HANDLE_SIZE); getOperationHandle( - opHandle, - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + opHandle, + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); //Update an existing operation state. while (index < MAX_OPS) { opId = (byte[]) ((Object[]) operationStateTable[index])[0]; if ((1 == opId[OPERATION_HANDLE_STATUS_OFFSET]) - && (0 == Util.arrayCompare( - opId, - OPERATION_HANDLE_OFFSET, - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()))) { + && (0 == Util.arrayCompare( + opId, + OPERATION_HANDLE_OFFSET, + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()))) { Object[] slot = (Object[]) ((Object[]) operationStateTable[index])[1]; JCSystem.beginTransaction(); Util.arrayCopy(data, (short) 0, (byte[]) slot[0], (short) 0, - (short) ((byte[]) slot[0]).length); + (short) ((byte[]) slot[0]).length); Object[] ops = ((Object[]) slot[1]); ops[0] = op; JCSystem.commitTransaction(); @@ -204,11 +208,11 @@ public void persistOperation(byte[] data, short opHandle, KMOperation op) { index = 0; //Persist a new operation. - while(index < MAX_OPS){ - opId = (byte[])((Object[])operationStateTable[index])[0]; - if(0 == opId[OPERATION_HANDLE_STATUS_OFFSET]){ - Object[] slot = (Object[])((Object[])operationStateTable[index])[1]; - JCSystem.beginTransaction(); + while (index < MAX_OPS) { + opId = (byte[]) ((Object[]) operationStateTable[index])[0]; + if (0 == opId[OPERATION_HANDLE_STATUS_OFFSET]) { + Object[] slot = (Object[]) ((Object[]) operationStateTable[index])[1]; + JCSystem.beginTransaction(); opId[OPERATION_HANDLE_STATUS_OFFSET] = 1;/*reserved */ Util.arrayCopy( KMByteBlob.cast(buf).getBuffer(), @@ -216,11 +220,12 @@ public void persistOperation(byte[] data, short opHandle, KMOperation op) { opId, OPERATION_HANDLE_OFFSET, OPERATION_HANDLE_SIZE); - Util.arrayCopy(data, (short) 0, (byte[]) slot[0], (short) 0, (short) ((byte[]) slot[0]).length); + Util.arrayCopy(data, (short) 0, (byte[]) slot[0], (short) 0, + (short) ((byte[]) slot[0]).length); Object[] ops = ((Object[]) slot[1]); ops[0] = op; JCSystem.commitTransaction(); - break; + break; } index++; } @@ -231,18 +236,18 @@ public void releaseOperation(KMOperationState op) { byte[] var; short buf = KMByteBlob.instance(OPERATION_HANDLE_SIZE); getOperationHandle( - op.getHandle(), - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()); + op.getHandle(), + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()); while (index < MAX_OPS) { var = ((byte[]) ((Object[]) operationStateTable[index])[0]); if ((var[OPERATION_HANDLE_STATUS_OFFSET] == 1) && - (0 == Util.arrayCompare(var, - OPERATION_HANDLE_OFFSET, - KMByteBlob.cast(buf).getBuffer(), - KMByteBlob.cast(buf).getStartOff(), - KMByteBlob.cast(buf).length()))) { + (0 == Util.arrayCompare(var, + OPERATION_HANDLE_OFFSET, + KMByteBlob.cast(buf).getBuffer(), + KMByteBlob.cast(buf).getStartOff(), + KMByteBlob.cast(buf).length()))) { Util.arrayFillNonAtomic(var, (short) 0, (short) var.length, (byte) 0); op.release(); break; @@ -252,13 +257,17 @@ public void releaseOperation(KMOperationState op) { } public void initComputedHmac(byte[] key, short start, short len) { - if(len != COMPUTED_HMAC_KEY_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(COMPUTED_HMAC_KEY,key,start,len); + if (len != COMPUTED_HMAC_KEY_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(COMPUTED_HMAC_KEY, key, start, len); } public void initHmacNonce(byte[] nonce, short offset, short len) { - if (len != HMAC_SEED_NONCE_SIZE) { KMException.throwIt(KMError.INVALID_INPUT_LENGTH);} - writeDataEntry(HMAC_NONCE,nonce,offset,len); + if (len != HMAC_SEED_NONCE_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(HMAC_NONCE, nonce, offset, len); } public void clearHmacNonce() { @@ -274,7 +283,8 @@ public void onUninstall() { } - public void onProcess() {} + public void onProcess() { + } public void clean() { Util.arrayFillNonAtomic(heap, (short) 0, heapIndex, (byte) 0); @@ -282,7 +292,8 @@ public void clean() { reclaimIndex = HEAP_SIZE; } - public void onDeselect() {} + public void onDeselect() { + } public void onSelect() { // If write through caching is implemented then this method will restore the data into cache @@ -292,7 +303,7 @@ public void onSelect() { // reclaimMemory function immediately after the use. public short allocReclaimableMemory(short length) { if ((((short) (reclaimIndex - length)) <= heapIndex) - || (length >= HEAP_SIZE / 2)) { + || (length >= HEAP_SIZE / 2)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } reclaimIndex -= length; @@ -318,7 +329,7 @@ public short allocAvailableMemory() { public short alloc(short length) { if ((((short) (heapIndex + length)) > heap.length) || - (((short) (heapIndex + length)) > reclaimIndex)) { + (((short) (heapIndex + length)) > reclaimIndex)) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } heapIndex += length; @@ -334,7 +345,7 @@ private short dataAlloc(short length) { } - private void newDataTable(boolean isUpgrading){ + private void newDataTable(boolean isUpgrading) { if (!isUpgrading) { if (dataTable == null) { dataTable = new byte[DATA_MEM_SIZE]; @@ -343,26 +354,27 @@ private void newDataTable(boolean isUpgrading){ } } - public void restoreData(short blob){ + public void restoreData(short blob) { JCSystem.beginTransaction(); Util.arrayCopy( - KMByteBlob.cast(blob).getBuffer(),KMByteBlob.cast(blob).getStartOff(),dataTable,(short)0, - KMByteBlob.cast(blob).length() + KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff(), dataTable, + (short) 0, + KMByteBlob.cast(blob).length() ); JCSystem.commitTransaction(); } - public byte[] getDataTable(){ + public byte[] getDataTable() { return dataTable; } - private void clearDataEntry(short id){ + private void clearDataEntry(short id) { JCSystem.beginTransaction(); - id = (short)(id * DATA_INDEX_ENTRY_SIZE); - short dataLen = Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_LENGTH)); + id = (short) (id * DATA_INDEX_ENTRY_SIZE); + short dataLen = Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_LENGTH)); if (dataLen != 0) { - short dataPtr = Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_OFFSET)); - Util.arrayFillNonAtomic(dataTable, dataPtr,dataLen,(byte)0); + short dataPtr = Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_OFFSET)); + Util.arrayFillNonAtomic(dataTable, dataPtr, dataLen, (byte) 0); } JCSystem.commitTransaction(); } @@ -370,24 +382,26 @@ private void clearDataEntry(short id){ private void writeDataEntry(short id, byte[] buf, short offset, short len) { JCSystem.beginTransaction(); short dataPtr; - id = (short)(id * DATA_INDEX_ENTRY_SIZE); - short dataLen = Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_LENGTH)); + id = (short) (id * DATA_INDEX_ENTRY_SIZE); + short dataLen = Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_LENGTH)); if (dataLen == 0) { dataPtr = dataAlloc(len); - Util.setShort(dataTable,(short)(id+DATA_INDEX_ENTRY_OFFSET),dataPtr); - Util.setShort(dataTable,(short)(id+DATA_INDEX_ENTRY_LENGTH),len); - Util.arrayCopyNonAtomic(buf, offset,dataTable,dataPtr, len); + Util.setShort(dataTable, (short) (id + DATA_INDEX_ENTRY_OFFSET), dataPtr); + Util.setShort(dataTable, (short) (id + DATA_INDEX_ENTRY_LENGTH), len); + Util.arrayCopyNonAtomic(buf, offset, dataTable, dataPtr, len); } else { - if(len != dataLen) KMException.throwIt(KMError.UNKNOWN_ERROR); - dataPtr = Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_OFFSET)); - Util.arrayCopyNonAtomic(buf, offset,dataTable,dataPtr, len); + if (len != dataLen) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } + dataPtr = Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_OFFSET)); + Util.arrayCopyNonAtomic(buf, offset, dataTable, dataPtr, len); } JCSystem.commitTransaction(); } - private short readDataEntry(short id, byte[] buf, short offset){ - id = (short)(id * DATA_INDEX_ENTRY_SIZE); - short len = Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_LENGTH)); + private short readDataEntry(short id, byte[] buf, short offset) { + id = (short) (id * DATA_INDEX_ENTRY_SIZE); + short len = Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_LENGTH)); if (len != 0) { Util.arrayCopyNonAtomic( dataTable, @@ -399,9 +413,9 @@ private short readDataEntry(short id, byte[] buf, short offset){ return len; } - private short dataLength(short id){ - id = (short)(id * DATA_INDEX_ENTRY_SIZE); - return Util.getShort(dataTable,(short)(id+DATA_INDEX_ENTRY_LENGTH)); + private short dataLength(short id) { + id = (short) (id * DATA_INDEX_ENTRY_SIZE); + return Util.getShort(dataTable, (short) (id + DATA_INDEX_ENTRY_LENGTH)); } public byte[] getHeap() { @@ -416,15 +430,15 @@ public short getComputedHmacKey() { return readData(COMPUTED_HMAC_KEY); } - public void persistAttId(byte id, byte[] buf, short start, short len){ - writeDataEntry(id, buf,start,len); + public void persistAttId(byte id, byte[] buf, short start, short len) { + writeDataEntry(id, buf, start, len); } - public short getAttId(byte id){ + public short getAttId(byte id) { return readData(id); } - public void deleteAttIds(){ + public void deleteAttIds() { clearDataEntry(ATT_ID_BRAND); clearDataEntry(ATT_ID_MEID); clearDataEntry(ATT_ID_DEVICE); @@ -439,15 +453,17 @@ public short getIssuer() { return readData(CERT_ISSUER); } - public short readData(short id){ + public short readData(short id) { short blob = KMByteBlob.instance(dataLength(id)); - if(readDataEntry(id,KMByteBlob.cast(blob).getBuffer(),KMByteBlob.cast(blob).getStartOff())== 0){ + if (readDataEntry(id, KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()) + == 0) { return 0; } return blob; } + public void setIssuer(byte[] buf, short start, short len) { - writeDataEntry(CERT_ISSUER,buf,start,len); + writeDataEntry(CERT_ISSUER, buf, start, len); } @@ -456,48 +472,48 @@ public short getCertExpiryTime() { } public void setCertExpiryTime(byte[] buf, short start, short len) { - writeDataEntry(CERT_EXPIRY_TIME, buf,start,len); + writeDataEntry(CERT_EXPIRY_TIME, buf, start, len); } - private static final byte[] zero = {0,0,0,0,0,0,0,0}; + private static final byte[] zero = {0, 0, 0, 0, 0, 0, 0, 0}; - public short getOsVersion(){ + public short getOsVersion() { short blob = readData(BOOT_OS_VERSION); if (blob != 0) { return KMInteger.uint_32( KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()); - }else{ - return KMInteger.uint_32(zero,(short)0); + } else { + return KMInteger.uint_32(zero, (short) 0); } } - public short getVendorPatchLevel(){ + public short getVendorPatchLevel() { short blob = readData(VENDOR_PATCH_LEVEL); if (blob != 0) { return KMInteger.uint_32( KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()); - }else{ - return KMInteger.uint_32(zero,(short)0); + } else { + return KMInteger.uint_32(zero, (short) 0); } } - public short getBootPatchLevel(){ + public short getBootPatchLevel() { short blob = readData(BOOT_PATCH_LEVEL); if (blob != 0) { return KMInteger.uint_32( KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()); - }else{ - return KMInteger.uint_32(zero,(short)0); + } else { + return KMInteger.uint_32(zero, (short) 0); } } - public short getOsPatch(){ + public short getOsPatch() { short blob = readData(BOOT_OS_PATCH); if (blob != 0) { return KMInteger.uint_32( KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()); - }else{ - return KMInteger.uint_32(zero,(short)0); + } else { + return KMInteger.uint_32(zero, (short) 0); } } @@ -523,127 +539,148 @@ public short readROT() { short blob = KMByteBlob.instance(totalLength); length = readDataEntry(BOOT_VERIFIED_BOOT_KEY, KMByteBlob.cast(blob) - .getBuffer(), KMByteBlob.cast(blob).getStartOff()); + .getBuffer(), KMByteBlob.cast(blob).getStartOff()); length += readDataEntry(BOOT_VERIFIED_BOOT_HASH, KMByteBlob.cast(blob) .getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length)); + (short) (KMByteBlob.cast(blob).getStartOff() + length)); length += readDataEntry(BOOT_VERIFIED_BOOT_STATE, KMByteBlob.cast(blob) .getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length)); + (short) (KMByteBlob.cast(blob).getStartOff() + length)); readDataEntry(BOOT_DEVICE_LOCKED_STATUS, KMByteBlob.cast(blob) .getBuffer(), - (short) (KMByteBlob.cast(blob).getStartOff() + length)); + (short) (KMByteBlob.cast(blob).getStartOff() + length)); return blob; } - public short getVerifiedBootKey(){ + public short getVerifiedBootKey() { return readData(BOOT_VERIFIED_BOOT_KEY); } - public short getVerifiedBootHash(){ + public short getVerifiedBootHash() { return readData(BOOT_VERIFIED_BOOT_HASH); } public boolean getBootLoaderLock() { short blob = readData(BOOT_DEVICE_LOCKED_STATUS); - return (byte)((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFE) != 0; + return (byte) ((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFE) != 0; } - public byte getBootState(){ + public byte getBootState() { short blob = readData(BOOT_VERIFIED_BOOT_STATE); return (getHeap())[KMByteBlob.cast(blob).getStartOff()]; } - public boolean getDeviceLock(){ + public boolean getDeviceLock() { short blob = readData(DEVICE_LOCKED); - return (byte)((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFE) != 0; + return (byte) ((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFE) != 0; } - public boolean getDeviceLockPasswordOnly(){ + public boolean getDeviceLockPasswordOnly() { short blob = readData(DEVICE_LOCKED); - return (byte)((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFD) != 0; + return (byte) ((getHeap())[KMByteBlob.cast(blob).getStartOff()] & 0xFD) != 0; } - public short getDeviceTimeStamp(){ + public short getDeviceTimeStamp() { short blob = readData(DEVICE_LOCKED_TIME); - if(blob != 0){ - return KMInteger.uint_64(KMByteBlob.cast(blob).getBuffer(), - KMByteBlob.cast(blob).getStartOff()); - }else{ - return KMInteger.uint_64(zero,(short)0); + if (blob != 0) { + return KMInteger.uint_64(KMByteBlob.cast(blob).getBuffer(), + KMByteBlob.cast(blob).getStartOff()); + } else { + return KMInteger.uint_64(zero, (short) 0); } } - public void setOsVersion(byte[] buf, short start, short len){ - if(len != OS_VERSION_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(BOOT_OS_VERSION,buf,start,len); + public void setOsVersion(byte[] buf, short start, short len) { + if (len != OS_VERSION_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(BOOT_OS_VERSION, buf, start, len); } public void setVendorPatchLevel(byte[] buf, short start, short len) { - if (len != VENDOR_PATCH_SIZE) + if (len != VENDOR_PATCH_SIZE) { KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } writeDataEntry(VENDOR_PATCH_LEVEL, buf, start, len); } public void setBootPatchLevel(byte[] buf, short start, short len) { - if (len != BOOT_PATCH_SIZE) + if (len != BOOT_PATCH_SIZE) { KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } writeDataEntry(BOOT_PATCH_LEVEL, buf, start, len); } public void setBootloaderLocked(boolean flag) { short start = alloc(DEVICE_LOCK_FLAG_SIZE); - if(flag) (getHeap())[start] = (byte)((getHeap())[start] | 0x01); - else (getHeap())[start] = (byte)((getHeap())[start] & 0xFE); - writeDataEntry(BOOT_DEVICE_LOCKED_STATUS,getHeap(),start,DEVICE_LOCK_FLAG_SIZE); + if (flag) { + (getHeap())[start] = (byte) ((getHeap())[start] | 0x01); + } else { + (getHeap())[start] = (byte) ((getHeap())[start] & 0xFE); + } + writeDataEntry(BOOT_DEVICE_LOCKED_STATUS, getHeap(), start, DEVICE_LOCK_FLAG_SIZE); } - public void setDeviceLock(boolean flag){ + public void setDeviceLock(boolean flag) { short start = alloc(DEVICE_LOCK_FLAG_SIZE); - if(flag) (getHeap())[start] = (byte)((getHeap())[start] | 0x01); - else (getHeap())[start] = (byte)((getHeap())[start] & 0xFE); - writeDataEntry(DEVICE_LOCKED,getHeap(),start,DEVICE_LOCK_FLAG_SIZE); + if (flag) { + (getHeap())[start] = (byte) ((getHeap())[start] | 0x01); + } else { + (getHeap())[start] = (byte) ((getHeap())[start] & 0xFE); + } + writeDataEntry(DEVICE_LOCKED, getHeap(), start, DEVICE_LOCK_FLAG_SIZE); } - public void setDeviceLockPasswordOnly(boolean flag){ + public void setDeviceLockPasswordOnly(boolean flag) { short start = alloc(DEVICE_LOCK_FLAG_SIZE); - if(flag) (getHeap())[start] = (byte)((getHeap())[start] | 0x02); - else (getHeap())[start] = (byte)((getHeap())[start] & 0xFD); - writeDataEntry(DEVICE_LOCKED,getHeap(),start,DEVICE_LOCK_FLAG_SIZE); + if (flag) { + (getHeap())[start] = (byte) ((getHeap())[start] | 0x02); + } else { + (getHeap())[start] = (byte) ((getHeap())[start] & 0xFD); + } + writeDataEntry(DEVICE_LOCKED, getHeap(), start, DEVICE_LOCK_FLAG_SIZE); } - public void setDeviceLockTimestamp(byte[] buf, short start, short len){ - if(len != DEVICE_LOCK_TS_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(DEVICE_LOCKED_TIME, buf, start,len); + public void setDeviceLockTimestamp(byte[] buf, short start, short len) { + if (len != DEVICE_LOCK_TS_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(DEVICE_LOCKED_TIME, buf, start, len); } - public void clearDeviceLockTimeStamp(){ + public void clearDeviceLockTimeStamp() { clearDataEntry(DEVICE_LOCKED_TIME); } - public void setOsPatch(byte[] buf, short start, short len){ - if(len != OS_PATCH_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(BOOT_OS_PATCH,buf,start,len); + public void setOsPatch(byte[] buf, short start, short len) { + if (len != OS_PATCH_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(BOOT_OS_PATCH, buf, start, len); } - public void setVerifiedBootKey(byte[] buf, short start, short len){ - if(len > BOOT_KEY_MAX_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(BOOT_VERIFIED_BOOT_KEY,buf,start,len); + public void setVerifiedBootKey(byte[] buf, short start, short len) { + if (len > BOOT_KEY_MAX_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(BOOT_VERIFIED_BOOT_KEY, buf, start, len); } - public void setVerifiedBootHash(byte[] buf, short start, short len){ - if(len > BOOT_HASH_MAX_SIZE) KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - writeDataEntry(BOOT_VERIFIED_BOOT_HASH,buf,start,len); + public void setVerifiedBootHash(byte[] buf, short start, short len) { + if (len > BOOT_HASH_MAX_SIZE) { + KMException.throwIt(KMError.INVALID_INPUT_LENGTH); + } + writeDataEntry(BOOT_VERIFIED_BOOT_HASH, buf, start, len); } - public void setBootState(byte state){ + public void setBootState(byte state) { short start = alloc(BOOT_STATE_SIZE); (getHeap())[start] = state; - writeDataEntry(BOOT_VERIFIED_BOOT_STATE,getHeap(),start,BOOT_STATE_SIZE); + writeDataEntry(BOOT_VERIFIED_BOOT_STATE, getHeap(), start, BOOT_STATE_SIZE); } @Override diff --git a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java index a057eb9e..65ae8fb3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMSEProvider.java +++ b/Applet/src/com/android/javacard/keymaster/KMSEProvider.java @@ -24,12 +24,14 @@ * can be only one provider in the applet package. */ public interface KMSEProvider extends KMUpgradable { + /** * Create a symmetric key instance. If the algorithm and/or keysize are not supported then it * should throw a CryptoException. * * @param alg will be KMType.AES, KMType.DES or KMType.HMAC. - * @param keysize will be 128 or 256 for AES or DES. It can be 64 to 512 (multiple of 8) for HMAC. + * @param keysize will be 128 or 256 for AES or DES. It can be 64 to 512 (multiple of 8) for + * HMAC. * @param buf is the buffer in which key has to be returned * @param startOff is the start offset. * @return length of the data in the buf. This should match the keysize (in bytes). @@ -43,15 +45,15 @@ public interface KMSEProvider extends KMUpgradable { * * @param alg will be KMType.RSA or KMType.EC. * @param privKeyBuf is the buffer to return the private key exponent in case of RSA or private - * key in case of EC. + * key in case of EC. * @param privKeyStart is the start offset. * @param privKeyMaxLength is the maximum length of this private key buffer. * @param pubModBuf is the buffer to return the modulus in case of RSA or public key in case of - * EC. + * EC. * @param pubModStart is the start of offset. * @param pubModMaxLength is the maximum length of this public key buffer. * @param lengths is the actual length of the key pair - lengths[0] should be private key and - * lengths[1] should be public key. + * lengths[1] should be public key. */ void createAsymmetricKey( byte alg, @@ -64,11 +66,12 @@ void createAsymmetricKey( short[] lengths); /** - * Verify that the imported key is valid. If the algorithm and/or keysize are not supported then it - * should throw a CryptoException. + * Verify that the imported key is valid. If the algorithm and/or keysize are not supported then + * it should throw a CryptoException. * * @param alg will be KMType.AES, KMType.DES or KMType.HMAC. - * @param keysize will be 128 or 256 for AES or DES. It can be 64 to 512 (multiple of 8) for HMAC. + * @param keysize will be 128 or 256 for AES or DES. It can be 64 to 512 (multiple of 8) for + * HMAC. * @param buf is the buffer that contains the symmetric key. * @param startOff is the start offset. * @param length of the data in the buf. This should match the keysize (in bytes). @@ -83,12 +86,12 @@ void createAsymmetricKey( * CryptoException. * * @param alg will be KMType.RSA or KMType.EC. - * @param privKeyBuf is the buffer that contains the private key exponent in case of RSA or private - * key in case of EC. + * @param privKeyBuf is the buffer that contains the private key exponent in case of RSA or + * private key in case of EC. * @param privKeyStart is the start offset. * @param privKeyLength is the length of this private key buffer. - * @param pubModBuf is the buffer that contains the modulus in case of RSA or public key in case of - * EC. + * @param pubModBuf is the buffer that contains the modulus in case of RSA or public key in case + * of EC. * @param pubModStart is the start of offset. * @param pubModLength is the length of this public key buffer. * @return true if the key pair is supported and valid. @@ -132,8 +135,8 @@ boolean importAsymmetricKey( void getTrueRandomNumber(byte[] num, short offset, short length); /** - * This is a oneshot operation that performs encryption operation using AES GCM algorithm. It throws - * CryptoException if algorithm is not supported or if tag length is not equal to 16 or + * This is a oneshot operation that performs encryption operation using AES GCM algorithm. It + * throws CryptoException if algorithm is not supported or if tag length is not equal to 16 or * nonce length is not equal to 12. * * @param aesKey is the buffer that contains 128 bit or 256 bit aes key used to encrypt. @@ -175,8 +178,8 @@ short aesGCMEncrypt( short authTagLen); /** - * This is a oneshot operation that performs decryption operation using AES GCM algorithm. It throws - * CryptoException if algorithm is not supported. + * This is a oneshot operation that performs decryption operation using AES GCM algorithm. It + * throws CryptoException if algorithm is not supported. * * @param aesKey is the buffer that contains 128 bit or 256 bit aes key used to encrypt. * @param aesKeyStart is the start in aes key buffer. @@ -216,7 +219,7 @@ boolean aesGCMDecrypt( short authTagStart, short authTagLen); - /** + /** * This is a oneshot operation that performs key derivation function using cmac kdf (CKDF) as * defined in android keymaster hal definition. * @@ -266,8 +269,8 @@ short hmacSign( short signatureStart); /** - * This is a oneshot operation that signs the data using hmac algorithm. - * This is used to derive the key, which is used to encrypt the keyblob. + * This is a oneshot operation that signs the data using hmac algorithm. This is used to derive + * the key, which is used to encrypt the keyblob. * * @param instance of masterkey. * @param data is the buffer containing data to be signed. @@ -278,12 +281,12 @@ short hmacSign( * @return length of the signature buffer in bytes. */ short hmacKDF( - KMMasterKey masterkey, - byte[] data, - short dataStart, - short dataLength, - byte[] signature, - short signatureStart); + KMMasterKey masterkey, + byte[] data, + short dataStart, + short dataLength, + byte[] signature, + short signatureStart); /** * This is a oneshot operation that verifies the signature using hmac algorithm. @@ -353,12 +356,12 @@ short rsaDecipherOAEP256( * @return length of the decrypted data. */ short ecSign256( - KMAttestationKey ecPrivKey, - byte[] inputDataBuf, - short inputDataStart, - short inputDataLength, - byte[] outputDataBuf, - short outputDataStart); + KMAttestationKey ecPrivKey, + byte[] inputDataBuf, + short inputDataStart, + short inputDataLength, + byte[] outputDataBuf, + short outputDataStart); /** * This creates a persistent operation for signing, verify, encryption and decryption using HMAC, @@ -367,19 +370,19 @@ short ecSign256( * aborted. It throws CryptoException if algorithm is not supported. * * @param purpose is KMType.ENCRYPT or KMType.DECRYPT for AES and DES algorithm. It will be - * KMType.SIGN and KMType.VERIFY for HMAC algorithm + * KMType.SIGN and KMType.VERIFY for HMAC algorithm * @param alg is KMType.HMAC, KMType.AES or KMType.DES. * @param digest is KMType.SHA2_256 in case of HMAC else it will be KMType.DIGEST_NONE. * @param padding is KMType.PADDING_NONE or KMType.PKCS7 (in case of AES and DES). * @param blockMode is KMType.CTR, KMType.GCM. KMType.CBC or KMType.ECB for AES or DES else it is - * 0. + * 0. * @param keyBuf is aes, des or hmac key buffer. * @param keyStart is the start of the key buffer. * @param keyLength is the length of the key buffer. * @param ivBuf is the iv buffer (in case on AES and DES algorithm without ECB mode) * @param ivStart is the start of the iv buffer. * @param ivLength is the length of the iv buffer. It will be zero in case of HMAC and AES/DES - * with ECB mode. + * with ECB mode. * @param macLength is the mac length in case of signing operation for hmac algorithm. * @return KMOperation instance. */ @@ -401,14 +404,14 @@ KMOperation initSymmetricOperation( * This creates a persistent operation for signing, verify, encryption and decryption using RSA * and EC algorithms when keymaster hal's beginOperation function is executed. For RSA the public * exponent is always 0x0100101. For EC the curve is always p256. The KMOperation instance can be - * reclaimed by the seProvider when KMOperation is finished or aborted. It throws CryptoException + * reclaimed by the seProvider when KMOperation is finished or aborted. It throws CryptoException * if algorithm is not supported. * * @param purpose is KMType.ENCRYPT or KMType.DECRYPT for RSA. It will be * KMType.SIGN and - * KMType.VERIFY for RSA and EC algorithms. + * KMType.VERIFY for RSA and EC algorithms. * @param alg is KMType.RSA or KMType.EC algorithms. * @param padding is KMType.PADDING_NONE or KMType.RSA_OAEP, KMType.RSA_PKCS1_1_5_ENCRYPT, - * KMType.RSA_PKCS1_1_5_SIGN or KMType.RSA_PSS. + * KMType.RSA_PKCS1_1_5_SIGN or KMType.RSA_PSS. * @param digest is KMType.DIGEST_NONE or KMType.SHA2_256. * @param privKeyBuf is the private key in case of EC or private key exponent is case of RSA. * @param privKeyStart is the start of the private key. @@ -436,14 +439,13 @@ KMOperation initAsymmetricOperation( * The attestation certificate implementation will comply keymaster hal specifications. * * @param rsaCert if true indicates that certificate will attest a rsa public key else if false it - * is for ec public key. + * is for ec public key. * @return An empty instance of KMAttestationCert implementation. */ KMAttestationCert getAttestationCert(boolean rsaCert); /** - * This operation persists the certificate chain in the persistent memory - * in multiple requests. + * This operation persists the certificate chain in the persistent memory in multiple requests. * * @param buf buffer containing certificate chain. * @param offset is the start of the buffer. @@ -488,7 +490,9 @@ KMOperation initAsymmetricOperation( boolean isDeviceRebooted(); /** - * This function is supposed to be used to reset the device booted stated after set boot param is handled + * This function is supposed to be used to reset the device booted stated after set boot param is + * handled + * * @param resetBootFlag is false if event has been handled */ void clearDeviceBooted(boolean resetBootFlag); @@ -501,9 +505,9 @@ KMOperation initAsymmetricOperation( boolean isUpgrading(); /** - * This function generates an AES Key of keySizeBits, which is used as - * an master key. This generated key is maintained by the SEProvider. - * This function should be called only once at the time of installation. + * This function generates an AES Key of keySizeBits, which is used as an master key. This + * generated key is maintained by the SEProvider. This function should be called only once at the + * time of installation. * * @param keySizeBits key size in bits. * @return An instance of KMMasterKey. @@ -511,10 +515,9 @@ KMOperation initAsymmetricOperation( KMMasterKey createMasterKey(short keySizeBits); /** - * This function creates an ECKey and initializes the ECPrivateKey with - * the provided input key data. The initialized Key is maintained by the - * SEProvider. This function should be called only while provisioning the - * attestation key. + * This function creates an ECKey and initializes the ECPrivateKey with the provided input key + * data. The initialized Key is maintained by the SEProvider. This function should be called only + * while provisioning the attestation key. * * @param keyData buffer containing the ec private key. * @param offset start of the buffer. @@ -524,10 +527,9 @@ KMOperation initAsymmetricOperation( KMAttestationKey createAttestationKey(byte[] keyData, short offset, short length); /** - * This function creates an HMACKey and initializes the key with the - * provided input key data. This created key is maintained by the - * SEProvider. This function should be called only while provisioing the - * pre-shared secret. + * This function creates an HMACKey and initializes the key with the provided input key data. This + * created key is maintained by the SEProvider. This function should be called only while + * provisioing the pre-shared secret. * * @param keyData buffer containing the key data. * @param offset start of the buffer. diff --git a/Applet/src/com/android/javacard/keymaster/KMTag.java b/Applet/src/com/android/javacard/keymaster/KMTag.java index 6cc251a6..fa9bb38e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMTag.java @@ -19,14 +19,21 @@ import javacard.framework.Util; /** - * This class represents a tag as defined by keymaster hal specifications. It is composed of key value pair. - * The key consists of short tag type e.g. KMType.ENUM and short tag key e.g. KMType.ALGORITHM. The key is encoded as - * uint CBOR type with 4 bytes. This is followed by value which can be any CBOR type based on key. - * struct{byte tag=KMType.TAG_TYPE, short length, value) where value is subtype of KMTag i.e. - * struct{short tagType=one of tag types declared in KMType , short tagKey=one of the tag keys declared in KMType, - * value} where value is one of the sub-types of KMType. + * This class represents a tag as defined by keymaster hal specifications. It is composed of key + * value pair. The key consists of short tag type e.g. KMType.ENUM and short tag key e.g. + * KMType.ALGORITHM. The key is encoded as uint CBOR type with 4 bytes. This is followed by value + * which can be any CBOR type based on key. struct{byte tag=KMType.TAG_TYPE, short length, value) + * where value is subtype of KMTag i.e. struct{short tagType=one of tag types declared in KMType , + * short tagKey=one of the tag keys declared in KMType, value} where value is one of the sub-types + * of KMType. */ public class KMTag extends KMType { - public static short getTagType(short ptr){return Util.getShort(heap, (short)(ptr+TLV_HEADER_SIZE));} - public static short getKey(short ptr){return Util.getShort(heap, (short)(ptr+TLV_HEADER_SIZE+2));} + + public static short getTagType(short ptr) { + return Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); + } + + public static short getKey(short ptr) { + return Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE + 2)); + } } diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 4d81de45..59a4b172 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -27,7 +27,8 @@ * prototype objects which just cast the structure over contiguous memory buffer. */ public abstract class KMType { - public static final short INVALID_VALUE = (short)0x8000; + + public static final short INVALID_VALUE = (short) 0x8000; protected static final byte TLV_HEADER_SIZE = 3; // Types @@ -283,12 +284,22 @@ public static void initialize() { KMType.heap = repository.getHeap(); } - public static byte getType(short ptr){return heap[ptr];} - public static short length(short ptr){return Util.getShort(heap, (short)(ptr+1));} - public static short getValue(short ptr){return Util.getShort(heap, (short)(ptr+TLV_HEADER_SIZE));} + public static byte getType(short ptr) { + return heap[ptr]; + } + + public static short length(short ptr) { + return Util.getShort(heap, (short) (ptr + 1)); + } + + public static short getValue(short ptr) { + return Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); + } - protected static short instance(byte type, short length){ - if (length < 0) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + protected static short instance(byte type, short length) { + if (length < 0) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } short ptr = repository.alloc((short) (length + TLV_HEADER_SIZE)); heap[ptr] = type; Util.setShort(heap, (short) (ptr + 1), length); diff --git a/Applet/src/com/android/javacard/keymaster/KMUpgradable.java b/Applet/src/com/android/javacard/keymaster/KMUpgradable.java index 6815374e..0a241652 100644 --- a/Applet/src/com/android/javacard/keymaster/KMUpgradable.java +++ b/Applet/src/com/android/javacard/keymaster/KMUpgradable.java @@ -18,12 +18,13 @@ import org.globalplatform.upgrade.Element; public interface KMUpgradable { + void onSave(Element ele); - + void onRestore(Element ele); - + short getBackupPrimitiveByteCount(); - + short getBackupObjectCount(); } diff --git a/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java b/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java index c9c2f412..1a03b33c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java +++ b/Applet/src/com/android/javacard/keymaster/KMVerificationToken.java @@ -19,15 +19,16 @@ import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacard.framework.Util; + /** - * KMVerificationToken represents VerificationToken structure from android keymaster hal specifications. - * It corresponds to CBOR array type. - * struct{byte type=VERIFICATION_TOKEN_TYPE; short length=2; short arrayPtr} where arrayPtr is a pointer to - * ordered array with following elements: - * {KMInteger Challenge; KMInteger Timestamp; KMByteBlob PARAMETERS_VERIFIED; SecurityLevel level; - * KMByteBlob Mac}. + * KMVerificationToken represents VerificationToken structure from android keymaster hal + * specifications. It corresponds to CBOR array type. struct{byte type=VERIFICATION_TOKEN_TYPE; + * short length=2; short arrayPtr} where arrayPtr is a pointer to ordered array with following + * elements: {KMInteger Challenge; KMInteger Timestamp; KMByteBlob PARAMETERS_VERIFIED; + * SecurityLevel level; KMByteBlob Mac}. */ public class KMVerificationToken extends KMType { + public static final byte CHALLENGE = 0x00; public static final byte TIMESTAMP = 0x01; public static final byte PARAMETERS_VERIFIED = 0x02; @@ -37,10 +38,11 @@ public class KMVerificationToken extends KMType { private static KMVerificationToken prototype; private static short instPtr; - private KMVerificationToken() {} + private KMVerificationToken() { + } public static short exp() { - short arrPtr = KMArray.instance((short)5); + short arrPtr = KMArray.instance((short) 5); KMArray arr = KMArray.cast(arrPtr); arr.add(CHALLENGE, KMInteger.exp()); arr.add(TIMESTAMP, KMInteger.exp()); @@ -52,34 +54,42 @@ public static short exp() { } private static KMVerificationToken proto(short ptr) { - if (prototype == null) prototype = new KMVerificationToken(); + if (prototype == null) { + prototype = new KMVerificationToken(); + } instPtr = ptr; return prototype; } public static short instance() { - short arrPtr = KMArray.instance((short)5); + short arrPtr = KMArray.instance((short) 5); KMArray arr = KMArray.cast(arrPtr); - arr.add(CHALLENGE, KMInteger.uint_16((short)0)); - arr.add(TIMESTAMP, KMInteger.uint_16((short)0)); - arr.add(PARAMETERS_VERIFIED, KMByteBlob.instance((short)0)); + arr.add(CHALLENGE, KMInteger.uint_16((short) 0)); + arr.add(TIMESTAMP, KMInteger.uint_16((short) 0)); + arr.add(PARAMETERS_VERIFIED, KMByteBlob.instance((short) 0)); arr.add(SECURITY_LEVEL, KMEnum.instance(KMType.HARDWARE_TYPE, KMType.STRONGBOX)); - arr.add(MAC, KMByteBlob.instance((short)0)); + arr.add(MAC, KMByteBlob.instance((short) 0)); return instance(arrPtr); } public static short instance(short vals) { KMArray arr = KMArray.cast(vals); - if(arr.length() != 5)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); - short ptr = KMType.instance(VERIFICATION_TOKEN_TYPE, (short)2); - Util.setShort(heap, (short)(ptr + TLV_HEADER_SIZE), vals); + if (arr.length() != 5) { + ISOException.throwIt(ISO7816.SW_WRONG_LENGTH); + } + short ptr = KMType.instance(VERIFICATION_TOKEN_TYPE, (short) 2); + Util.setShort(heap, (short) (ptr + TLV_HEADER_SIZE), vals); return ptr; } public static KMVerificationToken cast(short ptr) { - if (heap[ptr] != VERIFICATION_TOKEN_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[ptr] != VERIFICATION_TOKEN_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } short arrPtr = Util.getShort(heap, (short) (ptr + TLV_HEADER_SIZE)); - if(heap[arrPtr] != ARRAY_TYPE) ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + if (heap[arrPtr] != ARRAY_TYPE) { + ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); + } return proto(ptr); } @@ -131,7 +141,7 @@ public short getParametersVerified() { } public void setParametersVerified(short vals) { - // KMKeyParameters.cast(vals); + // KMKeyParameters.cast(vals); KMByteBlob.cast(vals); short arrPtr = getVals(); KMArray.cast(arrPtr).add(PARAMETERS_VERIFIED, vals); diff --git a/HAL/keymaster/4.1/android.hardware.keymaster@4.1-javacard.service.xml b/HAL/keymaster/4.1/android.hardware.keymaster@4.1-javacard.service.xml index 5e365def..83fccabe 100644 --- a/HAL/keymaster/4.1/android.hardware.keymaster@4.1-javacard.service.xml +++ b/HAL/keymaster/4.1/android.hardware.keymaster@4.1-javacard.service.xml @@ -1,7 +1,7 @@ - - android.hardware.keymaster - hwbinder - @4.1::IKeymasterDevice/javacard - + + android.hardware.keymaster + hwbinder + @4.1::IKeymasterDevice/javacard + From 708f99d669ed4a24ae591e1ec4b3b5297724735f Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Thu, 11 Feb 2021 12:44:09 +0530 Subject: [PATCH 13/15] Added test unsupported block mode --- .../javacard/test/KMFunctionalTest.java | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 3e0653eb..787b9f97 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -2294,6 +2294,25 @@ public short generateRandom(short upperBound) { return int_random; } + @Test + public void testUnsupportedBlockMode() { + init(); + short desKey = generateAesDesKey(KMType.DES, (short) 168, null, null, false); + short desKeyPtr = KMArray.cast(desKey).get((short) 1); + byte[] keyBlob = new byte[KMByteBlob.cast(desKeyPtr).length()]; + Util.arrayCopyNonAtomic(KMByteBlob.cast(desKeyPtr).getBuffer(), KMByteBlob + .cast(desKeyPtr).getStartOff(), keyBlob, (short) 0, + (short) keyBlob.length); + short desPkcs7Params = getAesDesParams(KMType.DES, (byte) KMType.CTR, + KMType.PKCS7, new byte[12]); + short ret = begin(KMType.ENCRYPT, + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + KMKeyParameters.instance(desPkcs7Params), (short) 0, + KMError.UNSUPPORTED_BLOCK_MODE); + + cleanUp(); + } + @Test public void testDesEcbPkcs7PaddingCorrupted() { init(); @@ -2951,36 +2970,46 @@ public short processMessage( return ret; } - public short begin(byte keyPurpose, short keyBlob, short keyParmas, short hwToken) { - short arrPtr = KMArray.instance((short)4); - KMArray.cast(arrPtr).add((short)0, KMEnum.instance(KMType.PURPOSE, keyPurpose)); - KMArray.cast(arrPtr).add((short)1, keyBlob); - KMArray.cast(arrPtr).add((short)2, keyParmas); - if(hwToken == 0) { + public short begin(byte keyPurpose, short keyBlob, short keyParmas, + short hwToken, short expectedErr) { + short arrPtr = KMArray.instance((short) 4); + KMArray.cast(arrPtr).add((short) 0, + KMEnum.instance(KMType.PURPOSE, keyPurpose)); + KMArray.cast(arrPtr).add((short) 1, keyBlob); + KMArray.cast(arrPtr).add((short) 2, keyParmas); + if (hwToken == 0) { hwToken = KMHardwareAuthToken.instance(); } - KMArray.cast(arrPtr).add((short)3, hwToken); - CommandAPDU apdu = encodeApdu((byte)INS_BEGIN_OPERATION_CMD, arrPtr); - //print(apdu.getBytes(),(short)0,(short)apdu.getBytes().length); + KMArray.cast(arrPtr).add((short) 3, hwToken); + CommandAPDU apdu = encodeApdu((byte) INS_BEGIN_OPERATION_CMD, arrPtr); + // print(apdu.getBytes(),(short)0,(short)apdu.getBytes().length); ResponseAPDU response = simulator.transmitCommand(apdu); short ret = KMArray.instance((short) 3); short outParams = KMKeyParameters.exp(); - KMArray.cast(ret).add((short)0, KMInteger.exp()); - KMArray.cast(ret).add((short)1, outParams); - KMArray.cast(ret).add((short)2, KMInteger.exp()); + KMArray.cast(ret).add((short) 0, KMInteger.exp()); + KMArray.cast(ret).add((short) 1, outParams); + KMArray.cast(ret).add((short) 2, KMInteger.exp()); byte[] respBuf = response.getBytes(); short len = (short) respBuf.length; - if(len > 5){ - ret = decoder.decode(ret, respBuf, (short) 0, len); - short error = KMInteger.cast(KMArray.cast(ret).get((short)0)).getShort(); - Assert.assertEquals(error, KMError.OK); - return ret;}else{ - if(len == 3) return respBuf[0]; - if(len == 4) return respBuf[1]; - return Util.getShort(respBuf,(short)0); + if (len > 5) { + ret = decoder.decode(ret, respBuf, (short) 0, len); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + Assert.assertEquals(error, expectedErr); + return ret; + } else { + if (len == 3) + return respBuf[0]; + if (len == 4) + return respBuf[1]; + return Util.getShort(respBuf, (short) 0); } } + public short begin(byte keyPurpose, short keyBlob, short keyParmas, + short hwToken) { + return begin(keyPurpose, keyBlob, keyParmas, hwToken, KMError.OK); + } + public short translateExtendedErrorCodes(short err) { switch (err) { case KMError.SW_CONDITIONS_NOT_SATISFIED: From d9b8f3e03d4fe3ba2a2b02b4e9002e463feac3a5 Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Thu, 11 Feb 2021 20:37:07 +0530 Subject: [PATCH 14/15] Updated KMFunctionalTest --- .../android/javacard/test/KMFunctionalTest.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 787b9f97..a96e34f8 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -2307,9 +2307,8 @@ public void testUnsupportedBlockMode() { KMType.PKCS7, new byte[12]); short ret = begin(KMType.ENCRYPT, KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - KMKeyParameters.instance(desPkcs7Params), (short) 0, - KMError.UNSUPPORTED_BLOCK_MODE); - + KMKeyParameters.instance(desPkcs7Params), (short) 0); + Assert.assertTrue(ret == KMError.UNSUPPORTED_BLOCK_MODE); cleanUp(); } @@ -2971,7 +2970,7 @@ public short processMessage( } public short begin(byte keyPurpose, short keyBlob, short keyParmas, - short hwToken, short expectedErr) { + short hwToken) { short arrPtr = KMArray.instance((short) 4); KMArray.cast(arrPtr).add((short) 0, KMEnum.instance(KMType.PURPOSE, keyPurpose)); @@ -2994,7 +2993,7 @@ public short begin(byte keyPurpose, short keyBlob, short keyParmas, if (len > 5) { ret = decoder.decode(ret, respBuf, (short) 0, len); short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); - Assert.assertEquals(error, expectedErr); + Assert.assertEquals(error, KMError.OK); return ret; } else { if (len == 3) @@ -3005,11 +3004,6 @@ public short begin(byte keyPurpose, short keyBlob, short keyParmas, } } - public short begin(byte keyPurpose, short keyBlob, short keyParmas, - short hwToken) { - return begin(keyPurpose, keyBlob, keyParmas, hwToken, KMError.OK); - } - public short translateExtendedErrorCodes(short err) { switch (err) { case KMError.SW_CONDITIONS_NOT_SATISFIED: From 087da74c4d75c33ab4b33c2a18de439a6e485a94 Mon Sep 17 00:00:00 2001 From: bvenkateswarlu Date: Fri, 12 Feb 2021 23:00:07 +0530 Subject: [PATCH 15/15] 1. return INVALID_KEY_BLOB incase if parEncryptedKeyblob fails for any reason. 2. Incase of NOPAD sign if signature length is less than 256 add zero to the front and make length equal to 256. --- .../javacard/keymaster/KMKeymasterApplet.java | 109 +++++++++--------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index b4914308..07cc134b 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1782,26 +1782,23 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 256, (byte) 0); switch (op.getAlgorithm()) { case KMType.RSA: - // Output for signature is always 256 bytes. - data[OUTPUT_DATA] = KMByteBlob.instance((short) 256); // If there is no padding we can treat signing as a RSA decryption operation. - if (op.getDigest() == KMType.DIGEST_NONE && op.getPadding() == KMType.PADDING_NONE) { - // Input data of Verify operation must be 256 bytes - if (op.getPurpose() == KMType.VERIFY - && KMByteBlob.cast(data[INPUT_DATA]).length() != 256) { - KMException.throwIt(KMError.INVALID_INPUT_LENGTH); - } - } try { if (op.getPurpose() == KMType.SIGN) { // len of signature will be 256 bytes - op.getOperation() - .sign( + short len = op.getOperation().sign( KMByteBlob.cast(data[INPUT_DATA]).getBuffer(), KMByteBlob.cast(data[INPUT_DATA]).getStartOff(), - KMByteBlob.cast(data[INPUT_DATA]).length(), + KMByteBlob.cast(data[INPUT_DATA]).length(), scratchPad, + (short) 0); + // Maximum output size of signature is 256 bytes. + data[OUTPUT_DATA] = KMByteBlob.instance((short) 256); + Util.arrayCopyNonAtomic( + scratchPad, + (short) 0, KMByteBlob.cast(data[OUTPUT_DATA]).getBuffer(), - KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff()); + (short) (KMByteBlob.cast(data[OUTPUT_DATA]).getStartOff() + 256 - len), + len); } else { KMException.throwIt(KMError.UNSUPPORTED_PURPOSE); } @@ -3625,53 +3622,57 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { } private static void parseEncryptedKeyBlob(byte[] scratchPad) { - tmpVariables[0] = KMByteBlob.cast(data[KEY_BLOB]).getStartOff(); - tmpVariables[1] = KMArray.instance((short) 5); - KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_SECRET, KMByteBlob.exp()); - KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, KMByteBlob.exp()); - KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_NONCE, KMByteBlob.exp()); - tmpVariables[2] = KMKeyCharacteristics.exp(); - KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_KEYCHAR, tmpVariables[2]); - KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, KMByteBlob.exp()); + data[ROT] = repository.readROT(); + if (data[ROT] == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } try { - data[KEY_BLOB] = - decoder.decodeArray( - tmpVariables[1], + tmpVariables[0] = KMByteBlob.cast(data[KEY_BLOB]).getStartOff(); + tmpVariables[1] = KMArray.instance((short) 5); + KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_SECRET, + KMByteBlob.exp()); + KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, + KMByteBlob.exp()); + KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_NONCE, + KMByteBlob.exp()); + tmpVariables[2] = KMKeyCharacteristics.exp(); + KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_KEYCHAR, + tmpVariables[2]); + KMArray.cast(tmpVariables[1]).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, + KMByteBlob.exp()); + data[KEY_BLOB] = decoder.decodeArray(tmpVariables[1], KMByteBlob.cast(data[KEY_BLOB]).getBuffer(), KMByteBlob.cast(data[KEY_BLOB]).getStartOff(), KMByteBlob.cast(data[KEY_BLOB]).length()); - } catch (ISOException e) { - KMException.throwIt(KMError.INVALID_KEY_BLOB); - } - tmpVariables[0] = KMArray.cast(data[KEY_BLOB]).length(); - if (tmpVariables[0] < 4) { + tmpVariables[0] = KMArray.cast(data[KEY_BLOB]).length(); + if (tmpVariables[0] < 4) { + KMException.throwIt(KMError.INVALID_KEY_BLOB); + } + data[AUTH_TAG] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_AUTH_TAG); + + // initialize data + data[NONCE] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_NONCE); + data[SECRET] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_SECRET); + data[KEY_CHARACTERISTICS] = KMArray.cast(data[KEY_BLOB]).get( + KEY_BLOB_KEYCHAR); + data[PUB_KEY] = KMType.INVALID_VALUE; + if (tmpVariables[0] == 5) { + data[PUB_KEY] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_PUB_KEY); + } + data[HW_PARAMETERS] = KMKeyCharacteristics + .cast(data[KEY_CHARACTERISTICS]).getHardwareEnforced(); + data[SW_PARAMETERS] = KMKeyCharacteristics + .cast(data[KEY_CHARACTERISTICS]).getSoftwareEnforced(); + + data[HIDDEN_PARAMETERS] = KMKeyParameters.makeHidden(data[APP_ID], + data[APP_DATA], data[ROT], scratchPad); + // make auth data + makeAuthData(scratchPad); + // Decrypt Secret and verify auth tag + decryptSecret(scratchPad); + } catch (Exception e) { KMException.throwIt(KMError.INVALID_KEY_BLOB); } - data[AUTH_TAG] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_AUTH_TAG); - - // initialize data - data[NONCE] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_NONCE); - data[SECRET] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_SECRET); - data[KEY_CHARACTERISTICS] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_KEYCHAR); - data[PUB_KEY] = KMType.INVALID_VALUE; - if (tmpVariables[0] == 5) { - data[PUB_KEY] = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_PUB_KEY); - } - data[HW_PARAMETERS] = - KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getHardwareEnforced(); - data[SW_PARAMETERS] = - KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getSoftwareEnforced(); - data[ROT] = repository.readROT(); - if (data[ROT] == KMType.INVALID_VALUE) { - KMException.throwIt(KMError.UNKNOWN_ERROR); - } - - data[HIDDEN_PARAMETERS] = - KMKeyParameters.makeHidden(data[APP_ID], data[APP_DATA], data[ROT], scratchPad); - // make auth data - makeAuthData(scratchPad); - // Decrypt Secret and verify auth tag - decryptSecret(scratchPad); } private static void decryptSecret(byte[] scratchPad) {