Skip to content

Commit 0d842b6

Browse files
authored
Merge pull request #112 from subrahmanyaman/hmac_sign_len_validation
Hmac sign len validation
2 parents b0061fc + 21449c0 commit 0d842b6

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

Applet/src/com/android/javacard/keymaster/KMKeyParameters.java

+1
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ public static short makeHidden(short appIdBlob, short appDataBlob, short rootOfT
425425
index += 2;
426426
}
427427
if (appDataBlob != KMTag.INVALID_VALUE) {
428+
KMByteBlob.cast(appDataBlob);
428429
Util.setShort(scratchPad, index, appDataBlob);
429430
index += 2;
430431
}

Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java

+32-17
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.android.javacard.seprovider.KMAttestationCert;
2020
import com.android.javacard.seprovider.KMDeviceUniqueKeyPair;
2121
import com.android.javacard.seprovider.KMException;
22-
import com.android.javacard.seprovider.KMHmacKey;
2322
import com.android.javacard.seprovider.KMSEProvider;
2423
import javacard.framework.APDU;
2524
import javacard.framework.Applet;
@@ -29,8 +28,6 @@
2928
import javacard.framework.JCSystem;
3029
import javacard.framework.Util;
3130
import javacard.security.CryptoException;
32-
import javacard.security.HMACKey;
33-
import javacard.security.KeyBuilder;
3431
import javacardx.apdu.ExtendedLength;
3532

