summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2009-10-02 17:47:44 -0500
committerDenis Kenzior <denkenz@gmail.com>2009-10-02 18:25:56 -0500
commit8bf64ef07da99cce57142bdb6ce8274f0690ec5e (patch)
tree34cca99051e25bfa76e3e41af96d4329b4737e23 /src
parentc9a2eedc08b5a7ba625dac3764f176676c11d304 (diff)
downloadofono-8bf64ef07da99cce57142bdb6ce8274f0690ec5e.tar.bz2
Add utility to parse 3G get response data
Based on ETSI 102.221
Diffstat (limited to 'src')
-rw-r--r--src/simutil.c109
-rw-r--r--src/simutil.h5
2 files changed, 114 insertions, 0 deletions
diff --git a/src/simutil.c b/src/simutil.c
index 2b5db2af..c294489e 100644
--- a/src/simutil.c
+++ b/src/simutil.c
@@ -574,6 +574,115 @@ struct sim_ef_info *sim_ef_db_lookup(unsigned short id)
return result;
}
+gboolean sim_parse_3G_get_response(unsigned char *data, int len,
+ int *file_len, int *record_len,
+ int *structure, unsigned char *access,
+ unsigned short *efid)
+{
+ const unsigned char *fcp;
+ int fcp_length;
+ const unsigned char *tlv;
+ int tlv_length;
+ int i;
+ int flen, rlen, str;
+ unsigned short id;
+ unsigned char acc[3];
+ struct sim_ef_info *info;
+
+ fcp = ber_tlv_find_by_tag(data, 0x62, len, &fcp_length);
+
+ if (fcp == NULL)
+ return FALSE;
+
+ /* Find the file size tag 0x80 according to
+ * ETSI 102.221 Section 11.1.1.3.2 */
+ tlv = ber_tlv_find_by_tag(fcp, 0x80, fcp_length, &tlv_length);
+
+ if (!tlv || tlv_length < 2)
+ return FALSE;
+
+ flen = tlv[0];
+ for (i = 1; i < tlv_length; i++)
+ flen = (flen << 8) | tlv[i];
+
+ tlv = ber_tlv_find_by_tag(fcp, 0x83, fcp_length, &tlv_length);
+
+ if (!tlv || tlv_length != 2)
+ return FALSE;
+
+ id = (tlv[0] << 8) | tlv[1];
+
+ tlv = ber_tlv_find_by_tag(fcp, 0x82, fcp_length, &tlv_length);
+
+ if (!tlv || (tlv_length != 2 && tlv_length != 5))
+ return FALSE;
+
+ if (tlv[1] != 0x21)
+ return FALSE;
+
+ switch (tlv[0] & 0x3) {
+ case 1: /* Transparent */
+ str = 0x00;
+ break;
+ case 2: /* Linear Fixed */
+ str = 0x01;
+ break;
+ case 6: /* Cyclic */
+ str = 0x03;
+ break;
+ default:
+ return FALSE;
+ };
+
+ /* For cyclic or linear fixed we need record size & num records */
+ if (str != 0x00 && tlv_length != 5)
+ return FALSE;
+
+ /* strictly speaking the record length is 16 bit, but the valid
+ * range is 0x01 to 0xFF according to 102.221 */
+ if (str != 0x00)
+ rlen = tlv[3];
+ else
+ rlen = 0;
+
+ /* The 3G response data contains references to EFarr which actually
+ * contains the security attributes. These are usually not carried
+ * along with the response data unlike in 2G. Instead of querying
+ * this, we simply look it up in our database. We fudge it somewhat
+ * and guess if the file isn't found.
+ */
+ info = sim_ef_db_lookup(id);
+
+ if (str == 0x03)
+ acc[1] = 0x1f;
+ else
+ acc[1] = 0xff;
+
+ acc[2] = 0x44;
+
+ if (!info)
+ acc[0] = 0x11;
+ else
+ acc[0] = (info->perm_read << 4) | info->perm_update;
+
+ if (file_len)
+ *file_len = flen;
+
+ if (record_len)
+ *record_len = rlen;
+
+ if (efid)
+ *efid = id;
+
+ if (structure)
+ *structure = str;
+
+ if (access)
+ memcpy(access, acc, 3);
+
+ return TRUE;
+}
+
gboolean sim_parse_2G_get_response(unsigned char *response, int len,
int *file_len, int *record_len,
int *structure, unsigned char *access)
diff --git a/src/simutil.h b/src/simutil.h
index 805ead03..843490fa 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -107,6 +107,11 @@ void sim_adn_build(unsigned char *data, int length,
struct sim_ef_info *sim_ef_db_lookup(unsigned short efid);
+gboolean sim_parse_3G_get_response(unsigned char *data, int len,
+ int *file_len, int *record_len,
+ int *structure, unsigned char *access,
+ unsigned short *efid);
+
gboolean sim_parse_2G_get_response(unsigned char *response, int len,
int *file_len, int *record_len,
int *structure, unsigned char *access);