Bug 947110 - Part1: RIL patch. B2G RIL: Add support for decoding FCP Template in BerTlvHelper. v5. r=yoshi.

This commit is contained in:
Shawn Ku 2013-12-23 10:35:39 +08:00
parent e559b96055
commit 01379a1bbf
2 changed files with 196 additions and 41 deletions

View File

@ -545,6 +545,12 @@ this.EF_TYPE_TRANSPARENT = 0;
this.EF_TYPE_LINEAR_FIXED = 1;
this.EF_TYPE_CYCLIC = 3;
// TS 102.221 11.1.1.4.3 Table 11.5: File descriptor byte.
this.UICC_EF_STRUCTURE = {};
this.UICC_EF_STRUCTURE[this.EF_TYPE_TRANSPARENT]= 1;
this.UICC_EF_STRUCTURE[this.EF_TYPE_LINEAR_FIXED]= 2;
this.UICC_EF_STRUCTURE[this.EF_TYPE_CYCLIC]= 6;
// Status code of EFsms
// see 3GPP TS 51.011 clause 10.5.3
this.EFSMS_STATUS_FREE = 0x00;
@ -687,10 +693,24 @@ this.CSIM_IMSI_M_PROGRAMMED_BYTE = 7;
this.CSIM_IMSI_M_MCC_BYTE = 8;
/**
* STK constants.
* Tags for Ber Tlv.
* See 3GPP TS 101 220 clause 7.2 - Assigned TLV tag values.
*/
// Tags for Ber Tlv.
this.BER_UNKNOWN_TAG = 0x00;
this.BER_FCP_TEMPLATE_TAG = 0x62;
this.BER_FCP_FILE_SIZE_DATA_TAG = 0x80;
this.BER_FCP_FILE_SIZE_TOTAL_TAG = 0x81;
this.BER_FCP_FILE_DESCRIPTOR_TAG = 0x82;
this.BER_FCP_FILE_IDENTIFIER_TAG = 0x83;
this.BER_FCP_DF_NAME_TAG = 0x84; // AID.
this.BER_FCP_PROPRIETARY_PRIMITIVE_TAG = 0x85;
this.BER_FCP_SFI_SUPPORT_TAG = 0x88;
this.BER_FCP_LIFE_CYCLE_STATUS_TAG = 0x8a;
this.BER_FCP_SA_REFERENCE_FORMAT_TAG = 0x8b; // Security Attribute - Reference Format.
this.BER_FCP_SA_COMPACT_FORMAT_TAG = 0x8c; // Security Attribute - Compact Format.
this.BER_FCP_SAT_EXPANDED_FORMAT_TAG = 0xab; // Security Attribute Template - Expanded Format.
this.BER_FCP_PROPRIETARY_TEMPLATE_TAG = 0xa5;
this.BER_FCP_PIN_STATUS_DATA_OBJECTS_TAG = 0xc6;
this.BER_PROACTIVE_COMMAND_TAG = 0xd0;
this.BER_SMS_PP_DOWNLOAD_TAG = 0xd1;
this.BER_MENU_SELECTION_TAG = 0xd3;

View File

