laforge has submitted this change. ( https://gerrit.osmocom.org/c/onomondo-ipa/+/43025?usp=email )
Change subject: V1.2: Update from "EnableUsingDD" to "ImmediateEnable" function ......................................................................
V1.2: Update from "EnableUsingDD" to "ImmediateEnable" function
Rename function to Version 1.2 of ASN.1 specification.
A refresh flag can be set via context. Also add a command line option to set the refresh flag. If the immediate enable of an installed profile was requested via PSMO, forward the refresh flag to the eUICC. The eUICC will perform CAT refresh after switching profile.
The refresh flag will be used for other profile operations in later patches.
Reference: SGP.32 Section 5.9.15
Related: SYS#8101 Change-Id: Id750b2f5ca6c08a013aa30f876aa37e6291a30d5 --- M asn1/SGP32Definitions.asn M src/ipa/libasn/CMakeLists.txt D src/ipa/libasn/EnableUsingDDRequest.c D src/ipa/libasn/EnableUsingDDResponse.c D src/ipa/libasn/EnableUsingDDResponse.h A src/ipa/libasn/ImmediateEnableRequest.c R src/ipa/libasn/ImmediateEnableRequest.h A src/ipa/libasn/ImmediateEnableResponse.c A src/ipa/libasn/ImmediateEnableResponse.h M src/ipa/libipa/CMakeLists.txt M src/ipa/libipa/context.h D src/ipa/libipa/es10b_enable_using_dd.c A src/ipa/libipa/es10b_immediate_enable.c R src/ipa/libipa/es10b_immediate_enable.h M src/ipa/libipa/es10b_load_bnd_prfle_pkg.c M src/ipa/libipa/proc_prfle_inst.c M src/ipa/main.c 17 files changed, 407 insertions(+), 369 deletions(-)
Approvals: Jenkins Builder: Verified dexter: Looks good to me, approved
diff --git a/asn1/SGP32Definitions.asn b/asn1/SGP32Definitions.asn index bc4fdad..9b5da2f 100644 --- a/asn1/SGP32Definitions.asn +++ b/asn1/SGP32Definitions.asn @@ -458,15 +458,17 @@
-- Section 5.9.15 -- ASN1START -EnableUsingDDRequest ::= [90] SEQUENCE { -- Tag 'BF5A' +ImmediateEnableRequest ::= [90] SEQUENCE { -- Tag 'BF5A' + refreshFlag BOOLEAN -- indicating whether REFRESH is required } -- ASN1STOP -- ASN1START -EnableUsingDDResponse ::= [90] SEQUENCE { -- Tag 'BF5A' - enableUsingDDResult [0] INTEGER { +ImmediateEnableResponse ::= [90] SEQUENCE { -- Tag 'BF5A' + immediateEnableResult [0] INTEGER { ok(0), immediateEnableNotAvailable(1), noSessionContext(4), + catBusy(5), undefinedError(127) } } diff --git a/src/ipa/libasn/CMakeLists.txt b/src/ipa/libasn/CMakeLists.txt index 8efadc9..90d7b42 100644 --- a/src/ipa/libasn/CMakeLists.txt +++ b/src/ipa/libasn/CMakeLists.txt @@ -289,10 +289,6 @@ EnableProfileResponse.h EnableProfileResult.c EnableProfileResult.h -EnableUsingDDRequest.c -EnableUsingDDRequest.h -EnableUsingDDResponse.c -EnableUsingDDResponse.h ErrorReason.c ErrorReason.h ErrorResult.c @@ -437,6 +433,10 @@ Iccid.h IconType.c IconType.h +ImmediateEnableRequest.c +ImmediateEnableRequest.h +ImmediateEnableResponse.c +ImmediateEnableResponse.h InhibitAnyPolicy.c InhibitAnyPolicy.h InitialiseSecureChannelRequest.c diff --git a/src/ipa/libasn/EnableUsingDDRequest.c b/src/ipa/libasn/EnableUsingDDRequest.c deleted file mode 100644 index c37fbfe..0000000 --- a/src/ipa/libasn/EnableUsingDDRequest.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) - * From ASN.1 module "SGP32Definitions" - * found in "../../../asn1/SGP32Definitions.asn" - * `asn1c -fcompound-names -no-gen-example` - */ - -#include "EnableUsingDDRequest.h" - -static const ber_tlv_tag_t asn_DEF_EnableUsingDDRequest_tags_1[] = { - (ASN_TAG_CLASS_CONTEXT | (90 << 2)), - (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) -}; -static asn_SEQUENCE_specifics_t asn_SPC_EnableUsingDDRequest_specs_1 = { - sizeof(struct EnableUsingDDRequest), - offsetof(struct EnableUsingDDRequest, _asn_ctx), - 0, /* No top level tags */ - 0, /* No tags in the map */ - 0, 0, 0, /* Optional elements (not needed) */ - -1, /* First extension addition */ -}; -asn_TYPE_descriptor_t asn_DEF_EnableUsingDDRequest = { - "EnableUsingDDRequest", - "EnableUsingDDRequest", - &asn_OP_SEQUENCE, - asn_DEF_EnableUsingDDRequest_tags_1, - sizeof(asn_DEF_EnableUsingDDRequest_tags_1) - /sizeof(asn_DEF_EnableUsingDDRequest_tags_1[0]) - 1, /* 1 */ - asn_DEF_EnableUsingDDRequest_tags_1, /* Same as above */ - sizeof(asn_DEF_EnableUsingDDRequest_tags_1) - /sizeof(asn_DEF_EnableUsingDDRequest_tags_1[0]), /* 2 */ - { 0, 0, SEQUENCE_constraint }, - 0, 0, /* No members */ - &asn_SPC_EnableUsingDDRequest_specs_1 /* Additional specs */ -}; - diff --git a/src/ipa/libasn/EnableUsingDDResponse.c b/src/ipa/libasn/EnableUsingDDResponse.c deleted file mode 100644 index af30721..0000000 --- a/src/ipa/libasn/EnableUsingDDResponse.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) - * From ASN.1 module "SGP32Definitions" - * found in "../../../asn1/SGP32Definitions.asn" - * `asn1c -fcompound-names -no-gen-example` - */ - -#include "EnableUsingDDResponse.h" - -static asn_TYPE_member_t asn_MBR_EnableUsingDDResponse_1[] = { - { ATF_NOFLAGS, 0, offsetof(struct EnableUsingDDResponse, enableUsingDDResult), - (ASN_TAG_CLASS_CONTEXT | (0 << 2)), - -1, /* IMPLICIT tag at current level */ - &asn_DEF_NativeInteger, - 0, - { 0, 0, 0 }, - 0, 0, /* No default value */ - "enableUsingDDResult" - }, -}; -static const ber_tlv_tag_t asn_DEF_EnableUsingDDResponse_tags_1[] = { - (ASN_TAG_CLASS_CONTEXT | (90 << 2)), - (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) -}; -static const asn_TYPE_tag2member_t asn_MAP_EnableUsingDDResponse_tag2el_1[] = { - { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* enableUsingDDResult */ -}; -static asn_SEQUENCE_specifics_t asn_SPC_EnableUsingDDResponse_specs_1 = { - sizeof(struct EnableUsingDDResponse), - offsetof(struct EnableUsingDDResponse, _asn_ctx), - asn_MAP_EnableUsingDDResponse_tag2el_1, - 1, /* Count of tags in the map */ - 0, 0, 0, /* Optional elements (not needed) */ - 1, /* First extension addition */ -}; -asn_TYPE_descriptor_t asn_DEF_EnableUsingDDResponse = { - "EnableUsingDDResponse", - "EnableUsingDDResponse", - &asn_OP_SEQUENCE, - asn_DEF_EnableUsingDDResponse_tags_1, - sizeof(asn_DEF_EnableUsingDDResponse_tags_1) - /sizeof(asn_DEF_EnableUsingDDResponse_tags_1[0]) - 1, /* 1 */ - asn_DEF_EnableUsingDDResponse_tags_1, /* Same as above */ - sizeof(asn_DEF_EnableUsingDDResponse_tags_1) - /sizeof(asn_DEF_EnableUsingDDResponse_tags_1[0]), /* 2 */ - { 0, 0, SEQUENCE_constraint }, - asn_MBR_EnableUsingDDResponse_1, - 1, /* Elements count */ - &asn_SPC_EnableUsingDDResponse_specs_1 /* Additional specs */ -}; - diff --git a/src/ipa/libasn/EnableUsingDDResponse.h b/src/ipa/libasn/EnableUsingDDResponse.h deleted file mode 100644 index faa2c26..0000000 --- a/src/ipa/libasn/EnableUsingDDResponse.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) - * From ASN.1 module "SGP32Definitions" - * found in "../../../asn1/SGP32Definitions.asn" - * `asn1c -fcompound-names -no-gen-example` - */ - -#ifndef _EnableUsingDDResponse_H_ -#define _EnableUsingDDResponse_H_ - - -#include <asn_application.h> - -/* Including external dependencies */ -#include <NativeInteger.h> -#include <constr_SEQUENCE.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* Dependencies */ -typedef enum EnableUsingDDResponse__enableUsingDDResult { - EnableUsingDDResponse__enableUsingDDResult_ok = 0, - EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable = 1, - EnableUsingDDResponse__enableUsingDDResult_noSessionContext = 4, - EnableUsingDDResponse__enableUsingDDResult_undefinedError = 127 -} e_EnableUsingDDResponse__enableUsingDDResult; - -/* EnableUsingDDResponse */ -typedef struct EnableUsingDDResponse { - long enableUsingDDResult; - /* - * This type is extensible, - * possible extensions are below. - */ - - /* Context for parsing across buffer boundaries */ - asn_struct_ctx_t _asn_ctx; -} EnableUsingDDResponse_t; - -/* Implementation */ -extern asn_TYPE_descriptor_t asn_DEF_EnableUsingDDResponse; - -#ifdef __cplusplus -} -#endif - -#endif /* _EnableUsingDDResponse_H_ */ -#include <asn_internal.h> diff --git a/src/ipa/libasn/ImmediateEnableRequest.c b/src/ipa/libasn/ImmediateEnableRequest.c new file mode 100644 index 0000000..e08fe51 --- /dev/null +++ b/src/ipa/libasn/ImmediateEnableRequest.c @@ -0,0 +1,51 @@ +/* + * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) + * From ASN.1 module "SGP32Definitions" + * found in "../../../asn1/SGP32Definitions.asn" + * `asn1c -fcompound-names -no-gen-example` + */ + +#include "ImmediateEnableRequest.h" + +static asn_TYPE_member_t asn_MBR_ImmediateEnableRequest_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ImmediateEnableRequest, refreshFlag), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_BOOLEAN, + 0, + { 0, 0, 0 }, + 0, 0, /* No default value */ + "refreshFlag" + }, +}; +static const ber_tlv_tag_t asn_DEF_ImmediateEnableRequest_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (90 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_ImmediateEnableRequest_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* refreshFlag */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ImmediateEnableRequest_specs_1 = { + sizeof(struct ImmediateEnableRequest), + offsetof(struct ImmediateEnableRequest, _asn_ctx), + asn_MAP_ImmediateEnableRequest_tag2el_1, + 1, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + 1, /* First extension addition */ +}; +asn_TYPE_descriptor_t asn_DEF_ImmediateEnableRequest = { + "ImmediateEnableRequest", + "ImmediateEnableRequest", + &asn_OP_SEQUENCE, + asn_DEF_ImmediateEnableRequest_tags_1, + sizeof(asn_DEF_ImmediateEnableRequest_tags_1) + /sizeof(asn_DEF_ImmediateEnableRequest_tags_1[0]) - 1, /* 1 */ + asn_DEF_ImmediateEnableRequest_tags_1, /* Same as above */ + sizeof(asn_DEF_ImmediateEnableRequest_tags_1) + /sizeof(asn_DEF_ImmediateEnableRequest_tags_1[0]), /* 2 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_ImmediateEnableRequest_1, + 1, /* Elements count */ + &asn_SPC_ImmediateEnableRequest_specs_1 /* Additional specs */ +}; + diff --git a/src/ipa/libasn/EnableUsingDDRequest.h b/src/ipa/libasn/ImmediateEnableRequest.h similarity index 64% rename from src/ipa/libasn/EnableUsingDDRequest.h rename to src/ipa/libasn/ImmediateEnableRequest.h index ab1573b..0def067 100644 --- a/src/ipa/libasn/EnableUsingDDRequest.h +++ b/src/ipa/libasn/ImmediateEnableRequest.h @@ -5,21 +5,23 @@ * `asn1c -fcompound-names -no-gen-example` */
-#ifndef _EnableUsingDDRequest_H_ -#define _EnableUsingDDRequest_H_ +#ifndef _ImmediateEnableRequest_H_ +#define _ImmediateEnableRequest_H_
#include <asn_application.h>
/* Including external dependencies */ +#include <BOOLEAN.h> #include <constr_SEQUENCE.h>
#ifdef __cplusplus extern "C" { #endif
-/* EnableUsingDDRequest */ -typedef struct EnableUsingDDRequest { +/* ImmediateEnableRequest */ +typedef struct ImmediateEnableRequest { + BOOLEAN_t refreshFlag; /* * This type is extensible, * possible extensions are below. @@ -27,14 +29,14 @@ /* Context for parsing across buffer boundaries */ asn_struct_ctx_t _asn_ctx; -} EnableUsingDDRequest_t; +} ImmediateEnableRequest_t;
/* Implementation */ -extern asn_TYPE_descriptor_t asn_DEF_EnableUsingDDRequest; +extern asn_TYPE_descriptor_t asn_DEF_ImmediateEnableRequest;
#ifdef __cplusplus } #endif
-#endif /* _EnableUsingDDRequest_H_ */ +#endif /* _ImmediateEnableRequest_H_ */ #include <asn_internal.h> diff --git a/src/ipa/libasn/ImmediateEnableResponse.c b/src/ipa/libasn/ImmediateEnableResponse.c new file mode 100644 index 0000000..e6197b1 --- /dev/null +++ b/src/ipa/libasn/ImmediateEnableResponse.c @@ -0,0 +1,51 @@ +/* + * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) + * From ASN.1 module "SGP32Definitions" + * found in "../../../asn1/SGP32Definitions.asn" + * `asn1c -fcompound-names -no-gen-example` + */ + +#include "ImmediateEnableResponse.h" + +static asn_TYPE_member_t asn_MBR_ImmediateEnableResponse_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ImmediateEnableResponse, immediateEnableResult), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_NativeInteger, + 0, + { 0, 0, 0 }, + 0, 0, /* No default value */ + "immediateEnableResult" + }, +}; +static const ber_tlv_tag_t asn_DEF_ImmediateEnableResponse_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (90 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_ImmediateEnableResponse_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* immediateEnableResult */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_ImmediateEnableResponse_specs_1 = { + sizeof(struct ImmediateEnableResponse), + offsetof(struct ImmediateEnableResponse, _asn_ctx), + asn_MAP_ImmediateEnableResponse_tag2el_1, + 1, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + 1, /* First extension addition */ +}; +asn_TYPE_descriptor_t asn_DEF_ImmediateEnableResponse = { + "ImmediateEnableResponse", + "ImmediateEnableResponse", + &asn_OP_SEQUENCE, + asn_DEF_ImmediateEnableResponse_tags_1, + sizeof(asn_DEF_ImmediateEnableResponse_tags_1) + /sizeof(asn_DEF_ImmediateEnableResponse_tags_1[0]) - 1, /* 1 */ + asn_DEF_ImmediateEnableResponse_tags_1, /* Same as above */ + sizeof(asn_DEF_ImmediateEnableResponse_tags_1) + /sizeof(asn_DEF_ImmediateEnableResponse_tags_1[0]), /* 2 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_ImmediateEnableResponse_1, + 1, /* Elements count */ + &asn_SPC_ImmediateEnableResponse_specs_1 /* Additional specs */ +}; + diff --git a/src/ipa/libasn/ImmediateEnableResponse.h b/src/ipa/libasn/ImmediateEnableResponse.h new file mode 100644 index 0000000..f4c4445 --- /dev/null +++ b/src/ipa/libasn/ImmediateEnableResponse.h @@ -0,0 +1,51 @@ +/* + * Generated by asn1c-0.9.29 (http://lionet.info/asn1c) + * From ASN.1 module "SGP32Definitions" + * found in "../../../asn1/SGP32Definitions.asn" + * `asn1c -fcompound-names -no-gen-example` + */ + +#ifndef _ImmediateEnableResponse_H_ +#define _ImmediateEnableResponse_H_ + + +#include <asn_application.h> + +/* Including external dependencies */ +#include <NativeInteger.h> +#include <constr_SEQUENCE.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ImmediateEnableResponse__immediateEnableResult { + ImmediateEnableResponse__immediateEnableResult_ok = 0, + ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable = 1, + ImmediateEnableResponse__immediateEnableResult_noSessionContext = 4, + ImmediateEnableResponse__immediateEnableResult_catBusy = 5, + ImmediateEnableResponse__immediateEnableResult_undefinedError = 127 +} e_ImmediateEnableResponse__immediateEnableResult; + +/* ImmediateEnableResponse */ +typedef struct ImmediateEnableResponse { + long immediateEnableResult; + /* + * This type is extensible, + * possible extensions are below. + */ + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ImmediateEnableResponse_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ImmediateEnableResponse; + +#ifdef __cplusplus +} +#endif + +#endif /* _ImmediateEnableResponse_H_ */ +#include <asn_internal.h> diff --git a/src/ipa/libipa/CMakeLists.txt b/src/ipa/libipa/CMakeLists.txt index 49a2c14..e6bed87 100644 --- a/src/ipa/libipa/CMakeLists.txt +++ b/src/ipa/libipa/CMakeLists.txt @@ -23,7 +23,7 @@ es10c_delete_prfle.c es10c_disable_prfle.c es10c_enable_prfle.c - es10b_enable_using_dd.c + es10b_immediate_enable.c es10c_get_eid.c es10c_get_prfle_info.c es10x.c diff --git a/src/ipa/libipa/context.h b/src/ipa/libipa/context.h index 5065286..e0080d4 100644 --- a/src/ipa/libipa/context.h +++ b/src/ipa/libipa/context.h @@ -32,6 +32,7 @@ bool flag; struct ipa_buf *smdp_oid; struct ipa_buf *smdp_address; + bool refresh; } immediate_enable; } iot_euicc_emu;
diff --git a/src/ipa/libipa/es10b_enable_using_dd.c b/src/ipa/libipa/es10b_enable_using_dd.c deleted file mode 100644 index 87e731d..0000000 --- a/src/ipa/libipa/es10b_enable_using_dd.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2025 Onomondo ApS & sysmocom - s.f.m.c. GmbH. All rights reserved. - * - * SPDX-License-Identifier: AGPL-3.0-only - * - * Author: Philipp Maier pmaier@sysmocom.de / sysmocom - s.f.m.c. GmbH - * - * See also: GSMA SGP.23, 5.9.15: Function (ES10b): EnableUsingDD - */ - -#include <stdio.h> -#include <assert.h> -#include <string.h> -#include <errno.h> -#include <onomondo/ipa/mem.h> -#include <onomondo/ipa/utils.h> -#include <onomondo/ipa/scard.h> -#include <onomondo/ipa/log.h> -#include <EnableUsingDDRequest.h> -#include <EnableUsingDDResponse.h> -#include "context.h" -#include "length.h" -#include "utils.h" -#include "euicc.h" -#include "es10x.h" -#include "es10b_enable_using_dd.h" -#include "es10c_enable_prfle.h" - -static const struct num_str_map error_code_strings[] = { - { EnableUsingDDResponse__enableUsingDDResult_ok, "ok" }, - { EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable, "immediateEnableNotAvailable" }, - { EnableUsingDDResponse__enableUsingDDResult_noSessionContext, "noSessionContext" }, - { EnableUsingDDResponse__enableUsingDDResult_undefinedError, "undefinedError" }, - { 0, NULL } -}; - -static int dec_enable_using_dd_res(const struct ipa_buf *es10b_res) -{ - struct EnableUsingDDResponse *asn = NULL; - int rc; - - asn = ipa_es10x_res_dec(&asn_DEF_EnableUsingDDResponse, es10b_res, "EnableUsingDD"); - if (!asn) - return -EINVAL; - - rc = asn->enableUsingDDResult; - - if (rc == EnableUsingDDResponse__enableUsingDDResult_ok) { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, "function succeeded with status code %d=%s!\n", - rc, ipa_str_from_num(error_code_strings, rc, "(unknown)")); - } else { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, "function failed with error code %d=%s!\n", - rc, ipa_str_from_num(error_code_strings, rc, "(unknown)")); - } - - ASN_STRUCT_FREE(asn_DEF_EnableUsingDDResponse, asn); - return rc; -} - -int enable_using_dd(struct ipa_context *ctx) -{ - struct ipa_buf *es10b_req = NULL; - struct ipa_buf *es10b_res = NULL; - struct EnableUsingDDRequest enable_using_dd_req = { 0 }; - int rc = -EINVAL; - - es10b_req = ipa_es10x_req_enc(&asn_DEF_EnableUsingDDRequest, &enable_using_dd_req, "EnableUsingDD"); - if (!es10b_req) { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, "unable to encode ES10b request\n"); - goto error; - } - - es10b_res = ipa_euicc_transceive_es10x(ctx, es10b_req); - if (!es10b_res) { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, "no ES10b response\n"); - goto error; - } - - rc = dec_enable_using_dd_res(es10b_res); - if (rc < 0) - goto error; - -error: - IPA_FREE(es10b_req); - IPA_FREE(es10b_res); - return rc; -} - -int enable_using_dd_emu(struct ipa_context *ctx) -{ - struct ipa_es10c_enable_prfle_req enable_prfle_req = { 0 }; - struct ipa_es10c_enable_prfle_res *enable_prfle_res = NULL; - int rc = EnableUsingDDResponse__enableUsingDDResult_undefinedError; - - /* Auto enable must be active */ - if (ctx->nvstate.iot_euicc_emu.immediate_enable.flag == false) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - - /* We also need either the smdp_oid or the smdp_address to verify against */ - if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid == NULL && - ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address == NULL) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - - /* Ensure the session context is present and complete */ - if (ctx->iot_euicc_emu.immediate_enable.smdp_address == NULL) { - rc = EnableUsingDDResponse__enableUsingDDResult_noSessionContext; - goto error; - } - if (ctx->iot_euicc_emu.immediate_enable.smdp_oid == NULL) { - rc = EnableUsingDDResponse__enableUsingDDResult_noSessionContext; - goto error; - } - if (ctx->iot_euicc_emu.immediate_enable.profile_aid == NULL) { - rc = EnableUsingDDResponse__enableUsingDDResult_noSessionContext; - goto error; - } - - /* Verify smdp OID (if configured) */ - if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid) { - if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid->len != - ctx->iot_euicc_emu.immediate_enable.smdp_oid->len) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - if (memcmp(ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid->data, - ctx->iot_euicc_emu.immediate_enable.smdp_oid->data, - ctx->iot_euicc_emu.immediate_enable.smdp_oid->len)) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - } - - /* Verify smdp address (if configured) */ - if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address) { - if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address->len != - ctx->iot_euicc_emu.immediate_enable.smdp_address->len) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - if (memcmp(ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address->data, - ctx->iot_euicc_emu.immediate_enable.smdp_address->data, - ctx->iot_euicc_emu.immediate_enable.smdp_address->len)) { - rc = EnableUsingDDResponse__enableUsingDDResult_immediateEnableNotAvailable; - goto error; - } - } - - /* Enable profile */ - enable_prfle_req.req.profileIdentifier.present = EnableProfileRequest__profileIdentifier_PR_isdpAid; - IPA_ASSIGN_BUF_TO_ASN(enable_prfle_req.req.profileIdentifier.choice.isdpAid, - ctx->iot_euicc_emu.immediate_enable.profile_aid->data, - ctx->iot_euicc_emu.immediate_enable.profile_aid->len); - - enable_prfle_res = ipa_es10c_enable_prfle(ctx, &enable_prfle_req); - if (enable_prfle_res && enable_prfle_res->res->enableResult == EnableProfileResponse__enableResult_ok) - rc = EnableUsingDDResponse__enableUsingDDResult_ok; - else - rc = EnableUsingDDResponse__enableUsingDDResult_undefinedError; - -error: - if (rc == EnableUsingDDResponse__enableUsingDDResult_ok) { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, - "IoT eUICC emulation active, function succeeded with status code %d=%s!\n", rc, - ipa_str_from_num(error_code_strings, rc, "(unknown)")); - } else { - IPA_LOGP_ES10X("EnableUsingDD", LERROR, - "IoT eUICC emulation active, function failed with error code %d=%s!\n", rc, - ipa_str_from_num(error_code_strings, rc, "(unknown)")); - } - - /* Ensure the auto enable data is cleared after use */ - ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.smdp_oid); - ctx->iot_euicc_emu.immediate_enable.smdp_oid = NULL; - ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.smdp_address); - ctx->iot_euicc_emu.immediate_enable.smdp_address = NULL; - ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.profile_aid); - ctx->iot_euicc_emu.immediate_enable.profile_aid = NULL; - - ipa_es10c_enable_prfle_res_free(enable_prfle_res); - return rc; -} - -/*! Function (ES10b): EnableUsingDD. - * \param[inout] ctx pointer to ipa_context. - * \returns positive status code on success, negative on error. */ -int ipa_es10b_enable_using_dd(struct ipa_context *ctx) -{ - if (ctx->cfg->iot_euicc_emu_enabled) - return enable_using_dd_emu(ctx); - else - return enable_using_dd(ctx); -} diff --git a/src/ipa/libipa/es10b_immediate_enable.c b/src/ipa/libipa/es10b_immediate_enable.c new file mode 100644 index 0000000..2c76153 --- /dev/null +++ b/src/ipa/libipa/es10b_immediate_enable.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2025 Onomondo ApS & sysmocom - s.f.m.c. GmbH. All rights reserved. + * + * SPDX-License-Identifier: AGPL-3.0-only + * + * Author: Philipp Maier pmaier@sysmocom.de / sysmocom - s.f.m.c. GmbH + * + * See also: GSMA SGP.32, 5.9.15: Function (ES10b): ImmediateEnable + */ + +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <onomondo/ipa/mem.h> +#include <onomondo/ipa/utils.h> +#include <onomondo/ipa/scard.h> +#include <onomondo/ipa/log.h> +#include <ImmediateEnableRequest.h> +#include <ImmediateEnableResponse.h> +#include "context.h" +#include "length.h" +#include "utils.h" +#include "euicc.h" +#include "es10x.h" +#include "es10b_immediate_enable.h" +#include "es10c_enable_prfle.h" + +static const struct num_str_map error_code_strings[] = { + { ImmediateEnableResponse__immediateEnableResult_ok, "ok" }, + { ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable, "immediateEnableNotAvailable" }, + { ImmediateEnableResponse__immediateEnableResult_noSessionContext, "noSessionContext" }, + { ImmediateEnableResponse__immediateEnableResult_undefinedError, "undefinedError" }, + { 0, NULL } +}; + +static int dec_immediate_enable_res(const struct ipa_buf *es10b_res) +{ + struct ImmediateEnableResponse *asn = NULL; + int rc; + + asn = ipa_es10x_res_dec(&asn_DEF_ImmediateEnableResponse, es10b_res, "ImmediateEnable"); + if (!asn) + return -EINVAL; + + rc = asn->immediateEnableResult; + + if (rc == ImmediateEnableResponse__immediateEnableResult_ok) { + IPA_LOGP_ES10X("ImmediateEnable", LERROR, "function succeeded with status code %d=%s!\n", + rc, ipa_str_from_num(error_code_strings, rc, "(unknown)")); + } else { + IPA_LOGP_ES10X("ImmediateEnable", LERROR, "function failed with error code %d=%s!\n", + rc, ipa_str_from_num(error_code_strings, rc, "(unknown)")); + } + + ASN_STRUCT_FREE(asn_DEF_ImmediateEnableResponse, asn); + return rc; +} + +int immediate_enable(struct ipa_context *ctx, bool refresh_flag) +{ + struct ipa_buf *es10b_req = NULL; + struct ipa_buf *es10b_res = NULL; + struct ImmediateEnableRequest immediate_enable_req = { 0 }; + int rc = -EINVAL; + + immediate_enable_req.refreshFlag = refresh_flag; + es10b_req = ipa_es10x_req_enc(&asn_DEF_ImmediateEnableRequest, &immediate_enable_req, "ImmediateEnable"); + if (!es10b_req) { + IPA_LOGP_ES10X("ImmediateEnable", LERROR, "unable to encode ES10b request\n"); + goto error; + } + + es10b_res = ipa_euicc_transceive_es10x(ctx, es10b_req); + if (!es10b_res) { + IPA_LOGP_ES10X("ImmediateEnable", LERROR, "no ES10b response\n"); + goto error; + } + + rc = dec_immediate_enable_res(es10b_res); + if (rc < 0) + goto error; + +error: + IPA_FREE(es10b_req); + IPA_FREE(es10b_res); + return rc; +} + +int immediate_enable_emu(struct ipa_context *ctx, bool refresh_flag) +{ + struct ipa_es10c_enable_prfle_req enable_prfle_req = { 0 }; + struct ipa_es10c_enable_prfle_res *enable_prfle_res = NULL; + int rc = ImmediateEnableResponse__immediateEnableResult_undefinedError; + + /* Auto enable must be active */ + if (ctx->nvstate.iot_euicc_emu.immediate_enable.flag == false) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + + /* We also need either the smdp_oid or the smdp_address to verify against */ + if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid == NULL && + ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address == NULL) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + + /* Ensure the session context is present and complete */ + if (ctx->iot_euicc_emu.immediate_enable.smdp_address == NULL) { + rc = ImmediateEnableResponse__immediateEnableResult_noSessionContext; + goto error; + } + if (ctx->iot_euicc_emu.immediate_enable.smdp_oid == NULL) { + rc = ImmediateEnableResponse__immediateEnableResult_noSessionContext; + goto error; + } + if (ctx->iot_euicc_emu.immediate_enable.profile_aid == NULL) { + rc = ImmediateEnableResponse__immediateEnableResult_noSessionContext; + goto error; + } + + /* Verify smdp OID (if configured) */ + if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid) { + if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid->len != + ctx->iot_euicc_emu.immediate_enable.smdp_oid->len) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + if (memcmp(ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_oid->data, + ctx->iot_euicc_emu.immediate_enable.smdp_oid->data, + ctx->iot_euicc_emu.immediate_enable.smdp_oid->len)) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + } + + /* Verify smdp address (if configured) */ + if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address) { + if (ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address->len != + ctx->iot_euicc_emu.immediate_enable.smdp_address->len) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + if (memcmp(ctx->nvstate.iot_euicc_emu.immediate_enable.smdp_address->data, + ctx->iot_euicc_emu.immediate_enable.smdp_address->data, + ctx->iot_euicc_emu.immediate_enable.smdp_address->len)) { + rc = ImmediateEnableResponse__immediateEnableResult_immediateEnableNotAvailable; + goto error; + } + } + + /* Enable profile */ + enable_prfle_req.req.profileIdentifier.present = EnableProfileRequest__profileIdentifier_PR_isdpAid; + IPA_ASSIGN_BUF_TO_ASN(enable_prfle_req.req.profileIdentifier.choice.isdpAid, + ctx->iot_euicc_emu.immediate_enable.profile_aid->data, + ctx->iot_euicc_emu.immediate_enable.profile_aid->len); + enable_prfle_req.req.refreshFlag = refresh_flag; + + enable_prfle_res = ipa_es10c_enable_prfle(ctx, &enable_prfle_req); + if (enable_prfle_res && enable_prfle_res->res->enableResult == EnableProfileResponse__enableResult_ok) + rc = ImmediateEnableResponse__immediateEnableResult_ok; + else + rc = ImmediateEnableResponse__immediateEnableResult_undefinedError; + +error: + if (rc == ImmediateEnableResponse__immediateEnableResult_ok) { + IPA_LOGP_ES10X("ImmediateEnable", LINFO, + "IoT eUICC emulation active, function succeeded with status code %d=%s!\n", rc, + ipa_str_from_num(error_code_strings, rc, "(unknown)")); + } else { + IPA_LOGP_ES10X("ImmediateEnable", LERROR, + "IoT eUICC emulation active, function failed with error code %d=%s!\n", rc, + ipa_str_from_num(error_code_strings, rc, "(unknown)")); + } + + /* Ensure the auto enable data is cleared after use */ + ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.smdp_oid); + ctx->iot_euicc_emu.immediate_enable.smdp_oid = NULL; + ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.smdp_address); + ctx->iot_euicc_emu.immediate_enable.smdp_address = NULL; + ipa_buf_free(ctx->iot_euicc_emu.immediate_enable.profile_aid); + ctx->iot_euicc_emu.immediate_enable.profile_aid = NULL; + + ipa_es10c_enable_prfle_res_free(enable_prfle_res); + return rc; +} + +/*! Function (ES10b): ImmediateEnable. + * \param[inout] ctx pointer to ipa_context. + * \param[in] refresh_flag send a CAT refresh after enabling profile + * \returns positive status code on success, negative on error. */ +int ipa_es10b_immediate_enable(struct ipa_context *ctx, bool refresh_flag) +{ + if (ctx->cfg->iot_euicc_emu_enabled) + return immediate_enable_emu(ctx, refresh_flag); + else + return immediate_enable(ctx, refresh_flag); +} diff --git a/src/ipa/libipa/es10b_enable_using_dd.h b/src/ipa/libipa/es10b_immediate_enable.h similarity index 69% rename from src/ipa/libipa/es10b_enable_using_dd.h rename to src/ipa/libipa/es10b_immediate_enable.h index b73c541..673416d 100644 --- a/src/ipa/libipa/es10b_enable_using_dd.h +++ b/src/ipa/libipa/es10b_immediate_enable.h @@ -8,4 +8,4 @@
struct ipa_context;
-int ipa_es10b_enable_using_dd(struct ipa_context *ctx); +int ipa_es10b_immediate_enable(struct ipa_context *ctx, bool refresh_flag); diff --git a/src/ipa/libipa/es10b_load_bnd_prfle_pkg.c b/src/ipa/libipa/es10b_load_bnd_prfle_pkg.c index d11eb7d..946ccb2 100644 --- a/src/ipa/libipa/es10b_load_bnd_prfle_pkg.c +++ b/src/ipa/libipa/es10b_load_bnd_prfle_pkg.c @@ -95,7 +95,7 @@ goto error;
/* In case IoT eUICC emulation is active, collect immediate enable data to support the emulation of - * the ES10b function EnableUsingDD. */ + * the ES10b function ImmediateEnable. */ if (ctx->cfg->iot_euicc_emu_enabled) collect_immediate_enable_data_from_prfle_inst_rslt(ctx, res->res); } diff --git a/src/ipa/libipa/proc_prfle_inst.c b/src/ipa/libipa/proc_prfle_inst.c index 1d08910..fc7eaf7 100644 --- a/src/ipa/libipa/proc_prfle_inst.c +++ b/src/ipa/libipa/proc_prfle_inst.c @@ -21,7 +21,7 @@ #include "es10b_load_bnd_prfle_pkg.h" #include "esipa_handle_notif.h" #include "es10b_rm_notif_from_lst.h" -#include "es10b_enable_using_dd.h" +#include "es10b_immediate_enable.h" #include "bpp_segments.h" #include "proc_prfle_inst.h"
@@ -42,7 +42,7 @@ }
/* Instruct the eUICC to enable the newly installed profile (if configured and granted) */ - ipa_es10b_enable_using_dd(ctx); + ipa_es10b_immediate_enable(ctx, ctx->cfg->refresh_flag);
/* A response is present, this is either the normal ending of the installation sequence or the eUICC has aborted * the installation. In both situations we forward the ProfileInstallationResult to the eIM. */ diff --git a/src/ipa/main.c b/src/ipa/main.c index d4316f2..fae8476 100644 --- a/src/ipa/main.c +++ b/src/ipa/main.c @@ -42,22 +42,23 @@ static void print_help(void) { printf("options:\n"); - printf(" -h .................. print this text.\n"); - printf(" -t TAC .............. set TAC (default: %s)\n", DEFAULT_TAC); - printf(" -e eimId ............ set preferred eIM (in case the eUICC has multiple)\n"); - printf(" -r N ................ set reader number (default: %d)\n", DEFAULT_READER_NUMBER); - printf(" -c N ................ set logical channel number (default: %d)\n", DEFAULT_CHANNEL_NUMBER); - printf(" -f PATH ............. set initial eIM configuration\n"); - printf(" -m .................. reset eUICC memory\n"); - printf(" -n PATH ............. path to nvstate file (default: %s)\n", DEFAULT_NVSTATE_PATH); - printf(" -y NUM .............. number of retries for ESipa requests (default: %u)\n", + printf(" -h ......................... print this text.\n"); + printf(" -t TAC ..................... set TAC (default: %s)\n", DEFAULT_TAC); + printf(" -e eimId ................... set preferred eIM (in case the eUICC has multiple)\n"); + printf(" -r N ....................... set reader number (default: %d)\n", DEFAULT_READER_NUMBER); + printf(" -c N ....................... set logical channel number (default: %d)\n", DEFAULT_CHANNEL_NUMBER); + printf(" -f PATH .................... set initial eIM configuration\n"); + printf(" -m ......................... reset eUICC memory\n"); + printf(" --refresh-flag.............. Make eUICC send a CAT refresh after switching profile\n"); + printf(" -n PATH .................... path to nvstate file (default: %s)\n", DEFAULT_NVSTATE_PATH); + printf(" -y NUM ..................... number of retries for ESipa requests (default: %u)\n", DEFAULT_ESIPA_REQ_RETRIES); - printf(" -a .................. ask end user for consent\n"); - printf(" -C .................. CA (Certificate Authority) Bundle file\n"); - printf(" -S .................. disable HTTPS\n"); - printf(" -I .................. disable SSL certificate verification (insecure)\n"); - printf(" -E .................. emulate IoT eUICC (compatibility mode to use consumer eUICCs)\n"); - printf(" -1 .................. force the IPAd to process only one eUICC package (debug, use with caution)\n"); + printf(" -a ......................... ask end user for consent\n"); + printf(" -C ......................... CA (Certificate Authority) Bundle file\n"); + printf(" -S ......................... disable HTTPS\n"); + printf(" -I ......................... disable SSL certificate verification (insecure)\n"); + printf(" -E ......................... emulate IoT eUICC (compatibility mode to use consumer eUICCs)\n"); + printf(" -1 ......................... force the IPAd to process only one eUICC package (debug, use with caution)\n"); }
struct ipa_buf *load_ber_from_file(char *dir, char *file) @@ -146,6 +147,7 @@ struct ipa_buf *nvstate_load = NULL; struct ipa_buf *nvstate_save = NULL; bool getopt_one_euicc_pkg_only = false; + int option_index = 0;
signal(SIGUSR1, sig_usr1);
@@ -157,9 +159,18 @@ ipa_binary_from_hexstr(cfg.tac, sizeof(cfg.tac), DEFAULT_TAC); cfg.esipa_req_retries = DEFAULT_ESIPA_REQ_RETRIES;
+ enum { + OPT_REFRESHFLAG = 256, + }; + + struct option long_options[] = { + { "refresh-flag", no_argument, NULL, OPT_REFRESHFLAG}, + { NULL, 0, NULL, 0} + }; + /* Overwrite configuration values with user defined parameters */ while (1) { - opt = getopt(argc, argv, "ht:e:r:c:f:mn:C:SIEy:a1"); + opt = getopt_long(argc, argv, "ht:e:r:c:f:mn:C:SIEy:a1", long_options, &option_index); if (opt == -1) break;
@@ -186,6 +197,9 @@ case 'm': getopt_euicc_memory_reset = true; break; + case OPT_REFRESHFLAG: + cfg.refresh_flag = true; + break; case 'n': getopt_nvstate_path = optarg; break; @@ -222,6 +236,7 @@ printf(" preferred_eim_id = %s\n", cfg.preferred_eim_id ? cfg.preferred_eim_id : "(first configured eIM)"); printf(" reader_num = %d\n", cfg.reader_num); printf(" euicc_channel = %d\n", cfg.euicc_channel); + printf(" refresh_flag = %u\n", cfg.refresh_flag); if (cfg.eim_cabundle) printf(" eim_cabundle = %s\n", cfg.eim_cabundle); printf(" eim_disable_ssl = %d\n", cfg.eim_disable_ssl); @@ -229,7 +244,6 @@ printf(" tac = %s\n", ipa_hexdump(cfg.tac, sizeof(cfg.tac))); printf(" iot_euicc_emu_enabled = %u\n", cfg.iot_euicc_emu_enabled); printf(" esipa_req_retries = %u\n", cfg.esipa_req_retries); - printf(" refresh_flag = %u\n", cfg.refresh_flag); printf("\n");
if (cfg.eim_cabundle) {