WIP: eIM_Tests: add testsuite for an eIM

Change-Id: Iba72ee00d10aba7831feedadacd943bf943de53e
Related: SYS#6824
This commit is contained in:
Philipp Maier 2024-03-11 14:57:17 +01:00
parent 485c77b99c
commit c58a455520
10 changed files with 1195 additions and 0 deletions

View File

@ -21,6 +21,7 @@ SUBDIRS= \
cbc \
ccid \
dia2gsup \
eim \
fr \
fr-net \
epdg \

141
eim/REST_Types_JSON.ttcn Normal file
View File

@ -0,0 +1,141 @@
/* 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_order {
charstring activationCode
};
type record JSON_REST_enable_psmo {
octetstring iccid,
boolean rollback
};
type record JSON_REST_disable_psmo {
octetstring iccid
};
type record JSON_REST_delete_psmo {
octetstring iccid
};
type union JSON_REST_psmo {
JSON_REST_enable_psmo enable,
JSON_REST_disable_psmo disable,
JSON_REST_delete_psmo delete
};
/* A PSMO order consists of a list of PSMOs */
type record of JSON_REST_psmo JSON_REST_psmo_order;
type union JSON_REST_order {
JSON_REST_download_order download,
JSON_REST_psmo_order psmo
};
type record JSON_REST_resource {
charstring eidValue,
JSON_REST_order order
};
type record JSON_REST_response_long {
charstring status,
charstring timestamp,
JSON_REST_resource resource,
charstring outcome
};
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"
}
/* Definition for JSON REST requests */
type union JSON_REST_request {
JSON_REST_resource resource
} 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 := "success",
timestamp := ?,
resource := ?,
outcome := ?
}
}
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 } } } }
}
} with {
encode "JSON";
}

23
eim/eIM_Tests.cfg Normal file
View File

@ -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

8
eim/eIM_Tests.default Normal file
View File

@ -0,0 +1,8 @@
[LOGGING]
mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING; // | DEBUG_ENCDEC;
[TESTPORT_PARAMETERS]
[MODULE_PARAMETERS]
[EXECUTE]

666
eim/eIM_Tests.ttcn Normal file
View File

@ -0,0 +1,666 @@
/* 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);
}
[] 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));
}
[] T.timeout {
setverdict(fail, "no response from REST API while creating download");
}
}
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");
}
}
[] T.timeout {
setverdict(fail, "no response from REST API while deleting download");
}
}
}
/* ********************************************* */
/* ************* 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(charstring id, JSON_REST_resource psmo_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(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(psmo_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(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(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(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(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);
}
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() );
}
}

235
eim/es9p_Types_JSON.ttcn Normal file
View File

@ -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";
}

46
eim/gen_links.sh Executable file
View File

@ -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

25
eim/regen_makefile.sh Executable file
View File

@ -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

23
eim/server.crt Normal file
View File

@ -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-----

27
eim/server.key Normal file
View File

@ -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-----