Skip to content

Commit dd579c7

Browse files
Length validations
1 parent 4977e65 commit dd579c7

7 files changed

Lines changed: 83 additions & 31 deletions

File tree

Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMConfigurations.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ public class KMConfigurations {
2020
public static final byte LITTLE_ENDIAN = 0x00;
2121
public static final byte BIG_ENDIAN = 0x01;
2222
public static final byte TEE_MACHINE_TYPE = LITTLE_ENDIAN;
23+
public static final byte MAX_ATTESTATION_IDS_SIZE = 48;
2324
}

Applet/src/com/android/javacard/keymaster/KMPKCS8Decoder.java renamed to Applet/src/com/android/javacard/keymaster/KMAsn1Parser.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
import com.android.javacard.seprovider.KMException;
44
import javacard.framework.Util;
55

6-
public class KMPKCS8Decoder {
6+
public class KMAsn1Parser {
77
public static final byte ASN1_OCTET_STRING= 0x04;
88
public static final byte ASN1_SEQUENCE= 0x30;
9+
public static final byte ASN1_SET= 0x31;
910
public static final byte ASN1_INTEGER= 0x02;
11+
public static final byte OBJECT_IDENTIFIER = 0x06;
1012
public static final byte ASN1_A0_TAG = (byte) 0xA0;
1113
public static final byte ASN1_A1_TAG = (byte) 0xA1;
1214
public static final byte ASN1_BIT_STRING = 0x03;
15+
public static final byte ASN1_UTF8_STRING = 0x0C;
1316
public static final byte[] EC_CURVE = {
1417
0x06,0x08,0x2a,(byte)0x86,0x48,(byte)0xce,0x3d,0x03,
1518
0x01,0x07
@@ -23,12 +26,15 @@ public class KMPKCS8Decoder {
2326
0x3d,0x02,0x01,0x06,0x08,0x2a,(byte)0x86,0x48,
2427
(byte)0xce,0x3d,0x03,0x01,0x07
2528
};
29+
public static final byte[] COMMON_NAME_OID = {
30+
0x55, 0x04, 0x03
31+
};
2632
private byte[] data;
2733
private short start;
2834
private short length;
2935
private short cur;
30-
private static KMPKCS8Decoder inst;
31-
private KMPKCS8Decoder(){
36+
private static KMAsn1Parser inst;
37+
private KMAsn1Parser(){
3238
start = 0;
3339
length = 0;
3440
cur = 0;
@@ -45,6 +51,15 @@ public short decodeEc(short blob){
4551
decodeCommon((short)0, EC_ALGORITHM);
4652
return decodeEcPrivateKey((short)1);
4753
}
54+
55+
public short decodeSubject(short blob) {
56+
init(blob);
57+
header(ASN1_SEQUENCE);
58+
header(ASN1_SET);
59+
header(ASN1_SEQUENCE);
60+
objectIdentifier(COMMON_NAME_OID);
61+
return header(ASN1_UTF8_STRING);
62+
}
4863

4964
public short decodeEcSubjectPublicKeyInfo(short blob) {
5065
init(blob);
@@ -183,6 +198,17 @@ private void validateTag0IfPresent(){
183198
if(Util.arrayCompare(data, cur, EC_CURVE, (short)0, len) != 0) KMException.throwIt(KMError.UNKNOWN_ERROR);
184199
incrementCursor(len);
185200
}
201+
202+
private short objectIdentifier(byte[] oid) {
203+
short length = header(OBJECT_IDENTIFIER);
204+
if (length != oid.length) {
205+
KMException.throwIt(KMError.UNKNOWN_ERROR);
206+
}
207+
if(Util.arrayCompare(data, cur, oid, (short)0, length) != 0) KMException.throwIt(KMError.UNKNOWN_ERROR);
208+
incrementCursor(length);
209+
return length;
210+
}
211+
186212
private short header(short tag){
187213
short t = getByte();
188214
if(t != tag) KMException.throwIt(KMError.UNKNOWN_ERROR);
@@ -222,9 +248,9 @@ private short getLength(){
222248
else KMException.throwIt(KMError.UNKNOWN_ERROR);
223249
return KMType.INVALID_VALUE; //should not come here
224250
}
225-
public static KMPKCS8Decoder instance() {
251+
public static KMAsn1Parser instance() {
226252
if (inst == null) {
227-
inst = new KMPKCS8Decoder();
253+
inst = new KMAsn1Parser();
228254
}
229255
return inst;
230256
}

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

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,26 +95,23 @@ public short length() {
9595
return KMByteBlob.cast(blobPtr).length();
9696
}
9797

98+
// TODO Review this function
9899
private static boolean validateKey(short key, short byteBlob) {
99100
short valueLen = KMByteBlob.cast(byteBlob).length();
100101
switch (key) {
101-
case ROOT_OF_TRUST:
102-
case UNIQUE_ID:
103102
case ATTESTATION_APPLICATION_ID:
104-
case ATTESTATION_ID_BRAND:
105-
case ATTESTATION_ID_DEVICE:
106-
case ATTESTATION_ID_PRODUCT:
107-
case ATTESTATION_ID_SERIAL:
108-
case ATTESTATION_ID_IMEI:
109-
case ATTESTATION_ID_MEID:
110-
case ATTESTATION_ID_MANUFACTURER:
111-
case ATTESTATION_ID_MODEL:
112-
case ASSOCIATED_DATA:
113-
case NONCE:
114-
case CONFIRMATION_TOKEN:
115-
case VERIFIED_BOOT_KEY:
116-
case VERIFIED_BOOT_HASH:
103+
if (valueLen > MAX_ATTESTATION_APP_ID_SIZE) {
104+
return false;
105+
}
106+
break;
117107
case CERTIFICATE_SUBJECT_NAME:
108+
{
109+
KMAsn1Parser asn1Decoder = KMAsn1Parser.instance();
110+
short length = asn1Decoder.decodeSubject(byteBlob);
111+
if (length > MAX_SUBJECT_CN_LEN) {
112+
return false;
113+
}
114+
}
118115
break;
119116
case APPLICATION_ID:
120117
case APPLICATION_DATA:
@@ -127,6 +124,25 @@ private static boolean validateKey(short key, short byteBlob) {
127124
return false;
128125
}
129126
break;
127+
case ATTESTATION_ID_BRAND:
128+
case ATTESTATION_ID_DEVICE:
129+
case ATTESTATION_ID_PRODUCT:
130+
case ATTESTATION_ID_SERIAL:
131+
case ATTESTATION_ID_IMEI:
132+
case ATTESTATION_ID_MEID:
133+
case ATTESTATION_ID_MANUFACTURER:
134+
case ATTESTATION_ID_MODEL:
135+
if (valueLen > KMConfigurations.MAX_ATTESTATION_IDS_SIZE) {
136+
return false;
137+
}
138+
break;
139+
case ROOT_OF_TRUST: // TODO : Not adding it as ByteTag in HiddenParamters.
140+
//case UNIQUE_ID: This tag never used in keyParamters.
141+
case NONCE: // Validation of nonce happends in begin operation.
142+
// Below two tags are obsolete in keymint.
143+
//case ASSOCIATED_DATA:
144+
//case CONFIRMATION_TOKEN:
145+
break;
130146
default:
131147
return false;
132148
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,17 @@ public static short makeHidden(short keyParamsPtr, short rootOfTrustBlob, byte[]
403403
short appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, keyParamsPtr);
404404
if (appId != KMTag.INVALID_VALUE) {
405405
appId = KMByteTag.cast(appId).getValue();
406+
if (KMByteBlob.cast(appId).length() == 0) {
407+
appId = KMTag.INVALID_VALUE;
408+
}
406409
}
407410
short appData =
408411
KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, keyParamsPtr);
409412
if (appData != KMTag.INVALID_VALUE) {
410413
appData = KMByteTag.cast(appData).getValue();
414+
if (KMByteBlob.cast(appData).length() == 0) {
415+
appData = KMTag.INVALID_VALUE;
416+
}
411417
}
412418
return makeHidden(appId, appData, rootOfTrustBlob, scratchPad);
413419
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,11 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara
13811381
if (!KMEnumArrayTag.cast(attKeyPurpose).contains(KMType.ATTEST_KEY)) {
13821382
KMException.throwIt(KMError.INCOMPATIBLE_PURPOSE);
13831383
}
1384+
KMAsn1Parser asn1Decoder = KMAsn1Parser.instance();
1385+
short length = asn1Decoder.decodeSubject(issuer);
1386+
if (length > KMType.MAX_SUBJECT_CN_LEN) {
1387+
KMException.throwIt(KMError.INVALID_ISSUER_SUBJECT_NAME);
1388+
}
13841389
// If issuer is not present then it is an error
13851390
if (KMByteBlob.cast(issuer).length() <= 0) {
13861391
KMException.throwIt(KMError.MISSING_ISSUER_SUBJECT_NAME);
@@ -1719,7 +1724,7 @@ private void finishAesDesOperation(KMOperationState op){
17191724

17201725
private void finishKeyAgreementOperation(KMOperationState op, byte[] scratchPad) {
17211726
try {
1722-
KMPKCS8Decoder pkcs8 = KMPKCS8Decoder.instance();
1727+
KMAsn1Parser pkcs8 = KMAsn1Parser.instance();
17231728
short blob = pkcs8.decodeEcSubjectPublicKeyInfo(data[INPUT_DATA]);
17241729
short len = op.getOperation().finish(
17251730
KMByteBlob.cast(blob).getBuffer(),
@@ -3061,7 +3066,7 @@ private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) {
30613066

30623067
private void importECKeys(byte[] scratchPad) {
30633068
// Decode key material
3064-
KMPKCS8Decoder pkcs8 = KMPKCS8Decoder.instance();
3069+
KMAsn1Parser pkcs8 = KMAsn1Parser.instance();
30653070
short keyBlob = pkcs8.decodeEc(data[IMPORTED_KEY_BLOB]);
30663071
data[PUB_KEY] = KMArray.cast(keyBlob).get((short) 0);
30673072
data[SECRET] = KMArray.cast(keyBlob).get((short) 1);
@@ -3253,7 +3258,7 @@ private void importAESKey(byte[] scratchPad) {
32533258

32543259
private void importRSAKey(byte[] scratchPad) {
32553260
// Decode key material
3256-
KMPKCS8Decoder pkcs8 = KMPKCS8Decoder.instance();
3261+
KMAsn1Parser pkcs8 = KMAsn1Parser.instance();
32573262
short keyblob = pkcs8.decodeRsa(data[IMPORTED_KEY_BLOB]);
32583263
data[PUB_KEY] = KMArray.cast(keyblob).get((short) 0);
32593264
short pubKeyExp = KMArray.cast(keyblob).get((short)1);
@@ -4384,7 +4389,7 @@ public static short generateBcc(boolean testMode, byte[] scratchPad) {
43844389
scratchPad,
43854390
temp
43864391
);
4387-
len = KMPKCS8Decoder.instance().
4392+
len = KMAsn1Parser.instance().
43884393
decodeEcdsa256Signature(KMByteBlob.instance(scratchPad, temp, len), scratchPad, temp);
43894394
coseSignStructure = KMByteBlob.instance(scratchPad, temp, len);
43904395

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,6 @@ public abstract class KMType {
145145
public static final byte UNVERIFIED_BOOT = 0x02;
146146
public static final byte FAILED_BOOT = 0x03;
147147

148-
// Verified Boot Key
149-
public static final short VERIFIED_BOOT_KEY = (short) 0xF004;
150-
151-
// Verified Boot Hash
152-
public static final short VERIFIED_BOOT_HASH = (short) 0xF005;
153-
154148
// Device Locked
155149
public static final short DEVICE_LOCKED = (short) 0xF006;
156150
public static final byte DEVICE_LOCKED_TRUE = 0x01;
@@ -364,6 +358,10 @@ public abstract class KMType {
364358
public static final short MAX_ATTESTATION_CHALLENGE_SIZE = 128;
365359
// Max certificate serial size.
366360
public static final short MAX_CERTIFICATE_SERIAL_SIZE = 20;
361+
// Attestation Application ID
362+
public static final short MAX_ATTESTATION_APP_ID_SIZE = 1024;
363+
// Maximum Certificate Subject Common name length.
364+
public static final short MAX_SUBJECT_CN_LEN = 64;
367365

368366

369367
protected static KMRepository repository;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ private short createSignedMac(KMDeviceUniqueKeyPair deviceUniqueKeyPair, byte[]
785785
scratchPad,
786786
signStructure
787787
);
788-
len = KMPKCS8Decoder.instance().
788+
len = KMAsn1Parser.instance().
789789
decodeEcdsa256Signature(KMByteBlob.instance(scratchPad, signStructure, len), scratchPad, signStructure);
790790
signStructure = KMByteBlob.instance(scratchPad, signStructure, len);
791791

0 commit comments

Comments
 (0)