Compare commits

...

21 Commits

Author SHA1 Message Date
Slava Monich
edd91c94eb Merge branch 'auth' into 'master'
Implement org.ofono.SimAuthentication interface

See merge request mer-core/ofono!283
2021-06-02 14:15:27 +00:00
Slava Monich
af0ab142e1 [ril] Implement org.ofono.SimAuthentication interface. JB#54048 2021-06-01 02:12:35 +03:00
Slava Monich
dffc04d404 [sim-auth] Support short AIDs. JB#54048
They can be shorter than 16 bytes.
2021-06-01 02:11:36 +03:00
Slava Monich
97b5fcbd87 [sim-auth] Parse auth response according to TS 31.102 2021-05-30 14:09:32 +03:00
Slava Monich
d7e740347f [sim-auth] Fill unused part of AID with FFs 2021-05-30 14:09:32 +03:00
Slava Monich
1116ca2481 [ril] Append ROOTMF path by default
Empty path never works and some RILs/modems don't like it so much
that it causes a reset.
2021-05-30 14:01:02 +03:00
Slava Monich
4ad02792db Merge branch 'omp-jb54420' into 'master'
[ril] Use ofono_sim_read_path() in case of reading EFpbr from USIM. Fixes JB#54420

See merge request mer-core/ofono!282
2021-05-25 23:50:07 +00:00
Bogdan Migunov
eddcb88af4 [ril] Use ofono_sim_read_path() in case of reading EFpbr from USIM. Fixes JB#54420
There is an issue when some of the Mediatek modems do not accept empty
path to the EFpbr file on the USIM and do reset themselves.
This fix appends usim_path to the GET DATA command when it comes to
exporting phonebook from SIM card and prevents crashes like described
one.
2021-05-25 19:18:57 +03:00
Denis Kenzior
f91df7f0fd simutil: Fix EF structure bit processing
The intent here was to find the contents of the 3 low order bits
according to Table 11-5 in ETSI 102.221.  However, the mask ended up
only grabbing the contents of the 2 low order bits.
2021-05-03 16:59:02 +03:00
Slava Monich
9d220ff9be [sim-auth] Only close open sessions
Session has to be open in order to have a valid session_id
2021-04-26 02:51:15 +03:00
Slava Monich
deefa2c454 [sim-auth] Remove watch if open_channel fails
Otherwise open_channel won't be called again after a failure.
2021-04-26 02:51:15 +03:00
Slava Monich
80224b283d Merge branch 'pcscf' into 'master'
Keep track of P-CSCF address

See merge request mer-core/ofono!281
2021-04-23 12:53:54 +00:00
Slava Monich
07e07b6ddc [ril] Keep track of P-CSCF address. JB#48905
And use IMS data profile for IMS data calls.
2021-04-23 15:14:36 +03:00
Slava Monich
bd836b4499 Merge branch 'misc' into 'master'
Miscellaneous mobile data issues

See merge request mer-core/ofono!280
2021-04-23 12:12:42 +00:00
Slava Monich
6c289b1432 [ril] Do not submit RIL_REQUEST_ALLOW_DATA if it's disabled 2021-04-16 03:13:16 +03:00
Slava Monich
296e46487f [ril] Cancel RIL_REQUEST_ALLOW_DATA when SIM is removed 2021-04-15 20:19:21 +03:00
Slava Monich
09e98234aa [ril] Tweaked network state polling logic
grilio_channel_retry_request() returns FALSE if the request is pending,
i.e. has been submitted but there was no reply yet. In that case, in
order to retry right away, we need to cancel the already submitted
request (and ignore the reply when it arrives) and resubmit a fresh
new one.
2021-04-15 19:40:32 +03:00
Slava Monich
0f4cdba932 [ril] Documented umtsNetworkMode parameter 2021-04-02 20:59:52 +03:00
Slava Monich
870bac93e9 Merge branch 'jb53576' into 'master'
Sumbit a pending request from the DBus queue