3633
/**
@@ -227,6 +224,10 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe
227224
// Key type constants
228225
public static final byte SYM_KEY_TYPE = 0;
229226
public static final byte ASYM_KEY_TYPE = 1;
227+
// SHA-256 Digest length in bits
228+
public static final short SHA256_DIGEST_LEN_BITS = 256;
229+
// Minimum HMAC length in bits
230+
public static final short MIN_HMAC_LENGTH_BITS = 64;
230231

231232
protected static RemotelyProvisionedComponentDevice rkp;
232233
protected static KMEncoder encoder;
@@ -983,7 +984,7 @@ private boolean isKeyUpgradeRequired(short keyBlob, short appId, short appData,
983984
KMException.throwIt(KMError.INVALID_ARGUMENT);
984985
}
985986
} else {
986-
KMException.throwIt(KMError.UNKNOWN_ERROR);
987+
KMException.throwIt(KMError.UNKNOWN_ERROR);
987988
}
988989
index += 4;
989990
}
@@ -1728,8 +1729,7 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch
17281729
// the truncated signature back to the caller. At the time of verfication
17291730
// we again compute the signature of the plain text input, truncate it to
17301731
// TAG_MAC_LENGTH and compare it with the input signature for
1731-
// verification. So this is the reason we are using KMType.SIGN directly
1732-
// instead of using op.getPurpose().
1732+
// verification.
17331733
op.getOperation()
17341734
.sign(
17351735
KMByteBlob.cast(data[INPUT_DATA]).getBuffer(),
@@ -1741,10 +1741,18 @@ private void finishSigningVerifyingOperation(KMOperationState op, byte[] scratch
17411741
// Copy only signature of mac length size.
17421742
data[OUTPUT_DATA] =
17431743
KMByteBlob.instance(scratchPad, (short) 0, (short) (op.getMacLength() / 8));
1744-
}else if (op.getPurpose() == KMType.VERIFY) {
1744+
} else if (op.getPurpose() == KMType.VERIFY) {
1745+
if ((KMByteBlob.cast(data[SIGNATURE]).length() < (MIN_HMAC_LENGTH_BITS / 8)) ||
1746+
KMByteBlob.cast(data[SIGNATURE]).length() > (SHA256_DIGEST_LEN_BITS / 8)) {
1747+
KMException.throwIt(KMError.UNSUPPORTED_MAC_LENGTH);
1748+
}
1749+
if ((KMByteBlob.cast(data[SIGNATURE]).length() < (short)(op.getMinMacLength() / 8))) {
1750+
KMException.throwIt(KMError.INVALID_MAC_LENGTH);
1751+
}
1752+
17451753
if (0
17461754
!= Util.arrayCompare(
1747-
scratchPad, (short)0,
1755+
scratchPad, (short) 0,
17481756
KMByteBlob.cast(data[SIGNATURE]).getBuffer(),
17491757
KMByteBlob.cast(data[SIGNATURE]).getStartOff(),
17501758
KMByteBlob.cast(data[SIGNATURE]).length())) {
@@ -2167,14 +2175,17 @@ private void processBeginOperationCmd(APDU apdu) {
21672175
} else {
21682176
iv = KMArray.instance((short) 0);
21692177
}
2170-
2178+
short macLen = 0;
2179+
if(op.getMacLength() != KMType.INVALID_VALUE) {
2180+
macLen = (short) (op.getMacLength()/8) ;
2181+
}
21712182
short params = KMKeyParameters.instance(iv);
21722183
short resp = KMArray.instance((short) 5);
21732184
KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK));
21742185
KMArray.cast(resp).add((short) 1, params);
21752186
KMArray.cast(resp).add((short) 2, data[OP_HANDLE]);
21762187
KMArray.cast(resp).add((short) 3, KMInteger.uint_8(op.getBufferingMode()));
2177-
KMArray.cast(resp).add((short) 4, KMInteger.uint_16((short) (op.getMacLength() / 8)));
2188+
KMArray.cast(resp).add((short) 4, KMInteger.uint_16(macLen));
21782189
sendOutgoing(apdu, resp);
21792190
}
21802191

@@ -2404,6 +2415,9 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) {
24042415
}
24052416
break;
24062417
case KMType.HMAC:
2418+
short minMacLen = KMIntegerTag.getShortValue(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH,
2419+
data[HW_PARAMETERS]);
2420+
op.setMinMacLength(minMacLen);
24072421
if (macLen == KMType.INVALID_VALUE) {
24082422
if (op.getPurpose() == KMType.SIGN) {
24092423
KMException.throwIt(KMError.MISSING_MAC_LENGTH);
@@ -2413,12 +2427,13 @@ private void authorizeBlockModeAndMacLength(KMOperationState op) {
24132427
if (op.getPurpose() == KMType.VERIFY) {
24142428
KMException.throwIt(KMError.INVALID_ARGUMENT);
24152429
}
2416-
if (macLen
2417-
< KMIntegerTag.getShortValue(
2418-
KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[HW_PARAMETERS])) {
2430+
if (macLen % 8 != 0 ||
2431+
macLen > SHA256_DIGEST_LEN_BITS ||
2432+
macLen < MIN_HMAC_LENGTH_BITS) {
2433+
KMException.throwIt(KMError.UNSUPPORTED_MAC_LENGTH);
2434+
}
2435+
if (macLen < minMacLen) {
24192436
KMException.throwIt(KMError.INVALID_MAC_LENGTH);
2420-
} else if (macLen % 8 != 0 || macLen > 256) {
2421-
KMException.throwIt(KMError.UNSUPPORTED_MAC_LENGTH);
24222437
}
24232438
op.setMacLength(macLen);
24242439
}
@@ -3720,8 +3735,8 @@ private static void validateHmacKey() {
37203735
KMIntegerTag.getShortValue(KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, data[KEY_PARAMETERS]);
37213736

37223737
if (((short) (minMacLength % 8) != 0)
3723-
|| minMacLength < (short) 64
3724-
|| minMacLength > (short) 256) {
3738+
|| minMacLength < MIN_HMAC_LENGTH_BITS
3739+
|| minMacLength > SHA256_DIGEST_LEN_BITS) {
37253740
KMException.throwIt(KMError.UNSUPPORTED_MIN_MAC_LENGTH);
37263741
}
37273742
// Read Keysize

Applet/src/com/android/javacard/keymaster/KMOperationState.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ public class KMOperationState {
4040
private static final byte MAC_LENGTH = 7;
4141
private static final byte MGF_DIGEST = 8;
4242
private static final byte AUTH_TYPE = 9;
43+
private static final byte MIN_MAC_LENGTH = 10;
4344
// sizes
4445
public static final byte OPERATION_HANDLE_SIZE = 8;
45-
public static final byte DATA_SIZE = 10;
46+
public static final byte DATA_SIZE = 11;
4647
public static final byte AUTH_TIME_SIZE = 8;
4748
// Secure user ids 5 * 8 = 40 bytes ( Considering Maximum 5 SECURE USER IDs)
4849
// First two bytes are reserved to store number of secure ids. So total 42 bytes.
@@ -278,6 +279,14 @@ public void setMacLength(short length) {
278279
data[MAC_LENGTH] = length;
279280
}
280281

282+
public void setMinMacLength(short length) {
283+
data[MIN_MAC_LENGTH] = length;
284+
}
285+
286+
public short getMinMacLength() {
287+
return data[MIN_MAC_LENGTH];
288+
}
289+
281290
public short getMacLength() {
282291
return data[MAC_LENGTH];
283292
}

0 commit comments

Comments
 (0)