@ -4896,7 +4896,16 @@ let RIL = {
*/
processStkProactiveCommand: function processStkProactiveCommand() {
let length = Buf.readInt32();
let berTlv = BerTlvHelper.decode(length / 2);
let berTlv;
try {
berTlv = BerTlvHelper.decode(length / 2);
} catch (e) {
if (DEBUG) debug("processStkProactiveCommand : " + e);
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
return;
}
Buf.readStringDelimiter(length);
let ctlvs = berTlv.value;
@ -10629,8 +10638,6 @@ let ComprehensionTlvHelper = {
case 0x0: // Not used.
case 0xff: // Not used.
case 0x80: // Reserved for future use.
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid octet when parsing Comprehension TLV :" + temp);
case 0x7f: // Tag is three byte format.
// TS 101.220 clause 7.1.1.2.
@ -10670,16 +10677,12 @@ let ComprehensionTlvHelper = {
length = GsmPDUHelper.readHexOctet();
hlen++;
if (length < 0x80) {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid length in Comprehension TLV :" + length);
}
} else if (temp == 0x82) {
length = (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
hlen += 2;
if (lenth < 0x0100) {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid length in 3-byte Comprehension TLV :" + length);
}
} else if (temp == 0x83) {
@ -10688,13 +10691,9 @@ let ComprehensionTlvHelper = {
GsmPDUHelper.readHexOctet();
hlen += 3;
if (length < 0x010000) {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid length in 4-byte Comprehension TLV :" + length);
}
} else {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid octet in Comprehension TLV :" + temp);
}
@ -10894,53 +10893,189 @@ let BerTlvHelper = {
* The length of data in bytes.
*/
decode: function decode(dataLen) {
// See TS 11.14, Annex D for BerTlv.
let hlen = 0;
let tag = GsmPDUHelper.readHexOctet();
hlen++;
// The length is coded onto 1 or 2 bytes.
// Length | Byte 1 | Byte 2
// 0 - 127 | length ('00' to '7f') | N/A
// 128 - 255 | '81' | length ('80' to 'ff')
let length;
if (tag == BER_PROACTIVE_COMMAND_TAG) {
let temp = GsmPDUHelper.readHexOctet();
hlen++;
if (temp < 0x80) {
length = temp;
} else if(temp == 0x81) {
} else if (temp === 0x81) {
length = GsmPDUHelper.readHexOctet();
hlen++;
if (length < 0x80) {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid length " + length);
}
} else {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Invalid length octet " + temp);
}
} else {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("Unknown BER tag");
// Header + body length check.
if (dataLen - hlen !== length) {
throw new Error("Unexpected BerTlvHelper value length!!");
}
// If the value length of the BerTlv is larger than remaining value on Parcel.
if (dataLen - hlen < length) {
RIL.sendStkTerminalResponse({
resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
throw new Error("BerTlvHelper value length too long!!");
let method = this[tag];
if (typeof method != "function") {
throw new Error("Unknown Ber tag 0x" + tag.toString(16));
}
let ctlvs = ComprehensionTlvHelper.decodeChunks(length);
let berTlv = {
let value = method.call(this, length);
return {
tag: tag,
length: length,
value: ctlvs
value: value
};
return berTlv;
},
/**
* Process the value part for FCP template TLV.
*
* @param length
* The length of data in bytes.
*/
processFcpTemplate: function processFcpTemplate(length) {
let tlvs = this.decodeChunks(length);
return tlvs;
},
/**
* Process the value part for proactive command TLV.
*
* @param length
* The length of data in bytes.
*/
processProactiveCommand: function processProactiveCommand(length) {
let ctlvs = ComprehensionTlvHelper.decodeChunks(length);
return ctlvs;
},
/**
* Decode raw data to a Ber-TLV.
*/
decodeInnerTlv: function decodeInnerTlv() {
let tag = GsmPDUHelper.readHexOctet();
let length = GsmPDUHelper.readHexOctet();
return {
tag: tag,
length: length,
value: this.retrieve(tag, length)
};
},
decodeChunks: function decodeChunks(length) {
let chunks = [];
let index = 0;
while (index < length) {
let tlv = this.decodeInnerTlv();
if (tlv.value) {
chunks.push(tlv);
}
index += tlv.length;
// tag + length fields consume 2 bytes.
index += 2;
}
return chunks;
},
retrieve: function retrieve(tag, length) {
let method = this[tag];
if (typeof method != "function") {
if (DEBUG) {
debug("Unknown Ber tag : 0x" + tag.toString(16));
}
Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
return null;
}
return method.call(this, length);
},
/**
* File Size Data.
*
* | Byte | Description | Length |
* | 1 | Tag | 1 |
* | 2 | Length | 1 |
* | 3 to X+24 | Number of allocated data bytes in the file | X |
* | | , excluding structural information | |
*/
retrieveFileSizeData: function retrieveFileSizeData(length) {
let fileSizeData = 0;
for (let i = 0; i < length; i++) {
fileSizeData = fileSizeData << 8;
fileSizeData += GsmPDUHelper.readHexOctet();
}
return {fileSizeData: fileSizeData};
},
/**
* File Descriptor.
*
* | Byte | Description | Length |
* | 1 | Tag | 1 |
* | 2 | Length | 1 |
* | 3 | File descriptor byte | 1 |
* | 4 | Data coding byte | 1 |
* | 5 ~ 6 | Record length | 2 |
* | 7 | Number of records | 1 |
*/
retrieveFileDescriptor: function retrieveFileDescriptor(length) {
let fileDescriptorByte = GsmPDUHelper.readHexOctet();
let dataCodingByte = GsmPDUHelper.readHexOctet();
// See TS 102 221 Table 11.5, we only care the least 3 bits for the
// structure of file.
let fileStructure = fileDescriptorByte & 0x07;
let fileDescriptor = {
fileStructure: fileStructure
};
// byte 5 ~ 7 are mandatory for linear fixed and cyclic files, otherwise
// they are not applicable.
if (fileStructure === UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED] ||
fileStructure === UICC_EF_STRUCTURE[EF_TYPE_CYCLIC]) {
fileDescriptor.recordLength = (GsmPDUHelper.readHexOctet() << 8) +
GsmPDUHelper.readHexOctet();
fileDescriptor.numOfRecords = GsmPDUHelper.readHexOctet();
}
return fileDescriptor;
},
/**
* File identifier.
*
* | Byte | Description | Length |
* | 1 | Tag | 1 |
* | 2 | Length | 1 |
* | 3 ~ 4 | File identifier | 2 |
*/
retrieveFileIdentifier: function retrieveFileIdentifier(length) {
return {fileId : (GsmPDUHelper.readHexOctet() << 8) +
GsmPDUHelper.readHexOctet()};
}
};
BerTlvHelper[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
return this.processFcpTemplate(length);
};
BerTlvHelper[BER_PROACTIVE_COMMAND_TAG] = function BER_PROACTIVE_COMMAND_TAG(length) {
return this.processProactiveCommand(length);
};
BerTlvHelper[BER_FCP_FILE_SIZE_DATA_TAG] = function BER_FCP_FILE_SIZE_DATA_TAG(length) {
return this.retrieveFileSizeData(length);
};
BerTlvHelper[BER_FCP_FILE_DESCRIPTOR_TAG] = function BER_FCP_FILE_DESCRIPTOR_TAG(length) {
return this.retrieveFileDescriptor(length);
};
BerTlvHelper[BER_FCP_FILE_IDENTIFIER_TAG] = function BER_FCP_FILE_IDENTIFIER_TAG(length) {
return this.retrieveFileIdentifier(length);
};
/**