aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2024-03-11 14:57:17 +0100
committerPhilipp Maier <pmaier@sysmocom.de>2024-05-24 17:20:55 +0200
commit32ddca9f5920ac9d4e05ee10e062132ee7825cc1 (patch)
tree99bbfbbb6993c1f917707a951f851901311a9b5f
parent1ff26e8af920e33e763fcdb8f3fdaa8af4ecaadf (diff)
WIP: eIM_Tests: add testsuite for an eIMpmaier/ipad
-rw-r--r--Makefile1
-rw-r--r--eim/REST_Types_JSON.ttcn256
-rw-r--r--eim/eIM_Tests.cfg23
-rw-r--r--eim/eIM_Tests.default8
-rw-r--r--eim/eIM_Tests.ttcn801
-rw-r--r--eim/es9p_Types_JSON.ttcn235
-rwxr-xr-xeim/gen_links.sh46
-rwxr-xr-xeim/regen_makefile.sh25
-rw-r--r--eim/server.crt23
-rw-r--r--eim/server.key27
10 files changed, 1445 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index d216aab4..2cb63d03 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@ SUBDIRS= \
cbc \
ccid \
dia2gsup \
+ eim \
fr \
fr-net \
epdg \
diff --git a/eim/REST_Types_JSON.ttcn b/eim/REST_Types_JSON.ttcn
new file mode 100644
index 00000000..1feaa325
--- /dev/null
+++ b/eim/REST_Types_JSON.ttcn
@@ -0,0 +1,256 @@
+/* REST message definitions for eIM REST API
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module REST_Types_JSON {
+
+type record JSON_REST_download {
+ charstring activationCode
+};
+
+type union JSON_REST_psmo {
+ record {
+ octetstring iccid,
+ boolean rollback
+ } enable,
+ record {
+ octetstring iccid
+ } disable,
+ record {
+ octetstring iccid
+ } delete,
+ record {
+ union {
+ octetstring isdpAid,
+ octetstring iccid,
+ integer profileClass
+ } searchCriteria optional,
+ octetstring tagList optional
+ } listProfileInfo,
+ record {
+ } getRAT,
+ record {
+ boolean autoEnableFlag,
+ objid smdpOid optional,
+ charstring smdpAddress optional
+ } configureAutoEnable
+};
+
+type union JSON_REST_eco {
+ record {
+ /* ASN.1 pre-encoded EimConfigurationData */
+ octetstring eimConfigurationData
+ } addEim,
+ record {
+ charstring eimId
+ } deleteEim,
+ record {
+ /* ASN.1 pre-encoded EimConfigurationData */
+ octetstring eimConfigurationData
+ } updateEim,
+ record {
+ } listEim
+};
+
+type record JSON_REST_resource {
+ charstring eidValue,
+ union {
+ JSON_REST_download download,
+ record of JSON_REST_psmo psmo,
+ record of JSON_REST_eco eco
+ } order
+};
+
+type record JSON_REST_ProfileInfo {
+ charstring iccid optional,
+ charstring isdpAid optional,
+ charstring profileState optional,
+ charstring profileNickname optional,
+ charstring serviceProviderName optional,
+ charstring profileName optional,
+ charstring iconType optional,
+ charstring icon optional,
+ charstring profileClass optional
+ //TODO: notificationConfigurationInfo
+ //TODO: profileOwner
+ //TODO: dpProprietaryData
+ //TODO: profilePolicyRules
+ //TODO: serviceSpecificDataStoredInEuicc
+};
+
+type record JSON_REST_eimIdList {
+ charstring iccid,
+ charstring eimIdType optional
+}
+
+type union JSON_REST_result {
+ charstring enableResult,
+ charstring disableResult,
+ charstring deleteResult,
+ record {
+ charstring finalResult,
+ record of JSON_REST_ProfileInfo profileInfoList optional
+ } listProfileInfoResult,
+ charstring getRATResult,
+ charstring configureAutoEnableResult,
+ record {
+ charstring addEimResultCode,
+ integer associationToken optional
+ } addEimResult,
+ charstring deleteEimResult,
+ charstring updateEimResult,
+ record {
+ charstring finalResult,
+ record of JSON_REST_eimIdList eimIdList optional
+ } listEimResult,
+ charstring rollbackResult,
+ charstring processingTerminated,
+ charstring notificationResult,
+ charstring cancelSessionResult,
+ record {
+ charstring finalResult,
+ charstring iccid
+ } profileInstallationResult
+}
+
+type record JSON_REST_response_long {
+ charstring status,
+ charstring timestamp,
+ JSON_REST_resource resource,
+ record of JSON_REST_result outcome,
+ charstring debuginfo
+};
+
+type record JSON_REST_response_short {
+ charstring status
+};
+
+/* Definition for JSON REST responses */
+type union JSON_REST_response {
+ JSON_REST_response_long long,
+ JSON_REST_response_short short
+} with {
+ variant "JSON : as value"
+}
+
+external function enc_JSON_REST_response(in JSON_REST_response msg)
+return octetstring with {
+ extension "prototype (convert) encode(JSON)";
+ extension "errorbehavior(ALL:ERROR)"
+}
+external function dec_JSON_REST_response(in octetstring stream) return JSON_REST_response with {
+ extension "prototype (convert) decode(JSON)"
+ extension "errorbehavior(ALL:ERROR)"
+}
+
+external function enc_JSON_REST_resource(in JSON_REST_resource msg)
+return octetstring with {
+ extension "prototype (convert) encode(JSON)";
+ extension "errorbehavior(ALL:ERROR)"
+}
+external function dec_JSON_REST_resource(in octetstring stream) return JSON_REST_resource with {
+ extension "prototype (convert) decode(JSON)"
+ extension "errorbehavior(ALL:ERROR)"
+}
+
+
+template (present) JSON_REST_response tr_JSON_REST_success := {
+ long := {
+ status := "done",
+ timestamp := ?,
+ resource := ?,
+ outcome := ?,
+ debuginfo := ?
+ }
+}
+
+template (present) JSON_REST_response tr_JSON_REST_deleted := {
+ short := { status := "deleted" }
+}
+
+template (present) JSON_REST_response tr_JSON_REST_absent := {
+ short := { status := "absent" }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_download_order(octetstring eidValue, charstring activationCode) := {
+ eidValue := oct2str(eidValue),
+ order := { download := { activationCode := activationCode } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_enable(octetstring eidValue, octetstring iccid, boolean rollback) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { enable := { iccid := iccid, rollback := rollback } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_disable(octetstring eidValue, octetstring iccid) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { disable := { iccid := iccid } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_delete(octetstring eidValue, octetstring iccid) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { delete := { iccid := iccid } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_disable_and_delete(octetstring eidValue, octetstring iccid) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { disable := { iccid := iccid } }, { delete := { iccid := iccid } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_listProfileInfo(octetstring eidValue, octetstring iccid) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { listProfileInfo := {searchCriteria := {iccid := iccid}, tagList := '92'O /* profileName */} } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_getRAT(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { getRAT := {} } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_psmo_order_configureAutoEnable(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { psmo := { { configureAutoEnable := { autoEnableFlag := true, smdpOid := objid {1 2 3}, smdpAddress := "smdp.example.com" } } } }
+}
+
+const octetstring eimConfigurationData :=
+'30820145800365494D810E3132372E302E302E313A383030308301008401
+FFA5820126A0820122300D06092A864886F70D01010105000382010F0030
+82010A0282010100AEDD235E43D7F9FE6B122298742F41D870CE914636EF
+CF41CF968A654D4F8C97E4F11B2E0897F8ECC9321BA64CC5366BFADD3525
+802806BF7CAF17F1CC8576C27484EBD3B5AFB568DCF0BD5A6A8C74708332
+A0C23490EB6E5DBA392BCED11165C33B8EBBF8FAB6D4EA415CE96F216F8C
+F877AE9126C0DED1CC2DB00BCFF5A8A9C2D3885B8FBA21D71DB87D2000DB
+0F69D79B533EC273597C2D441D7DBC14FFC555B65AF64473CCBE24A27566
+30A2B725618573337CEF1CCD5B39BA3F3CD081B2AF33F65F0A249A9C661B
+08F49F99FF93F31923464AF23B079E405191F3B7F13CE82691A46AD4AFE2
+9CB55EA3CFA083C1D64756CC51B8CBD62AC00BE41C3AE4BB0203010001'O
+
+template (value) JSON_REST_resource ts_JSON_REST_eco_order_addEim(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { eco := { { addEim := { eimConfigurationData := eimConfigurationData } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_eco_order_deleteEim(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { eco := { { deleteEim := { eimId := "eIM" } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_eco_order_updateEim(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { eco := { { updateEim := { eimConfigurationData := eimConfigurationData } } } }
+}
+
+template (value) JSON_REST_resource ts_JSON_REST_eco_order_listEim(octetstring eidValue) := {
+ eidValue := oct2str(eidValue),
+ order := { eco := { { listEim := { } } } }
+}
+
+} with {
+ encode "JSON";
+}
diff --git a/eim/eIM_Tests.cfg b/eim/eIM_Tests.cfg
new file mode 100644
index 00000000..dfc66c84
--- /dev/null
+++ b/eim/eIM_Tests.cfg
@@ -0,0 +1,23 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./eIM_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+system.HTTP_server_port.use_notification_ASPs := "no"
+system.HTTP_server_port.KEYFILE := "/home/owner/work/ttcn3/testsuite/osmo-ttcn3-hacks/eim/server.key"
+system.HTTP_server_port.CERTIFICATEFILE := "/home/owner/work/ttcn3/testsuite/osmo-ttcn3-hacks/eim/server.crt"
+system.HTTP_server_port.PASSWORD := "katinka1"
+system.HTTP_server_port.http_debugging := "yes"
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+eIM_Tests.control
diff --git a/eim/eIM_Tests.default b/eim/eIM_Tests.default
new file mode 100644
index 00000000..95b42e94
--- /dev/null
+++ b/eim/eIM_Tests.default
@@ -0,0 +1,8 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING; // | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[EXECUTE]
diff --git a/eim/eIM_Tests.ttcn b/eim/eIM_Tests.ttcn
new file mode 100644
index 00000000..d0e7c023
--- /dev/null
+++ b/eim/eIM_Tests.ttcn
@@ -0,0 +1,801 @@
+/* eIM testsuite in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module eIM_Tests {
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from SGP32Definitions all;
+import from SGP32Definitions_Types all;
+import from SGP32Definitions_Templates all;
+
+import from RSPDefinitions all;
+import from RSPDefinitions_Types all;
+import from RSPDefinitions_Templates all;
+
+import from PKIX1Explicit88 all;
+import from PKIX1Explicit88_Templates all;
+import from PKIX1Explicit88_Types all;
+
+import from PKIX1Implicit88 all;
+import from PKIX1Implicit88_Templates all;
+import from PKIX1Implicit88_Types all;
+
+import from HTTP_Server_Emulation all;
+import from HTTPmsg_Types all;
+
+import from HTTPmsg_PortType all;
+import from HTTP_Adapter all;
+
+import from es9p_Types_JSON all;
+import from REST_Types_JSON all;
+
+/* the PIPEasp port allows us to interact with restop.py via stdin/stdout */
+import from PIPEasp_PortType all;
+import from PIPEasp_Types all;
+
+type component MTC_CT {
+ timer g_Tguard;
+
+ /* HTTP server */
+ var HTTP_Server_Emulation_CT vc_HTTP;
+};
+
+type component eIM_ConnHdlr extends HTTP_ConnHdlr, http_CT {
+ port PIPEasp_PT PIPE;
+ var eIM_ConnHdlrPars g_pars_EIM;
+ var template integer g_http_client_id := omit; /* ESipa client */
+};
+
+type record eIM_ConnHdlrPars {
+ /* TODO: add some useful parameters */
+};
+
+private function f_init_pars()
+runs on MTC_CT return eIM_ConnHdlrPars {
+ var eIM_ConnHdlrPars pars := {
+ /* TODO: fill parameters with meaninful values */
+ };
+ return pars;
+}
+
+modulepar {
+ /* emulated ES9+ SMDP+ server */
+ charstring mp_es9p_ip := "127.0.0.1";
+ integer mp_es9p_port := 8090;
+ boolean mp_es9p_disable_ssl := true;
+
+ /* emulated ESipa IPAd HTTPs client */
+ charstring mp_esipa_ip := "127.0.0.1";
+ integer mp_esipa_port := 8000;
+ boolean mp_esipa_disable_ssl := true;
+
+ /* REST API tool */
+ /* TODO: no absolute path here */
+ charstring mp_restop_path := "/home/user/work/eIM_IPAd/git/onomondo-eim/contrib/restop.py"
+}
+
+private altstep as_Tguard() runs on MTC_CT {
+ [] g_Tguard.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
+ }
+}
+
+private type function void_fn(charstring id) runs on eIM_ConnHdlr;
+
+private function f_init_handler(void_fn fn, charstring id, eIM_ConnHdlrPars pars) runs on eIM_ConnHdlr {
+ g_pars_EIM := pars;
+ fn.apply(id);
+}
+
+private function f_start_handler(void_fn fn, eIM_ConnHdlrPars pars)
+runs on MTC_CT return eIM_ConnHdlr {
+ var eIM_ConnHdlr vc_conn;
+ var charstring id := testcasename();
+
+ vc_conn := eIM_ConnHdlr.create(id);
+
+ /* connect ES9+/HTTP-server ports */
+ if (isbound(vc_HTTP)) {
+ connect(vc_conn:HTTP_SRV, vc_HTTP:CLIENT);
+ connect(vc_conn:HTTP_SRV_PROC, vc_HTTP:CLIENT_PROC);
+ }
+
+ vc_conn.start(f_init_handler(fn, id, pars));
+ return vc_conn;
+}
+
+private function f_init(charstring id, float t_guard := 40.0) runs on MTC_CT {
+ g_Tguard.start(t_guard);
+ activate(as_Tguard());
+
+ /* start ES9+/HTTP-server */
+ var HttpServerEmulationCfg http_cfg := {
+ http_bind_ip := mp_es9p_ip,
+ http_bind_port := mp_es9p_port,
+ use_ssl := not mp_es9p_disable_ssl
+ };
+ vc_HTTP := HTTP_Server_Emulation_CT.create(id);
+ vc_HTTP.start(HTTP_Server_Emulation.main(http_cfg));
+}
+
+
+
+/* ********************************************* */
+/* ************* ES9+/HTTP-server ************** */
+/* ********************************************* */
+
+/* Helper function to send HTTP responses (ES9+) */
+private function f_make_http_resp(charstring resp) return HTTPMessage {
+ var HTTPMessage resp_msg;
+ var HTTPResponse resp_body := {
+ client_id := omit,
+ version_major := 1,
+ version_minor := 1,
+ statuscode := 200,
+ statustext := "OK",
+ /* See also SGP.32, section 6.1.1 */
+ header := {
+ {
+ header_name := "X-Admin-Protocol",
+ header_value := "gsma/rsp/v1.0.0"
+ },
+ {
+ header_name := "Content-Type",
+ header_value := "application/json"
+ },
+ {
+ header_name := "Content-Length",
+ header_value := int2str(lengthof(resp))
+ }
+ },
+ body := resp
+ };
+
+ resp_msg := { response := resp_body };
+ return resp_msg;
+}
+
+/* Receive one Es9p HTTP request */
+private function f_es9p_receive() runs on eIM_ConnHdlr return RemoteProfileProvisioningRequest {
+ var HTTPMessage es9p_req;
+ timer T := 10.0;
+ var RemoteProfileProvisioningRequest request;
+
+ T.start;
+ alt {
+ [] HTTP_SRV.receive({ request := ? }) -> value es9p_req {
+ dec_RemoteProfileProvisioningRequest_from_JSON(es9p_req.request.body, request);
+ }
+ [] T.timeout {
+ setverdict(fail, "no HTTP request received?");
+ }
+ }
+
+ return request;
+}
+
+/* Send Es9p HTTP response */
+private function f_es9p_send(RemoteProfileProvisioningResponse response) runs on eIM_ConnHdlr {
+ var charstring es9p_res;
+ enc_RemoteProfileProvisioningResponse_to_JSON(response, es9p_res);
+ HTTP_SRV.send(f_make_http_resp(es9p_res));
+}
+
+/* Perform Es9p HTTP request/response cycle */
+private function f_es9p_transceive(RemoteProfileProvisioningResponse response)
+runs on eIM_ConnHdlr return RemoteProfileProvisioningRequest {
+ var RemoteProfileProvisioningRequest request;
+ request := f_es9p_receive();
+ f_es9p_send(response);
+ return request;
+}
+
+/* Perform Es9p HTTP request/response cycle but with an empty response */
+private function f_es9p_transceive_empty_response()
+runs on eIM_ConnHdlr return RemoteProfileProvisioningRequest {
+ var RemoteProfileProvisioningResponse response; /* Intentionally left unbound */
+ return f_es9p_transceive(response);
+}
+
+
+
+/* ********************************************* */
+/* ************ PIPEasp (REST API) ************* */
+/* ********************************************* */
+
+template (value) ASP_PExecute ts_Exec(charstring cmd) := {
+ command := cmd,
+ stdin := ""
+}
+
+template (present) ASP_PResult tr_Result(template (present) charstring stdout,
+ template (present) charstring stderr,
+ template (present) integer code) := {
+ stdout := stdout,
+ stderr := stderr,
+ code := code
+}
+
+private function f_init_pipe() runs on eIM_ConnHdlr {
+ map(self:PIPE, system:PIPE);
+}
+
+/* Create a new rest resource (generic) */
+private function f_rest_create(charstring cmdline)
+runs on eIM_ConnHdlr return charstring {
+ var ASP_PResult result;
+
+ PIPE.send(ts_Exec(cmdline));
+ timer T := 4.0;
+ T.start;
+ alt {
+ [] PIPE.receive(tr_Result(?,?,0)) -> value result {
+ /* On success, stdout should contain an URL to a resource */
+ if (substr(result.stdout, 0, 7) != "http://") {
+ setverdict(fail, "got malformed resource URL from REST API while creating resource");
+ }
+ return regexp(result.stdout, "(?+)(lookup/)(?+)", 2);
+ }
+ [] PIPE.receive {
+ setverdict(fail, "unexpected response from REST API while creating resource");
+ }
+ [] T.timeout {
+ setverdict(fail, "no response from REST API while creating resource");
+ }
+ }
+
+ setverdict(fail, "got no resource URL from REST API while creating resource");
+ return "no resource";
+}
+
+/* Create a new rest resource (download) */
+private function f_rest_create_dwnld(octetstring eID, charstring activationCode)
+runs on eIM_ConnHdlr return charstring {
+ var charstring cmdline;
+ cmdline := mp_restop_path & " -c -f download -j " &
+ oct2char(enc_JSON_REST_resource(valueof(ts_JSON_REST_download_order(eID, activationCode))))
+ return f_rest_create(cmdline);
+}
+
+/* Create a new rest resource (psmo) */
+private function f_rest_create_psmo(template JSON_REST_resource psmo_order)
+runs on eIM_ConnHdlr return charstring {
+ var charstring cmdline;
+ cmdline := mp_restop_path & " -c -f psmo -j " &
+ oct2char(enc_JSON_REST_resource(valueof(psmo_order)));
+ return f_rest_create(cmdline);
+}
+
+/* Lookup an existing REST resource */
+private function f_rest_lookup_resource(charstring resource_id, charstring facility,
+ template JSON_REST_response expected_rest_res := omit)
+runs on eIM_ConnHdlr return JSON_REST_response {
+ var charstring cmdline;
+ var ASP_PResult result;
+ var JSON_REST_response rest_res;
+
+ cmdline := mp_restop_path & " -l -f " & facility & " -r " & resource_id;
+
+ PIPE.send(ts_Exec(cmdline));
+ timer T := 4.0;
+ T.start;
+ alt {
+ [] PIPE.receive(tr_Result(?,?,0)) -> value result {
+ rest_res := dec_JSON_REST_response(char2oct(result.stdout));
+ }
+ [] PIPE.receive {
+ setverdict(fail, "unexpected response from REST API while looking up resource");
+ }
+ [] T.timeout {
+ setverdict(fail, "no response from REST API while looking up resource");
+ }
+ }
+
+ if (not istemplatekind(expected_rest_res, "omit") and not match(rest_res, tr_JSON_REST_success)) {
+ setverdict(fail, "unexpected REST lookup result from eIM");
+ }
+
+ return rest_res;
+}
+
+/* Delete REST resource */
+private function f_rest_delete_resource(charstring resource_id, charstring facility)
+runs on eIM_ConnHdlr {
+ var charstring cmdline;
+ var ASP_PResult result;
+ var JSON_REST_response rest_res;
+ cmdline := mp_restop_path & " -d -f " & facility & " -r " & resource_id;
+
+ PIPE.send(ts_Exec(cmdline));
+ timer T := 4.0;
+ T.start;
+ alt {
+ [] PIPE.receive(tr_Result(?,?,0)) -> value result {
+ /* Verify that the resource has been deleted */
+ rest_res := dec_JSON_REST_response(char2oct(result.stdout));
+ if (not match(rest_res, tr_JSON_REST_deleted)) {
+ setverdict(fail, "unexpected REST delete result from eIM");
+ }
+
+ /* Make sure that the resource has really been deleted */
+ if (not match(f_rest_lookup_resource(resource_id, facility), tr_JSON_REST_absent)) {
+ setverdict(fail, "unexpected REST result from eIM while checking resource deletion");
+ }
+
+ }
+ [] PIPE.receive {
+ setverdict(fail, "unexpected response from REST API while deleting resource");
+ }
+ [] T.timeout {
+ setverdict(fail, "no response from REST API while deleting resource");
+ }
+ }
+}
+
+
+
+/* ********************************************* */
+/* ************* ESipa/HTTP-client ************* */
+/* ********************************************* */
+
+private function f_enc_http_req(in RemoteProfileProvisioningResponse es9p_res, out HTTPMessage http_res) {
+ var charstring json_body;
+ var HTTPResponse resp_body;
+
+ enc_RemoteProfileProvisioningResponse_to_JSON(es9p_res, json_body);
+ resp_body := {
+ client_id := omit,
+ version_major := 1,
+ version_minor := 1,
+ statuscode := 200,
+ statustext := "OK",
+ /* See also SGP.32, section 6.1.1 */
+ header := {
+ {
+ header_name := "X-Admin-Protocol",
+ header_value := "gsma/rsp/v1.0.0"
+ },
+ {
+ header_name := "Content-Type",
+ header_value := "application/x-gsma-rsp-asn1"
+ },
+ {
+ header_name := "Content-Length",
+ header_value := int2str(lengthof(json_body))
+ }
+ },
+ body := json_body
+ };
+
+ http_res := { response := resp_body };
+} with { extension "prototype(fast)" }
+
+template (value) HeaderLines ts_esipa_HTTP_Header := {
+ { header_name := "User-Agent", header_value := "TTCN3 eIM testsuite" },
+ { header_name := "X-Admin-Protocol", header_value := "gsma/rsp/v2.5.0" },
+ { header_name := "Content-Type", header_value := "application/x-gsma-rsp-asn1" }
+};
+
+/* Send ESipa HTTP request */
+private function f_esipa_send(EsipaMessageFromIpaToEim request) runs on eIM_ConnHdlr {
+ var octetstring request_enc;
+ request_enc := enc_EsipaMessageFromIpaToEim(request);
+ f_http_tx_request(url := "/gsma/rsp2/asn1",
+ method := "POST",
+ binary_body:= request_enc,
+ custom_hdr := valueof(ts_esipa_HTTP_Header),
+ client_id := g_http_client_id);
+}
+
+/* Receive ESipa HTTP response */
+private function f_esipa_receive() runs on eIM_ConnHdlr return template EsipaMessageFromEimToIpa {
+
+ var HTTPMessage response_http;
+ response_http := f_http_rx_response(exp := ?,
+ client_id := g_http_client_id,
+ keep_connection := true);
+
+ if (istemplatekind(g_http_client_id, "omit")) {
+ /* Memorize client_id of the first request. The client_id will identify the HTTP connection
+ * in all consecutive requests. */
+ g_http_client_id := f_http_client_id_from_http_response(response_http);
+ } else if (valueof(g_http_client_id) != valueof(f_http_client_id_from_http_response(response_http))) {
+ /* The client_id must not change. A sudden change of the client_id may indicate an interrupted
+ * HTTP connection. This must not happen unexpectetly. */
+ setverdict(fail, "unexpected ESipa HTTP connection");
+ }
+
+ if (ispresent(response_http.response_binary)) {
+ return dec_EsipaMessageFromEimToIpa(response_http.response_binary.body);
+ } else {
+ setverdict(fail, "unexpected ESipa response, the HTTP body did either contain no or a non binary response");
+ return omit;
+ }
+}
+
+/* Perform one ESipa HTTP request/response cycle */
+private function f_esipa_transceive(EsipaMessageFromIpaToEim request)
+runs on eIM_ConnHdlr return template EsipaMessageFromEimToIpa {
+ f_esipa_send(request);
+ return f_esipa_receive();
+}
+
+
+
+/* ********************************************* */
+/* ********** BELOW ONLY TESTCASES! ************ */
+/* ********************************************* */
+
+/* Common Mutual Authentication Procedure, see also: GSMA SGP.22, section 3.0.1 */
+private function f_proc_cmn_mtl_auth() runs on eIM_ConnHdlr {
+ var EsipaMessageFromIpaToEim esipa_req;
+ var template EsipaMessageFromEimToIpa esipa_res;
+ var template RemoteProfileProvisioningRequest es9p_req;
+ var RemoteProfileProvisioningResponse es9p_res;
+
+ /* InitiateAuthentication cycle */
+ esipa_req := valueof(ts_initiateAuthenticationRequestEsipa(smdpAddress := mp_es9p_ip & ":" & int2str(mp_es9p_port)));
+ f_esipa_send(esipa_req);
+
+ es9p_res := valueof(ts_initiateAuthenticationResponse);
+ es9p_req := f_es9p_transceive(es9p_res);
+ if (not match(valueof(es9p_req), tr_initiateAuthenticationRequest)) {
+ setverdict(fail, "unexpected request from eIM on ES9p");
+ }
+
+ esipa_res := f_esipa_receive();
+ if (not match(valueof(esipa_res), tr_initiateAuthenticationResponseEsipa)) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+
+ /* AuthenticateClient cycle */
+ esipa_req := valueof(ts_authenticateClientRequestEsipa);
+ f_esipa_send(esipa_req);
+
+ es9p_res := valueof(ts_authenticateClientResponseEs9);
+ es9p_req := f_es9p_transceive(es9p_res);
+ if (not match(valueof(es9p_req), tr_authenticateClientRequest)) {
+ setverdict(fail, "unexpected request from eIM on ES9p");
+ }
+
+ esipa_res := f_esipa_receive();
+ if (not match(valueof(esipa_res), tr_authenticateClientResponseEsipa_dpe)) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+}
+
+/* A testcase to try out an indirect profile download,
+ * See also: GSMA SGP.32, section 3.2.3.2: Indirect Profile Download */
+private function f_TC_proc_indirect_prfle_dwnld(charstring id) runs on eIM_ConnHdlr {
+ var charstring resource_id;
+ var HTTP_Adapter_Params http_adapter_pars;
+ var EsipaMessageFromIpaToEim esipa_req;
+ var template EsipaMessageFromEimToIpa esipa_res;
+ var template RemoteProfileProvisioningRequest es9p_req;
+ var RemoteProfileProvisioningResponse es9p_res;
+
+ var charstring activationCode := "1$" & mp_es9p_ip & ":" & int2str(mp_es9p_port) & "$MyMatchingId"
+ var octetstring eID := '89882119900000000000000000000005'O
+
+ f_http_register();
+
+ f_init_pipe();
+ http_adapter_pars := {
+ http_host := mp_esipa_ip,
+ http_port := mp_esipa_port,
+ use_ssl := not mp_esipa_disable_ssl
+ };
+ f_http_init(http_adapter_pars);
+
+ /* Create a new download at the eIM */
+ resource_id := f_rest_create_dwnld(eID, activationCode);
+
+ /* Check the eIM for new eIM packages, we expect to get a profileDownloadTriggerRequest that contains the activationCode
+ * that we have created the download with (see above) */
+ esipa_req := valueof(ts_getEimPackageRequest(eID));
+ esipa_res := valueof(f_esipa_transceive(esipa_req));
+ if (not match(valueof(esipa_res), tr_getEimPackageResponse_dnlTrigReq(activationCode))) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+
+ /* Perform common mutial authentication procedure */
+ f_proc_cmn_mtl_auth();
+
+ /* Request/download bound profile package */
+ esipa_req := valueof(ts_getBoundProfilePackageRequestEsipa);
+ f_esipa_send(esipa_req);
+ es9p_res := valueof(ts_getBoundProfilePackageResponse);
+ es9p_req := f_es9p_transceive(es9p_res);
+ if (not match(valueof(es9p_req), tr_getBoundProfilePackageRequest)) {
+ setverdict(fail, "unexpected request from eIM on ES9p");
+ }
+ esipa_res := f_esipa_receive();
+ if (not match(valueof(esipa_res), tr_getBoundProfilePackageResponseEsipa)) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+
+ /* Handle notification */
+ esipa_req := valueof(ts_handleNotificationEsipa_prfleInstRslt);
+ f_esipa_send(esipa_req);
+ es9p_req := f_es9p_transceive_empty_response();
+ if (not match(valueof(es9p_req), tr_handleNotification)) {
+ setverdict(fail, "unexpected request from eIM on ES9p");
+ }
+
+ f_rest_lookup_resource(resource_id, "download", tr_JSON_REST_success);
+ f_rest_delete_resource(resource_id, "download");
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_proc_indirect_prfle_dwnld() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_indirect_prfle_dwnld), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* A testcase to try out an the Generic eUICC Package Download and Execution Procedure (PSMO),
+ * See also: GSMA SGP.32, section 3.3.1: Generic eUICC Package Download and Execution */
+private function f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(charstring id, JSON_REST_resource order,
+ template (present) EuiccPackage euiccPackage,
+ template (present) EuiccPackageResult euiccPackageResult) runs on eIM_ConnHdlr {
+ var charstring resource_id;
+ var HTTP_Adapter_Params http_adapter_pars;
+ var EsipaMessageFromIpaToEim esipa_req;
+ var template EsipaMessageFromEimToIpa esipa_res;
+ var template RemoteProfileProvisioningRequest es9p_req;
+ var RemoteProfileProvisioningResponse es9p_res;
+
+ f_http_register();
+
+ f_init_pipe();
+ http_adapter_pars := {
+ http_host := mp_esipa_ip,
+ http_port := mp_esipa_port,
+ use_ssl := not mp_esipa_disable_ssl
+ };
+ f_http_init(http_adapter_pars);
+
+ /* Create a new download at the eIM */
+ resource_id := f_rest_create_psmo(order);
+
+ /* Check the eIM for new eIM packages, we expect to get an euiccPackageRequest that contains the PSMO
+ * that we have created (see above) */
+ esipa_req := valueof(ts_getEimPackageRequest(str2oct(order.eidValue)));
+ esipa_res := valueof(f_esipa_transceive(esipa_req));
+ if (not match(valueof(esipa_res), tr_getEimPackageResponse_euiccPkgReq(euiccPackage))) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+
+ /* Respond with a plausible EimPackage result */
+ esipa_req := valueof(ts_provideEimPackageResult_ePRAndNotif(euiccPackageResult));
+ esipa_res := valueof(f_esipa_transceive(esipa_req));
+ if (not match(valueof(esipa_res), tr_provideEimPackageResultResponse_eimAck)) {
+ setverdict(fail, "unexpected response from eIM on ESipa");
+ }
+
+ f_rest_lookup_resource(resource_id, "psmo", tr_JSON_REST_success);
+ f_rest_delete_resource(resource_id, "psmo");
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+
+/* (see also above) Test enable PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_enable_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_enable(eID, '123456789ABCDEFFAAAA'O, false));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_enablePsmo;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_enablePsmo);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_enable_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_enable_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test disable PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_disable_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_disable(eID, '123456789ABCDEFFAAAA'O));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_disablePsmo;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_disablePsmo);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_disable_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_disable_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test delete PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_delete_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_delete(eID, '123456789ABCDEFFAAAA'O));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_deletePsmo;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_deletePsmo);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_delete_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_delete_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test disable and delete PSMO at the same time to make sure that eUICC packages with multiple PSMOs
+ * are also accepted and processed correctly. */
+private function f_TC_proc_euicc_pkg_dwnld_exec_disable_and_delete_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_disable_and_delete(eID, '123456789ABCDEFFAAAA'O));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_disableAndDeletePsmo;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_disableAndDeletePsmo);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_disable_and_delete_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_disable_and_delete_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test listProfileInfo PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_listProfileInfo_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_listProfileInfo(eID, '123456789ABCDEFFAAAA'O));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_listProfileInfo;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_listProfileInfo);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_listProfileInfo_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_listProfileInfo_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test getRAT PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_getRAT_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_getRAT(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_getRAT;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_getRAT);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_getRAT_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_getRAT_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test configureAutoEnable PSMO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_configureAutoEnable_psmo(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource psmo_order := valueof(ts_JSON_REST_psmo_order_configureAutoEnable(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_configureAutoEnable;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, psmo_order, euiccPackage, ts_euiccPackageResultSigned_configureAutoEnable);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_configureAutoEnable_psmo() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_configureAutoEnable_psmo), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test addEim eCO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_addEim_eco(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource eco_order := valueof(ts_JSON_REST_eco_order_addEim(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_addEim;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, eco_order, euiccPackage, ts_euiccPackageResultSigned_addEim);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_addEim_eco() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_addEim_eco), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test deleteEim eCO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_deleteEim_eco(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource eco_order := valueof(ts_JSON_REST_eco_order_deleteEim(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_deleteEim;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, eco_order, euiccPackage, ts_euiccPackageResultSigned_deleteEim);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_deleteEim_eco() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_deleteEim_eco), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test updateEim eCO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_updateEim_eco(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource eco_order := valueof(ts_JSON_REST_eco_order_updateEim(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_updateEim;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, eco_order, euiccPackage, ts_euiccPackageResultSigned_updateEim);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_updateEim_eco() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_updateEim_eco), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* (see also above) Test listEim eCO */
+private function f_TC_proc_euicc_pkg_dwnld_exec_listEim_eco(charstring id) runs on eIM_ConnHdlr {
+ var octetstring eID := '89882119900000000000000000000005'O;
+ var JSON_REST_resource eco_order := valueof(ts_JSON_REST_eco_order_listEim(eID));
+ var template EuiccPackage euiccPackage := tr_euiccPackage_listEim;
+ f_TC_proc_euicc_pkg_dwnld_exec_psmo_or_eco(id, eco_order, euiccPackage, ts_euiccPackageResultSigned_listEim);
+}
+testcase TC_proc_euicc_pkg_dwnld_exec_listEim_eco() runs on MTC_CT {
+ var charstring id := testcasename();
+ var eIM_ConnHdlrPars pars := f_init_pars();
+ var eIM_ConnHdlr vc_conn;
+ f_init(id);
+ vc_conn := f_start_handler(refers(f_TC_proc_euicc_pkg_dwnld_exec_updateEim_eco), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+control {
+ execute ( TC_proc_indirect_prfle_dwnld() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_enable_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_disable_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_delete_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_disable_and_delete_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_listProfileInfo_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_getRAT_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_configureAutoEnable_psmo() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_addEim_eco() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_deleteEim_eco() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_updateEim_eco() );
+ execute ( TC_proc_euicc_pkg_dwnld_exec_listEim_eco() );
+}
+
+} \ No newline at end of file
diff --git a/eim/es9p_Types_JSON.ttcn b/eim/es9p_Types_JSON.ttcn
new file mode 100644
index 00000000..5a8587b2
--- /dev/null
+++ b/eim/es9p_Types_JSON.ttcn
@@ -0,0 +1,235 @@
+/* JSON message definitions for ES9+
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module es9p_Types_JSON {
+
+import from RSPDefinitions all;
+import from RSPDefinitions_Types all;
+import from RSPDefinitions_Templates all;
+
+import from PKIX1Explicit88 all;
+import from PKIX1Explicit88_Templates all;
+import from PKIX1Explicit88_Types all;
+
+import from PKIX1Implicit88 all;
+import from PKIX1Implicit88_Templates all;
+import from PKIX1Implicit88_Types all;
+
+
+/* GSMA SGP.22, section 6.5.1.3 */
+type record JSON_ES9p_RequestHeader {
+ charstring functionRequesterIdentifier,
+ charstring functionCallIdentifier
+};
+
+/* GSMA SGP.22, section 6.5.1.4 */
+type record JSON_ES9p_FunctionExecutionStatus {
+ charstring status
+};
+type record JSON_ES9p_ResponseHeader {
+ JSON_ES9p_FunctionExecutionStatus functionExecutionStatus
+};
+
+/* GSMA SGP.22, section 6.5.2.6 */
+type record JSON_ES9p_InitiateAuthenticationRequest {
+ JSON_ES9p_RequestHeader header,
+ charstring euiccChallenge,
+ charstring euiccInfo1,
+ charstring smdpAddress
+};
+type record JSON_ES9p_InitiateAuthenticationResponse {
+ JSON_ES9p_ResponseHeader header,
+ charstring transactionId,
+ charstring serverSigned1,
+ charstring serverSignature1,
+ charstring euiccCiPKIdToBeUsed,
+ charstring serverCertificate
+};
+
+/* GSMA SGP.22, section 6.5.2.7 */
+type record JSON_ES9p_GetBoundProfilePackageRequest {
+ JSON_ES9p_RequestHeader header,
+ charstring transactionId,
+ charstring prepareDownloadResponse
+};
+type record JSON_ES9p_GetBoundProfilePackageResponse {
+ JSON_ES9p_ResponseHeader header,
+ charstring transactionId,
+ charstring boundProfilePackage
+};
+
+/* GSMA SGP.22, section 6.5.2.8 */
+type record JSON_ES9p_AuthenticateClientRequest {
+ JSON_ES9p_RequestHeader header,
+ charstring transactionId,
+ charstring authenticateServerResponse
+};
+type record JSON_ES9p_AuthenticateClientResponseEs9 {
+ JSON_ES9p_ResponseHeader header,
+ charstring transactionId,
+ charstring profileMetadata,
+ charstring smdpSigned2,
+ charstring smdpSignature2,
+ charstring smdpCertificate
+};
+
+/* GSMA SGP.22, section 6.5.2.9 */
+type record JSON_ES9p_HandleNotification {
+ JSON_ES9p_RequestHeader header,
+ charstring pendingNotification
+};
+
+/* GSMA SGP.22, section 6.5.2.10 */
+type record JSON_ES9p_CancelSessionRequestEs9 {
+ JSON_ES9p_RequestHeader header,
+ charstring transactionId,
+ charstring cancelSessionResponse
+};
+
+/* An empty response that is used when the response only consists of a JSON header */
+type record JSON_ES9p_EmptyResponse {
+ JSON_ES9p_ResponseHeader header
+};
+
+
+/* Definition for JSON ES9+ requests */
+type union JSON_ES9p_RemoteProfileProvisioningRequest {
+ JSON_ES9p_InitiateAuthenticationRequest initiateAuthenticationRequest,
+ JSON_ES9p_GetBoundProfilePackageRequest getBoundProfilePackageRequest,
+ JSON_ES9p_AuthenticateClientRequest authenticateClientRequest,
+ JSON_ES9p_HandleNotification handleNotification,
+ JSON_ES9p_CancelSessionRequestEs9 cancelSessionRequestEs9
+} with {
+ variant "JSON : as value"
+}
+
+external function enc_JSON_ES9p_RemoteProfileProvisioningRequest(in JSON_ES9p_RemoteProfileProvisioningRequest msg) return octetstring
+with {
+ extension "prototype (convert) encode(JSON)";
+ extension "printing(pretty)";
+ extension "errorbehavior(ALL:ERROR)"
+}
+external function dec_JSON_ES9p_RemoteProfileProvisioningRequest(in octetstring stream) return JSON_ES9p_RemoteProfileProvisioningRequest
+with {
+ extension "prototype (convert) decode(JSON)"
+ extension "errorbehavior(ALL:ERROR)"
+}
+
+
+/* Definition for JSON ES9+ responses */
+type union JSON_ES9p_RemoteProfileProvisioningResponse
+{
+ JSON_ES9p_InitiateAuthenticationResponse initiateAuthenticationResponse,
+ JSON_ES9p_GetBoundProfilePackageResponse getBoundProfilePackageResponse,
+ JSON_ES9p_AuthenticateClientResponseEs9 authenticateClientResponseEs9,
+ JSON_ES9p_EmptyResponse emptyResponse
+} with {
+ variant "JSON : as value"
+}
+
+external function enc_JSON_ES9p_RemoteProfileProvisioningResponse(in JSON_ES9p_RemoteProfileProvisioningResponse msg) return octetstring
+with {
+ extension "prototype (convert) encode(JSON)";
+ extension "printing(pretty)";
+ extension "errorbehavior(ALL:ERROR)"
+}
+external function dec_JSON_ES9p_RemoteProfileProvisioningResponse(in octetstring stream) return JSON_ES9p_RemoteProfileProvisioningResponse
+with {
+ extension "prototype (convert) decode(JSON)"
+ extension "errorbehavior(ALL:ERROR)"
+}
+
+/* Converter function to decode a JSON formatted ES9+ request to its ASN.1 ES9+ record representation */
+function dec_RemoteProfileProvisioningRequest_from_JSON(in charstring json_pdu_enc, out RemoteProfileProvisioningRequest asn1_pdu_dec) {
+ var JSON_ES9p_RemoteProfileProvisioningRequest json_pdu;
+ json_pdu := dec_JSON_ES9p_RemoteProfileProvisioningRequest(char2oct(json_pdu_enc));
+
+ if (ispresent(json_pdu.initiateAuthenticationRequest)) {
+ asn1_pdu_dec := valueof(ts_initiateAuthenticationRequest(
+ decode_base64(json_pdu.initiateAuthenticationRequest.euiccChallenge),
+ json_pdu.initiateAuthenticationRequest.smdpAddress,
+ dec_EUICCInfo1(decode_base64(json_pdu.initiateAuthenticationRequest.euiccInfo1))));
+ } else if (ispresent(json_pdu.getBoundProfilePackageRequest)) {
+ asn1_pdu_dec := valueof(ts_getBoundProfilePackageRequest(
+ str2oct(json_pdu.getBoundProfilePackageRequest.transactionId),
+ dec_PrepareDownloadResponse(decode_base64(json_pdu.getBoundProfilePackageRequest.prepareDownloadResponse))));
+ } else if (ispresent(json_pdu.authenticateClientRequest)) {
+ asn1_pdu_dec := valueof(ts_authenticateClientRequest(
+ str2oct(json_pdu.authenticateClientRequest.transactionId),
+ dec_AuthenticateServerResponse(decode_base64(json_pdu.authenticateClientRequest.authenticateServerResponse))));
+ } else if (ispresent(json_pdu.handleNotification)) {
+ asn1_pdu_dec := valueof(ts_handleNotification(
+ dec_PendingNotification(decode_base64(json_pdu.handleNotification.pendingNotification))));
+ } else if (ispresent(json_pdu.cancelSessionRequestEs9)) {
+ asn1_pdu_dec := valueof(ts_cancelSessionRequestEs9(
+ str2oct(json_pdu.cancelSessionRequestEs9.transactionId),
+ dec_CancelSessionResponse(decode_base64(json_pdu.cancelSessionRequestEs9.cancelSessionResponse))));
+ } else {
+ setverdict(fail, "decoder path not implemented for JSON ES9+ message");
+ }
+} with { extension "prototype(fast)" }
+
+/* Converter function to encode an ASN.1 ES9+ response record to its JSON formatted ES9+ representation */
+function enc_RemoteProfileProvisioningResponse_to_JSON(in RemoteProfileProvisioningResponse asn1_pdu_dec, out charstring json_pdu_enc) {
+ var JSON_ES9p_RemoteProfileProvisioningResponse json_pdu;
+
+ if (ispresent(asn1_pdu_dec.initiateAuthenticationResponse)) {
+ json_pdu.initiateAuthenticationResponse.header.functionExecutionStatus.status := "Executed-Success";
+ json_pdu.initiateAuthenticationResponse.transactionId :=
+ oct2str(asn1_pdu_dec.initiateAuthenticationResponse.initiateAuthenticationOk.transactionId);
+ json_pdu.initiateAuthenticationResponse.serverSigned1 :=
+ encode_base64(enc_ServerSigned1(asn1_pdu_dec.initiateAuthenticationResponse.initiateAuthenticationOk.serverSigned1));
+ json_pdu.initiateAuthenticationResponse.serverSignature1 :=
+ encode_base64(asn1_pdu_dec.initiateAuthenticationResponse.initiateAuthenticationOk.serverSignature1);
+ json_pdu.initiateAuthenticationResponse.euiccCiPKIdToBeUsed :=
+ encode_base64(enc_SubjectKeyIdentifier(asn1_pdu_dec.initiateAuthenticationResponse.initiateAuthenticationOk.euiccCiPKIdToBeUsed));
+ json_pdu.initiateAuthenticationResponse.serverCertificate :=
+ encode_base64(enc_Certificate(asn1_pdu_dec.initiateAuthenticationResponse.initiateAuthenticationOk.serverCertificate));
+ json_pdu_enc := oct2char(enc_JSON_ES9p_RemoteProfileProvisioningResponse(json_pdu));
+ } else if (ispresent(asn1_pdu_dec.getBoundProfilePackageResponse)) {
+ json_pdu.getBoundProfilePackageResponse.header.functionExecutionStatus.status := "Executed-Success";
+ json_pdu.getBoundProfilePackageResponse.transactionId :=
+ oct2str(asn1_pdu_dec.getBoundProfilePackageResponse.getBoundProfilePackageOk.transactionId);
+ json_pdu.getBoundProfilePackageResponse.boundProfilePackage :=
+ encode_base64(enc_BoundProfilePackage(asn1_pdu_dec.getBoundProfilePackageResponse.getBoundProfilePackageOk.boundProfilePackage));
+ json_pdu_enc := oct2char(enc_JSON_ES9p_RemoteProfileProvisioningResponse(json_pdu));
+ } else if (ispresent(asn1_pdu_dec.authenticateClientResponseEs9)) {
+ json_pdu.authenticateClientResponseEs9.header.functionExecutionStatus.status := "Executed-Success";
+ json_pdu.authenticateClientResponseEs9.transactionId :=
+ oct2str(asn1_pdu_dec.authenticateClientResponseEs9.authenticateClientOk.transactionId);
+ json_pdu.authenticateClientResponseEs9.profileMetadata :=
+ encode_base64(enc_StoreMetadataRequest(asn1_pdu_dec.authenticateClientResponseEs9.authenticateClientOk.profileMetaData));
+ json_pdu.authenticateClientResponseEs9.smdpSigned2 :=
+ encode_base64(enc_SmdpSigned2(asn1_pdu_dec.authenticateClientResponseEs9.authenticateClientOk.smdpSigned2));
+ json_pdu.authenticateClientResponseEs9.smdpSignature2 :=
+ encode_base64(asn1_pdu_dec.authenticateClientResponseEs9.authenticateClientOk.smdpSignature2);
+ json_pdu.authenticateClientResponseEs9.smdpCertificate :=
+ encode_base64(enc_Certificate(asn1_pdu_dec.authenticateClientResponseEs9.authenticateClientOk.smdpCertificate));
+ json_pdu_enc := oct2char(enc_JSON_ES9p_RemoteProfileProvisioningResponse(json_pdu));
+ } else if (ispresent(asn1_pdu_dec.cancelSessionResponseEs9)) {
+ /* This message has no JSON body, see also GSMA SGP.22, section 6.5.2.10 */
+ json_pdu.emptyResponse.header.functionExecutionStatus.status := "Executed-Success";
+ json_pdu_enc := oct2char(enc_JSON_ES9p_RemoteProfileProvisioningResponse(json_pdu));
+ } else if (ispresent(asn1_pdu_dec.authenticateClientResponseEs11)) {
+ setverdict(fail, "encoder path not implemented for JSON ES9+ message AuthenticateClientResponseEs11");
+ } else {
+ json_pdu.emptyResponse.header.functionExecutionStatus.status := "Executed-Success";
+ json_pdu_enc := oct2char(enc_JSON_ES9p_RemoteProfileProvisioningResponse(json_pdu));
+ }
+} with { extension "prototype(fast)" }
+
+} with {
+ encode "JSON";
+}
+
+
+
+
+
diff --git a/eim/gen_links.sh b/eim/gen_links.sh
new file mode 100755
index 00000000..4bb1ea8c
--- /dev/null
+++ b/eim/gen_links.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Abstract_Socket/src
+FILES="Abstract_Socket.cc Abstract_Socket.hh "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.HTTPmsg/src
+FILES="HTTPmsg_MessageLen.ttcn HTTPmsg_MessageLen_Function.cc HTTPmsg_PT.cc HTTPmsg_PT.hh HTTPmsg_PortType.ttcn "
+FILES+="HTTPmsg_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
+FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn "
+FILES+="IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.PIPEasp/src
+FILES="PIPEasp_PT.cc PIPEasp_PT.hh PIPEasp_Types.ttcn PIPEasp_PortType.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library/euicc
+FILES="PEDefinitions.asn PKIX1Explicit88.asn PKIX1Implicit88.asn RSPDefinitions.asn SGP32Definitions.asn "
+FILES+="PKIX1Explicit88_Templates.ttcn PKIX1Explicit88_Types.ttcn PKIX1Implicit88_Templates.ttcn "
+FILES+="PKIX1Implicit88_Types.ttcn RSPDefinitions_Templates.ttcn RSPDefinitions_Types.ttcn "
+FILES+="SGP32Definitions_Templates.ttcn SGP32Definitions_Types.ttcn "
+FILES+="PKIX1Explicit88_EncDec.cc PKIX1Implicit88_EncDec.cc RSPDefinitions_EncDec.cc SGP32Definitions_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="HTTP_Server_Emulation.ttcn HTTP_Adapter.ttcn"
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/eim/regen_makefile.sh b/eim/regen_makefile.sh
new file mode 100755
index 00000000..cc0fd8ef
--- /dev/null
+++ b/eim/regen_makefile.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+NAME=eIM_Tests
+
+FILES="
+ *.ttcn
+ *.asn
+ Abstract_Socket.cc
+ HTTPmsg_MessageLen_Function.cc
+ HTTPmsg_PT.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ SGP32Definitions_EncDec.cc
+ RSPDefinitions_EncDec.cc
+ PKIX1Explicit88_EncDec.cc
+ PKIX1Implicit88_EncDec.cc
+ PIPEasp_PT.cc
+"
+../regen-makefile.sh eIM_Tests.ttcn $FILES
+
+# required for forkpty(3) used by PIPEasp
+sed -i -e '/^LINUX_LIBS/ s/$/ -lutil/' Makefile
diff --git a/eim/server.crt b/eim/server.crt
new file mode 100644
index 00000000..c113a770
--- /dev/null
+++ b/eim/server.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDyTCCArECFEz9Tzs8MSJUbUSExuS62RPPnfhjMA0GCSqGSIb3DQEBCwUAMIGg
+MQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4x
+HTAbBgNVBAoMFElQQWQgdGVzdCBpbmR1c3RyaWVzMRswGQYDVQQLDBJ0ZXN0aW5n
+IGRlcGFydG1lbnQxEjAQBgNVBAMMCTEyNy4wLjAuMTEfMB0GCSqGSIb3DQEJARYQ
+dGVzdEBleGFtcGxlLm5ldDAeFw0yNDAxMTUxMDMxMTJaFw0yNTAxMTQxMDMxMTJa
+MIGgMQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJs
+aW4xHTAbBgNVBAoMFElQQWQgdGVzdCBpbmR1c3RyaWVzMRswGQYDVQQLDBJ0ZXN0
+aW5nIGRlcGFydG1lbnQxEjAQBgNVBAMMCTEyNy4wLjAuMTEfMB0GCSqGSIb3DQEJ
+ARYQdGVzdEBleGFtcGxlLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAK7dI15D1/n+axIimHQvQdhwzpFGNu/PQc+WimVNT4yX5PEbLgiX+OzJMhum
+TMU2a/rdNSWAKAa/fK8X8cyFdsJ0hOvTta+1aNzwvVpqjHRwgzKgwjSQ625dujkr
+ztERZcM7jrv4+rbU6kFc6W8hb4z4d66RJsDe0cwtsAvP9aipwtOIW4+6IdcduH0g
+ANsPadebUz7Cc1l8LUQdfbwU/8VVtlr2RHPMviSidWYworclYYVzM3zvHM1bObo/
+PNCBsq8z9l8KJJqcZhsI9J+Z/5PzGSNGSvI7B55AUZHzt/E86CaRpGrUr+KctV6j
+z6CDwdZHVsxRuMvWKsAL5Bw65LsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAnPK4
+dyWCA9mYm5swYEcavhtyJvNwZ1zEp/MHJ40egZFpSnGqNbpEYgjCmqCrpHQxU1Qc
+CtgXKgQMuUbvzJio5Mdp1JeSWJD18cBEhWcuufVMvN/HqMw/yJBCmizarUKjRNrE
+o2C1P9287fUWdzGxXYPtevMV0E1DQ6v+xTnt1/gyiCtElctYO3f7tkioTmWXGzJY
+AyelLfp0F/+lX3Ep1uUIvO7Dofzu+tKilbqqZjBO+gqPQFPRXrbXO90p7bvBieb5
+dBG2segL2hmzYzfKXnKaXU42CgyJgJ2DFChz3RwD41Y8q53wrZjjqM5e8rLNwJEI
+dBbKBUSZVr0r9mY7dA==
+-----END CERTIFICATE-----
diff --git a/eim/server.key b/eim/server.key
new file mode 100644
index 00000000..936d6034
--- /dev/null
+++ b/eim/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEArt0jXkPX+f5rEiKYdC9B2HDOkUY2789Bz5aKZU1PjJfk8Rsu
+CJf47MkyG6ZMxTZr+t01JYAoBr98rxfxzIV2wnSE69O1r7Vo3PC9WmqMdHCDMqDC
+NJDrbl26OSvO0RFlwzuOu/j6ttTqQVzpbyFvjPh3rpEmwN7RzC2wC8/1qKnC04hb
+j7oh1x24fSAA2w9p15tTPsJzWXwtRB19vBT/xVW2WvZEc8y+JKJ1ZjCityVhhXMz
+fO8czVs5uj880IGyrzP2XwokmpxmGwj0n5n/k/MZI0ZK8jsHnkBRkfO38TzoJpGk
+atSv4py1XqPPoIPB1kdWzFG4y9YqwAvkHDrkuwIDAQABAoIBAQCN/JQ+c7pIjTSl
+uh+un7zIofipb6kmGlWm2OcxkJAaajAFMvuzEKuYoVolp2hI7oLJZZtFAwX9TLlS
+d4/ocSrYhMJ1tyedMCGg3X3zj/bSiZWOo4huJIp2yHZw+8hobMcDuzWQHoB9uu8n
++ei2SyEIB60uu0ALdiJGt4ZuYQNpWm55+TwC7j33+8dnPQQof+2vlxMhKoQmZV68
+2VK01o+P1184CqYisecjmKK1zqEvvHFr0QV5hjznZwJXA3eshJe2hydAI3aDamAz
+ZD3j54nKtGkwSB4W82SCHEzANTwF5QQYEUiKiGu8EjeTNpSlQ1P4Szf9tjx3rc2m
+gcot2YXRAoGBAOQyGQWazJ8EjNDwguc6qeOkSgnWq6HyxcATY9lB2QsPGDs6h6bM
+wfnrqEMD8DWyzCuFNtAHcV+KZaNWnGPSQT8pEGGFPgIuH0xSIKbuzu8bE1lv88jU
+nPrR+2+N0bd98ilVLQHRb3IlT9FswBF3c2wAm9+c7LoNJ/7pMUM7YQizAoGBAMQr
+geewxNjNd8p5NdAi3wp7W8e5XzoJ4iK6y8fnCm2XsVTROtP8xxc6dI4I3OcUzYIa
+woN0+RZ1PudC5oGmkPsXzoyORqjAuCOfrYZ62pg7pwRemGGq2Mk+eHfo09d1PrMT
+HpkzNRNOk/+pcyKfWUm81NTILPRm/XbIhB6d2+fZAoGBANsg9IA6T2YgQ2zcmIed
+AMk12VcrSrOAYr74n7hgECEbhKRTpzHYjCkHUBPSc1fNc1wTVzha/VbGmqVIJXOB
+0t/o+e77uTj0u19ZujszNYnMUT9gTxS6fmgpPi64W/u9OM7SGR8W09Mj20r7CFF9
+iFvdFdGcaoKa4Z5apdCu85YbAoGAW3EAY9S1XW4hecMYf4XRvBwWgzn4lqBGxfOW
+y/75kG5WXfgN2QUKdNxtukuNVTYQOaZpp0deWMacZMZ9lk/jYvgM8t3bOAxliU2E
+YJxhyvZ7ewDxPQ2bcetp0lM4dEWVzXmLGNSS2AYX3OPK5Ies4j9gYjNRKTfczILZ
+e0AQYrkCgYEAjJk1an5S6JQMMcdU1KX0uAUJOVu1xkkTvUBYOaC3VzeyYhMJXdOC
+g8z/xrFDm7spyCbQPfsA3RHb40ZiGpb2oYhdunEI3f3ZW7RVJSdVeeZAP+IXZOCd
+v4+rGNjjXLfpK+TOGkeSNkOivAvpw0mzskCRDfKcsndtwC28OElzCPc=
+-----END RSA PRIVATE KEY-----