See merge request mer-core/ofono!279
2021-03-17 14:58:19 +00:00
Denis Grigorev
246cd4e1d2 [unit] Fix the test for __ofono_dbus_queue_reply_all_error. JB#53576 2021-03-17 16:09:19 +03:00
Denis Grigorev
ca20b65098 [ofono] Sumbit a pending request from the DBus queue. JB#53576
Currently, the DBus queue stops working after an asynchronous request
has been completed while another request is pending. This commit adds
__ofono_dbus_queue_submit_next(), which fires a pending request after
the previous one completes.
2021-03-17 15:51:21 +03:00
18 changed files with 875 additions and 224 deletions

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2016-2021 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -243,6 +243,7 @@ struct ril_data_call *ril_data_call_dup(const struct ril_data_call *call)
dc->dnses = g_strdupv(call->dnses);
dc->gateways = g_strdupv(call->gateways);
dc->addresses = g_strdupv(call->addresses);
dc->pcscf = g_strdupv(call->pcscf);
return dc;
} else {
return NULL;
@@ -253,8 +254,9 @@ static void ril_data_call_destroy(struct ril_data_call *call)
{
g_free(call->ifname);
g_strfreev(call->dnses);
g_strfreev(call->addresses);
g_strfreev(call->gateways);
g_strfreev(call->addresses);
g_strfreev(call->pcscf);
}
void ril_data_call_free(struct ril_data_call *call)
@@ -322,8 +324,7 @@ static gboolean ril_data_call_parse_default(struct ril_data_call *call,
/* RIL_Data_Call_Response_v9 */
if (version >= 9) {
/* PCSCF */
grilio_parser_skip_string(rilp);
call->pcscf = grilio_parser_split_utf8(rilp, " ");
/* RIL_Data_Call_Response_v11 */
if (version >= 11) {
@@ -354,16 +355,19 @@ static struct ril_data_call *ril_data_call_parse(struct ril_vendor *vendor,
if (parsed) {
DBG("[status=%d,retry=%d,cid=%d,active=%d,type=%s,ifname=%s,"
"mtu=%d,address=%s,dns=%s %s,gateways=%s]",
"mtu=%d,address=%s,dns=%s %s,gateways=%s,pcscf=%s %s]",
call->status, call->retry_time,
call->cid, call->active,
ril_protocol_from_ofono(call->prot),
call->ifname, call->mtu,
call->addresses ? call->addresses[0] : NULL,
call->dnses ? call->dnses[0] : NULL,
call->addresses ? call->addresses[0] : "",
call->dnses ? call->dnses[0] : "",
(call->dnses && call->dnses[0] &&
call->dnses[1]) ? call->dnses[1] : "",
call->gateways ? call->gateways[0] : NULL);
call->gateways ? call->gateways[0] : "",
call->pcscf ? call->pcscf[0] : "",
(call->pcscf && call->pcscf[0] &&
call->pcscf[1]) ? call->pcscf[1] : "");
return call;
} else {
ril_data_call_free(call);
@@ -429,7 +433,8 @@ static gboolean ril_data_call_equal(const struct ril_data_call *c1,
!g_strcmp0(c1->ifname, c2->ifname) &&
gutil_strv_equal(c1->dnses, c2->dnses) &&
gutil_strv_equal(c1->gateways, c2->gateways) &&
gutil_strv_equal(c1->addresses, c2->addresses);
gutil_strv_equal(c1->addresses, c2->addresses) &&
gutil_strv_equal(c1->pcscf, c2->pcscf);
} else {
return FALSE;
}
@@ -951,7 +956,8 @@ static gboolean ril_data_call_setup_submit(struct ril_data_request *req)
*
* Makes little sense but it is what it is.
*/
tech = priv->network->data.ril_tech;
tech = (setup->profile_id == RIL_DATA_PROFILE_IMS) ?
RADIO_TECH_LTE : priv->network->data.ril_tech;
if (tech > 2) {
tech += 2;
} else {
@@ -1014,10 +1020,22 @@ static struct ril_data_request *ril_data_call_setup_new(struct ril_data *data,
g_new0(struct ril_data_request_setup, 1);
struct ril_data_request *req = &setup->req;
setup->profile_id = (priv->use_data_profiles &&
context_type == OFONO_GPRS_CONTEXT_TYPE_MMS) ?
priv->mms_data_profile_id :
RIL_DATA_PROFILE_DEFAULT;
setup->profile_id = RIL_DATA_PROFILE_DEFAULT;
if (priv->use_data_profiles) {
switch (context_type) {
case OFONO_GPRS_CONTEXT_TYPE_MMS:
setup->profile_id = priv->mms_data_profile_id;
break;
case OFONO_GPRS_CONTEXT_TYPE_IMS:
setup->profile_id = RIL_DATA_PROFILE_IMS;
break;
case OFONO_GPRS_CONTEXT_TYPE_ANY:
case OFONO_GPRS_CONTEXT_TYPE_INTERNET:
case OFONO_GPRS_CONTEXT_TYPE_WAP:
break;
}
}
setup->apn = g_strdup(ctx->apn);
setup->username = g_strdup(ctx->username);
setup->password = g_strdup(ctx->password);
@@ -1196,6 +1214,31 @@ static struct ril_data_request *ril_data_allow_new(struct ril_data *data,
return req;
}
static gboolean ril_data_allow_can_submit(struct ril_data *self)
{
if (self) {
switch (self->priv->options.allow_data) {
case RIL_ALLOW_DATA_ENABLED:
return TRUE;
case RIL_ALLOW_DATA_DISABLED:
case RIL_ALLOW_DATA_AUTO:
break;
}
}
return FALSE;
}
static gboolean ril_data_allow_submit_request(struct ril_data *data,
gboolean allow)
{
if (ril_data_allow_can_submit(data)) {
ril_data_request_queue(ril_data_allow_new(data, allow));
return TRUE;
} else {
return FALSE;
}
}
/*==========================================================================*
* ril_data
*==========================================================================*/
@@ -1226,6 +1269,22 @@ void ril_data_remove_handler(struct ril_data *self, gulong id)
}
}
static void ril_data_imsi_changed(struct ril_sim_settings *settings,
void *user_data)
{
struct ril_data *self = RIL_DATA(user_data);
struct ril_data_priv *priv = self->priv;
if (!settings->imsi) {
/*
* Most likely, SIM removal. In any case, no data requests
* make sense when IMSI is unavailable.
*/
ril_data_cancel_all_requests(self);
}
ril_data_manager_check_network_mode(priv->dm);
}
static void ril_data_settings_changed(struct ril_sim_settings *settings,
void *user_data)
{
@@ -1308,7 +1367,7 @@ struct ril_data *ril_data_new(struct ril_data_manager *dm, const char *name,
priv->settings_event_id[SETTINGS_EVENT_IMSI_CHANGED] =
ril_sim_settings_add_imsi_changed_handler(settings,
ril_data_settings_changed, self);
ril_data_imsi_changed, self);
priv->settings_event_id[SETTINGS_EVENT_PREF_MODE] =
ril_sim_settings_add_pref_mode_changed_handler(settings,
ril_data_settings_changed, self);
@@ -1466,10 +1525,8 @@ static void ril_data_disallow(struct ril_data *self)
*/
ril_data_deactivate_all(self);
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
/* Tell rild that the data is now disabled */
ril_data_request_queue(ril_data_allow_new(self, FALSE));
} else {
/* Tell rild that the data is now disabled */
if (!ril_data_allow_submit_request(self, FALSE)) {
priv->flags &= ~RIL_DATA_FLAG_ON;
GASSERT(!ril_data_allowed(self));
DBG_(self, "data off");
@@ -1779,12 +1836,14 @@ static void ril_data_manager_check_network_mode(struct ril_data_manager *self)
static struct ril_data *ril_data_manager_allowed(struct ril_data_manager *self)
{
GSList *l;
if (self) {
GSList *l;
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
return data;
for (l= self->data_list; l; l = l->next) {
struct ril_data *data = l->data;
if (data->priv->flags & RIL_DATA_FLAG_ALLOWED) {
return data;
}
}
}
@@ -1804,9 +1863,7 @@ static void ril_data_manager_switch_data_on(struct ril_data_manager *self,
ril_data_max_mode(data), TRUE);
}
if (priv->options.allow_data == RIL_ALLOW_DATA_ENABLED) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
} else {
if (!ril_data_allow_submit_request(data, TRUE)) {
priv->flags |= RIL_DATA_FLAG_ON;
GASSERT(ril_data_allowed(data));
DBG_(data, "data on");
@@ -1830,12 +1887,7 @@ void ril_data_manager_check_data(struct ril_data_manager *self)
void ril_data_manager_assert_data_on(struct ril_data_manager *self)
{
if (self) {
struct ril_data *data = ril_data_manager_allowed(self);
if (data) {
ril_data_request_queue(ril_data_allow_new(data, TRUE));
}
}
ril_data_allow_submit_request(ril_data_manager_allowed(self), TRUE);
}
/*

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2016-2020 Jolla Ltd.
* Copyright (C) 2016-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -40,6 +40,7 @@ struct ril_data_call {
char **dnses;
char **gateways;
char **addresses;
char **pcscf;
};
struct ril_data_call_list {

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -340,6 +340,7 @@ static void ril_modem_post_sim(struct ofono_modem *modem)
if (md->modem.config.enable_cbs) {
ofono_cbs_create(modem, 0, RILMODEM_DRIVER, md);
}
ofono_sim_auth_create(modem);
}
static void ril_modem_post_online(struct ofono_modem *modem)

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2020 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019-2020 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -444,14 +444,13 @@ static guint ril_network_poll_and_retry(struct ril_network *self, guint id,
{
struct ril_network_priv *priv = self->priv;
if (id) {
/* Retry right away, don't wait for retry timeout to expire */
grilio_channel_retry_request(priv->io, id);
} else {
/* Don't wait for retry timeout to expire */
if (!id || !grilio_channel_retry_request(priv->io, id)) {
GRilIoRequest *req = grilio_request_new();
grilio_request_set_retry(req, RIL_RETRY_SECS*1000, -1);
grilio_request_set_retry_func(req, ril_network_retry);
grilio_queue_cancel_request(priv->q, id, FALSE);
id = grilio_queue_send_request_full(priv->q, req, code, fn,
NULL, self);
grilio_request_unref(req);
@@ -697,7 +696,7 @@ struct ril_network_data_profile *ril_network_data_profile_new
ptr += G_ALIGN8(sizeof(*profile));
profile->profile_id = profile_id;
profile->type = RIL_PROFILE_3GPP;
profile->type = RIL_PROFILE_COMMON;
profile->auth_method = auth_method;
profile->proto = context->proto;
profile->enabled = TRUE;
@@ -826,6 +825,9 @@ static void ril_network_check_data_profiles(struct ril_network *self)
const struct ofono_gprs_primary_context* mms =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_MMS);
const struct ofono_gprs_primary_context* ims =
ofono_gprs_context_settings_by_type(gprs,
OFONO_GPRS_CONTEXT_TYPE_IMS);
GSList *l = NULL;
if (internet) {
@@ -841,6 +843,12 @@ static void ril_network_check_data_profiles(struct ril_network *self)
ril_network_data_profile_new(mms,
priv->mms_data_profile_id));
}
if (ims) {
DBG_(self, "ims apn \"%s\"", ims->apn);
l = g_slist_append(l,
ril_network_data_profile_new(ims,
RIL_DATA_PROFILE_IMS));
}
if (ril_network_data_profiles_equal(priv->data_profiles, l)) {
ril_network_data_profiles_free(l);

View File

@@ -998,8 +998,9 @@ static void ril_export_entries(struct ofono_phonebook *pb,
pbd->df_path = usim_path;
pbd->df_size = sizeof(usim_path);
ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
ofono_sim_read_path(pbd->sim_context, SIM_EFPBR_FILEID,
OFONO_SIM_FILE_STRUCTURE_FIXED,
pbd->df_path, pbd->df_size,
pb_reference_data_cb, pb);
}

View File

@@ -1,7 +1,7 @@
/*
* oFono - Open Source Telephony - RIL-based devices
*
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,6 +20,8 @@
#include <ofono/watch.h>
#include <gutil_misc.h>
#include "simutil.h"
#include "util.h"
#include "ofono.h"
@@ -86,6 +88,7 @@ struct ril_sim {
gboolean empty_pin_query_allowed;
gboolean inserted;
guint idle_id; /* Used by register and SIM reset callbacks */
guint list_apps_id;
gulong card_event_id[SIM_CARD_EVENT_COUNT];
gulong io_event_id[IO_EVENT_COUNT];
guint query_pin_retries_id;
@@ -118,12 +121,25 @@ struct ril_sim_cbd_io {
ofono_sim_write_cb_t write;
ofono_sim_imsi_cb_t imsi;
ofono_query_facility_lock_cb_t query_facility_lock;
ofono_sim_open_channel_cb_t open_channel;
ofono_sim_close_channel_cb_t close_channel;
gpointer ptr;
} cb;
gpointer data;
guint req_id;
};
struct ril_sim_session_cbd {
struct ril_sim *sd;
struct ril_sim_card *card;
ofono_sim_logical_access_cb_t cb;
gpointer data;
int ref_count;
int session_id;
int cla;
guint req_id;
};
struct ril_sim_pin_cbd {
struct ril_sim *sd;
ofono_sim_lock_unlock_cb_t cb;
@@ -150,6 +166,16 @@ struct ril_sim_retry_query {
GRilIoRequest *(*new_req)(struct ril_sim *sd);
};
/* TS 102.221 */
#define APP_TEMPLATE_TAG 0x61
#define APP_ID_TAG 0x4F
struct ril_sim_list_apps {
struct ril_sim *sd;
ofono_sim_list_apps_cb_t cb;
void *data;
};
static GRilIoRequest *ril_sim_empty_sim_pin_req(struct ril_sim *sd);
static GRilIoRequest *ril_sim_empty_sim_puk_req(struct ril_sim *sd);
static void ril_sim_query_retry_count_cb(GRilIoChannel *io, int status,
@@ -218,6 +244,45 @@ static void ril_sim_cbd_io_start(struct ril_sim_cbd_io *cbd, GRilIoRequest* req,
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
}
static struct ril_sim_session_cbd *ril_sim_session_cbd_new(struct ril_sim *sd,
int session_id, int cla, ofono_sim_logical_access_cb_t cb, void *data)
{
struct ril_sim_session_cbd *cbd = g_new0(struct ril_sim_session_cbd, 1);
cbd->sd = sd;
cbd->cb = cb;
cbd->data = data;
cbd->card = ril_sim_card_ref(sd->card);
cbd->session_id = session_id;
cbd->cla = cla;
cbd->ref_count = 1;
return cbd;
}
static void ril_sim_session_cbd_unref(void *data)
{
struct ril_sim_session_cbd *cbd = data;
if (--(cbd->ref_count) < 1) {
ril_sim_card_sim_io_finished(cbd->card, cbd->req_id);
ril_sim_card_unref(cbd->card);
g_free(cbd);
}
}
static void ril_sim_session_cbd_start(struct ril_sim_session_cbd *cbd,
GRilIoRequest* req, guint code, GRilIoChannelResponseFunc cb)
{
struct ril_sim *sd = cbd->sd;
const guint finished_req = cbd->req_id;
cbd->ref_count++;
cbd->req_id = grilio_queue_send_request_full(sd->q, req, code, cb,
ril_sim_session_cbd_unref, cbd);
ril_sim_card_sim_io_started(cbd->card, cbd->req_id);
ril_sim_card_sim_io_finished(cbd->card, finished_req);
}
static void ril_sim_pin_cbd_state_event_count_cb(struct ril_sim_card *sc,
void *user_data)
{
@@ -307,30 +372,13 @@ static void ril_sim_append_path(struct ril_sim *sd, GRilIoRequest *req,
grilio_request_append_utf8(req, hex_path);
DBG_(sd, "%s", hex_path);
g_free(hex_path);
} else if (fileid == SIM_EF_ICCID_FILEID || fileid == SIM_EFPL_FILEID) {
/*
* Special catch-all for EF_ICCID (unique card ID)
* and EF_PL files which exist in the root directory.
* As the sim_info_cb function may not have yet
* recorded the app_type for the SIM, and the path
* for both files is the same for 2g|3g, just hard-code.
*
* See 'struct ef_db' in:
* ../../src/simutil.c for more details.
*/
DBG_(sd, "%s", ROOTMF);
grilio_request_append_utf8(req, ROOTMF);
} else {
/*
* The only known case of this is EFPHASE_FILED (0x6FAE).
* The ef_db table ( see /src/simutil.c ) entry for
* EFPHASE contains a value of 0x0000 for it's
* 'parent3g' member. This causes a NULL path to
* be returned.
* Catch-all for EF_ICCID, EF_PL and other files absent
* from ef_db table in src/simutil.c, hard-code ROOTMF.
*/
DBG_(sd, "returning empty path.");
grilio_request_append_utf8(req, NULL);
DBG_(sd, "%s (default)", ROOTMF);
grilio_request_append_utf8(req, ROOTMF);
}
}
@@ -1422,6 +1470,294 @@ static void ril_sim_query_facility_lock(struct ofono_sim *sim,
grilio_request_unref(req);
}
static gboolean ril_sim_list_apps_cb(void *data)
{
struct ril_sim_list_apps *rd = data;
struct ril_sim *sd = rd->sd;
const struct ril_sim_card_status *status = sd->card->status;
struct ofono_error error;
GASSERT(sd->list_apps_id);
sd->list_apps_id = 0;
if (status) {
int i, n = status->num_apps;
GByteArray *tlv = g_byte_array_sized_new(n * 20);
/* Reconstruct EFdir contents */
for (i = 0; i < n; i++) {
const char *hex = status->apps[i].aid;
gsize hex_len = hex ? strlen(hex) : 0;
long aid_size;
guint8 aid[16];
if (hex_len >= 2 && hex_len <= 2 * sizeof(aid) &&
!(hex_len & 0x01) && decode_hex_own_buf(hex,
hex_len, &aid_size, 0, aid)) {
guint8 buf[4];
/*
* TS 102.221
* 13 Application independent files
* 13.1 EFdir
*
* Application template TLV object.
*/
buf[0] = APP_TEMPLATE_TAG;
buf[1] = (guint8)(aid_size + 2);
buf[2] = APP_ID_TAG;
buf[3] = (guint8)(aid_size);
g_byte_array_append(tlv, buf, sizeof(buf));
g_byte_array_append(tlv, aid, aid_size);
}
}
DBG_(sd, "reporting %u apps %u bytes", n, tlv->len);
rd->cb(ril_error_ok(&error), tlv->data, tlv->len, rd->data);
g_byte_array_unref(tlv);
} else {
DBG_(sd, "no SIM card, no apps");
rd->cb(ril_error_failure(&error), NULL, 0, rd->data);
}
return G_SOURCE_REMOVE;
}
static void ril_sim_list_apps(struct ofono_sim *sim,
ofono_sim_list_apps_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_list_apps *rd = g_new(struct ril_sim_list_apps, 1);
rd->sd = sd;
rd->cb = cb;
rd->data = data;
if (sd->list_apps_id) {
g_source_remove(sd->list_apps_id);
}
sd->list_apps_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
ril_sim_list_apps_cb, rd, g_free);
}
static void ril_sim_open_channel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_cbd_io *cbd = user_data;
ofono_sim_open_channel_cb_t cb = cbd->cb.open_channel;
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
guint32 n, session_id;
GRilIoParser rilp;
grilio_parser_init(&rilp, data, len);
if (grilio_parser_get_uint32(&rilp, &n) && n >= 1 &&
grilio_parser_get_uint32(&rilp, &session_id)) {
DBG_(cbd->sd, "%u", session_id);
cb(ril_error_ok(&error), session_id, cbd->data);
return;
}
} else {
ofono_error("Open logical channel failure: %s",
ril_error_to_string(status));
}
cb(ril_error_failure(&error), 0, cbd->data);
}
static void ril_sim_open_channel(struct ofono_sim *sim,
const unsigned char *aid, unsigned int len,
ofono_sim_open_channel_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
GRilIoRequest *req = grilio_request_new();
char *aid_hex = encode_hex(aid, len, 0);
DBG_(sd, "%s", aid_hex);
grilio_request_append_utf8(req, aid_hex);
grilio_request_append_int32(req, 0);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_OPEN_CHANNEL,
ril_sim_open_channel_cb);
grilio_request_unref(req);
g_free(aid_hex);
}
static void ril_sim_close_channel_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_cbd_io *cbd = user_data;
struct ofono_error error;
if (status == RIL_E_SUCCESS) {
ril_error_init_ok(&error);
} else {
ofono_error("Close logical channel failure: %s",
ril_error_to_string(status));
ril_error_init_failure(&error);
}
cbd->cb.close_channel(&error, cbd->data);
}
static void ril_sim_close_channel(struct ofono_sim *sim, int session_id,
ofono_sim_close_channel_cb_t cb, void *data)
{
struct ril_sim *sd = ril_sim_get_data(sim);
struct ril_sim_cbd_io *cbd = ril_sim_cbd_io_new(sd, cb, data);
GRilIoRequest *req = grilio_request_new();
DBG_(sd, "%u", session_id);
grilio_request_append_int32(req, 1);
grilio_request_append_int32(req, session_id);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_cbd_io_start(cbd, req, RIL_REQUEST_SIM_CLOSE_CHANNEL,
ril_sim_close_channel_cb);
grilio_request_unref(req);
}
static void ril_sim_logical_access_get_results_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_session_cbd *cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ril_sim_io_response *res;
struct ofono_error err;
res = ril_sim_parse_io_response(data, len);
if (ril_sim_io_response_ok(res) && status == RIL_E_SUCCESS) {
cb(ril_error_ok(&err), res->data, res->data_len, cbd->data);
} else if (res) {
cb(ril_error_sim(&err, res->sw1, res->sw2), NULL, 0, cbd->data);
} else {
cb(ril_error_failure(&err), NULL, 0, cbd->data);
}
ril_sim_io_response_free(res);
}
static void ril_sim_logical_access_transmit(struct ril_sim_session_cbd *cbd,
int ins, int p1, int p2, int p3, const char *hex_data,
GRilIoChannelResponseFunc cb)
{
GRilIoRequest *req = grilio_request_new();
DBG_(cbd->sd, "session=%u,cmd=%02X,%02X,%02X,%02X,%02X,%s",
cbd->session_id, cbd->cla, ins, p1, p2, p3,
hex_data ? hex_data : "");
grilio_request_append_int32(req, cbd->session_id);
grilio_request_append_int32(req, cbd->cla);
grilio_request_append_int32(req, ins);
grilio_request_append_int32(req, p1);
grilio_request_append_int32(req, p2);
grilio_request_append_int32(req, p3);
grilio_request_append_utf8(req, hex_data);
grilio_request_set_timeout(req, SIM_IO_TIMEOUT_SECS * 1000);
ril_sim_session_cbd_start(cbd, req,
RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, cb);
grilio_request_unref(req);
}
static void ril_sim_logical_access_cb(GRilIoChannel *io, int status,
const void *data, guint len, void *user_data)
{
struct ril_sim_session_cbd *cbd = user_data;
ofono_sim_logical_access_cb_t cb = cbd->cb;
struct ril_sim_io_response *res;
struct ofono_error error;
DBG_(cbd->sd, "");
cbd->req_id = 0;
res = ril_sim_parse_io_response(data, len);
if (res && status == RIL_E_SUCCESS) {
/*
* TS 102 221
* 7.3.1.1.5.2 Case 4 commands
*
* If the UICC receives a case 4 command, after processing
* the data sent with the C-APDU, it shall return:
*
* a) procedure bytes '61 xx' instructing the transport
* layer of the terminal to issue a GET RESPONSE command
* with a maximum length of 'xx'; or
* b) status indicating a warning or error condition (but
* not SW1 SW2 = '90 00').
*
* The GET RESPONSE command so issued is then treated as
* described for case 2 commands.
*/
if (res->sw1 == 0x61) {
ril_sim_logical_access_transmit(cbd,
CMD_GET_RESPONSE, 0, 0, res->sw2, NULL,
ril_sim_logical_access_get_results_cb);
} else if (ril_sim_io_response_ok(res)) {
cb(ril_error_ok(&error), res->data, res->data_len,
cbd->data);
} else {
cb(ril_error_sim(&error, res->sw1, res->sw2), NULL, 0,
cbd->data);
}
} else {
cb(ril_error_failure(&error), NULL, 0, cbd->data);
}
ril_sim_io_response_free(res);
}
static void ril_sim_logical_access(struct ofono_sim *sim, int session_id,
const unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data)
{
/* SIM Command APDU: CLA INS P1 P2 P3 Data */
struct ril_sim *sd = ril_sim_get_data(sim);
const char* hex_data;
char *tmp;
struct ril_sim_session_cbd *cbd = ril_sim_session_cbd_new(sd,
session_id, pdu[0], cb, data);
GASSERT(len >= 5);
if (len > 5) {
hex_data = tmp = encode_hex(pdu + 5, len - 5, 0);
} else {
tmp = NULL;
hex_data = "";
}
ril_sim_logical_access_transmit(cbd, pdu[1], pdu[2], pdu[3], pdu[4],
hex_data, ril_sim_logical_access_cb);
ril_sim_session_cbd_unref(cbd);
g_free(tmp);
}
static void ril_sim_session_read_binary(struct ofono_sim *sim, int session,
int fileid, int start, int length,
const unsigned char *path, unsigned int path_len,
ofono_sim_read_cb_t cb, void *data)
{
struct ofono_error error;
ofono_error("session_read_binary not implemented");
cb(ril_error_failure(&error), NULL, 0, data);
}
static void ril_sim_session_read_record(struct ofono_sim *sim, int session_id,
int fileid, int record, int length,
const unsigned char *path, unsigned int path_len,
ofono_sim_read_cb_t cb, void *data)
{
struct ofono_error error;
ofono_error("session_read_record not implemented");
cb(ril_error_failure(&error), NULL, 0, data);
}
static void ril_sim_session_read_info(struct ofono_sim *sim, int session_id,
int fileid, const unsigned char *path,
unsigned int path_len, ofono_sim_file_info_cb_t cb,
void *data)
{
struct ofono_error error;
ofono_error("session_read_info not implemented");
cb(ril_error_failure(&error), -1, -1, -1, NULL, 0, data);
}
static void ril_sim_refresh_cb(GRilIoChannel *io, guint code,
const void *data, guint len, void *user_data)
{
@@ -1503,6 +1839,9 @@ static void ril_sim_remove(struct ofono_sim *sim)
grilio_queue_cancel_all(sd->q, FALSE);
ofono_sim_set_data(sim, NULL);
if (sd->list_apps_id) {
g_source_remove(sd->list_apps_id);
}
if (sd->idle_id) {
g_source_remove(sd->idle_id);
}
@@ -1547,7 +1886,14 @@ const struct ofono_sim_driver ril_sim_driver = {
.reset_passwd = ril_sim_pin_send_puk,
.change_passwd = ril_sim_change_passwd,
.query_pin_retries = ril_sim_query_pin_retries,
.query_facility_lock = ril_sim_query_facility_lock
.query_facility_lock = ril_sim_query_facility_lock,
.list_apps = ril_sim_list_apps,
.open_channel2 = ril_sim_open_channel,
.close_channel = ril_sim_close_channel,
.session_read_binary = ril_sim_session_read_binary,
.session_read_record = ril_sim_session_read_record,
.session_read_info = ril_sim_session_read_info,
.logical_access = ril_sim_logical_access
};
/*

View File

@@ -231,6 +231,12 @@ socket=/dev/socket/rild
#
#lteNetworkMode=9
# UMTS network mode.
#
# Default 3 (PREF_NET_TYPE_GSM_WCDMA_AUTO)
#
#umtsNetworkMode=3
# Timeout for RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, in milliseconds.
#
# Default 20000 (20 seconds)

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -210,6 +211,10 @@ struct ofono_sim_driver {
void (*logical_access)(struct ofono_sim *sim, int session_id,
const unsigned char *pdu, unsigned int len,
ofono_sim_logical_access_cb_t cb, void *data);
/* Since mer/1.23+git28 */
void (*open_channel2)(struct ofono_sim *sim, const unsigned char *aid,
unsigned int len, ofono_sim_open_channel_cb_t cb,
void *data);
};
int ofono_sim_driver_register(const struct ofono_sim_driver *d);

View File

@@ -121,6 +121,30 @@ void __ofono_dbus_queue_request(struct ofono_dbus_queue *q,
}
}
static void __ofono_dbus_queue_submit_next(struct ofono_dbus_queue *q)
{
struct ofono_dbus_queue_request *next = q->requests;
while (next) {
struct ofono_dbus_queue_request *done;
DBusMessage *reply = next->fn(next->msg, next->data);
/* The request has been sent, no reply yet */
if (!reply)
break;
/* The request has completed synchronously */
done = next;
next = done->next;
q->requests = next;
done->next = NULL;
/* Send the reply */
__ofono_dbus_pending_reply(&done->msg, reply);
__ofono_dbus_queue_req_free(done);
}
}
/* Consumes one reference to the reply */
void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
DBusMessage *reply)
@@ -150,20 +174,7 @@ void __ofono_dbus_queue_reply_msg(struct ofono_dbus_queue *q,
__ofono_dbus_queue_req_free(done);
/* Submit the next request if there is any */
while (next && reply) {
reply = next->fn(next->msg, next->data);
if (reply) {
/* The request has completed synchronously */
done = next;
next = done->next;
q->requests = next;
done->next = NULL;
/* Send the reply */
__ofono_dbus_pending_reply(&done->msg, reply);
__ofono_dbus_queue_req_free(done);
}
}
__ofono_dbus_queue_submit_next(q);
}
void __ofono_dbus_queue_reply_ok(struct ofono_dbus_queue *q)
@@ -250,8 +261,10 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
* Find all other requests with the same handler and the same data
* and complete those too (except when the handler is NULL)
*/
if (!handler)
if (!handler) {
__ofono_dbus_queue_submit_next(q);
return;
}
prev = NULL;
req = q->requests;
@@ -274,6 +287,7 @@ void __ofono_dbus_queue_reply_all_fn_param(struct ofono_dbus_queue *q,
req = next;
}
__ofono_dbus_queue_submit_next(q);
}
/*

View File

@@ -3,7 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2019 Jolla Ltd.
* Copyright (C) 2015-2021 Jolla Ltd.
* Copyright (C) 2019 Open Mobile Platform LLC.
*
* This program is free software; you can redistribute it and/or modify
@@ -388,6 +388,7 @@ unsigned short __ofono_sms_get_next_ref(struct ofono_sms *sms);
#include <ofono/sim.h>
struct sim_aid;
struct ofono_sim_aid_session;
enum sim_app_type;
@@ -426,7 +427,7 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
unsigned int id);
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
struct ofono_sim *sim, unsigned char *aid);
struct ofono_sim *sim, const struct sim_aid *aid);
struct ofono_sim_aid_session *__ofono_sim_get_session_by_type(
struct ofono_sim *sim, enum sim_app_type type);
@@ -436,7 +437,7 @@ int __ofono_sim_session_get_id(struct ofono_sim_aid_session *session);
enum sim_app_type __ofono_sim_session_get_type(
struct ofono_sim_aid_session *session);
unsigned char *__ofono_sim_session_get_aid(
const struct sim_aid *__ofono_sim_session_get_aid(
struct ofono_sim_aid_session *session);
const char *__ofono_sim_get_impi(struct ofono_sim *sim);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -62,7 +63,7 @@ struct auth_request {
};
struct aid_object {
uint8_t aid[16];
struct sim_aid aid;
char *path;
enum sim_app_type type;
};
@@ -82,7 +83,7 @@ struct ofono_sim_auth {
/*
* Find an application by path. 'path' should be a DBusMessage object path.
*/
static uint8_t *find_aid_by_path(GSList *aid_objects,
static const struct aid_object *find_aid_by_path(GSList *aid_objects,
const char *path)
{
GSList *iter = aid_objects;
@@ -91,7 +92,7 @@ static uint8_t *find_aid_by_path(GSList *aid_objects,
struct aid_object *obj = iter->data;
if (!strcmp(path, obj->path))
return obj->aid;
return obj;
iter = g_slist_next(iter);
}
@@ -208,14 +209,10 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
DBusMessage *reply = NULL;
DBusMessageIter iter;
DBusMessageIter dict;
const uint8_t *res = NULL;
const uint8_t *ck = NULL;
const uint8_t *ik = NULL;
const uint8_t *auts = NULL;
const uint8_t *kc = NULL;
struct data_block res, ck, ik, auts, sres, kc;
if (!sim_parse_umts_authenticate(resp, len, &res, &ck, &ik,
&auts, &kc))
&auts, &sres, &kc))
goto umts_end;
reply = dbus_message_new_method_return(sa->pending->msg);
@@ -225,15 +222,23 @@ static void handle_umts(struct ofono_sim_auth *sa, const uint8_t *resp,
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
"{say}", &dict);
if (auts) {
append_dict_byte_array(&dict, "AUTS", auts, 14);
} else {
append_dict_byte_array(&dict, "RES", res, 8);
append_dict_byte_array(&dict, "CK", ck, 16);
append_dict_byte_array(&dict, "IK", ik, 16);
if (kc)
append_dict_byte_array(&dict, "Kc", kc, 8);
}
if (auts.data)
append_dict_byte_array(&dict, "AUTS", auts.data, auts.len);
if (sres.data)
append_dict_byte_array(&dict, "SRES", sres.data, sres.len);
if (res.data)
append_dict_byte_array(&dict, "RES", res.data, res.len);
if (ck.data)
append_dict_byte_array(&dict, "CK", ck.data, ck.len);
if (ik.data)
append_dict_byte_array(&dict, "IK", ik.data, ik.len);
if (kc.data)
append_dict_byte_array(&dict, "Kc", kc.data, kc.len);
dbus_message_iter_close_container(&iter, &dict);
@@ -368,6 +373,8 @@ static void get_session_cb(ofono_bool_t active, int session_id,
error:
__ofono_dbus_pending_reply(&sa->pending->msg,
__ofono_error_failed(sa->pending->msg));
__ofono_sim_remove_session_watch(sa->pending->session,
sa->pending->watch_id);
g_free(sa->pending);
sa->pending = NULL;
}
@@ -378,7 +385,7 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
struct ofono_sim_auth *sa = data;
DBusMessageIter iter;
DBusMessageIter array;
uint8_t *aid;
const struct aid_object *obj;
if (sa->pending)
return __ofono_error_busy(msg);
@@ -418,13 +425,20 @@ static DBusMessage *usim_gsm_authenticate(DBusConnection *conn,
/*
* retrieve session from SIM
*/
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
&obj->aid);
sa->pending->msg = dbus_message_ref(msg);
sa->pending->watch_id = __ofono_sim_add_session_watch(
sa->pending->session, get_session_cb, sa, NULL);
return NULL;
if (!sa->pending->watch_id) {
g_free(sa->pending);
sa->pending = NULL;
return __ofono_error_not_supported(msg);
}
return NULL;
format_error:
g_free(sa->pending);
@@ -440,7 +454,7 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
uint32_t rlen;
uint32_t alen;
struct ofono_sim_auth *sa = data;
uint8_t *aid;
const struct aid_object *obj;
if (sa->pending)
return __ofono_error_busy(msg);
@@ -465,12 +479,18 @@ static DBusMessage *umts_common(DBusConnection *conn, DBusMessage *msg,
/*
* retrieve session from SIM
*/
aid = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim, aid);
obj = find_aid_by_path(sa->aid_objects, dbus_message_get_path(msg));
sa->pending->session = __ofono_sim_get_session_by_aid(sa->sim,
&obj->aid);
sa->pending->watch_id = __ofono_sim_add_session_watch(
sa->pending->session, get_session_cb, sa, NULL);
if (!sa->pending->watch_id) {
g_free(sa->pending);
sa->pending = NULL;
return __ofono_error_not_supported(msg);
}
return NULL;
}
@@ -700,14 +720,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
ret = sprintf(new->path, "%s/", path);
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
new->path + ret);
g_dbus_register_interface(conn, new->path,
OFONO_USIM_APPLICATION_INTERFACE,
sim_auth_usim_app, NULL, NULL,
sa, NULL);
memcpy(new->aid, r->aid, 16);
new->aid = r->aid;
break;
case SIM_APP_TYPE_ISIM:
@@ -715,14 +736,15 @@ static void sim_auth_register(struct ofono_sim_auth *sa)
ret = sprintf(new->path, "%s/", path);
encode_hex_own_buf(r->aid, 16, 0, new->path + ret);
encode_hex_own_buf(r->aid.aid, r->aid.len, 0,
new->path + ret);
g_dbus_register_interface(conn, new->path,
OFONO_ISIM_APPLICATION_INTERFACE,
sim_auth_isim_app, NULL, NULL,
sa, NULL);
memcpy(new->aid, r->aid, 16);
new->aid = r->aid;
break;
default:

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -2441,7 +2442,7 @@ struct ofono_sim_context *ofono_sim_context_create_isim(
if (session->record->type == SIM_APP_TYPE_ISIM) {
return sim_fs_context_new_with_aid(sim->simfs_isim,
session->record->aid);
&session->record->aid);
}
iter = g_slist_next(iter);
@@ -3667,6 +3668,26 @@ const char *__ofono_sim_get_impi(struct ofono_sim *sim)
static void open_channel_cb(const struct ofono_error *error, int session_id,
void *data);
static gboolean open_channel(struct ofono_sim_aid_session *session)
{
struct ofono_sim *sim = session->sim;
const struct ofono_sim_driver *driver = sim->driver;
const struct sim_aid *aid = &session->record->aid;
if (driver->open_channel2) {
driver->open_channel2(sim, aid->aid, aid->len, open_channel_cb,
session);
return TRUE;
}
if (driver->open_channel && aid->len == 16) {
driver->open_channel(sim, aid->aid, open_channel_cb, session);
return TRUE;
}
return FALSE;
}
static void close_channel_cb(const struct ofono_error *error, void *data)
{
struct ofono_sim_aid_session *session = data;
@@ -3680,10 +3701,8 @@ static void close_channel_cb(const struct ofono_error *error, void *data)
* An atom requested to open during a close, we can re-open
* here.
*/
session->sim->driver->open_channel(session->sim,
session->record->aid, open_channel_cb,
session);
return;
if (open_channel(session))
return;
}
session->state = SESSION_STATE_INACTIVE;
@@ -3758,10 +3777,12 @@ unsigned int __ofono_sim_add_session_watch(
* If the session is inactive and there are no watchers, open
* a new session.
*/
session->state = SESSION_STATE_OPENING;
session->sim->driver->open_channel(session->sim,
session->record->aid, open_channel_cb,
session);
if (open_channel(session)) {
session->state = SESSION_STATE_OPENING;
} else {
g_free(item);
return 0;
}
} else if (session->state == SESSION_STATE_OPEN) {
/*
* Session is already open and available, just call the
@@ -3784,7 +3805,8 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
{
__ofono_watchlist_remove_item(session->watches, id);
if (g_slist_length(session->watches->items) == 0) {
if (g_slist_length(session->watches->items) == 0 &&
session->state == SESSION_STATE_OPEN) {
/* last watcher, close session */
session->state = SESSION_STATE_CLOSING;
session->sim->driver->close_channel(session->sim,
@@ -3793,14 +3815,15 @@ void __ofono_sim_remove_session_watch(struct ofono_sim_aid_session *session,
}
struct ofono_sim_aid_session *__ofono_sim_get_session_by_aid(
struct ofono_sim *sim, unsigned char *aid)
struct ofono_sim *sim, const struct sim_aid *aid)
{
GSList *iter = sim->aid_sessions;
while (iter) {
struct ofono_sim_aid_session *session = iter->data;
if (!memcmp(session->record->aid, aid, 16))
if (session->record->aid.len == aid->len &&
!memcmp(session->record->aid.aid, aid, aid->len))
return session;
iter = g_slist_next(iter);
@@ -3837,10 +3860,10 @@ enum sim_app_type __ofono_sim_session_get_type(
return session->record->type;
}
unsigned char *__ofono_sim_session_get_aid(
const struct sim_aid *__ofono_sim_session_get_aid(
struct ofono_sim_aid_session *session)
{
return session->record->aid;
return &session->record->aid;
}
GSList *__ofono_sim_get_aid_list(struct ofono_sim *sim)

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -164,7 +165,7 @@ struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs)
}
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
unsigned char *aid)
const struct sim_aid *aid)
{
struct ofono_sim_context *context = sim_fs_context_new(fs);

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -20,6 +21,7 @@
*/
struct sim_fs;
struct sim_aid;
typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
int total_length, int record_length,
@@ -30,7 +32,7 @@ struct sim_fs *sim_fs_new(struct ofono_sim *sim,
struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
struct ofono_sim_context *sim_fs_context_new_with_aid(struct sim_fs *fs,
unsigned char *aid);
const struct sim_aid *aid);
unsigned int sim_fs_file_watch_add(struct ofono_sim_context *context,
int id, ofono_sim_file_changed_cb_t cb,

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1419,7 +1420,7 @@ gboolean sim_parse_3g_get_response(const unsigned char *data, int len,
if (tlv[1] != 0x21)
return FALSE;
switch (tlv[0] & 0x3) {
switch (tlv[0] & 0x7) {
case 1: /* Transparent */
str = 0x00;
break;
@@ -1572,20 +1573,17 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
/* Find all the application entries */
while ((dataobj = ber_tlv_find_by_tag(buffer, 0x61, len,
&dataobj_len)) != NULL) {
struct sim_app_record app;
struct sim_app_record *app;
const unsigned char *aid, *label;
int label_len;
int label_len, aid_len;
char *app_label;
/* Find the aid (mandatory) */
aid = ber_tlv_find_by_tag(dataobj, 0x4f, dataobj_len,
&app.aid_len);
if (!aid || app.aid_len < 0x01 || app.aid_len > 0x10)
&aid_len);
if (!aid || aid_len < 0x01 || aid_len > 0x10)
goto error;
memcpy(app.aid, aid, app.aid_len);
app.type = (app.aid[5] << 8) | app.aid[6];
/* Find the label (optional) */
label = ber_tlv_find_by_tag(dataobj, 0x50, dataobj_len,
&label_len);
@@ -1594,14 +1592,21 @@ GSList *sim_parse_app_template_entries(const unsigned char *buffer, int len)
* Label field uses the extra complicated
* encoding in 102.221 Annex A
*/
app.label = sim_string_to_utf8(label, label_len);
app_label = sim_string_to_utf8(label, label_len);
if (app.label == NULL)
if (app_label == NULL)
goto error;
} else
app.label = NULL;
app_label = NULL;
ret = g_slist_prepend(ret, g_memdup(&app, sizeof(app)));
app = g_new0(struct sim_app_record, 1);
memcpy(app->aid.aid, aid, aid_len);
app->aid.len = aid_len;
app->label = app_label;
app->type = (aid[5] << 8) | aid[6];
ret = g_slist_prepend(ret, app);
len -= (dataobj - buffer) + dataobj_len;
buffer = dataobj + dataobj_len;
@@ -1667,67 +1672,135 @@ int sim_build_gsm_authenticate(unsigned char *buffer, int len,
return build_authenticate(buffer, rand, NULL);
}
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
int len, const unsigned char **res, const unsigned char **ck,
const unsigned char **ik, const unsigned char **auts,
const unsigned char **kc)
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
struct data_block *res, struct data_block *ck,
struct data_block *ik, struct data_block *auts,
struct data_block *sres, struct data_block *kc)
{
if (len < 16 || !buffer)
const unsigned char *ptr = buffer;
const unsigned char *end = ptr + len;
unsigned int l;
if (!buffer || len < 2)
return FALSE;
switch (buffer[0]) {
memset(res, 0, sizeof(*res));
memset(ck, 0, sizeof(*ck));
memset(ik, 0, sizeof(*ik));
memset(kc, 0, sizeof(*kc));
memset(auts, 0, sizeof(*auts));
memset(sres, 0, sizeof(*sres));
/*
* TS 31.102
* 7.1.2.1 GSM/3G security context
*/
switch (*ptr++) {
case 0xdb:
/* 'DB' + '08' + RES(16) + '10' + CK(32) + '10' + IK(32) = 43 */
if (len < 43)
goto umts_end;
/*
* Response parameters/data, case 1, 3G security context,
* command successful:
*
* "Successful 3G authentication" tag = 'DB'
* 'DB' + L3 + RES(L3) + L4 + CK(L4) + L5 + IK(L5) + 8 + Kc(8)
*/
l = *ptr++; /* L3 */
if ((ptr + l) > end)
return FALSE;
/* success */
if (buffer[1] != 0x08)
goto umts_end;
res->data = ptr;
res->len = l;
ptr += l;
*res = buffer + 2;
if (ptr == end)
return FALSE;
if (buffer[10] != 0x10)
goto umts_end;
l = *ptr++; /* L4 */
if ((ptr + l) > end)
return FALSE;
*ck = buffer + 11;
ck->data = ptr;
ck->len = l;
ptr += l;
if (buffer[27] != 0x10)
goto umts_end;
if (ptr == end)
return FALSE;
*ik = buffer + 28;
l = *ptr++; /* L5 */
if ((ptr + l) > end)
return FALSE;
if (len >= 53 && kc) {
if (buffer[44] != 0x08)
goto umts_end;
ik->data = ptr;
ik->len = l;
ptr += l;
*kc = buffer + 45;
} else {
*kc = NULL;
if (ptr < end) {
l = *ptr++;
if (l != 8 || (ptr + l) != end)
return FALSE;
kc->data = ptr;
kc->len = l;
ptr += l;
}
*auts = NULL;
return TRUE;
break;
case 0xdc:
/* 'DC' + '0E' + AUTS(14) = 16 */
if (len < 16)
goto umts_end;
/*
* Response parameters/data, case 2, 3G security context,
* synchronisation failure:
*
* "Synchronisation failure" tag = 'DC'
* 'DC' + L1 + AUTS(L1)
*/
l = *ptr++; /* L1 */
if ((ptr + l) > end)
return FALSE;
/* sync error */
if (buffer[1] != 0x0e)
goto umts_end;
auts->data = ptr;
auts->len = l;
ptr += l;
*auts = buffer + 2;
if (ptr != end)
return FALSE;
return TRUE;
case 0x04:
/*
* Response parameters/data, case 3, GSM security context,
* command successful:
*
* 4 + SRES(4) + 8 + Kc(8)
*/
l = 4; /* Already skipped this one */
if ((ptr + l) > end)
return FALSE;
sres->data = ptr;
sres->len = l;
ptr += l;
if (ptr == end)
return FALSE;
l = *ptr++; /* 8 */
if (l != 8 || (ptr + l) > end)
return FALSE;
kc->data = ptr;
kc->len = l;
ptr += l;
if (ptr != end)
return FALSE;
return TRUE;
break;
default:
goto umts_end;
break;
}
return TRUE;
umts_end:
return FALSE;
}

View File

@@ -314,9 +314,13 @@ struct sim_ef_info {
enum sim_file_access perm_update;
};
struct sim_app_record {
struct sim_aid {
unsigned char aid[16];
int aid_len;
unsigned int len;
};
struct sim_app_record {
struct sim_aid aid;
char *label;
enum sim_app_type type;
};
@@ -371,6 +375,11 @@ struct comprehension_tlv_builder {
struct ber_tlv_builder *parent;
};
struct data_block {
const unsigned char *data;
unsigned int len;
};
void simple_tlv_iter_init(struct simple_tlv_iter *iter,
const unsigned char *pdu, unsigned int len);
gboolean simple_tlv_iter_next(struct simple_tlv_iter *iter);
@@ -526,10 +535,10 @@ int sim_build_umts_authenticate(unsigned char *buffer, int len,
int sim_build_gsm_authenticate(unsigned char *buffer, int len,
const unsigned char *rand);
gboolean sim_parse_umts_authenticate(const unsigned char *buffer,
int len, const unsigned char **res, const unsigned char **ck,
const unsigned char **ik, const unsigned char **auts,
const unsigned char **kc);
gboolean sim_parse_umts_authenticate(const unsigned char *buffer, int len,
struct data_block *res, struct data_block *ck,
struct data_block *ik, struct data_block *auts,
struct data_block *sres, struct data_block *kc);
gboolean sim_parse_gsm_authenticate(const unsigned char *buffer, int len,
const unsigned char **sres, const unsigned char **kc);

View File

@@ -417,7 +417,7 @@ static void test_reply_last_reply(DBusPendingCall *call, void *dbus)
G_CAST(dbus, struct test_reply_data, dbus);
DBG("");
test_dbus_check_error_reply(call, TEST_ERROR_FAILED);
test_dbus_check_empty_reply(call, NULL);
g_main_loop_quit(test->dbus.loop);
}
@@ -445,6 +445,12 @@ static DBusMessage *test_reply_4(DBusMessage *msg, void *data)
return NULL;
}
static DBusMessage *test_reply_5(DBusMessage *msg, void *data)
{
DBG("");
return dbus_message_new_method_return(msg);
}
static DBusMessage *test_reply_handler(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -485,10 +491,17 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
case 6:
__ofono_dbus_queue_request(test->queue, test_reply_4,
msg, NULL);
break;
case 7:
/* Call the same method again */
__ofono_dbus_queue_request(test->queue, test_reply_4,
msg, NULL);
break;
case 7:
case 8:
/* Call the last one */
__ofono_dbus_queue_request(test->queue, test_reply_5,
msg, NULL);
/* This completes the first one, with NULL handler */
__ofono_dbus_queue_reply_all_fn_param(test->queue, NULL, NULL);
g_assert(__ofono_dbus_queue_pending(test->queue));
@@ -508,10 +521,12 @@ static DBusMessage *test_reply_handler(DBusConnection *conn,
/* This one test_reply_3 with Failed */
__ofono_dbus_queue_reply_all_error(test->queue, NULL);
/* This one test_reply_4 with NotSupported */
/* This one completes all test_reply_4 with NotSupported */
error.type = OFONO_ERROR_TYPE_ERRNO;
error.error = -EOPNOTSUPP;
__ofono_dbus_queue_reply_all_error(test->queue, &error);
/* test_reply_5 must be already completed */
g_assert(!__ofono_dbus_queue_pending(test->queue));
/* And this one does nothing */
@@ -541,7 +556,8 @@ static void test_reply_start(struct test_dbus_context *dbus)
test_client_call(dbus, 4, test_dbus_expect_empty_reply);
test_client_call(dbus, 5, test_expect_failed);
test_client_call(dbus, 6, test_expect_not_supported);
test_client_call(dbus, 7, test_reply_last_reply);
test_client_call(dbus, 7, test_expect_not_supported);
test_client_call(dbus, 8, test_reply_last_reply);
}
static void test_reply(void)

View File

@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
* Copyright (C) 2015-2021 Jolla Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -491,12 +492,12 @@ static void test_application_entry_decode(void)
app[0] = entries->next->data;
app[1] = entries->data;
g_assert(app[0]->aid_len == 0x10);
g_assert(!memcmp(app[0]->aid, &ef_dir[4], 0x10));
g_assert(app[0]->aid.len == 0x10);
g_assert(!memcmp(app[0]->aid.aid, &ef_dir[4], 0x10));
g_assert(app[0]->label == NULL);
g_assert(app[1]->aid_len == 0x0c);
g_assert(!memcmp(app[1]->aid, &ef_dir[37], 0x0c));
g_assert(app[1]->aid.len == 0x0c);
g_assert(!memcmp(app[1]->aid.aid, &ef_dir[37], 0x0c));
g_assert(app[1]->label != NULL);
g_assert(!strcmp(app[1]->label, "MIDPfiles"));
@@ -529,32 +530,34 @@ static void test_get_2g_path(void)
static void test_auth_build_parse(void)
{
unsigned char auth_cmd[40];
const unsigned char rand[16] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
const unsigned char rand[] = { 0x00, 0x01, 0x02, 0x03, 0x04,0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f };
const unsigned char sres[4] = { 0x00, 0x11, 0x22, 0x33 };
const unsigned char sres[] = { 0x00, 0x11, 0x22, 0x33 };
const unsigned char *sres_p;
struct data_block sres_b;
const unsigned char kc[8] = { 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56,
0x78, 0x9a };
const unsigned char *kc_p;
struct data_block kc_b;
const unsigned char gsm_success[] = { 0x04, 0x00, 0x11, 0x22, 0x33,
0x08,0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
const unsigned char autn[16] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
const unsigned char autn[] = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02,
0x01, 0x00 };
const unsigned char res[8] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
const unsigned char res[] = { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa,
0x11, 0x22 };
const unsigned char *res_p;
const unsigned char ck[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
struct data_block res_b;
const unsigned char ck[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
const unsigned char *ck_p;
const unsigned char ik[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
struct data_block ck_b;
const unsigned char ik[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd,
0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
const unsigned char *ik_p;
const unsigned char auts[16] = { 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea,
0xbe, 0xef };
const unsigned char *auts_p;
struct data_block ik_b;
const unsigned char auts[] = { 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
0xef, 0xde, 0xea };
struct data_block auts_b;
const unsigned char umts_success[] = { 0xdb, 0x08, 0xff, 0xee, 0xdd,
0xcc, 0xbb, 0xaa, 0x11, 0x22, 0x10, 0x00, 0x11, 0x22,
@@ -572,6 +575,8 @@ static void test_auth_build_parse(void)
const unsigned char umts_sync_failure[] = { 0xdc, 0x0e, 0xde, 0xea,
0xbe, 0xef, 0xde, 0xea, 0xbe, 0xef, 0xde, 0xea, 0xbe,
0xef, 0xde, 0xea };
const unsigned char case3[] = { 0x04, 0x01, 0x02, 0x03, 0x04,
0x08, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x9a };
int len = 0;
/* test GSM auth command */
@@ -606,31 +611,96 @@ static void test_auth_build_parse(void)
g_assert(!memcmp(sres_p, sres, 4));
g_assert(!memcmp(kc_p, kc, 8));
/* test truncated messages */
g_assert(!sim_parse_umts_authenticate(umts_success, 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 10,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 11,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 27,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_success, 28,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_sync_failure, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 2,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 5,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, 6,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* the extra byte won't actually be accessed */
g_assert(!sim_parse_umts_authenticate(umts_success,
sizeof(umts_success) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(umts_sync_failure,
sizeof(umts_sync_failure) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert(!sim_parse_umts_authenticate(case3, sizeof(case3) + 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* unrecognized data */
g_assert(!sim_parse_umts_authenticate(case3 + 1, sizeof(case3) - 1,
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
/* test UMTS success parse, no kc */
g_assert(sim_parse_umts_authenticate(umts_success, sizeof(umts_success),
&res_p, &ck_p, &ik_p, &auts_p, &kc_p));
g_assert(!memcmp(res_p, res, 8));
g_assert(!memcmp(ck_p, ck, 16));
g_assert(!memcmp(ik_p, ik, 16));
g_assert(!auts_p && !kc_p);
&res_b, &ck_b, &ik_b, &auts_b, &sres_b, &kc_b));
g_assert_cmpuint(res_b.len, == , sizeof(res));
g_assert(!memcmp(res_b.data, res, sizeof(res)));
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
g_assert(!sres_b.len && !sres_b.data);
g_assert(!auts_b.len && !auts_b.data);
g_assert(!kc_b.len && !kc_b.data);
/* test UMTS sync failure */
g_assert(sim_parse_umts_authenticate(umts_sync_failure,
sizeof(umts_sync_failure),
&res_p, &ck_p, &ik_p, &auts_p,
&kc_p));
g_assert(!memcmp(auts_p, auts, 14));
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert_cmpuint(auts_b.len, == , sizeof(auts));
g_assert(!memcmp(auts_b.data, auts, sizeof(auts)));
g_assert(!res_b.len && !res_b.data);
g_assert(!ck_b.len && !ck_b.data);
g_assert(!ik_b.len && !ik_b.data);
g_assert(!sres_b.len && !sres_b.data);
g_assert(!kc_b.len && !kc_b.data);
/* test UMTS success parse, with kc */
g_assert(sim_parse_umts_authenticate(umts_success_kc,
sizeof(umts_success_kc),
&res_p, &ck_p, &ik_p, &auts_p,
&kc_p));
g_assert(!memcmp(res_p, res, 8));
g_assert(!memcmp(ck_p, ck, 16));
g_assert(!memcmp(ik_p, ik, 16));
g_assert(!memcmp(kc_p, kc, 8));
g_assert(!auts_p);
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert_cmpuint(res_b.len, == , sizeof(res));
g_assert(!memcmp(res_b.data, res, sizeof(res)));
g_assert_cmpuint(ck_b.len, == , sizeof(ck));
g_assert(!memcmp(ck_b.data, ck, sizeof(ck)));
g_assert_cmpuint(ik_b.len, == , sizeof(ik));
g_assert(!memcmp(ik_b.data, ik, sizeof(ik)));
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
g_assert(!sres_b.len && !sres_b.data);
g_assert(!auts_b.len && !auts_b.data);
/* test case3 */
g_assert(sim_parse_umts_authenticate(case3, sizeof(case3),
&res_b, &ck_b, &ik_b, &auts_b,
&sres_b, &kc_b));
g_assert(!res_b.len && !res_b.data);
g_assert(!ck_b.len && !ck_b.data);
g_assert(!ik_b.len && !ik_b.data);
g_assert(!auts_b.len && !auts_b.data);
g_assert_cmpuint(sres_b.len, == , 4);
g_assert(!memcmp(sres_b.data, case3 + 1, sres_b.len));
g_assert_cmpuint(kc_b.len, == , sizeof(kc));
g_assert(!memcmp(kc_b.data, kc, sizeof(kc)));
}
int main(int argc, char **argv)