jolly has submitted this change. ( https://gerrit.osmocom.org/c/onomondo-ipa/+/43043?usp=email )
Change subject: V1.2: Add function ES10b.EnableEmergencyProfile ......................................................................
V1.2: Add function ES10b.EnableEmergencyProfile
Add new library function to enable emergency profile on IoT eUICC. Also add an option to the command line interface to call the library function. The optional refresh flag may be set via command line option.
The function cannot be emulated with non-IoT eUICC.
Reference: SGP.32 Section 5.9.22
Related: SYS#8101 Change-Id: I0304b869a14a36b82cc2d1676b2a5f613e1da171 --- M asn1/SGP32Definitions.asn M include/onomondo/ipa/ipad.h M src/ipa/libasn/CMakeLists.txt A src/ipa/libasn/EnableEmergencyProfileRequest.c A src/ipa/libasn/EnableEmergencyProfileRequest.h A src/ipa/libasn/EnableEmergencyProfileResponse.c A src/ipa/libasn/EnableEmergencyProfileResponse.h M src/ipa/libipa/CMakeLists.txt A src/ipa/libipa/es10b_en_emerg_prfle.c A src/ipa/libipa/es10b_en_emerg_prfle.h M src/ipa/libipa/ipad.c M src/ipa/main.c 12 files changed, 377 insertions(+), 0 deletions(-)
Approvals: dexter: Looks good to me, approved laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified
diff --git a/asn1/SGP32Definitions.asn b/asn1/SGP32Definitions.asn index 9f3ce9c..9c06255 100644 --- a/asn1/SGP32Definitions.asn +++ b/asn1/SGP32Definitions.asn @@ -630,6 +630,24 @@ } -- ASN1STOP
+-- Section 5.9.22 +-- ASN1START +EnableEmergencyProfileRequest ::= [91] SEQUENCE { -- Tag 'BF5B' + refreshFlag BOOLEAN -- indicating whether REFRESH is required +} +-- ASN1STOP +-- ASN1START +EnableEmergencyProfileResponse ::= [91] SEQUENCE { -- Tag 'BF5B' + enableEmergencyProfileResult [0] INTEGER { + ok(0), + profileNotInDisabledState(2), + catBusy(5), + ecallNotAvailable(8), -- Emergency Profile does not exist + undefinedError(127) + } +} +-- ASN1STOP + -- Section 5.9.25 -- ASN1START SGP32-SetDefaultDpAddressRequest ::= [101] SEQUENCE { -- Tag 'BF65' diff --git a/include/onomondo/ipa/ipad.h b/include/onomondo/ipa/ipad.h index 8474097..db43fac 100644 --- a/include/onomondo/ipa/ipad.h +++ b/include/onomondo/ipa/ipad.h @@ -96,6 +96,7 @@ bool eim_cfg_data, bool immediate_enable_cfg); int ipa_execute_fallback_mechanism(struct ipa_context *ctx); int ipa_return_from_fallback(struct ipa_context *ctx); +int ipa_enable_emerg_prfle(struct ipa_context *ctx); int ipa_poll(struct ipa_context *ctx); void ipa_close(struct ipa_context *ctx); struct ipa_buf *ipa_free_ctx(struct ipa_context *ctx); diff --git a/src/ipa/libasn/CMakeLists.txt b/src/ipa/libasn/CMakeLists.txt index 859578a..f25fa19 100644 --- a/src/ipa/libasn/CMakeLists.txt +++ b/src/ipa/libasn/CMakeLists.txt @@ -283,6 +283,10 @@ EimSupportedProtocol.h EmailAddress.c EmailAddress.h +EnableEmergencyProfileRequest.c +EnableEmergencyProfileRequest.h +EnableEmergencyProfileResponse.c +EnableEmergencyProfileResponse.h EnableProfileRequest.c EnableProfileRequest.h EnableProfileResponse.c diff --git a/src/ipa/libasn/EnableEmergencyProfileRequest.c b/src/ipa/libasn/EnableEmergencyProfileRequest.c new file mode 100644 index 0000000..2bbadb5 --- /dev/null +++ b/src/ipa/libasn/EnableEmergencyProfileRequest.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 "EnableEmergencyProfileRequest.h" + +static asn_TYPE_member_t asn_MBR_EnableEmergencyProfileRequest_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct EnableEmergencyProfileRequest, 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_EnableEmergencyProfileRequest_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (91 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_EnableEmergencyProfileRequest_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* refreshFlag */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_EnableEmergencyProfileRequest_specs_1 = { + sizeof(struct EnableEmergencyProfileRequest), + offsetof(struct EnableEmergencyProfileRequest, _asn_ctx), + asn_MAP_EnableEmergencyProfileRequest_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_EnableEmergencyProfileRequest = { + "EnableEmergencyProfileRequest", + "EnableEmergencyProfileRequest", + &asn_OP_SEQUENCE, + asn_DEF_EnableEmergencyProfileRequest_tags_1, + sizeof(asn_DEF_EnableEmergencyProfileRequest_tags_1) + /sizeof(asn_DEF_EnableEmergencyProfileRequest_tags_1[0]) - 1, /* 1 */ + asn_DEF_EnableEmergencyProfileRequest_tags_1, /* Same as above */ + sizeof(asn_DEF_EnableEmergencyProfileRequest_tags_1) + /sizeof(asn_DEF_EnableEmergencyProfileRequest_tags_1[0]), /* 2 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_EnableEmergencyProfileRequest_1, + 1, /* Elements count */ + &asn_SPC_EnableEmergencyProfileRequest_specs_1 /* Additional specs */ +}; + diff --git a/src/ipa/libasn/EnableEmergencyProfileRequest.h b/src/ipa/libasn/EnableEmergencyProfileRequest.h new file mode 100644 index 0000000..2eeb5a8 --- /dev/null +++ b/src/ipa/libasn/EnableEmergencyProfileRequest.h @@ -0,0 +1,42 @@ +/* + * 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 _EnableEmergencyProfileRequest_H_ +#define _EnableEmergencyProfileRequest_H_ + + +#include <asn_application.h> + +/* Including external dependencies */ +#include <BOOLEAN.h> +#include <constr_SEQUENCE.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* EnableEmergencyProfileRequest */ +typedef struct EnableEmergencyProfileRequest { + BOOLEAN_t refreshFlag; + /* + * This type is extensible, + * possible extensions are below. + */ + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} EnableEmergencyProfileRequest_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_EnableEmergencyProfileRequest; + +#ifdef __cplusplus +} +#endif + +#endif /* _EnableEmergencyProfileRequest_H_ */ +#include <asn_internal.h> diff --git a/src/ipa/libasn/EnableEmergencyProfileResponse.c b/src/ipa/libasn/EnableEmergencyProfileResponse.c new file mode 100644 index 0000000..4e8c04e --- /dev/null +++ b/src/ipa/libasn/EnableEmergencyProfileResponse.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 "EnableEmergencyProfileResponse.h" + +static asn_TYPE_member_t asn_MBR_EnableEmergencyProfileResponse_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct EnableEmergencyProfileResponse, enableEmergencyProfileResult), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + -1, /* IMPLICIT tag at current level */ + &asn_DEF_NativeInteger, + 0, + { 0, 0, 0 }, + 0, 0, /* No default value */ + "enableEmergencyProfileResult" + }, +}; +static const ber_tlv_tag_t asn_DEF_EnableEmergencyProfileResponse_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (91 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static const asn_TYPE_tag2member_t asn_MAP_EnableEmergencyProfileResponse_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* enableEmergencyProfileResult */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_EnableEmergencyProfileResponse_specs_1 = { + sizeof(struct EnableEmergencyProfileResponse), + offsetof(struct EnableEmergencyProfileResponse, _asn_ctx), + asn_MAP_EnableEmergencyProfileResponse_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_EnableEmergencyProfileResponse = { + "EnableEmergencyProfileResponse", + "EnableEmergencyProfileResponse", + &asn_OP_SEQUENCE, + asn_DEF_EnableEmergencyProfileResponse_tags_1, + sizeof(asn_DEF_EnableEmergencyProfileResponse_tags_1) + /sizeof(asn_DEF_EnableEmergencyProfileResponse_tags_1[0]) - 1, /* 1 */ + asn_DEF_EnableEmergencyProfileResponse_tags_1, /* Same as above */ + sizeof(asn_DEF_EnableEmergencyProfileResponse_tags_1) + /sizeof(asn_DEF_EnableEmergencyProfileResponse_tags_1[0]), /* 2 */ + { 0, 0, SEQUENCE_constraint }, + asn_MBR_EnableEmergencyProfileResponse_1, + 1, /* Elements count */ + &asn_SPC_EnableEmergencyProfileResponse_specs_1 /* Additional specs */ +}; + diff --git a/src/ipa/libasn/EnableEmergencyProfileResponse.h b/src/ipa/libasn/EnableEmergencyProfileResponse.h new file mode 100644 index 0000000..7ff7e36 --- /dev/null +++ b/src/ipa/libasn/EnableEmergencyProfileResponse.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 _EnableEmergencyProfileResponse_H_ +#define _EnableEmergencyProfileResponse_H_ + + +#include <asn_application.h> + +/* Including external dependencies */ +#include <NativeInteger.h> +#include <constr_SEQUENCE.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum EnableEmergencyProfileResponse__enableEmergencyProfileResult { + EnableEmergencyProfileResponse__enableEmergencyProfileResult_ok = 0, + EnableEmergencyProfileResponse__enableEmergencyProfileResult_profileNotInDisabledState = 2, + EnableEmergencyProfileResponse__enableEmergencyProfileResult_catBusy = 5, + EnableEmergencyProfileResponse__enableEmergencyProfileResult_ecallNotAvailable = 8, + EnableEmergencyProfileResponse__enableEmergencyProfileResult_undefinedError = 127 +} e_EnableEmergencyProfileResponse__enableEmergencyProfileResult; + +/* EnableEmergencyProfileResponse */ +typedef struct EnableEmergencyProfileResponse { + long enableEmergencyProfileResult; + /* + * This type is extensible, + * possible extensions are below. + */ + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} EnableEmergencyProfileResponse_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_EnableEmergencyProfileResponse; + +#ifdef __cplusplus +} +#endif + +#endif /* _EnableEmergencyProfileResponse_H_ */ +#include <asn_internal.h> diff --git a/src/ipa/libipa/CMakeLists.txt b/src/ipa/libipa/CMakeLists.txt index 45d8f4a..8b5b9f8 100644 --- a/src/ipa/libipa/CMakeLists.txt +++ b/src/ipa/libipa/CMakeLists.txt @@ -22,6 +22,7 @@ es10b_rm_notif_from_lst.c es10b_exec_fallback_mech.c es10b_ret_from_fallback.c + es10b_en_emerg_prfle.c es10c_delete_prfle.c es10c_disable_prfle.c es10c_enable_prfle.c diff --git a/src/ipa/libipa/es10b_en_emerg_prfle.c b/src/ipa/libipa/es10b_en_emerg_prfle.c new file mode 100644 index 0000000..d9db952 --- /dev/null +++ b/src/ipa/libipa/es10b_en_emerg_prfle.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2026 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 + * Andreas Eversberg aeversberg@sysmocom.de / sysmocom - s.f.m.c. GmbH + * + * See also: GSMA SGP.22, 5.9.22: Function (ES10b): EnableEmergencyProfile + */ + +#include <stdio.h> +#include <assert.h> +#include <onomondo/ipa/utils.h> +#include "context.h" +#include "utils.h" +#include "euicc.h" +#include "es10x.h" +#include "es10b_en_emerg_prfle.h" + +static const struct num_str_map error_code_strings[] = { + { EnableEmergencyProfileResponse__enableEmergencyProfileResult_ok, "ok" }, + { EnableEmergencyProfileResponse__enableEmergencyProfileResult_profileNotInDisabledState, "profileNotInDisabledState" }, + { EnableEmergencyProfileResponse__enableEmergencyProfileResult_catBusy, "catBusy" }, + { EnableEmergencyProfileResponse__enableEmergencyProfileResult_ecallNotAvailable, "ecallNotAvailable" }, + { EnableEmergencyProfileResponse__enableEmergencyProfileResult_undefinedError, "undefinedError" }, + { 0, NULL } +}; + +static int dec_en_emerg_prfle_res(struct ipa_es10b_en_emerg_prfle_res *res, const struct ipa_buf *es10b_res) +{ + struct EnableEmergencyProfileResponse *asn = NULL; + + asn = ipa_es10x_res_dec(&asn_DEF_EnableEmergencyProfileResponse, es10b_res, "EnableEmergencyProfile"); + if (!asn) + return -EINVAL; + + if (asn->enableEmergencyProfileResult != EnableEmergencyProfileResponse__enableEmergencyProfileResult_ok) { + IPA_LOGP_ES10X("EnableEmergencyProfile", LERROR, "function failed with error code %ld=%s!\n", + asn->enableEmergencyProfileResult, + ipa_str_from_num(error_code_strings, asn->enableEmergencyProfileResult, "(unknown)")); + } else { + IPA_LOGP_ES10X("EnableEmergencyProfile", LERROR, "function succeeded with status code %ld=%s!\n", + asn->enableEmergencyProfileResult, + ipa_str_from_num(error_code_strings, asn->enableEmergencyProfileResult, "(unknown)")); + } + + res->res = asn; + return 0; +} + +static struct EnableEmergencyProfileResponse *generate_en_emerg_prfle_err(void) +{ + struct EnableEmergencyProfileResponse *res = IPA_ALLOC_ZERO(struct EnableEmergencyProfileResponse); + + assert(res); + res->enableEmergencyProfileResult = EnableEmergencyProfileResponse__enableEmergencyProfileResult_undefinedError; + return res; +} + +/*! Function (Es10b): EnableEmergencyProfile. + * \param[inout] ctx pointer to ipa_context. + * \param[in] refresh_flag send a CAT refresh after enabling profile. + * \returns pointer newly allocated struct with function result, NULL on error. */ +struct ipa_es10b_en_emerg_prfle_res *ipa_es10b_en_emerg_prfle(struct ipa_context *ctx, bool refresh_flag) +{ + struct ipa_buf *es10b_req = NULL; + struct ipa_buf *es10b_res = NULL; + struct EnableEmergencyProfileRequest req = { 0 }; + struct ipa_es10b_en_emerg_prfle_res *res = IPA_ALLOC_ZERO(struct ipa_es10b_en_emerg_prfle_res); + int rc; + + if (ctx->cfg->iot_euicc_emu_enabled) { + IPA_LOGP_ES10X("EnableEmergencyProfile", LERROR, + "Unable to emulate switching to emergency profile.\n"); + res->res = generate_en_emerg_prfle_err(); + return res; + } + + req.refreshFlag = refresh_flag; + + es10b_req = ipa_es10x_req_enc(&asn_DEF_EnableEmergencyProfileRequest, &req, "EnableEmergencyProfile"); + if (!es10b_req) { + IPA_LOGP_ES10X("EnableEmergencyProfile", LERROR, "unable to encode Es10b request\n"); + goto error; + } + + es10b_res = ipa_euicc_transceive_es10x(ctx, es10b_req); + if (!es10b_res) { + IPA_LOGP_ES10X("EnableEmergencyProfile", LERROR, "no Es10b response\n"); + goto error; + } + + rc = dec_en_emerg_prfle_res(res, es10b_res); + if (rc < 0) + goto error; + + IPA_FREE(es10b_req); + IPA_FREE(es10b_res); + return res; +error: + IPA_FREE(es10b_req); + IPA_FREE(es10b_res); + ipa_es10b_en_emerg_prfle_res_free(res); + return NULL; +} + +/*! Free results of function (Es10b): EnableEmergencyProfile. + * \param[in] res pointer to function result. */ +void ipa_es10b_en_emerg_prfle_res_free(struct ipa_es10b_en_emerg_prfle_res *res) +{ + IPA_ES10X_RES_FREE(asn_DEF_EnableEmergencyProfileResponse, res); +} diff --git a/src/ipa/libipa/es10b_en_emerg_prfle.h b/src/ipa/libipa/es10b_en_emerg_prfle.h new file mode 100644 index 0000000..e40cb53 --- /dev/null +++ b/src/ipa/libipa/es10b_en_emerg_prfle.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 sysmocom - s.f.m.c. GmbH. All rights reserved. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#pragma once + +#include <EnableEmergencyProfileRequest.h> +#include <EnableEmergencyProfileResponse.h> +struct ipa_context; + +struct ipa_es10b_en_emerg_prfle_res { + struct EnableEmergencyProfileResponse *res; +}; + +struct ipa_es10b_en_emerg_prfle_res *ipa_es10b_en_emerg_prfle(struct ipa_context *ctx, bool refresh_flag); +void ipa_es10b_en_emerg_prfle_res_free(struct ipa_es10b_en_emerg_prfle_res *res); diff --git a/src/ipa/libipa/ipad.c b/src/ipa/libipa/ipad.c index d151969..e79592c 100644 --- a/src/ipa/libipa/ipad.c +++ b/src/ipa/libipa/ipad.c @@ -27,6 +27,7 @@ #include "es10b_load_euicc_pkg.h" #include "es10b_exec_fallback_mech.h" #include "es10b_ret_from_fallback.h" +#include "es10b_en_emerg_prfle.h" #include "proc_euicc_pkg_dwnld_exec.h" #include "proc_notif_delivery.h"
@@ -303,6 +304,24 @@ return rc; }
+/*! Trigger return from emergency profile to previous profile. + * \param[inout] ctx pointer to ipa_context. + * \returns 0 on success, negative on error. */ +int ipa_enable_emerg_prfle(struct ipa_context *ctx) +{ + struct ipa_es10b_en_emerg_prfle_res *res; + int rc = -EINVAL; + + res = ipa_es10b_en_emerg_prfle(ctx, ctx->cfg->refresh_flag); + if (!res) + return -EIO; + if (res->res->enableEmergencyProfileResult == EnableEmergencyProfileResponse__enableEmergencyProfileResult_ok) + rc = 0; + ipa_es10b_en_emerg_prfle_res_free(res); + + return rc; +} + static int check_canaries(struct ipa_context *ctx) { if (ctx->check_http) diff --git a/src/ipa/main.c b/src/ipa/main.c index bf54f56..c422fa7 100644 --- a/src/ipa/main.c +++ b/src/ipa/main.c @@ -30,6 +30,7 @@ OPER_EUICC_MEMORY_RESET, OPER_EXEC_FALLBACK_MECH, OPER_RETURN_FROM_FALLBACK, + OPER_ENABLE_EMERG_PRFLE, };
bool running = true; @@ -72,6 +73,7 @@ printf(" euicc-memory-reset .......... reset eUICC memory\n"); printf(" execute-fallback-mechanism .. Trigger enabling of fallback profile\n"); printf(" return-from-fallback ........ Trigger return from fallback profile to previous profile\n"); + printf(" enable-emergency-profile .... Trigger enabling of emergency profile\n"); }
struct ipa_buf *load_ber_from_file(char *dir, char *file) @@ -244,6 +246,8 @@ operation = OPER_EXEC_FALLBACK_MECH; } else if (!strcmp(argv[optind], "return-from-fallback")) { operation = OPER_RETURN_FROM_FALLBACK; + } else if (!strcmp(argv[optind], "enable-emergency-profile")) { + operation = OPER_ENABLE_EMERG_PRFLE; } else if (!!strcmp(argv[optind], "get-eim-package")) { printf("unknown operation: %s\n", argv[optind]); exit(-1); @@ -363,6 +367,10 @@ /* Trigger return from fallback profile to previous profile */ ipa_return_from_fallback(ctx); break; + case OPER_ENABLE_EMERG_PRFLE: + /* Trigger enabling of emergency profile */ + ipa_enable_emerg_prfle(ctx); + break; }
leave: