import LPA library implementation from TruPhone

Converted to gradle build and updated a bunch of dependencies.
This commit is contained in:
Peter Cai 2022-04-29 18:05:10 -04:00
parent 93f1d1baf1
commit 9ca4ce2798
100 changed files with 7773 additions and 4 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@
.externalNativeBuild .externalNativeBuild
.cxx .cxx
local.properties local.properties
/libs/**/build

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" /> <bytecodeTargetLevel target="1.8">
<module name="OpenEUICC.app" target="11" />
</bytecodeTargetLevel>
</component> </component>
</project> </project>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
@ -11,6 +12,8 @@
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" /> <option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/libs" />
<option value="$PROJECT_DIR$/libs/lpad-sm-dp-plus-connector" />
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -32,7 +32,7 @@ android {
} }
dependencies { dependencies {
implementation project(":libs:lpad-sm-dp-plus-connector")
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0' implementation 'com.google.android.material:material:1.5.0'

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="target/generated-sources/asn1">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>lpad-sm-dp-plus-connector</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,6 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//target/generated-sources/asn1=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=false

View File

@ -0,0 +1,9 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,36 @@
apply plugin: 'java'
configurations {
tool
}
dependencies {
tool 'javax.xml.bind:jaxb-api:2.3.0'
tool 'com.beanit:asn1bean-compiler:1.13.0'
implementation 'com.beanit:asn1bean:1.13.0'
implementation 'com.fazecast:jSerialComm:1.3.11'
implementation 'org.apache.commons:commons-lang3:3.7'
implementation 'commons-io:commons-io:2.6'
implementation 'commons-codec:commons-codec:1.11'
implementation 'com.google.code.gson:gson:2.8.4'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-all:1.10.19'
testImplementation 'com.github.tomakehurst:wiremock:2.17.0'
}
sourceSets.main.java.srcDirs = ['build/generated-sources/asn1','src/main/java']
task genAsn1(type: JavaExec) {
mainClass = 'com.beanit.asn1bean.compiler.Compiler'
args "-o", "$projectDir/build/generated-sources/asn1", "-p", "com.truphone.rsp.dto.asn1", "-f", "$projectDir/src/main/resources/PKIXExplicit88.asn", "$projectDir/src/main/resources/PKIXImplicit88.asn", "$projectDir/src/main/resources/rsp.asn"
classpath configurations.tool
}
compileJava.dependsOn genAsn1
description = 'LPAd SM-DP+ Connector'
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>lpad-sm-dp-plus-parent</artifactId>
<groupId>com.truphone.lpad</groupId>
<version>1.0.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lpad-sm-dp-plus-connector</artifactId>
<name>LPAd SM-DP+ Connector</name>
<dependencies>
<dependency>
<groupId>org.openmuc</groupId>
<artifactId>jasn1-compiler</artifactId>
</dependency>
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>${java.version}</compilerVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>${exec-maven-plugin.version}</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<mainClass>org.openmuc.jasn1.compiler.Compiler</mainClass>
<arguments>
<argument>-o</argument>
<argument>${project.basedir}/target/generated-sources/asn1/</argument>
<argument>-p</argument>
<argument>com.truphone.rsp.dto.asn1</argument>
<argument>-f</argument>
<argument>${project.basedir}/src/main/resources/PKIXExplicit88.asn</argument>
<argument>${project.basedir}/src/main/resources/PKIXImplicit88.asn</argument>
<argument>${project.basedir}/src/main/resources/rsp.asn</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${build-helper-maven-plugin}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/target/generated-sources/asn1/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.truphone.lpa.ProfileAssistant</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<configuration>
<archive>
<manifest>
<mainClass>com.truphone.lpa.ProfileAssistant</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,59 @@
package com.truphone.es9plus;
public class AllocateProfileResponse {
private String acFormat;
private String smDpPlusAddress;
private String acToken;
private String smDpPlusOid;
private String confirmationCodeRequiredFlag;
public String getAcFormat() {
return acFormat;
}
public void setAcFormat(String acFormat) {
this.acFormat = acFormat;
}
public String getSmDpPlusAddress() {
return smDpPlusAddress;
}
public void setSmDpPlusAddress(String smDpPlusAddress) {
this.smDpPlusAddress = smDpPlusAddress;
}
public String getAcToken() {
return acToken;
}
public void setAcToken(String acToken) {
this.acToken = acToken;
}
public String getSmDpPlusOid() {
return smDpPlusOid;
}
public void setSmDpPlusOid(String smDpPlusOid) {
this.smDpPlusOid = smDpPlusOid;
}
public String getConfirmationCodeRequiredFlag() {
return confirmationCodeRequiredFlag;
}
public void setConfirmationCodeRequiredFlag(String confirmationCodeRequiredFlag) {
this.confirmationCodeRequiredFlag = confirmationCodeRequiredFlag;
}
}

View File

@ -0,0 +1,216 @@
package com.truphone.es9plus;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.truphone.es9plus.message.request.AuthenticateClientReq;
import com.truphone.es9plus.message.request.GetBoundProfilePackageReq;
import com.truphone.es9plus.message.request.HandleNotificationReq;
import com.truphone.es9plus.message.request.InitiateAuthenticationReq;
import com.truphone.es9plus.message.response.AuthenticateClientResp;
import com.truphone.es9plus.message.response.GetBoundProfilePackageResp;
import com.truphone.es9plus.message.response.InitiateAuthenticationResp;
import com.truphone.util.LogStub;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Es9PlusImpl {
private static final Gson GS = new GsonBuilder().disableHtmlEscaping().create();
private static final Logger LOG = Logger.getLogger(Es9PlusImpl.class.getName());
private static final String INITIATE_AUTHENTICATION_PATH = "/gsma/rsp2/es9plus/initiateAuthentication";
private static final String AUTHENTICATE_CLIENT_PATH = "/gsma/rsp2/es9plus/authenticateClient";
private static final String GET_BOUND_PROFILE_PACKAGE_PATH = "/gsma/rsp2/es9plus/getBoundProfilePackage";
private static final String HANDLE_NOTIFICATION_PATH = "/gsma/rsp2/es9plus/handleNotification";
//private static final String ALLOCATE_PROFILE_PATH = "/custom/profile/";
// private String rspServerUrl;
// public void configure(String rspServerUrl) {
//
// this.rspServerUrl = rspServerUrl;
// }
public InitiateAuthenticationResp initiateAuthentication(final String euiccChallenge,
final String euiccInfo1,
final String smdpAddress) {
try {
InitiateAuthenticationReq initiateAuthenticationReq = new InitiateAuthenticationReq();
initiateAuthenticationReq.setEuiccChallenge(euiccChallenge);
initiateAuthenticationReq.setEuiccInfo1(euiccInfo1);
initiateAuthenticationReq.setSmdpAddress(smdpAddress);
String body = GS.toJson(initiateAuthenticationReq);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Request: " + body);
}
HttpResponse result = new HttpRSPClient().clientRSPRequest(body, "https://"+smdpAddress, INITIATE_AUTHENTICATION_PATH);
if (result != null && !"".equals(result.getContent())) {
String response = toJsonString(result.getContent());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Response: " + response);
}
return GS.fromJson(response, InitiateAuthenticationResp.class);
}
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error contacting RSP Server", e);
throw new RuntimeException("Unable to communicate with RSP Server");
}
return null;
}
public AuthenticateClientResp authenticateClient(final String transactionId,
final String authenticateServerResponse,
final String smdpAddress) {
try {
AuthenticateClientReq authenticateClientReq = new AuthenticateClientReq();
authenticateClientReq.setTransactionId(transactionId);
authenticateClientReq.setAuthenticateServerResponse(authenticateServerResponse);
String body = GS.toJson(authenticateClientReq);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Request: " + body);
}
HttpResponse result = new HttpRSPClient().clientRSPRequest(body, "https://" + smdpAddress, AUTHENTICATE_CLIENT_PATH);
if (result != null && !"".equals(result.getContent())) {
String response = toJsonString(result.getContent());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Response: " + response);
}
return GS.fromJson(response, AuthenticateClientResp.class);
} else {
LOG.severe("Error contacting RSP Server");
throw new RuntimeException("Unable to communicate with RSP Server");
}
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error contacting RSP Server", e);
throw new RuntimeException("Unable to communicate with RSP Server");
}
}
public GetBoundProfilePackageResp getBoundProfilePackage(final String transactionId,
final String prepareDownloadResponse,
final String smdpAddress) {
try {
GetBoundProfilePackageReq getBoundProfilePackageReq = new GetBoundProfilePackageReq();
getBoundProfilePackageReq.setTransactionId(transactionId);
getBoundProfilePackageReq.setPrepareDownloadResponse(prepareDownloadResponse);
String body = GS.toJson(getBoundProfilePackageReq);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Request: " + body);
}
HttpResponse result = new HttpRSPClient().clientRSPRequest(body, "https://" + smdpAddress, GET_BOUND_PROFILE_PACKAGE_PATH);
if (result != null && !"".equals(result.getContent())) {
String response = toJsonString(result.getContent());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Response: " + response);
}
return GS.fromJson(response, GetBoundProfilePackageResp.class);
}
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error contacting RSP Server", e);
throw new RuntimeException("Unable to communicate with RSP Server");
}
return null;
}
/**
* ES9+.handleNotification
*/
public void handleNotification(final String pendingNotification, String serverAddress) {
try {
HandleNotificationReq handleNotificationReq = new HandleNotificationReq();
handleNotificationReq.setPendingNotification(pendingNotification);
String body = GS.toJson(handleNotificationReq);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Request: " + body);
}
HttpResponse result = new HttpRSPClient().clientRSPRequest(body, "https://"+serverAddress, HANDLE_NOTIFICATION_PATH);
if (result != null && result.getStatusCode() == 204) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, "RSP Response was 204 ");
}
} else {
LOG.severe("Error contacting RSP Server or not 204: " + result);
throw new RuntimeException("Unable to handle notification with RSP Server");
}
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error contacting RSP Server", e);
throw new RuntimeException("Unable to handle notification with RSP Server");
}
}
// public AllocateProfileResponse allocateProfile(final String eid,
// final String mcc) {
//
// try {
// String body = "eid=" + eid + "&mcc=" + mcc;
//
// if (LogStub.getInstance().isDebugEnabled()) {
// LogStub.getInstance().logDebug(LOG, "RSP Request: " + body);
// }
//
// HttpResponse result = new HttpRSPClient().clientSimpleRequest(body, rspServerUrl, ALLOCATE_PROFILE_PATH);
//
// if (result != null && !"".equals(result.getContent())) {
// if (LogStub.getInstance().isDebugEnabled()) {
// LogStub.getInstance().logDebug(LOG, "RSP Response: " + result);
// }
//
// return getAllocateProfileResponse(result.getContent());
// } else {
// throw new RuntimeException("No profile could be allocated");
// }
// } catch (Exception e) {
// LOG.log(Level.SEVERE, e.getMessage(), e);
//
// throw new RuntimeException("Unable to allocate profile with RSP Server");
// }
// }
private AllocateProfileResponse getAllocateProfileResponse(final String content) {
AllocateProfileResponse allocateProfileResponse = null;
String fixedContent = content != null ? (content.startsWith("$") ? content.substring(1) : content) : "";
String[] responseTokens = fixedContent.split("\\$");
if (responseTokens.length > 1) {
allocateProfileResponse = new AllocateProfileResponse();
allocateProfileResponse.setAcFormat(responseTokens[0]);
allocateProfileResponse.setSmDpPlusAddress(responseTokens[1]);
allocateProfileResponse.setAcToken(responseTokens.length > 2 ? responseTokens[2] : "");
allocateProfileResponse.setSmDpPlusOid(responseTokens.length > 3 ? responseTokens[3] : null);
allocateProfileResponse.setConfirmationCodeRequiredFlag(responseTokens.length > 4 ? responseTokens[4] : null);
}
return allocateProfileResponse;
}
private String toJsonString(final String msg) {
int index = msg.indexOf("{");
return msg.substring(index);
}
}

View File

@ -0,0 +1,122 @@
package com.truphone.es9plus;
import com.truphone.util.LogStub;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
public class HttpRSPClient {
private static final Logger LOG = Logger.getLogger(HttpRSPClient.class.getName());
public HttpResponse clientRSPRequest(final String body,
final String rspServerUrl,
final String url) throws Exception {
Pair<String, String> contentType = new Pair<>("Content-Type", "application/json");
Pair<String, String> accept = new Pair<>("Accept", "application/json");
Pair<String, String> userAgent = new Pair<>("User-Agent", "gsma-rsp-com.truphone.lpad");
Pair<String, String> xAdminProtocol = new Pair<>("X-Admin-Protocol", "gsma/rsp/v2.2.0");
return invoke("POST", body, rspServerUrl, url, Arrays.asList(contentType, accept, userAgent, xAdminProtocol));
}
public HttpResponse clientSimpleRequest(final String body,
final String rspServerUrl,
final String url) throws Exception {
Pair<String, String> contentType = new Pair<>("Content-type", "application/x-www-form-urlencoded");
Pair<String, String> userAgent = new Pair<>("User-Agent", "gsma-rsp-com.truphone.lpad");
Pair<String, String> xAdminProtocol = new Pair<>("X-Admin-Protocol", "gsma/rsp/v2.2.0");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - HttpRSPClient - clientSimpleRequest parameters - body : " +
body + " rspServerUrl:" + rspServerUrl + " contentType: " + contentType + " user agent: " + userAgent +
" xAdminProtocol: " + xAdminProtocol + " url: " + url);
}
return invoke("POST", body, rspServerUrl, url, Arrays.asList(contentType, userAgent, xAdminProtocol));
}
private HttpResponse invoke(final String method,
final String body,
final String rspServerUrl,
final String url,
final List<Pair<String, String>> headers) throws Exception {
StringBuilder endpoint = new StringBuilder(rspServerUrl);
HttpResponse httpResponse = new HttpResponse();
if (StringUtils.isNotBlank(url)) {
endpoint.append(url);
}
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - HttpRSPClient - invoke URL: " + endpoint.toString());
}
URL urlResource = new URL(endpoint.toString());
HttpURLConnection con = (HttpURLConnection) urlResource.openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestMethod(method);
con.setConnectTimeout(600000);
con.setReadTimeout(600000);
if (headers != null) {
for (Pair<String, String> header : headers) {
con.setRequestProperty(header.getKey(), header.getValue());
}
}
OutputStream os = con.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(body);
writer.flush();
writer.close();
os.close();
httpResponse.setStatusCode(con.getResponseCode());
httpResponse.setContent(IOUtils.toString(con.getInputStream(), StandardCharsets.UTF_8));
return httpResponse;
}
private class Pair<T, E> {
private T key;
private E value;
public Pair(T key, E value) {
this.key = key;
this.value = value;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
}

View File

@ -0,0 +1,26 @@
package com.truphone.es9plus;
public class HttpResponse {
private String content;
private int statusCode;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
}

View File

@ -0,0 +1,10 @@
package com.truphone.es9plus;
public class LpaUtils {
public static String generateCtxParams1() {
return "";
}
}

View File

@ -0,0 +1,4 @@
package com.truphone.es9plus.message;
public interface MsgBody {
}

View File

@ -0,0 +1,12 @@
package com.truphone.es9plus.message;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgType {
String value();
}

View File

@ -0,0 +1,28 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es9plus/authenticateClient")
public class AuthenticateClientReq extends RequestMsgBody {
private String transactionId;
private String authenticateServerResponse;
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getAuthenticateServerResponse() {
return authenticateServerResponse;
}
public void setAuthenticateServerResponse(String authenticateServerResponse) {
this.authenticateServerResponse = authenticateServerResponse;
}
}

View File

@ -0,0 +1,37 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es9plus/cancelSession")
public class CancelSessionReq extends RequestMsgBody {
private String transactionId;
private String euiccCancelSessionSigned;
private String euiccCancelSessionSignature;
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getEuiccCancelSessionSigned() {
return euiccCancelSessionSigned;
}
public void setEuiccCancelSessionSigned(String euiccCancelSessionSigned) {
this.euiccCancelSessionSigned = euiccCancelSessionSigned;
}
public String getEuiccCancelSessionSignature() {
return euiccCancelSessionSignature;
}
public void setEuiccCancelSessionSignature(String euiccCancelSessionSignature) {
this.euiccCancelSessionSignature = euiccCancelSessionSignature;
}
}

View File

@ -0,0 +1,53 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es2plus/confirmOrder")
public class ConfirmOrderReq extends RequestMsgBody {
private String iccid;
private String eid;
private String matchingId;
private String comfirmationCode;
private String smdsAddress;
private boolean releaseFlag;
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
public String getEid() {
return eid;
}
public void setEid(String eid) {
this.eid = eid;
}
public String getMatchingId() {
return matchingId;
}
public void setMatchingId(String matchingId) {
this.matchingId = matchingId;
}
public String getComfirmationCode() {
return comfirmationCode;
}
public void setComfirmationCode(String comfirmationCode) {
this.comfirmationCode = comfirmationCode;
}
public String getSmdsAddress() {
return smdsAddress;
}
public void setSmdsAddress(String smdsAddress) {
this.smdsAddress = smdsAddress;
}
public boolean getReleaseFlag() {
return releaseFlag;
}
public void setReleaseFlag(boolean releaseFlag) {
this.releaseFlag = releaseFlag;
}
}

View File

@ -0,0 +1,45 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es2plus/downloadOrder")
public class DownloadOrderReq extends RequestMsgBody {
private String eid;
private String iccid;
private String profileType;
private String msisdn;
public String getMsisdn() {
return msisdn;
}
public void setMsisdn(String msisdn) {
this.msisdn = msisdn;
}
public String getEid() {
return eid;
}
public void setEid(String eid) {
this.eid = eid;
}
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
public String getProfileType() {
return profileType;
}
public void setProfileType(String profileType) {
this.profileType = profileType;
}
}

View File

@ -0,0 +1,28 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es9plus/getBoundProfilePackage")
public class GetBoundProfilePackageReq extends RequestMsgBody {
private String transactionId;
private String prepareDownloadResponse;
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getPrepareDownloadResponse() {
return prepareDownloadResponse;
}
public void setPrepareDownloadResponse(String prepareDownloadResponse) {
this.prepareDownloadResponse = prepareDownloadResponse;
}
}

View File

@ -0,0 +1,74 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
import java.util.Date;
@MsgType("/gsma/rsp2/es2plus/handleDownloadProgressInfo")
public class HandleDownloadProgressInfoReq extends RequestMsgBody {
private String eid;
private String iccid;
private String profileType;
private Date timestamp;
private int notificationPointId;
private String notificationPointStatus;
private String resultData;
public String getEid() {
return eid;
}
public void setEid(String eid) {
this.eid = eid;
}
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
public String getProfileType() {
return profileType;
}
public void setProfileType(String profileType) {
this.profileType = profileType;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
public int getNotificationPointId() {
return notificationPointId;
}
public void setNotificationPointId(int notificationPointId) {
this.notificationPointId = notificationPointId;
}
public String getNotificationPointStatus() {
return notificationPointStatus;
}
public void setNotificationPointStatus(String notificationPointStatus) {
this.notificationPointStatus = notificationPointStatus;
}
public String getResultData() {
return resultData;
}
public void setResultData(String resultData) {
this.resultData = resultData;
}
}

View File

@ -0,0 +1,19 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es9plus/handleNotification")
public class HandleNotificationReq extends RequestMsgBody {
private String pendingNotification;
public String getPendingNotification() {
return pendingNotification;
}
public void setPendingNotification(String pendingNotification) {
this.pendingNotification = pendingNotification;
}
}

View File

@ -0,0 +1,37 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es9plus/initiateAuthentication")
public class InitiateAuthenticationReq extends RequestMsgBody {
private String euiccChallenge;
private String euiccInfo1;
private String smdpAddress;
public String getEuiccChallenge() {
return euiccChallenge;
}
public void setEuiccChallenge(String euiccChallenge) {
this.euiccChallenge = euiccChallenge;
}
public String getEuiccInfo1() {
return euiccInfo1;
}
public void setEuiccInfo1(String euiccInfo1) {
this.euiccInfo1 = euiccInfo1;
}
public String getSmdpAddress() {
return smdpAddress;
}
public void setSmdpAddress(String smdpAddress) {
this.smdpAddress = smdpAddress;
}
}

View File

@ -0,0 +1,19 @@
package com.truphone.es9plus.message.request;
import com.truphone.es9plus.message.MsgType;
import com.truphone.es9plus.message.request.base.RequestMsgBody;
@MsgType("/gsma/rsp2/es2plus/releaseProfile")
public class ReleaseProfileReq extends RequestMsgBody {
private String iccid;
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
}

View File

@ -0,0 +1,12 @@
package com.truphone.es9plus.message.request.base;
import com.truphone.es9plus.message.MsgBody;
import java.security.InvalidParameterException;
public abstract class RequestMsgBody implements MsgBody {
public void checkParameters() throws InvalidParameterException {
}
}

View File

@ -0,0 +1,63 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class AuthenticateClientResp extends ResponseMsgBody {
private String transactionID;
private String profileMetadata;
private String smdpSigned2;
private String smdpSignature2;
private String smdpCertificate;
public String getTransactionID() {
return transactionID;
}
public void setTransactionID(String transactionID) {
this.transactionID = transactionID;
}
public String getProfileMetadata() {
return profileMetadata;
}
public void setProfileMetadata(String profileMetadata) {
this.profileMetadata = profileMetadata;
}
public String getSmdpSigned2() {
return smdpSigned2;
}
public void setSmdpSigned2(String smdpSigned2) {
this.smdpSigned2 = smdpSigned2;
}
public String getSmdpSignature2() {
return smdpSignature2;
}
public void setSmdpSignature2(String smdpSignature2) {
this.smdpSignature2 = smdpSignature2;
}
public String getSmdpCertificate() {
return smdpCertificate;
}
public void setSmdpCertificate(String smdpCertificate) {
this.smdpCertificate = smdpCertificate;
}
@Override
public String toString() {
return "AuthenticateClientResp{" +
"transactionID='" + transactionID + '\'' +
", profileMetadata='" + profileMetadata + '\'' +
", smdpSigned2='" + smdpSigned2 + '\'' +
", smdpSignature2='" + smdpSignature2 + '\'' +
", smdpCertificate='" + smdpCertificate + '\'' +
'}';
}
}

View File

@ -0,0 +1,8 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class CancelSessionResp extends ResponseMsgBody {
}

View File

@ -0,0 +1,34 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class ConfirmOrderResp extends ResponseMsgBody {
private String eid;
private String matchingId;
private String smdpAddress;
public String getEid() {
return eid;
}
public void setEid(String eid) {
this.eid = eid;
}
public String getMatchingId() {
return matchingId;
}
public void setMatchingId(String matchingId) {
this.matchingId = matchingId;
}
public String getSmdpAddress() {
return smdpAddress;
}
public void setSmdpAddress(String smdpAddress) {
this.smdpAddress = smdpAddress;
}
}

View File

@ -0,0 +1,17 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class DownloadOrderResp extends ResponseMsgBody {
private String iccid;
public String getIccid() {
return iccid;
}
public void setIccid(String iccid) {
this.iccid = iccid;
}
}

View File

@ -0,0 +1,26 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class GetBoundProfilePackageResp extends ResponseMsgBody {
private String transactionID;
private String boundProfilePackage;
public String getTransactionID() {
return transactionID;
}
public void setTransactionID(String transactionID) {
this.transactionID = transactionID;
}
public String getBoundProfilePackage() {
return boundProfilePackage;
}
public void setBoundProfilePackage(String boundProfilePackage) {
this.boundProfilePackage = boundProfilePackage;
}
}

View File

@ -0,0 +1,8 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class HandleDownloadProgressInfoResp extends ResponseMsgBody {
}

View File

@ -0,0 +1,8 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class HandleNotificationResp extends ResponseMsgBody {
}

View File

@ -0,0 +1,64 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class InitiateAuthenticationResp extends ResponseMsgBody {
private String transactionId;
private String serverSigned1;
private String serverSignature1;
private String euiccCiPKIdToBeUsed;
private String serverCertificate;
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getServerSigned1() {
return serverSigned1;
}
public void setServerSigned1(String serverSigned1) {
this.serverSigned1 = serverSigned1;
}
public String getServerSignature1() {
return serverSignature1;
}
public void setServerSignature1(String serverSignature1) {
this.serverSignature1 = serverSignature1;
}
public String getEuiccCiPKIdToBeUsed() {
return euiccCiPKIdToBeUsed;
}
public void setEuiccCiPKIdToBeUsed(String euiccCiPKIdToBeUsed) {
this.euiccCiPKIdToBeUsed = euiccCiPKIdToBeUsed;
}
public String getServerCertificate() {
return serverCertificate;
}
public void setServerCertificate(String serverCertificate) {
this.serverCertificate = serverCertificate;
}
@Override
public String toString() {
return "InitiateAuthenticationResp{" +
"transactionId='" + transactionId + '\'' +
", serverSigned1='" + serverSigned1 + '\'' +
", serverSignature1='" + serverSignature1 + '\'' +
", euiccCiPKIdToBeUsed='" + euiccCiPKIdToBeUsed + '\'' +
", serverCertificate='" + serverCertificate + '\'' +
'}';
}
}

View File

@ -0,0 +1,8 @@
package com.truphone.es9plus.message.response;
import com.truphone.es9plus.message.response.base.ResponseMsgBody;
public class ReleaseProfileResp extends ResponseMsgBody {
}

View File

@ -0,0 +1,33 @@
package com.truphone.es9plus.message.response.base;
public class FunctionExecutionStatus {
private String status;
private StatusCodeData statusCodeData;
public FunctionExecutionStatus(String status) {
super();
this.status = status;
}
public FunctionExecutionStatus(String status, StatusCodeData statusCodeData) {
super();
this.status = status;
this.statusCodeData = statusCodeData;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public StatusCodeData getStatusCodeData() {
return statusCodeData;
}
public void setStatusCodeData(StatusCodeData statusCodeData) {
this.statusCodeData = statusCodeData;
}
}

View File

@ -0,0 +1,19 @@
package com.truphone.es9plus.message.response.base;
public class HeaderResp {
private FunctionExecutionStatus functionExecutionStatus;
public HeaderResp(FunctionExecutionStatus functionExecutionStatus) {
super();
this.functionExecutionStatus = functionExecutionStatus;
}
public FunctionExecutionStatus getFunctionExecutionStatus() {
return functionExecutionStatus;
}
public void setFunctionExecutionStatus(FunctionExecutionStatus functionExecutionStatus) {
this.functionExecutionStatus = functionExecutionStatus;
}
}

View File

@ -0,0 +1,24 @@
package com.truphone.es9plus.message.response.base;
public class NotificationPointStatus {
private String status;
private StatusCodeData statusCodeData;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public StatusCodeData getStatusCodeData() {
return statusCodeData;
}
public void setStatusCodeData(StatusCodeData statusCodeData) {
this.statusCodeData = statusCodeData;
}
}

View File

@ -0,0 +1,16 @@
package com.truphone.es9plus.message.response.base;
import com.truphone.es9plus.message.MsgBody;
public abstract class ResponseMsgBody implements MsgBody {
private HeaderResp header;
public HeaderResp getHeader() {
return header;
}
public void setHeader(HeaderResp header) {
this.header = header;
}
}

View File

@ -0,0 +1,64 @@
package com.truphone.es9plus.message.response.base;
public class StatusCodeData {
private String subjectCode;
private String reasonCode;
private String message;
private String subjectIdentifier;
public StatusCodeData() {
super();
}
public StatusCodeData(String subjectCode, String reasonCode, String message) {
super();
this.subjectCode = subjectCode;
this.reasonCode = reasonCode;
this.message = message;
}
public StatusCodeData(String subjectCode, String reasonCode, String message, String subjectIdentifier) {
super();
this.subjectCode = subjectCode;
this.reasonCode = reasonCode;
this.message = message;
this.subjectIdentifier = subjectIdentifier;
}
public String getSubjectCode() {
return subjectCode;
}
public void setSubjectCode(String subjectCode) {
this.subjectCode = subjectCode;
}
public String getReasonCode() {
return reasonCode;
}
public void setReasonCode(String reasonCode) {
this.reasonCode = reasonCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getSubjectIdentifier() {
return subjectIdentifier;
}
public void setSubjectIdentifier(String subjectIdentifier) {
this.subjectIdentifier = subjectIdentifier;
}
}

View File

@ -0,0 +1,15 @@
package com.truphone.lpa;
import java.util.List;
public interface ApduChannel {
String transmitAPDU(String apdu);
String transmitAPDUS(List<String> apdus);
void sendStatus();
void setApduTransmittedListener(ApduTransmittedListener apduTransmittedListener);
void removeApduTransmittedListener(ApduTransmittedListener apduTransmittedListener);
}

View File

@ -0,0 +1,5 @@
package com.truphone.lpa;
public interface ApduTransmittedListener {
void onApduTransmitted();
}

View File

@ -0,0 +1,40 @@
package com.truphone.lpa;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpad.progress.Progress;
import java.util.List;
import java.util.Map;
public interface LocalProfileAssistant {
String enableProfile(String iccid, Progress progress);
String disableProfile(String iccid, Progress progress);
String deleteProfile(String iccid, Progress progress);
String getDefaultSMDP();
String setDefaultSMDP(String smdpAddress, Progress progress);
void downloadProfile(String matchingId, DownloadProgress progress) throws Exception;
List<Map<String, String>> getProfiles();
/**
* Gets the EID from the eUICC
* @return the EID from the eUICC
*/
String getEID();
/**
* Allocates the Protected Profile Packages to specified EIDs based on given MCC
* @param mcc Mobile country code
* @return Activation Code Token
*/
String allocateProfile(String mcc);
void processPendingNotifications();
}

View File

@ -0,0 +1,362 @@
package com.truphone.lpa.apdu;
import org.apache.commons.lang3.StringUtils;
import com.truphone.util.ToTLV;
import com.truphone.util.Tools;
import java.util.ArrayList;
import java.util.List;
public class ApduUtils {
private static final String CLA = "81";
private static final String INSTRUCTION = "E2";
private static final String P1_11 = "11";
private static final String P1_91 = "91";
private static final String P2 = "00";
private static final int len = 120;
public static String getEuiccInfo1Apdu() {
String data = ToTLV.toTLV("BF20", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getEuiccInfo2Apdu() {
String data = ToTLV.toTLV("BF22", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getEUICCChallengeApdu() {
String data = ToTLV.toTLV("BF2E", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static List<String> authenticateServerApdu(String smdpSigned1, String smdpSignature1, String euiccCiPKIdToBeUsed,
String cert, String matchingId) {
String sctxParams1 = ToTLV.toTLV("A0", ToTLV.toTLV("80", matchingId) + ToTLV.toTLV("A1", ToTLV.toTLV("80", "35550607") + ToTLV.toTLV("A1", "")));
String data = ToTLV.toTLV("BF38", smdpSigned1 + smdpSignature1 + euiccCiPKIdToBeUsed + cert + sctxParams1);
return subCommandData(data, len, false);
}
public static List<String> prepareDownloadApdu(String smdpSigned2, String smdpSignature2, String cert, String hashCc) {
StringBuilder data = new StringBuilder().append(smdpSigned2).append(smdpSignature2);
if (hashCc != null) {
data.append(ToTLV.toTLV("04", hashCc));
}
data.append(cert);
return subCommandData(ToTLV.toTLV("BF21", data.toString()), len, false);
}
public static List<String> loadInitialiseSecureChannelApdu(List<String[]> data) {
if (data.size() != 4 && data.size() != 5) {
throw new RuntimeException("SBPP Error");
}
return subCommandData(data.get(0)[0], len, true);
}
public static List<String> loadConfigureISDPApdu(List<String[]> data) {
if (data.size() != 4 && data.size() != 5) {
throw new RuntimeException("SBPP Error");
}
List<String> SBPPList = new ArrayList<>();
String configureISDP = data.get(1)[0];
String configureISDPLength = Tools.toHex(String.valueOf(configureISDP.length() / 2));
StringBuilder configureISDPApdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2)
.append(configureISDPLength).append(configureISDP);
SBPPList.add(configureISDPApdu.toString());
return SBPPList;
}
public static List<String> loadStoreMetadataApdu(List<String[]> data) {
if (data.size() != 4 && data.size() != 5) {
throw new RuntimeException("SBPP Error");
}
List<String> SBPPList = new ArrayList<>();
String[] storeMetadata = data.get(2);
for (int i = 0; i < storeMetadata.length; i++) {
List<String> storeMetadataList = subCommandData(storeMetadata[i], len, true);
SBPPList.addAll(storeMetadataList);
}
return SBPPList;
}
public static List<String> loadProfileProtectionKeys(List<String[]> data) {
if (data.size() != 5) {
throw new RuntimeException("SBPP Error");
}
List<String> SBPPList = new ArrayList<>();
String[] profileProtectionKeys = data.get(3);
for (int i = 0; i < profileProtectionKeys.length; i++) {
List<String> loadProfileElementsList = subCommandData(profileProtectionKeys[i], len, true);
SBPPList.addAll(loadProfileElementsList);
}
return SBPPList;
}
public static List<String> loadBoundProfilePackageApdu(List<String[]> data) {
if (data.size() != 4 && data.size() != 5) {
throw new RuntimeException("SBPP Error");
}
List<String> SBPPList = new ArrayList<>();
String[] loadProfileElements = (data.size() == 4) ? data.get(3) : data.get(4);
for (int i = 0; i < loadProfileElements.length; i++) {
List<String> loadProfileElementsList = subCommandData(loadProfileElements[i], len, true);
SBPPList.addAll(loadProfileElementsList);
}
return SBPPList;
}
public static String removeNotificationFromListApdu(int notifycounter) {
String data = ToTLV.toTLV("BF30", ToTLV.integerToTLV("80", notifycounter));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String listNotificationApdu(String notificationType) {
String data;
if (StringUtils.isNotBlank(notificationType)) {
data = ToTLV.toTLV("BF28", ToTLV.toTLV("81", "04" + notificationType));
} else {
data = ToTLV.toTLV("BF28", "");
}
return new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data)).toString();
}
public static String retrievePendingNotificationsListApdu(int notifyCounter) {
String data = ToTLV.toTLV("BF2B", ToTLV.toTLV("A0", ToTLV.integerToTLV("80", notifyCounter)));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getProfilesInfoApdu(String isdp1) {
String searchCriteria = "";
if (!StringUtils.isEmpty(isdp1)) {
searchCriteria = ToTLV.toTLV("A0", ToTLV.toTLV("4F", isdp1));
}
String data = ToTLV.toTLV("BF2D", searchCriteria);// + tagList);
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getEIDApdu() {
String data = ToTLV.toTLV("BF3E", ToTLV.toTLV("5C", "5A"));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String setNicknameApdu(String iccid, String profileNickname) {
String data = ToTLV.toTLV("BF29", ToTLV.toTLV("5A", iccid) + ToTLV.toTLV("90", profileNickname));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String enableProfileApdu(String iccidOrISDPaid, String refreshflag) {
String data;
if (iccidOrISDPaid.length() / 2 == 10) {
data = ToTLV.toTLV("BF31", ToTLV.toTLV("A0", ToTLV.toTLV("5A", iccidOrISDPaid)) + ToTLV.toTLV("81", refreshflag));
} else if (iccidOrISDPaid.length() / 2 == 16) {
data = ToTLV.toTLV("BF31", ToTLV.toTLV("A0", ToTLV.toTLV("4F", iccidOrISDPaid)) + ToTLV.toTLV("81", refreshflag));
} else {
throw new RuntimeException("No iccid Or ISDPaid supplied");
}
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String disableProfileApdu(String iccidOrISDPaid, String refreshflag) {
String data;
if (iccidOrISDPaid.length() / 2 == 10) {
data = ToTLV.toTLV("BF32", ToTLV.toTLV("A0", ToTLV.toTLV("5A", iccidOrISDPaid)) + ToTLV.toTLV("81", refreshflag));
} else if (iccidOrISDPaid.length() / 2 == 16) {
data = ToTLV.toTLV("BF32", ToTLV.toTLV("A0", ToTLV.toTLV("4F", iccidOrISDPaid)) + ToTLV.toTLV("81", refreshflag));
} else {
throw new RuntimeException("No iccid Or ISDPaid supplied");
}
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String deleteProfileApdu(String iccidOrISDPaid) {
String data;
if (iccidOrISDPaid.length() / 2 == 10) {
data = ToTLV.toTLV("BF33", ToTLV.toTLV("5A", iccidOrISDPaid));
} else if (iccidOrISDPaid.length() / 2 == 16) {
data = ToTLV.toTLV("BF33", ToTLV.toTLV("4F", iccidOrISDPaid));
} else {
throw new RuntimeException("No iccid Or ISDPaid supplied");
}
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getEuiccConfiguredAddressesApdu() {
String data = "BF3C00";
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String setDefaultDpAddressApdu(String dpAddrNew) {
String data = ToTLV.toTLV("BF3F", ToTLV.toTLV("80", dpAddrNew));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getProfilesInfo_profileStateApdu(String iccidOrISDPaid) {
String taglist = ToTLV.toTLV("5C", "9F70");
String searchCriteria = null;
if (iccidOrISDPaid.length() / 2 == 10) {
searchCriteria = ToTLV.toTLV("A0", ToTLV.toTLV("5A", iccidOrISDPaid));
} else if (iccidOrISDPaid.length() / 2 == 16) {
searchCriteria = ToTLV.toTLV("A0", ToTLV.toTLV("4F", iccidOrISDPaid));
}
String data = ToTLV.toTLV("BF2D", searchCriteria + taglist);
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getEUICCInfo_spaceApdu() {
String data = ToTLV.toTLV("BF22", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getProfilesInfo_ISDPaidApdu(String iccid) {
String taglist = ToTLV.toTLV("5C", "4F");
String searchCriteria = ToTLV.toTLV("A0", ToTLV.toTLV("5A", iccid));
String data = ToTLV.toTLV("BF2D", searchCriteria + taglist);
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String checkIfAnyEnabledProfileApdu() {
String taglist = ToTLV.toTLV("5C", "9F70");
String searchCriteria = "";
String data = ToTLV.toTLV("BF2D", searchCriteria + taglist);
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getNotifyCounterApdu() {
String data = ToTLV.toTLV("BF28", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String getNotifyTypeApdu() {
String data = ToTLV.toTLV("BF28", "");
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String removeNotificationApdu(String notifyCounter) {
String data = ToTLV.toTLV("BF30", ToTLV.toTLV("80", notifyCounter));
StringBuilder apdu = new StringBuilder().append(CLA).append(INSTRUCTION).append(P1_91).append(P2).append(ToTLV.toTLV(data));
return apdu.toString();
}
public static String nextNotifyCounterApdu(String iccGp_notifycounter) {
String nextNotifyCounter = "";
int inotifycounter = Integer.valueOf(iccGp_notifycounter, 16);
String inotifycounterHex = Tools.toHex(String.valueOf(++inotifycounter));
inotifycounterHex = "000000" + inotifycounterHex;
if (inotifycounter < 127) {
nextNotifyCounter = inotifycounterHex.substring(inotifycounterHex.length() - 2);
} else if (inotifycounter < 32767) {
nextNotifyCounter = inotifycounterHex.substring(inotifycounterHex.length() - 4);
} else if (inotifycounter < 8388607) {
nextNotifyCounter = inotifycounterHex.substring(inotifycounterHex.length() - 6);
} else {
nextNotifyCounter = inotifycounterHex.substring(inotifycounterHex.length() - 8);
}
return nextNotifyCounter;
}
private static List<String> subCommandData(String data, int len, boolean isLenSub) {
List<String> commandDataList = new ArrayList<>();
int dataLen = data.length() / 2;
int cP2 = 0;
while (dataLen != 0) {
if (dataLen > len) {
String subData = data.substring(0, 2 * len);
StringBuilder apdu = new StringBuilder();
if (isLenSub) {
apdu.append(CLA).append(INSTRUCTION).append(P1_11).append(Tools.toHex(String.valueOf(cP2))).append(Tools.itoa(len, 1)).append(subData);
} else {
apdu.append(CLA).append(INSTRUCTION).append(P1_11).append(Tools.toHex(String.valueOf(cP2))).append(Tools.toHex(String.valueOf(len))).append(subData);
}
commandDataList.add(apdu.toString());
data = data.substring(2 * len);
dataLen = dataLen - len;
cP2++;
} else {
StringBuilder apdu = new StringBuilder();
if (isLenSub) {
apdu.append(CLA).append(INSTRUCTION).append(P1_91).append(Tools.toHex(String.valueOf(cP2))).append(Tools.itoa(dataLen, 1)).append(data);
} else {
apdu.append(CLA).append(INSTRUCTION).append(P1_91).append(Tools.toHex(String.valueOf(cP2))).append(Tools.toHex(String.valueOf(dataLen))).append(data);
}
dataLen = 0;
commandDataList.add(apdu.toString());
}
}
return commandDataList;
}
public static String getResponse() {
StringBuilder apdu = new StringBuilder();
apdu.append(CLA).append("C0").append("00").append("00").append("00");
return apdu.toString();
}
/**
* * Proprietary Commands *
*/
public static String getLPAeDownloadProfileApdu() {
StringBuilder apdu = new StringBuilder();
apdu.append(CLA).append("B0").append("00").append("00").append("01").append("02");
return apdu.toString();
}
public static String getLPAeGetProgressInfoApdu() {
StringBuilder apdu = new StringBuilder();
apdu.append(CLA).append("B0").append("00").append("00").append("01").append("08");
return apdu.toString();
}
public static String getLPAeMemoryResetApdu() {
StringBuilder apdu = new StringBuilder();
apdu.append(CLA).append("B0").append("00").append("00").append("01").append("06");
return apdu.toString();
}
public static String getLPAeSetLPAModeApdu(String mode) {
StringBuilder apdu = new StringBuilder();
apdu.append(CLA).append("B0").append("00").append("00").append("02").append("09").append(mode);
return apdu.toString();
}
public static String getSendStatusAPDU() {
return "80F20100";
}
}

View File

@ -0,0 +1,17 @@
package com.truphone.lpa.apdu;
public enum NotificationType {
ALL(""), INSTALLED("80"), ENABLED("40"), DISABLED("20"), DELETED("10");
private final String text;
NotificationType(final String text) {
this.text = text;
}
@Override
public String toString() {
return text;
}
}

View File

@ -0,0 +1,275 @@
package com.truphone.lpa.apdu;
import com.truphone.util.LogStub;
import com.truphone.util.TLVBean;
import java.util.ArrayList;
import java.util.logging.Logger;
public class ProfileUtil {
private static final Logger LOG = Logger.getLogger(ProfileUtil.class
.getName());
public ArrayList<String[]> generateSBPP(String BPP) {
if (!BPP.substring(0, 4).equals("BF36")) {
throw new RuntimeException("Incorrect format in BPP");
}
ArrayList<String[]> array = new ArrayList<String[]>();
int endOfSeg = 0;
String[] initChannel = new String[1];
initChannel[0] = headAndInitChannel(BPP);
array.add(initChannel);
endOfSeg += initChannel[0].length();
String[] isdp = new String[1];
isdp[0] = configIsdp(BPP.substring(endOfSeg));
array.add(isdp);
endOfSeg += isdp[0].length();
String[] metaData = metaData(BPP.substring(endOfSeg));
array.add(metaData);
for (int i = 0; i < metaData.length; i++) {
endOfSeg += metaData[i].length();
}
int beginOfSeg = BPP.substring(endOfSeg).indexOf("A2");
if (beginOfSeg == 0) {
String[] ppk = new String[1];
ppk[0] = ppk(BPP.substring(endOfSeg));
array.add(ppk);
endOfSeg += ppk[0].length();
}
String[] ppp = ppp(BPP.substring(endOfSeg));
array.add(ppp);
return array;
}
private String headAndInitChannel(String data) {
int beginOfSeg = data.indexOf("BF36");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in BPP");
}
data += "FFFF";// endTag
TLVBean tlv = null;
tlv = selectTlv(data, "BF36", "FFFF");
if (tlv == null) {
throw new RuntimeException("Incorrect format in BPP");
}
String head = tlv.getTaglen();
data = tlv.getValue();
// InitChannel
beginOfSeg = data.indexOf("BF23");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in InitialiseSecureChannel of BPP");
}
tlv = null;
tlv = selectTlv(data, "BF23", "A0");
if (tlv == null) {
throw new RuntimeException("Incorrect format in InitialiseSecureChannel of BPP");
}
String initChannel = tlv.getTaglen() + tlv.getValue();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"headAndInitChannel: " + head + initChannel);
}
return head + initChannel;
}
private String configIsdp(String data) {
int beginOfSeg = data.indexOf("A0");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in configIsdp of BPP");
}
String str = null;
TLVBean tlv = null;
tlv = selectTlv(data, "A0", "A1");
if (tlv == null) {
throw new RuntimeException("Incorrect format in configIsdp of BPP");
}
str = tlv.getTaglen() + tlv.getValue();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"configIsdp: " + str);
}
return str;
}
private String[] metaData(String data) {
int beginOfSeg = data.indexOf("A1");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in head of metaData");
}
TLVBean tlv = null;
tlv = selectTlv(data, "A1", "A2");
if (tlv == null) {
tlv = selectTlv(data, "A1", "A3");
if (tlv == null) {
throw new RuntimeException("Incorrect format in head of metaData");
}
}
String head = tlv.getTaglen();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"headOfMetadata: " + head);
}
data = tlv.getValue();
ArrayList<String> array = new ArrayList<String>();
beginOfSeg = data.indexOf("88");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in body of metaData");
}
tlv = null;
data += "FFFF";
TLVBean tlvBean = null;
while (tlvBean == null) {
tlv = selectTlv(data, "88", "FFFF");
tlvBean = tlv;
if (tlvBean == null) {
tlv = selectTlv(data, "88", "88");
if (tlv == null) {
throw new RuntimeException("Incorrect format in body of metaData");
}
String segBody = tlv.getTaglen() + tlv.getValue();
array.add(segBody);
data = data.substring(segBody.length());
} else {
array.add(tlv.getTaglen() + tlv.getValue());
}
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"bodyOfMetadata: " + tlv.getTaglen() + tlv.getValue());
}
}
String[] body = (String[]) array.toArray(new String[0]);
ArrayList<String> metaData = new ArrayList<String>();
metaData.add(head);
for (int i = 0, n = body.length; i < n; i++) {
metaData.add(body[i]);
}
return metaData.toArray(new String[0]);
}
private String ppk(String data) {
int beginOfSeg = data.indexOf("A2");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in ppk of BPP");
}
String ppk = null;
TLVBean tlvBean = null;
tlvBean = selectTlv(data, "A2", "A3");
if (tlvBean == null) {
throw new RuntimeException("Incorrect format in ppk of BPP");
}
ppk = tlvBean.getTaglen() + tlvBean.getValue();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"ppk: " + ppk);
}
return ppk;
}
private String[] ppp(String data) {
int beginOfSeg = data.indexOf("A3");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in head of ppp");
}
TLVBean tlvBean = null;
data += "FFFF";
tlvBean = selectTlv(data, "A3", "FFFF");
if (tlvBean == null) {
throw new RuntimeException("Incorrect format in head of ppp");
}
String head = tlvBean.getTaglen();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"headOfPPP: " + head);
}
data = tlvBean.getValue();
ArrayList<String> array = new ArrayList<String>();
beginOfSeg = data.indexOf("86");
if (!(beginOfSeg == 0)) {
throw new RuntimeException("Incorrect format in body of ppp");
}
tlvBean = null;
data += "FFFF";
TLVBean tlvBeanAux = null;
while (tlvBeanAux == null) {
tlvBean = selectTlv(data, "86", "FFFF");
tlvBeanAux = tlvBean;
if (tlvBeanAux == null) {
tlvBean = selectTlv(data, "86", "86");
if (tlvBean == null) {
throw new RuntimeException("Incorrect format in body of ppp");
}
String segBody = tlvBean.getTaglen() + tlvBean.getValue();
array.add(segBody);
data = data.substring(segBody.length());
} else {
array.add(tlvBean.getTaglen() + tlvBean.getValue());
}
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"bodyOfPPP: " + tlvBean.getTaglen() + tlvBean.getValue());
}
}
String[] body = (String[]) array.toArray(new String[0]);
ArrayList<String> ppp = new ArrayList<String>();
ppp.add(head);
for (int i = 0, n = body.length; i < n; i++) {
ppp.add(body[i]);
}
return ppp.toArray(new String[0]);
}
public TLVBean selectTlv(String inputData, String beginTag, String endTag) {
int beginOfSeg = inputData.indexOf(beginTag);
String s = inputData.substring(beginOfSeg + beginTag.length());
if (s.substring(0, 2).equals("83")) {
int num83 = Integer.parseInt("83", 16) * 2 + 2;
int num = Integer.parseInt(s.substring(2, 8), 16) * 2 + 8;
if ((num <= s.length()) && (s.substring(num).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + s.substring(0, 8), s.substring(8, num));
} else if ((num83 <= s.length()) && (s.substring(num83).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + "83", s.substring(2, num83));
}
} else if (s.substring(0, 2).equals("82")) {
int num82 = Integer.parseInt("82", 16) * 2 + 2;
int num = Integer.parseInt(s.substring(2, 6), 16) * 2 + 6;
if ((num <= s.length()) && (s.substring(num).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + s.substring(0, 6), s.substring(6, num));
} else if ((num82 <= s.length()) && (s.substring(num82).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + "82", s.substring(2, num82));
}
} else if (s.substring(0, 2).equals("81")) {
int num81 = Integer.parseInt("81", 16) * 2 + 2;
int num = Integer.parseInt(s.substring(2, 4), 16) * 2 + 4;
if ((num <= s.length()) && (s.substring(num).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + s.substring(0, 4), s.substring(4, num));
} else if ((num81 <= s.length()) && (s.substring(num81).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + "81", s.substring(2, num81));
}
} else {
int num = Integer.parseInt(s.substring(0, 2), 16) * 2 + 2;
if ((num <= s.length()) && (s.substring(num).indexOf(endTag) == 0)) {
return new TLVBean(beginTag + s.substring(0, 2), s.substring(2, num));
}
}
return null;
}
}

View File

@ -0,0 +1,42 @@
package com.truphone.lpa.impl;
public class AuthenticateClientSmDp {
private String smdpSigned2;
private String smdpSignature2;
private String smdpCertificate;
public AuthenticateClientSmDp() {
super();
}
public String getSmdpSigned2() {
return smdpSigned2;
}
public String getSmdpSignature2() {
return smdpSignature2;
}
public String getSmdpCertificate() {
return smdpCertificate;
}
public void setSmdpSigned2(String smdpSigned2) {
this.smdpSigned2 = smdpSigned2;
}
public void setSmdpSignature2(String smdpSignature2) {
this.smdpSignature2 = smdpSignature2;
}
public void setSmdpCertificate(String smdpCertificate) {
this.smdpCertificate = smdpCertificate;
}
}

View File

@ -0,0 +1,101 @@
package com.truphone.lpa.impl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.DisableProfileResponse;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
class DisableProfileWorker {
private static final Logger LOG = Logger.getLogger(DisableProfileWorker.class.getName());
private final String iccid;
private final Progress progress;
private final ApduChannel apduChannel;
DisableProfileWorker(String iccid, Progress progress, ApduChannel apduChannel) {
this.iccid = iccid;
this.progress = progress;
this.apduChannel = apduChannel;
}
String run() {
String eResponse = transmitDisableProfile(iccid, progress);
return convertDisableProfileResponse(iccid, progress, eResponse);
}
private String convertDisableProfileResponse(String iccid, Progress progress, String eResponse) {
progress.stepExecuted(ProgressStep.DISABLE_PROFILE_CONVERTING_RESPONSE, "Converting response");
try {
InputStream is = new ByteArrayInputStream(Hex.decodeHex(eResponse.toCharArray()));
DisableProfileResponse disableProfileResponse = new DisableProfileResponse();
disableProfileResponse.decode(is);
if (LocalProfileAssistantImpl.PROFILE_RESULT_SUCESS.equals(disableProfileResponse.getDisableResult().toString())) {
progress.stepExecuted(ProgressStep.DISABLE_PROFILE_DISABLED, iccid + " disabled");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - SEND Status to APDU Channel");
}
apduChannel.sendStatus();
progress.stepExecuted(ProgressStep.DISABLE_PROFILE_TRIGGERED_PROFILE_SWITCH, iccid + " triggered profile switch");
} else {
progress.stepExecuted(ProgressStep.DISABLE_PROFILE_NOT_DISABLED, iccid + " profile not disabled");
LOG.info(LogStub.getInstance().getTag() + " - iccid:" + iccid + " profile not disabled");
}
return disableProfileResponse.getDisableResult().toString();
} catch (IOException ioe) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile failed to be disabled");
throw new RuntimeException("Unable to disable profile: " + iccid + ", response: " + eResponse);
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile failed to be disabled. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to disable profile: " + iccid + ", response: " + eResponse);
}
}
private String transmitDisableProfile(String iccid, Progress progress) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Disabling profile: " + iccid);
}
progress.setTotalSteps(4);
progress.stepExecuted(ProgressStep.DISABLE_PROFILE_DISABLING_PROFILE, iccid + " disabling profile");
String apdu = ApduUtils.disableProfileApdu(iccid, LocalProfileAssistantImpl.TRIGGER_PROFILE_REFRESH);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Disable profile apdu: " + apdu);
}
String eResponse = apduChannel.transmitAPDU(apdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Disable response: " + eResponse);
}
return eResponse;
}
}

View File

@ -0,0 +1,77 @@
package com.truphone.lpa.impl;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.impl.download.*;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.util.LogStub;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.apache.commons.lang3.StringUtils;
class DownloadProfileWorker {
private static final Logger LOG = Logger.getLogger(DownloadProfileWorker.class.getName());
private final DownloadProgress progress;
private final Es9PlusImpl es9Module;
private String matchingId;
private ApduTransmitter apduTransmitter;
DownloadProfileWorker(String matchingId, DownloadProgress progress, ApduChannel apduChannel, Es9PlusImpl es9Module) {
this.matchingId = matchingId;
this.progress = progress;
this.es9Module = es9Module;
apduTransmitter = new ApduTransmitter(apduChannel);
}
void run() throws Exception {
AuthenticatingPhaseWorker authenticatingPhaseWorker = new AuthenticatingPhaseWorker(progress, apduTransmitter, es9Module);
DownloadPhaseWorker downloadPhaseWorker = new DownloadPhaseWorker(progress, apduTransmitter, es9Module);
LOG.info(LogStub.getInstance().getTag() + " - Downloading profile with matching Id: " + matchingId);
//AP Added this to support Activation Codes
//If matchingId is an Activation Code, parses AC to retrieve DP Address and Matching ID.
//Otherwise LPA shall use the default SMDP configured on the cards
String serverAddress;
if(matchingId.contains("$")){
//Its activation code
String[] acParts = matchingId.split("\\$");
if(acParts.length<3 )
throw new RuntimeException("Invalid ActivationCode format");
serverAddress = acParts[1];
matchingId = acParts[2];
}else
{
serverAddress = new ConnectingPhaseWorker(progress, apduTransmitter).getEuiccConfiguredAddress(matchingId);
}
InitialAuthenticationKeys initialAuthenticationKeys = new InitialAuthenticationKeys(matchingId,
serverAddress,
authenticatingPhaseWorker.getEuiccInfo(),
authenticatingPhaseWorker.getEuiccChallenge(matchingId));
authenticatingPhaseWorker.initiateAuthentication(initialAuthenticationKeys);
downloadAndInstallProfilePackage(initialAuthenticationKeys,
downloadPhaseWorker.prepareDownload(authenticatingPhaseWorker.authenticateClient(initialAuthenticationKeys,
authenticatingPhaseWorker.authenticateWithEuicc(initialAuthenticationKeys))), downloadPhaseWorker);
}
private void downloadAndInstallProfilePackage(InitialAuthenticationKeys initialAuthenticationKeys,
String encodedPrepareDownloadResponse, DownloadPhaseWorker downloadPhaseWorker) throws IOException {
String bpp = downloadPhaseWorker.getBoundProfilePackage(initialAuthenticationKeys, encodedPrepareDownloadResponse);
Map<SbppApdu, List<String>> sbpp = new GeneratePhaseWorker(progress).generateSbpp(bpp);
new InstallationPhaseWorker(progress, apduTransmitter).loadingSbppApdu(sbpp);
}
}

View File

@ -0,0 +1,106 @@
package com.truphone.lpa.impl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.EnableProfileResponse;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
class EnableProfileWorker {
private static final Logger LOG = Logger.getLogger(EnableProfileWorker.class.getName());
private final String iccid;
private final Progress progress;
private final ApduChannel apduChannel;
EnableProfileWorker(String iccid, Progress progress, ApduChannel apduChannel) {
this.iccid = iccid;
this.progress = progress;
this.apduChannel = apduChannel;
}
String run() {
String eResponse = transmitEnableProfile();
return convertEnableProfileResponse(eResponse);
}
private String convertEnableProfileResponse(String eResponse) {
progress.stepExecuted(ProgressStep.ENABLE_PROFILE_CONVERTING_RESPONSE, "Enable profile APDU");
try {
EnableProfileResponse enableProfileResponse = new EnableProfileResponse();
InputStream is = new ByteArrayInputStream(Hex.decodeHex(eResponse.toCharArray()));
enableProfileResponse.decode(is);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Enable response: " + enableProfileResponse.toString());
}
if (LocalProfileAssistantImpl.PROFILE_RESULT_SUCESS.equals(enableProfileResponse.getEnableResult().toString())) {
progress.stepExecuted(ProgressStep.ENABLE_PROFILE_PROFILE_ENABLED, iccid + " profile enabled successfully");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - iccid:" + iccid + " profile enabled successfully");
}
apduChannel.sendStatus();
progress.stepExecuted(ProgressStep.ENABLE_PROFILE_TRIGGERED_PROFILE_SWITCH, iccid + " triggered profile switch");
} else {
progress.stepExecuted(ProgressStep.ENABLE_PROFILE_PROFILE_NOT_ENABLED, iccid + " profile not enabled");
LOG.info(LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile not enabled");
}
return enableProfileResponse.getEnableResult().toString();
} catch (IOException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.severe(LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile failed to be enabled. message: " + e.getMessage());
throw new RuntimeException("Unable to enable profile: " + iccid + ", response: " + eResponse);
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.severe(LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile failed to be enabled. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to enable profile: " + iccid + ", response: " + eResponse);
}
}
private String transmitEnableProfile() {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Enabling profile: " + iccid);
}
progress.setTotalSteps(4);
progress.stepExecuted(ProgressStep.ENABLE_PROFILE_ENABLING_PROFILE, "Enabling profile");
String apdu = ApduUtils.enableProfileApdu(iccid, LocalProfileAssistantImpl.TRIGGER_PROFILE_REFRESH);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Enable profile APDU: " + apdu);
}
String eResponse = apduChannel.transmitAPDU(apdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Enable profile response: " + eResponse);
}
return eResponse;
}
}

View File

@ -0,0 +1,57 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.truphone.lpa.impl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.EuiccConfiguredAddressesResponse;
import com.truphone.util.LogStub;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
/**
*
* @author amilcar.pereira
*/
public class GetSMDPAddressWorker {
private static final Logger LOG = Logger.getLogger(EnableProfileWorker.class.getName());
private final ApduChannel apduChannel;
private final Progress progress;
public GetSMDPAddressWorker(ApduChannel apduChannel, Progress progress) {
this.apduChannel = apduChannel;
this.progress = progress;
}
public String run(){
return transmitGetSMDPAddress();
}
private String transmitGetSMDPAddress() {
String apdu = ApduUtils.getEuiccConfiguredAddressesApdu();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - getEuiccConfiguredAddressesApdu APDU: " + apdu);
}
String eResponse = apduChannel.transmitAPDU(apdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - getEuiccConfiguredAddressesApdu response: " + eResponse);
}
return eResponse;
}
}

View File

@ -0,0 +1,193 @@
package com.truphone.lpa.impl;
import com.truphone.rsp.dto.asn1.rspdefinitions.*;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.apdu.NotificationType;
import com.truphone.util.LogStub;
import com.truphone.util.Util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HandleNotificationsWorker {
private static final Logger LOG = Logger.getLogger(HandleNotificationsWorker.class.getName());
private final ApduChannel apduChannel;
private final Es9PlusImpl es9Module;
HandleNotificationsWorker(ApduChannel apduChannel, Es9PlusImpl es9Module) {
this.apduChannel = apduChannel;
this.es9Module = es9Module;
}
void run(NotificationType notificationType) {
String notificationList = getNotificationsList(notificationType);
ListNotificationResponse list = new ListNotificationResponse();
try {
decodeNotificationList(notificationList, list);
for (NotificationMetadata notification : list.getNotificationMetadataList().getNotificationMetadata()) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Notification: " + notification.toString());
}
int seqNo = notification.getSeqNumber().intValue();
RetrieveNotificationsListResponse notificationListResponse = getRetrieveNotificationsListResponse(seqNo);
handlePendingNotification(seqNo, notificationListResponse);
}
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - Unable to retrieve profiles. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve profiles");
} catch (IOException ioe) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + ioe.getMessage(), ioe);
throw new RuntimeException("Unable to retrieve profiles");
}
}
private void decodeNotificationList(String notificationList, ListNotificationResponse list) throws DecoderException, IOException {
InputStream is = new ByteArrayInputStream(Hex.decodeHex(notificationList.toCharArray()));
list.decode(is, true);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - List of notifications: " + list.toString());
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Number of notifications: " + list.getNotificationMetadataList().getNotificationMetadata().size());
}
}
private String getNotificationsList(NotificationType notificationType) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Listing notification for type: " + notificationType.toString() +
"[" + notificationType.name() + "]");
}
String listNotificationsApdu = ApduUtils.listNotificationApdu(notificationType.toString());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Listing notifications apdu: " + listNotificationsApdu);
}
String notificationList = apduChannel.transmitAPDU(listNotificationsApdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Notification list response: " + notificationList);
}
return notificationList;
}
private void handlePendingNotification(int seqNo, RetrieveNotificationsListResponse notificationListResponse) throws IOException, DecoderException {
if (notificationListResponse != null && notificationListResponse.getNotificationList() != null &&
notificationListResponse.getNotificationList().getPendingNotification() != null)
for (PendingNotification pendingNotification : notificationListResponse.getNotificationList().getPendingNotification()) {
String encodedPendingNotification = getEncodedPendingNotification(pendingNotification);
String serverAddress="";
if(pendingNotification.getProfileInstallationResult()!=null){
//It's a PIR
serverAddress = pendingNotification.getProfileInstallationResult().getProfileInstallationResultData().getNotificationMetadata().getNotificationAddress().toString();
}else{
serverAddress = pendingNotification.getOtherSignedNotification().getTbsOtherNotification().getNotificationAddress().toString();
}
es9Module.handleNotification(encodedPendingNotification, serverAddress);
removeNotification(seqNo);
}
}
private RetrieveNotificationsListResponse getRetrieveNotificationsListResponse(int seqNo) throws DecoderException, IOException {
String retrieveNotificationFromListApdu = ApduUtils.retrievePendingNotificationsListApdu(seqNo);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Retrieving notification: " + retrieveNotificationFromListApdu);
}
String notificationResponse = apduChannel.transmitAPDU(retrieveNotificationFromListApdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Notification response: " + notificationResponse);
}
return decodeNotificationResponse(notificationResponse);
}
private RetrieveNotificationsListResponse decodeNotificationResponse(String notificationResponse) throws DecoderException, IOException {
InputStream is3 = new ByteArrayInputStream(Hex.decodeHex(notificationResponse.toCharArray()));
RetrieveNotificationsListResponse notificationListResponse = new RetrieveNotificationsListResponse();
notificationListResponse.decode(is3, true);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Notification: " + notificationListResponse.toString());
}
return notificationListResponse;
}
private String getEncodedPendingNotification(PendingNotification pendingNotification) throws IOException {
ReverseByteArrayOutputStream berByteArrayOutputStream = new ReverseByteArrayOutputStream(4000, true);
pendingNotification.encode(berByteArrayOutputStream);
String pendingNotificationStr = Util.byteArrayToHexString(berByteArrayOutputStream.getArray(), "");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Pending notification: " + pendingNotificationStr);
}
String encodedPendingNotification = Base64.encodeBase64String(Util.hexStringToByteArray(pendingNotificationStr));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Encoded pending notification: " + encodedPendingNotification);
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Sending notification to SM-DP+");
}
return encodedPendingNotification;
}
private void removeNotification(int seqNo) throws DecoderException, IOException {
String removeNotificationApdu = ApduUtils.removeNotificationFromListApdu(seqNo);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Remove notification apdu: " + removeNotificationApdu);
}
String removeNotificationResponse = apduChannel.transmitAPDU(removeNotificationApdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Remove notification response: " + removeNotificationResponse);
}
decodeRemoveNotification(removeNotificationResponse);
}
private void decodeRemoveNotification(String removeNotificationResponse) throws DecoderException, IOException {
InputStream is2 = new ByteArrayInputStream(Hex.decodeHex(removeNotificationResponse.toCharArray()));
NotificationSentResponse notificationSentResponse = new NotificationSentResponse();
notificationSentResponse.decode(is2, true);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Notification removal response: " + notificationSentResponse.toString());
}
}
}

View File

@ -0,0 +1,123 @@
package com.truphone.lpa.impl;
public class InitialAuthenticationKeys {
private String matchingId;
private String euiccConfiguredAddress;
private String euiccInfo1;
private String euiccChallenge;
private String serverSigned1;
private String serverSignature1;
private String euiccCiPKIdTobeUsed;
private String serverCertificate;
private String transactionId;
private String ctxParams1;
InitialAuthenticationKeys(String matchingId, String euiccConfiguredAddress, String euiccInfo1, String euiccChallenge) {
this.matchingId = matchingId;
this.euiccConfiguredAddress = euiccConfiguredAddress;
this.euiccInfo1 = euiccInfo1;
this.euiccChallenge = euiccChallenge;
}
public String getMatchingId() {
return matchingId;
}
public String getServerSigned1() {
return serverSigned1;
}
public String getServerSignature1() {
return serverSignature1;
}
public String getEuiccCiPKIdTobeUsed() {
return euiccCiPKIdTobeUsed;
}
public String getServerCertificate() {
return serverCertificate;
}
public String getTransactionId() {
return transactionId;
}
public String getCtxParams1() {
return ctxParams1;
}
public String getEuiccConfiguredAddress() {
return euiccConfiguredAddress;
}
public String getEuiccInfo1() {
return euiccInfo1;
}
public String getEuiccChallenge() {
return euiccChallenge;
}
public void setMatchingId(String matchingId) {
this.matchingId = matchingId;
}
public void setServerSigned1(String serverSigned1) {
this.serverSigned1 = serverSigned1;
}
public void setServerSignature1(String serverSignature1) {
this.serverSignature1 = serverSignature1;
}
public void setEuiccCiPKIdTobeUsed(String euiccCiPKIdTobeUsed) {
this.euiccCiPKIdTobeUsed = euiccCiPKIdTobeUsed;
}
public void setServerCertificate(String serverCertificate) {
this.serverCertificate = serverCertificate;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public void setCtxParams1(String ctxParams1) {
this.ctxParams1 = ctxParams1;
}
@Override
public String toString() {
return "InitialAuthenticationKeys{" +
"matchingId='" + matchingId + '\'' +
", euiccConfiguredAddress='" + euiccConfiguredAddress + '\'' +
", euiccInfo1='" + euiccInfo1 + '\'' +
", euiccChallenge='" + euiccChallenge + '\'' +
", serverSigned1='" + serverSigned1 + '\'' +
", serverSignature1='" + serverSignature1 + '\'' +
", euiccCiPKIdTobeUsed='" + euiccCiPKIdTobeUsed + '\'' +
", serverCertificate='" + serverCertificate + '\'' +
", transactionId='" + transactionId + '\'' +
", ctxParams1='" + ctxParams1 + '\'' +
'}';
}
}

View File

@ -0,0 +1,95 @@
package com.truphone.lpa.impl;
import com.truphone.rsp.dto.asn1.rspdefinitions.ProfileInfo;
import com.truphone.rsp.dto.asn1.rspdefinitions.ProfileInfoListResponse;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.util.LogStub;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
class ListProfilesWorker {
private static final Logger LOG = Logger.getLogger(ListProfilesWorker.class.getName());
private final ApduChannel apduChannel;
ListProfilesWorker(ApduChannel apduChannel) {
this.apduChannel = apduChannel;
}
List<Map<String, String>> run() {
String profilesInfo = getProfileInfoListResponse();
ProfileInfoListResponse profiles = new ProfileInfoListResponse();
List<Map<String, String>> profileList = new ArrayList<>();
try {
decodeProfiles(profilesInfo, profiles);
for (ProfileInfo info : profiles.getProfileInfoListOk().getProfileInfo()) {
Map<String, String> profileMap = new HashMap<>();
profileMap.put(ProfileKey.STATE.name(), LocalProfileAssistantImpl.DISABLED_STATE.equals(info.getProfileState().toString()) ? "Disabled" : "Enabled");
profileMap.put(ProfileKey.ICCID.name(), info.getIccid().toString());
profileMap.put(ProfileKey.NAME.name(), (info.getProfileName()!=null)?info.getProfileName().toString():"");
profileMap.put(ProfileKey.PROVIDER_NAME.name(), (info.getServiceProviderName()!=null)?info.getServiceProviderName().toString():"");
profileMap.put(ProfileKey.ISDP_AID.name(), (info.getIsdpAid()!=null)?info.getIsdpAid().toString():"");
profileMap.put(ProfileKey.PROFILE_CLASS.name(), (info.getProfileClass()!=null)?info.getProfileClass().toString():"");
profileMap.put(ProfileKey.PROFILE_STATE.name(), info.getProfileState().toString());
profileList.add(profileMap);
}
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG, LogStub.getInstance().getTag() + " - getProfiles - returning: " + profileList.toString());
}
return profileList;
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - Unable to retrieve profiles. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve profiles");
} catch (IOException ioe) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + ioe.getMessage(), ioe);
throw new RuntimeException("Unable to retrieve profiles");
}
}
private void decodeProfiles(String profilesInfo, ProfileInfoListResponse profiles) throws DecoderException, IOException {
InputStream is = new ByteArrayInputStream(Hex.decodeHex(profilesInfo.toCharArray()));
profiles.decode(is);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"Profile list object: " + profiles.toString());
}
}
private String getProfileInfoListResponse() {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG, LogStub.getInstance().getTag() + " - Getting Profiles");
}
String apdu = ApduUtils.getProfilesInfoApdu(null);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug (LOG,"List profiles APDU: " + apdu);
}
return apduChannel.transmitAPDU(apdu);
}
}

View File

@ -0,0 +1,142 @@
package com.truphone.lpa.impl;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.LocalProfileAssistant;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.apdu.NotificationType;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.worker.AllocateProfileWorker;
import com.truphone.lpad.worker.DeleteProfileWorker;
import com.truphone.lpad.worker.GetEidLpadWorker;
import com.truphone.lpad.worker.LpadWorkerExchange;
import com.truphone.util.LogStub;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LocalProfileAssistantImpl implements LocalProfileAssistant {
static final String PROFILE_RESULT_SUCESS = "0";
static final String TRIGGER_PROFILE_REFRESH = "FF";
static final String DISABLED_STATE = PROFILE_RESULT_SUCESS;
private static final Logger LOG = Logger.getLogger(LocalProfileAssistantImpl.class.getName());
private final ApduChannel apduChannel;
private Es9PlusImpl es9Module;
// public LocalProfileAssistantImpl(final ApduChannel apduChannel,
// final String rspServerUrl) {
public LocalProfileAssistantImpl(final ApduChannel apduChannel){
this.apduChannel = apduChannel;
es9Module = new Es9PlusImpl();
//LOG.info(LogStub.getInstance().getTag() + " - Init SM-DP connection - " + rspServerUrl);
// if (!StringUtils.isNotBlank(rspServerUrl) || !checkRspServerURL(rspServerUrl)) {
// if (LogStub.getInstance().isDebugEnabled()) {
// LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Fixing RSP Server URL to default - " + rspServerUrl);
// }
//
// throw new IllegalArgumentException("RSP Server URL is invalid: " + rspServerUrl);
// }
// es9Module.configure(rspServerUrl);
//es9Module.configure();
LOG.log(Level.INFO, LogStub.getInstance().getTag() + " - SM-DP connection initiated.");
}
private boolean checkRspServerURL(final String rspServerUrl) {
return rspServerUrl.matches("^(https?:\\/\\/)?([\\da-z\\.-]+\\.[a-z\\.]{2,6}|[\\d\\.]+)([\\/:?=&#]{1}[\\da-z\\.-]+)*[\\/\\?]?$");
}
@Override
public String enableProfile(final String iccid,
final Progress progress) {
return new EnableProfileWorker(iccid, progress, apduChannel).run();
}
@Override
public String disableProfile(final String iccid,
final Progress progress) {
return new DisableProfileWorker(iccid, progress, apduChannel).run();
}
@Override
public String deleteProfile(final String iccid,
final Progress progress) {
DeleteProfileWorker deleteProfileWorker = new DeleteProfileWorker(progress, apduChannel);
LpadWorkerExchange<DeleteProfileWorker.DeleteProfileInputParams> exchange =
new LpadWorkerExchange<>(deleteProfileWorker.new DeleteProfileInputParams(iccid));
return deleteProfileWorker.run(exchange);
}
@Override
public void downloadProfile(final String matchingId,
final DownloadProgress progress) throws Exception {
new DownloadProfileWorker(matchingId, progress, apduChannel, es9Module).run();
}
@Override
public List<Map<String, String>> getProfiles() {
return new ListProfilesWorker(apduChannel).run();
}
@Override
public String getEID() {
LpadWorkerExchange<String> exchange = new LpadWorkerExchange<>(ApduUtils.getEIDApdu());
return new GetEidLpadWorker(new Progress(), apduChannel).run(exchange);
}
@Override
public String allocateProfile(final String mcc) {
Progress progress = new Progress();
AllocateProfileWorker allocateProfileWorker = new AllocateProfileWorker(progress, es9Module);
LpadWorkerExchange<AllocateProfileWorker.AllocateProfileInputParams> exchange
= new LpadWorkerExchange<>(allocateProfileWorker.new AllocateProfileInputParams(mcc, getEID()));
return allocateProfileWorker.run(exchange);
}
@Override
public void processPendingNotifications() {
new HandleNotificationsWorker(apduChannel, es9Module).run(NotificationType.ALL);
}
@Override
public String getDefaultSMDP() {
//LpadWorkerExchange<String> exchange = new LpadWorkerExchange<>(ApduUtils.setDefaultDpAddressApdu(smdpAddress));
return new GetSMDPAddressWorker(apduChannel, new Progress()).run();
}
@Override
public String setDefaultSMDP(String smdpAddress, Progress progress) {
return new SetSMDPAddressWorker(apduChannel, progress, smdpAddress).run();
}
public void smdsRetrieveEvents(Progress progress) {
// return new SmdsRetrieveEvents();
}
}

View File

@ -0,0 +1,12 @@
package com.truphone.lpa.impl;
public enum ProfileKey {
ICCID,
STATE,
NAME,
PROVIDER_NAME,
ISDP_AID,
PROFILE_CLASS,
PROFILE_STATE
}

View File

@ -0,0 +1,50 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.truphone.lpa.impl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.util.LogStub;
import com.truphone.util.TextUtil;
import java.util.logging.Logger;
/**
*
* @author amilcar.pereira
*/
public class SetSMDPAddressWorker {
private static final Logger LOG = Logger.getLogger(EnableProfileWorker.class.getName());
private final ApduChannel apduChannel;
private final Progress progress;
private String dpAddrNew;
public SetSMDPAddressWorker(ApduChannel apduChannel, Progress progress, String dpAddrNew) {
this.apduChannel = apduChannel;
this.progress = progress;
this.dpAddrNew=dpAddrNew;
}
public String run() {
String hexDPAddress = TextUtil.toHexString(dpAddrNew.getBytes());
String apdu = ApduUtils.setDefaultDpAddressApdu(hexDPAddress);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - setEuiccConfiguredAddressesApdu APDU: " + apdu);
}
String eResponse = apduChannel.transmitAPDU(apdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - setEuiccConfiguredAddressesApdu response: " + eResponse);
}
return eResponse;
}
}

View File

@ -0,0 +1,57 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.truphone.lpa.impl;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.EuiccConfiguredAddressesResponse;
import com.truphone.util.LogStub;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
/**
*
* @author amilcar.pereira
*/
public class SmdsRetrieveEventsWorker {
// private static final Logger LOG = Logger.getLogger(EnableProfileWorker.class.getName());
// private final ApduChannel apduChannel;
// private final Progress progress;
//
// public SmdsRetrieveEventsWorker(ApduChannel apduChannel, Progress progress) {
// this.apduChannel = apduChannel;
// this.progress = progress;
// }
//
// public String run(){
// return transmitGetSMDPAddress();
// }
//
// private String transmitGetSMDPAddress() {
//
// String apdu = ApduUtils.getEuiccConfiguredAddressesApdu();
//
// if (LogStub.getInstance().isDebugEnabled()) {
// LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - getEuiccConfiguredAddressesApdu APDU: " + apdu);
// }
//
// String eResponse = apduChannel.transmitAPDU(apdu);
//
// if (LogStub.getInstance().isDebugEnabled()) {
// LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - getEuiccConfiguredAddressesApdu response: " + eResponse);
// }
//
// return eResponse;
// }
}

View File

@ -0,0 +1,61 @@
package com.truphone.lpa.impl.download;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.ApduTransmittedListener;
import com.truphone.util.LogStub;
import java.util.List;
import java.util.logging.Logger;
public class ApduTransmitter {
private static final Logger LOG = Logger.getLogger(ApduTransmitter.class.getName());
private ApduChannel apduChannel;
public ApduTransmitter(ApduChannel apduChannel) {
this.apduChannel = apduChannel;
}
String transmitApdu(String apdu) {
String apduResponse;
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - APDU to transmit: " + apdu);
}
apduResponse = apduChannel.transmitAPDU(apdu);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Transmit APDU response: " + apduResponse);
}
return apduResponse;
}
String transmitApdus(List<String> apdus) {
String apduResponse;
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - APDUs to transmit: " + apdus);
}
apduResponse = apduChannel.transmitAPDUS(apdus);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Transmit APDUs response: " + apduResponse);
}
return apduResponse;
}
void addApduTransmittedListener(ApduTransmittedListener apduTransmittedListener) {
apduChannel.setApduTransmittedListener(apduTransmittedListener);
}
void removeApduTransmittedListener(ApduTransmittedListener apduTransmittedListener) {
apduChannel.removeApduTransmittedListener(apduTransmittedListener);
}
}

View File

@ -0,0 +1,290 @@
package com.truphone.lpa.impl.download;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.es9plus.LpaUtils;
import com.truphone.es9plus.message.response.AuthenticateClientResp;
import com.truphone.es9plus.message.response.InitiateAuthenticationResp;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.impl.AuthenticateClientSmDp;
import com.truphone.lpa.impl.InitialAuthenticationKeys;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpa.progress.DownloadProgressPhase;
import com.truphone.rsp.dto.asn1.rspdefinitions.GetEuiccChallengeResponse;
import com.truphone.util.LogStub;
import com.truphone.util.Util;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.truphone.lpad.progress.ProgressStep.*;
public class AuthenticatingPhaseWorker {
private static final Logger LOG = Logger.getLogger(AuthenticatingPhaseWorker.class.getName());
private final DownloadProgress progress;
private final ApduTransmitter apduTransmitter;
private final Es9PlusImpl es9Module;
public AuthenticatingPhaseWorker(DownloadProgress progress, ApduTransmitter apduTransmitter, Es9PlusImpl es9Module) {
this.progress = progress;
this.apduTransmitter = apduTransmitter;
this.es9Module = es9Module;
}
public String getEuiccInfo() {
progress.setCurrentPhase(DownloadProgressPhase.AUTHENTICATING);
progress.stepExecuted(DOWNLOAD_PROFILE_GET_EUICC_INFO, "getEuiccInfo retrieving...");
return convertEuiccInfo1(apduTransmitter.transmitApdu(ApduUtils.getEuiccInfo1Apdu()));
}
private String convertEuiccInfo1(String euicInfo1APDUResponse) {
String euiccInfo1;
progress.stepExecuted(DOWNLOAD_PROFILE_CONVERTING_EUICC_INFO, "getEUICCInfo1 Success!");
euiccInfo1 = euicInfo1APDUResponse.toUpperCase();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - EUICC Info Object: " + euiccInfo1);
}
euiccInfo1 = Base64.encodeBase64String(Util.hexStringToByteArray(euiccInfo1));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - EUICC Info Object (Base 64): " + euiccInfo1);
}
progress.stepExecuted(DOWNLOAD_PROFILE_CONVERTED_EUICC_INFO, "getEUICCInfo1 Success!");
return euiccInfo1;
}
public String getEuiccChallenge(String matchingId) {
progress.stepExecuted(DOWNLOAD_PROFILE_GET_EUICC_CHALLENGE, "getEuiccChallenge retrieving...");
return convertEuiccChallenge(apduTransmitter.transmitApdu(ApduUtils.getEUICCChallengeApdu()), matchingId);
}
private String convertEuiccChallenge(String euiccChallengeApduResponse, String matchingId) {
String euiccChallenge;
progress.stepExecuted(DOWNLOAD_PROFILE_CONVERTING_EUICC_CHALLENGE, "convertEuiccChallenge converting...");
try {
euiccChallenge = Base64.encodeBase64String(Util.hexStringToByteArray(decodeGetEuiccChallengeResponse(euiccChallengeApduResponse)));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - eUICCChallenge is " + euiccChallenge);
}
} catch (DecoderException e) {
LOG.log(Level.SEVERE, "KOL.007" + e.getMessage(), e);
LOG.severe(LogStub.getInstance().getTag() + " - matchingId: " + matchingId +
" Unable to retrieve eUICC challenge. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve eUICC challenge: " + matchingId);
} catch (IOException ioe) {
LOG.log(Level.SEVERE, "KOL.007" + ioe.getMessage(), ioe);
LOG.severe(LogStub.getInstance().getTag() + " - matchingId: " + matchingId +
" Unable to retrieve eUICC challenge. IOException:" + ioe.getMessage());
throw new RuntimeException("Unable to retrieve eUICC challenge");
}
progress.stepExecuted(DOWNLOAD_PROFILE_CONVERTED_EUICC_CHALLENGE, "convertEuiccChallenge converted...");
return euiccChallenge;
}
private String decodeGetEuiccChallengeResponse(String euiccChallengeApduResponse) throws DecoderException, IOException {
InputStream is = null;
try {
GetEuiccChallengeResponse euiccChallengeResponse = new GetEuiccChallengeResponse();
is = new ByteArrayInputStream(Hex.decodeHex(euiccChallengeApduResponse.toCharArray()));
euiccChallengeResponse.decode(is);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Decoded euiccChallengeResponse: " + euiccChallengeResponse.toString());
}
return euiccChallengeResponse.getEuiccChallenge().toString();
} finally {
CloseResources.closeResources(is);
}
}
public void initiateAuthentication(InitialAuthenticationKeys initialAuthenticationKeys) {
progress.stepExecuted(DOWNLOAD_PROFILE_INITIATE_AUTHENTICATION, "initiateAuthentication retrieving...");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Initiating Auth with SM-DP+");
}
InitiateAuthenticationResp initiateAuthenticationResp = getInitiateAuthenticationResp(initialAuthenticationKeys);
setServerSigned1(initialAuthenticationKeys, initiateAuthenticationResp);
setServerSignature1(initialAuthenticationKeys, initiateAuthenticationResp);
setEuiccCiPKIdToveUsed(initialAuthenticationKeys, initiateAuthenticationResp);
setServerCertificate(initialAuthenticationKeys, initiateAuthenticationResp);
setTransactionId(initialAuthenticationKeys, initiateAuthenticationResp);
setMatchingId(initialAuthenticationKeys);
setCtxParams1(initialAuthenticationKeys);
progress.stepExecuted(DOWNLOAD_PROFILE_INITIATED_AUTHENTICATION, "initiateAuthentication initiated...");
}
private void setCtxParams1(InitialAuthenticationKeys initialAuthenticationKeys) {
initialAuthenticationKeys.setCtxParams1(LpaUtils.generateCtxParams1());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - ctxParams1: " + initialAuthenticationKeys.getCtxParams1());
}
}
private void setMatchingId(InitialAuthenticationKeys initialAuthenticationKeys) {
initialAuthenticationKeys.setMatchingId(Util.ASCIIToHex(initialAuthenticationKeys.getMatchingId()));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - matchingId: " + initialAuthenticationKeys.getMatchingId());
}
}
private void setTransactionId(InitialAuthenticationKeys initialAuthenticationKeys, InitiateAuthenticationResp initiateAuthenticationResp) {
initialAuthenticationKeys.setTransactionId(initiateAuthenticationResp.getTransactionId());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - transactionId: " + initialAuthenticationKeys.getTransactionId());
}
}
private void setServerCertificate(InitialAuthenticationKeys initialAuthenticationKeys, InitiateAuthenticationResp initiateAuthenticationResp) {
initialAuthenticationKeys.setServerCertificate(initiateAuthenticationResp.getServerCertificate());
initialAuthenticationKeys.setServerCertificate(Util.byteArrayToHexString(Base64.decodeBase64(initialAuthenticationKeys.getServerCertificate()), ""));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - serverCertificate: " + initialAuthenticationKeys.getServerCertificate());
}
}
private void setEuiccCiPKIdToveUsed(InitialAuthenticationKeys initialAuthenticationKeys, InitiateAuthenticationResp initiateAuthenticationResp) {
initialAuthenticationKeys.setEuiccCiPKIdTobeUsed(initiateAuthenticationResp.getEuiccCiPKIdToBeUsed());
initialAuthenticationKeys.setEuiccCiPKIdTobeUsed(Util.byteArrayToHexString(Base64.decodeBase64(initialAuthenticationKeys.getEuiccCiPKIdTobeUsed()), ""));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - euiccCiPKIdTobeUsed: " + initialAuthenticationKeys.getEuiccCiPKIdTobeUsed());
}
}
private void setServerSignature1(InitialAuthenticationKeys initialAuthenticationKeys, InitiateAuthenticationResp initiateAuthenticationResp) {
initialAuthenticationKeys.setServerSignature1(initiateAuthenticationResp.getServerSignature1());
initialAuthenticationKeys.setServerSignature1(Util.byteArrayToHexString(Base64.decodeBase64(initialAuthenticationKeys.getServerSignature1()), ""));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - serverSignature1: " + initialAuthenticationKeys.getServerSignature1());
}
}
private void setServerSigned1(InitialAuthenticationKeys initialAuthenticationKeys, InitiateAuthenticationResp initiateAuthenticationResp) {
initialAuthenticationKeys.setServerSigned1(initiateAuthenticationResp.getServerSigned1());
initialAuthenticationKeys.setServerSigned1(Util.byteArrayToHexString(Base64.decodeBase64(initialAuthenticationKeys.getServerSigned1()), ""));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - serverSigned1: " + initialAuthenticationKeys.getServerSigned1());
}
}
private InitiateAuthenticationResp getInitiateAuthenticationResp(InitialAuthenticationKeys initialAuthenticationKeys) {
InitiateAuthenticationResp initiateAuthenticationResp = es9Module.initiateAuthentication(initialAuthenticationKeys.getEuiccChallenge(),
initialAuthenticationKeys.getEuiccInfo1(), initialAuthenticationKeys.getEuiccConfiguredAddress());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Initiating Auth with SM-DP+ - Response: " + initiateAuthenticationResp);
}
return initiateAuthenticationResp;
}
public AuthenticateClientSmDp authenticateClient(InitialAuthenticationKeys initialAuthenticationKeys, String encodedAuthenticateServerResponse) {
progress.stepExecuted(DOWNLOAD_PROFILE_AUTHENTICATE_CLIENT, "authenticateClient retrieving...");
AuthenticateClientResp authenticateClientResp = getAuthenticateClientResponse(initialAuthenticationKeys, encodedAuthenticateServerResponse);
AuthenticateClientSmDp authenticateClientSmDp = convertAuthenticateClientResp(authenticateClientResp);
progress.stepExecuted(DOWNLOAD_PROFILE_AUTHENTICATED_CLIENT, "authenticateClient authenticated...");
return authenticateClientSmDp;
}
private AuthenticateClientSmDp convertAuthenticateClientResp(AuthenticateClientResp authenticateClientResp) {
AuthenticateClientSmDp authenticateClientSmDp = new AuthenticateClientSmDp();
authenticateClientSmDp.setSmdpSigned2(Util.byteArrayToHexString(Base64.decodeBase64(authenticateClientResp.getSmdpSigned2()), ""));
authenticateClientSmDp.setSmdpSignature2(Util.byteArrayToHexString(Base64.decodeBase64(authenticateClientResp.getSmdpSignature2()), ""));
authenticateClientSmDp.setSmdpCertificate(Util.byteArrayToHexString(Base64.decodeBase64(authenticateClientResp.getSmdpCertificate()), ""));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - authenticateClient returning: " + authenticateClientSmDp);
}
return authenticateClientSmDp;
}
private AuthenticateClientResp getAuthenticateClientResponse(InitialAuthenticationKeys initialAuthenticationKeys, String encodedAuthenticateServerResponse) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Authenticate client with SM-DP+ with initialAuthenticationKeys: " +
initialAuthenticationKeys +
" encodedAuthenticateServerResponse: " +
encodedAuthenticateServerResponse);
}
AuthenticateClientResp authenticateClientResp = es9Module.authenticateClient(initialAuthenticationKeys.getTransactionId(), encodedAuthenticateServerResponse, initialAuthenticationKeys.getEuiccConfiguredAddress());
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Authenticate client with SM-DP+ - Response : " + authenticateClientResp);
}
return authenticateClientResp;
}
public String authenticateWithEuicc(InitialAuthenticationKeys initialAuthenticationKeys) {
progress.stepExecuted(DOWNLOAD_PROFILE_AUTHENTICATE_WITH_EUICC, "authenticateWithEuicc retrieving...");
String authenticateServerResponse = apduTransmitter.transmitApdus(ApduUtils.authenticateServerApdu(initialAuthenticationKeys.getServerSigned1(),
initialAuthenticationKeys.getServerSignature1(),
initialAuthenticationKeys.getEuiccCiPKIdTobeUsed(), initialAuthenticationKeys.getServerCertificate(),
initialAuthenticationKeys.getMatchingId()));
String encodedAuthenticateServerResponse = Base64.encodeBase64String(Util.hexStringToByteArray(authenticateServerResponse));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Authenticate server response (base64): " + encodedAuthenticateServerResponse);
}
progress.stepExecuted(DOWNLOAD_PROFILE_AUTHENTICATED_WITH_EUICC, "authenticateWithEuicc authenticated...");
return encodedAuthenticateServerResponse;
}
}

View File

@ -0,0 +1,16 @@
package com.truphone.lpa.impl.download;
import java.io.InputStream;
public class CloseResources {
static void closeResources(InputStream is) {
if (is != null) {
try {
is.close();
} catch (Exception ignored) {
}
}
}
}

View File

@ -0,0 +1,94 @@
package com.truphone.lpa.impl.download;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpa.progress.DownloadProgressPhase;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.EuiccConfiguredAddressesResponse;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ConnectingPhaseWorker {
private static final Logger LOG = Logger.getLogger(ConnectingPhaseWorker.class.getName());
private DownloadProgress progress;
private ApduTransmitter apduTransmitter;
public ConnectingPhaseWorker(DownloadProgress progress, ApduTransmitter apduTransmitter) {
this.progress = progress;
this.apduTransmitter = apduTransmitter;
}
public String getEuiccConfiguredAddress(String matchingId) {
progress.setCurrentPhase(DownloadProgressPhase.CONNECTING);
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_RETRIEVING_EUICC_ADDRESS, "getEuiccConfiguredAddress - retrieving...");
return convertEuiccConfiguredAddress(apduTransmitter.transmitApdu(ApduUtils.getEuiccConfiguredAddressesApdu()), matchingId);
}
private String convertEuiccConfiguredAddress(String euiCCConfiguredAddressAPDUResponse, String matchingId) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_CONVERTING_EUICC_CONFIGURED_ADDRESS, "getEuiccConfiguredAddresses Success!");
String euiccConfiguredAddresses = getEuiccConfiguredAddress(euiCCConfiguredAddressAPDUResponse, matchingId);
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_CONVERTED_EUICC_ADDRESS, "Converted EUICC Address Success!");
return euiccConfiguredAddresses;
}
private String getEuiccConfiguredAddress(String euiCCConfiguredAddressAPDUResponse, String matchingId) {
try {
EuiccConfiguredAddressesResponse euiccConfiguredAddressesResponse = decodeEuiccConfiguredAddressesResponse(euiCCConfiguredAddressAPDUResponse);
String euiccConfiguredAddress = euiccConfiguredAddressesResponse.getDefaultDpAddress().toString();
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - SM-DP+ configured address: " + euiccConfiguredAddress);
}
return euiccConfiguredAddress;
} catch (DecoderException e) {
LOG.log(Level.SEVERE, "KOL.007" + e.getMessage(), e);
LOG.severe(LogStub.getInstance().getTag() + " - matchingId: " + matchingId +
" Unable to retrieve eUICC configured address. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve eUICC configured address: " + matchingId);
} catch (IOException ioe) {
LOG.log(Level.SEVERE, "KOL.007" + ioe.getMessage(), ioe);
LOG.severe(LogStub.getInstance().getTag() + " - matchingId: " + matchingId +
" Unable to retrieve eUICC configured address. IOException:" + ioe.getMessage());
throw new RuntimeException("Unable to retrieve eUICC configured address");
}
}
private EuiccConfiguredAddressesResponse decodeEuiccConfiguredAddressesResponse(String euiCCConfiguredAddressAPDUResponse) throws DecoderException, IOException {
InputStream is = null;
try {
EuiccConfiguredAddressesResponse euiccConfiguredAddressesResponse = new EuiccConfiguredAddressesResponse();
is = new ByteArrayInputStream(Hex.decodeHex(euiCCConfiguredAddressAPDUResponse.toCharArray()));
euiccConfiguredAddressesResponse.decode(is);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - decoded euiccConfiguredAddressesResponse: " + euiccConfiguredAddressesResponse.toString());
}
return euiccConfiguredAddressesResponse;
} finally {
CloseResources.closeResources(is);
}
}
}

View File

@ -0,0 +1,85 @@
package com.truphone.lpa.impl.download;
import com.truphone.lpa.impl.InitialAuthenticationKeys;
import org.apache.commons.codec.binary.Base64;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.es9plus.message.response.GetBoundProfilePackageResp;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.impl.AuthenticateClientSmDp;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpa.progress.DownloadProgressPhase;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.util.LogStub;
import com.truphone.util.Util;
import java.util.logging.Logger;
public class DownloadPhaseWorker {
private static final Logger LOG = Logger.getLogger(DownloadPhaseWorker.class.getName());
private final DownloadProgress progress;
private final ApduTransmitter apduTransmitter;
private final Es9PlusImpl es9Module;
public DownloadPhaseWorker(DownloadProgress progress, ApduTransmitter apduTransmitter, Es9PlusImpl es9Module) {
this.progress = progress;
this.apduTransmitter = apduTransmitter;
this.es9Module = es9Module;
}
public String prepareDownload(AuthenticateClientSmDp authenticateClientSmDp) {
progress.setCurrentPhase(DownloadProgressPhase.DOWNLOADING);
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_PREPARE_DOWNLOAD, "prepareDownload retrieving...");
String prepareDownloadResponse = apduTransmitter.transmitApdus(ApduUtils.prepareDownloadApdu(authenticateClientSmDp.getSmdpSigned2(),
authenticateClientSmDp.getSmdpSignature2(), authenticateClientSmDp.getSmdpCertificate(),
null));
String encodedPrepareDownloadResponse = Base64.encodeBase64String(Util.hexStringToByteArray(prepareDownloadResponse));
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Prepare download response (base64): " + encodedPrepareDownloadResponse);
}
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_PREPARED_DOWNLOAD, "prepareDownload retrieved...");
return encodedPrepareDownloadResponse;
}
public String getBoundProfilePackage(InitialAuthenticationKeys initialAuthenticationKeys, String encodedPrepareDownloadResponse) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_GET_BOUND_PROFILE_PACKAGE,
"downloadAndInstallProfilePackage retrieving...");
GetBoundProfilePackageResp getBoundProfilePackageResp = getGetBoundProfilePackageResp(initialAuthenticationKeys, encodedPrepareDownloadResponse, initialAuthenticationKeys.getEuiccConfiguredAddress());
String bpp = Util.byteArrayToHexString(Base64.decodeBase64(getBoundProfilePackageResp.getBoundProfilePackage()), "");
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE_RETRIEVED,
"downloadAndInstallProfilePackage retrieved...");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - getBoundProfilePackage - BPP is: " + bpp);
}
return bpp;
}
private GetBoundProfilePackageResp getGetBoundProfilePackageResp(InitialAuthenticationKeys initialAuthenticationKeys, String encodedPrepareDownloadResponse, String smdpAddress) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Getting bound profile package from SM-DP+");
}
GetBoundProfilePackageResp getBoundProfilePackageResp = es9Module.getBoundProfilePackage(initialAuthenticationKeys.getTransactionId(),
encodedPrepareDownloadResponse,smdpAddress);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Getting bound profile package from SM-DP+ - Response - " +
encodedPrepareDownloadResponse);
}
return getBoundProfilePackageResp;
}
}

View File

@ -0,0 +1,115 @@
package com.truphone.lpa.impl.download;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpa.apdu.ProfileUtil;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpa.progress.DownloadProgressPhase;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.BoundProfilePackage;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class GeneratePhaseWorker {
private static final Logger LOG = Logger.getLogger(GeneratePhaseWorker.class.getName());
private final DownloadProgress progress;
public GeneratePhaseWorker(DownloadProgress progress) {
this.progress = progress;
}
public Map<SbppApdu, List<String>> generateSbpp(String bpp) throws IOException {
progress.setCurrentPhase(DownloadProgressPhase.GENERATING);
List<String[]> sbpp = generateSbpps(bpp);
return generateSbppMap(sbpp);
}
private Map<SbppApdu, List<String>> generateSbppMap(List<String[]> sbpp) {
Map<SbppApdu, List<String>> sbppApduMap = new HashMap<>();
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_GENERATING_SBPP_APDUS,
"generateSbpp generating...");
sbppApduMap.put(SbppApdu.BOUND_PROFILE_PACKAGE, ApduUtils.loadBoundProfilePackageApdu(sbpp));
if(sbpp.size()==5){
//secondSequenceOf87
sbppApduMap.put(SbppApdu.REPLACE_SESSIONS_KEYS, ApduUtils.loadProfileProtectionKeys(sbpp));
}
sbppApduMap.put(SbppApdu.STORE_METADATA, ApduUtils.loadStoreMetadataApdu(sbpp));
sbppApduMap.put(SbppApdu.CONFIGURE_ISDPA, ApduUtils.loadConfigureISDPApdu(sbpp));
sbppApduMap.put(SbppApdu.INITIALIZE_SECURE_CHANNEL, ApduUtils.loadInitialiseSecureChannelApdu(sbpp));
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_GENERATED_SBPP_APDUS,
"generateSbpp generated...");
return sbppApduMap;
}
private List<String[]> generateSbpps(String bpp) throws IOException {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_GENERATING_SBPP,
"generateSbpp generating...");
ProfileUtil util = new ProfileUtil();
logPrintBpp(bpp);
// TODO: This should be refactored to use the jASN1 objects
List<String[]> sbpp = util.generateSBPP(bpp);
logPrintSbpp(sbpp);
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_GENERATED_SBPP,
"generateSbpp generated...");
return sbpp;
}
private void logPrintSbpp(List<String[]> sbpp) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - SBPP count: " + sbpp.size());
for (String[] s : sbpp) {
for (String s1 : s) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - generateSbpp - SBPP is: " + s1);
}
}
}
}
private void logPrintBpp(String bpp) throws IOException {
if (LogStub.getInstance().isDebugEnabled()) {
InputStream bppIs = null;
BoundProfilePackage bppObj = new BoundProfilePackage();
try {
bppIs = new ByteArrayInputStream(Hex.decodeHex(bpp.toCharArray()));
bppObj.decode(bppIs);
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - BPP Object is: " + bppObj);
} catch (DecoderException e) {
LOG.log(Level.INFO, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
} finally {
CloseResources.closeResources(bppIs);
}
}
}
}

View File

@ -0,0 +1,249 @@
package com.truphone.lpa.impl.download;
import com.truphone.lpa.ApduTransmittedListener;
import com.truphone.lpa.progress.DownloadProgress;
import com.truphone.lpa.progress.DownloadProgressPhase;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.ProfileInstallationResult;
import com.truphone.rsp.dto.asn1.rspdefinitions.ProfileInstallationResultData;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class InstallationPhaseWorker {
private static final Logger LOG = Logger.getLogger(InstallationPhaseWorker.class
.getName());
private final DownloadProgress progress;
private final ApduTransmitter apduTransmitter;
public InstallationPhaseWorker(DownloadProgress progress, ApduTransmitter apduTransmitter) {
this.progress = progress;
this.apduTransmitter = apduTransmitter;
}
public void loadingSbppApdu(Map<SbppApdu, List<String>> sbpp) {
ApduTransmittedListener apduTransmittedListener;
progress.setCurrentPhase(DownloadProgressPhase.INSTALLING, getTotalApdus(sbpp)
+ DownloadProgressPhase.INSTALLING.getProgressSteps().size());
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_LOADING_SBPP,
"generateSbpp generating...");
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Sending SBPP to eUICC");
}
apduTransmittedListener = addApduTransmittedListener();
loadInitialiseSecureChannel(sbpp.get(SbppApdu.INITIALIZE_SECURE_CHANNEL));
loadConfigureIsdpa(sbpp.get(SbppApdu.CONFIGURE_ISDPA));
loadStoreMetadata(sbpp.get(SbppApdu.STORE_METADATA));
if (sbpp.size() == 5) {
loadReplaceSessionKeys(sbpp.get(SbppApdu.REPLACE_SESSIONS_KEYS));
}
loadBoundProfilePackage(sbpp.get(SbppApdu.BOUND_PROFILE_PACKAGE));
removeApduTransmittedListener(apduTransmittedListener);
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_INSTALLED,
"INSTALLED!");
}
private int getTotalApdus(Map<SbppApdu, List<String>> sbpp) {
int totalApdus = 0;
for (List<String> apdus : sbpp.values()) {
totalApdus += apdus.size();
}
return totalApdus;
}
private ApduTransmittedListener addApduTransmittedListener() {
ApduTransmittedListener apduTransmittedListener = new ApduTransmittedListener() {
@Override
public void onApduTransmitted() {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_APDU_TRANSMITTED, "Apdu transmitted");
}
};
apduTransmitter.addApduTransmittedListener(apduTransmittedListener);
return apduTransmittedListener;
}
private void removeApduTransmittedListener(ApduTransmittedListener apduTransmittedListener) {
apduTransmitter.removeApduTransmittedListener(apduTransmittedListener);
}
private void loadBoundProfilePackage(List<String> sbpp) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE,
"loadBoundProfilePackage...");
String profileInstallationResult = apduTransmitter.transmitApdus(sbpp);
if (StringUtils.isNotBlank(profileInstallationResult) && profileInstallationResult.length() > 4) {
checkProfileInstallationResult(profileInstallationResult);
} else {
throw new RuntimeException("Unexpected response on loadBoundProfilePackage");
}
}
private void loadStoreMetadata(List<String> sbpp) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_STORE_METADATA,
"loadStoreMetadata...");
String profileInstallationResult = apduTransmitter.transmitApdus(sbpp);
if (profileInstallationResult.compareTo("9000") != 0) {
if (StringUtils.isNotBlank(profileInstallationResult) && profileInstallationResult.length() > 4) {
checkProfileInstallationResult(profileInstallationResult);
} else {
throw new RuntimeException("Unexpected response on loadStoreMetadata");
}
}
}
private void loadConfigureIsdpa(List<String> sbpp) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_CONFIGURE_ISDPA,
"loadConfigureIsdpa...");
String profileInstallationResult = apduTransmitter.transmitApdus(sbpp);
if (profileInstallationResult.compareTo("9000") != 0) {
if (StringUtils.isNotBlank(profileInstallationResult) && profileInstallationResult.length() > 4) {
checkProfileInstallationResult(profileInstallationResult);
} else {
throw new RuntimeException("Unexpected response on loadConfigureIsdpa");
}
}
}
private void loadInitialiseSecureChannel(List<String> sbpp) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_INITIALIZE_SECURE_CHANNEL,
"loadInitialiseSecureChannel...");
String profileInstallationResult = apduTransmitter.transmitApdus(sbpp);
if (profileInstallationResult.compareTo("9000") != 0) {
if (StringUtils.isNotBlank(profileInstallationResult) && profileInstallationResult.length() > 4) {
checkProfileInstallationResult(profileInstallationResult);
} else {
throw new RuntimeException("Unexpected response on loadInitialiseSecureChannel");
}
}
}
private void checkProfileInstallationResult(String profileInstallationResultRaw) {
boolean success = false;
String errorMessage = "";
try {
ProfileInstallationResult profileInstallationResult = getProfileInstallationResult(profileInstallationResultRaw);
if (profileInstallationResult.getProfileInstallationResultData() != null
&& profileInstallationResult.getProfileInstallationResultData().getFinalResult() != null) {
ProfileInstallationResultData.FinalResult finalResult = profileInstallationResult.getProfileInstallationResultData().getFinalResult();
if (finalResult.getSuccessResult() != null) {
LOG.info(LogStub.getInstance().getTag() + " - Decoded Success Result: " + finalResult.getSuccessResult().toString());
success = true;
} else {
errorMessage = invalidFinalResult(finalResult);
}
} else {
errorMessage = invalidProfileInstallationData();
}
if (!success) {
throw new RuntimeException(errorMessage);
}
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.severe(LogStub.getInstance().getTag() + " - Unable to retrieve Profile Installation Result. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve Profile Installation Result.");
} catch (IOException ioe) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + ioe.getMessage(), ioe);
LOG.severe(LogStub.getInstance().getTag() + " - Unable to retrieve Profile Installation Result. IOException:" + ioe.getMessage());
throw new RuntimeException("Unable to retrieve Profile Installation Result.");
}
}
private String invalidFinalResult(ProfileInstallationResultData.FinalResult finalResult) {
String errorMessage = finalResult.getErrorResult().getErrorReason().toString() + ":"
+ finalResult.getErrorResult().getBppCommandId().toString() + ":"
+ finalResult.getErrorResult().getSimaResponse().toString();
LOG.info(LogStub.getInstance().getTag() + " - Decoded ERROR Result: " + finalResult.getErrorResult().toString());
return errorMessage;
}
private String invalidProfileInstallationData() {
String errorMessage = "Could not parse Profile Installation Result";
LOG.info(LogStub.getInstance().getTag() + " - Profile Installation Result Data or Final result is null.");
return errorMessage;
}
private ProfileInstallationResult getProfileInstallationResult(String profileInstallationResultRaw) throws DecoderException, IOException {
InputStream is = null;
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - Check Profile Installation Result input: " + profileInstallationResultRaw);
}
try {
ProfileInstallationResult profileInstallationResult = new ProfileInstallationResult();
is = new ByteArrayInputStream(Hex.decodeHex(profileInstallationResultRaw.toCharArray()));
profileInstallationResult.decode(is, true);
return profileInstallationResult;
} finally {
CloseResources.closeResources(is);
}
}
private void loadReplaceSessionKeys(List<String> sbpp) {
progress.stepExecuted(ProgressStep.DOWNLOAD_PROFILE_REPLACE_SESSIONS_KEYS,
"loadReplaceSessionsKeys...");
String profileInstallationResult = apduTransmitter.transmitApdus(sbpp);
if (profileInstallationResult.compareTo("9000") != 0) {
if (StringUtils.isNotBlank(profileInstallationResult) && profileInstallationResult.length() > 4) {
checkProfileInstallationResult(profileInstallationResult);
} else {
throw new RuntimeException("Unexpected response on loadReplaceSessionsKeys");
}
}
}
}

View File

@ -0,0 +1,9 @@
package com.truphone.lpa.impl.download;
public enum SbppApdu {
INITIALIZE_SECURE_CHANNEL,
CONFIGURE_ISDPA,
STORE_METADATA,
REPLACE_SESSIONS_KEYS,
BOUND_PROFILE_PACKAGE
}

View File

@ -0,0 +1,132 @@
package com.truphone.lpa.progress;
import com.truphone.lpad.progress.ProgressListener;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.util.LogStub;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class DownloadProgress {
private static final Logger LOG = Logger.getLogger(DownloadProgress.class.getName());
private final Executor executor;
private ProgressListener progressListener;
private DownloadProgressPhase downloadProgressPhase;
private int totalPhaseSteps;
private int currentPhaseStepSum;
public DownloadProgress() {
executor = Executors.newSingleThreadExecutor();
downloadProgressPhase = DownloadProgressPhase.AUTHENTICATING;
totalPhaseSteps = DownloadProgressPhase.AUTHENTICATING.getProgressSteps().size();
currentPhaseStepSum = 0;
}
public void stepExecuted(final ProgressStep step,
final String message) {
if (progressListener != null) {
++currentPhaseStepSum;
final DownloadProgressPhase downloadProgressPhaseAux = downloadProgressPhase;
final int totalPhaseStepsAux = totalPhaseSteps;
final int currentPhaseStepSumAux = currentPhaseStepSum;
executor.execute(new Runnable() {
@Override
public void run() {
double percentage;
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - stepExecuted - step: " + step + "; currentPhaseStepSum: " + currentPhaseStepSumAux +
"; message: " + message + "; currentProgressPhase: " + downloadProgressPhaseAux +
"; totalPhaseSteps: " + totalPhaseStepsAux);
}
percentage = calculatePercentage(downloadProgressPhaseAux, currentPhaseStepSumAux, totalPhaseStepsAux);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - stepExecuted - onAction - step: " + step.name() +
"; message: " + message + "; percentage: " + percentage +
"; downloadProgressPhase: " + downloadProgressPhaseAux.name());
}
progressListener.onAction(downloadProgressPhaseAux.name(), step.name(), percentage, message);
}
private double calculatePercentage(final DownloadProgressPhase downloadProgressPhaseAux,
final int currentPhaseStepSumAux,
final int totalPhaseStepsAux) {
double percentage;
if (currentPhaseStepSumAux == totalPhaseStepsAux) {
percentage = 1.0;
} else {
percentage = (double) currentPhaseStepSumAux / totalPhaseStepsAux;
if (percentage > 1.0) {
percentage = 1.0;
}
}
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - calculatePercentage - percentage_1: " + percentage);
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - calculatePercentage - percentage_f: " +
(percentage * downloadProgressPhaseAux.getPhaseTotalPercentage() / 1.0 + getTotalPreviousPhases(downloadProgressPhaseAux)));
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - calculatePercentage - previous: " + getTotalPreviousPhases(downloadProgressPhaseAux));
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - calculatePercentage - current: " + (percentage * downloadProgressPhaseAux.getPhaseTotalPercentage()));
}
percentage = percentage * downloadProgressPhaseAux.getPhaseTotalPercentage() / 1.0 + getTotalPreviousPhases(downloadProgressPhaseAux);
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - DownloadProgress - calculatePercentage - final: " + percentage);
}
return percentage > 1.0 ? 1.0 : percentage;
}
private double getTotalPreviousPhases(DownloadProgressPhase downloadProgressPhase) {
int currentPhaseNumber = downloadProgressPhase.ordinal();
double total = 0.0;
for (int i = 0; i < currentPhaseNumber; i++) {
total += DownloadProgressPhase.values()[i].getPhaseTotalPercentage();
}
return total;
}
});
}
}
public void setProgressListener(ProgressListener progressListener) {
this.progressListener = progressListener;
}
public void setCurrentPhase(DownloadProgressPhase downloadProgressPhase,
int totalPhaseSteps) {
this.downloadProgressPhase = downloadProgressPhase;
this.totalPhaseSteps = totalPhaseSteps;
currentPhaseStepSum = 0;
}
public void setCurrentPhase(DownloadProgressPhase downloadProgressPhase) {
setCurrentPhase(downloadProgressPhase, downloadProgressPhase.getProgressSteps().size());
}
}

View File

@ -0,0 +1,61 @@
package com.truphone.lpa.progress;
import com.truphone.lpad.progress.ProgressStep;
import java.util.Arrays;
import java.util.List;
public enum DownloadProgressPhase {
CONNECTING(0.05, ProgressStep.DOWNLOAD_PROFILE_RETRIEVING_EUICC_ADDRESS,
ProgressStep.DOWNLOAD_PROFILE_CONVERTING_EUICC_CONFIGURED_ADDRESS,
ProgressStep.DOWNLOAD_PROFILE_CONVERTED_EUICC_ADDRESS),
AUTHENTICATING(0.3, ProgressStep.DOWNLOAD_PROFILE_GET_EUICC_INFO,
ProgressStep.DOWNLOAD_PROFILE_CONVERTING_EUICC_INFO,
ProgressStep.DOWNLOAD_PROFILE_CONVERTED_EUICC_INFO,
ProgressStep.DOWNLOAD_PROFILE_GET_EUICC_CHALLENGE,
ProgressStep.DOWNLOAD_PROFILE_CONVERTING_EUICC_CHALLENGE,
ProgressStep.DOWNLOAD_PROFILE_CONVERTED_EUICC_CHALLENGE,
ProgressStep.DOWNLOAD_PROFILE_INITIATE_AUTHENTICATION,
ProgressStep.DOWNLOAD_PROFILE_INITIATED_AUTHENTICATION,
ProgressStep.DOWNLOAD_PROFILE_AUTHENTICATE_WITH_EUICC,
ProgressStep.DOWNLOAD_PROFILE_AUTHENTICATED_WITH_EUICC,
ProgressStep.DOWNLOAD_PROFILE_AUTHENTICATE_CLIENT,
ProgressStep.DOWNLOAD_PROFILE_AUTHENTICATED_CLIENT),
DOWNLOADING(0.1,
ProgressStep.DOWNLOAD_PROFILE_PREPARE_DOWNLOAD,
ProgressStep.DOWNLOAD_PROFILE_PREPARED_DOWNLOAD,
ProgressStep.DOWNLOAD_PROFILE_GET_BOUND_PROFILE_PACKAGE,
ProgressStep.DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE_RETRIEVED),
GENERATING(0.05,
ProgressStep.DOWNLOAD_PROFILE_GENERATING_SBPP,
ProgressStep.DOWNLOAD_PROFILE_GENERATED_SBPP,
ProgressStep.DOWNLOAD_PROFILE_GENERATING_SBPP_APDUS,
ProgressStep.DOWNLOAD_PROFILE_GENERATED_SBPP_APDUS),
INSTALLING(0.5,
ProgressStep.DOWNLOAD_PROFILE_LOADING_SBPP,
ProgressStep.DOWNLOAD_PROFILE_INITIALIZE_SECURE_CHANNEL,
ProgressStep.DOWNLOAD_PROFILE_CONFIGURE_ISDPA,
ProgressStep.DOWNLOAD_PROFILE_STORE_METADATA,
ProgressStep.DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE,
ProgressStep.DOWNLOAD_PROFILE_INSTALLED);
private List<ProgressStep> progressSteps;
private double phaseTotalPercentage;
DownloadProgressPhase(double phaseTotalPercentage, ProgressStep... progressSteps) {
this.progressSteps = Arrays.asList(progressSteps);
this.phaseTotalPercentage = phaseTotalPercentage;
}
public List<ProgressStep> getProgressSteps() {
return progressSteps;
}
public double getPhaseTotalPercentage() {
return phaseTotalPercentage;
}
}

View File

@ -0,0 +1,5 @@
package com.truphone.lpa.progress;
public enum ProgressPhase {
RUNNING
}

View File

@ -0,0 +1,17 @@
package com.truphone.lpad;
import com.truphone.lpad.worker.WorkerExchange;
/**
* Representation of all classes that contains the implementation of LPAD operations
*/
public interface LpadWorker<T extends WorkerExchange, E> {
/**
* Execute operation
*
* @param input Input parameters
* @return Result of the LPAD operation
*/
E run(T input);
}

View File

@ -0,0 +1,68 @@
package com.truphone.lpad.progress;
import com.truphone.util.LogStub;
import com.truphone.lpa.progress.ProgressPhase;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class Progress {
private static final Logger LOG = Logger.getLogger(Progress.class.getName());
private final Executor executor;
private ProgressListener progressListener;
private ProgressPhase progressPhase;
private int totalSteps;
private int currentStep;
public Progress() {
executor = Executors.newSingleThreadExecutor();
progressPhase = ProgressPhase.RUNNING;
totalSteps = 1;
currentStep = 0;
}
public void stepExecuted(final ProgressStep step,
final String message) {
if (progressListener != null) {
++currentStep;
executor.execute(new Runnable() {
@Override
public void run() {
double percentage;
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() +
" - Progress - setAction - phase: " +
progressPhase + "; step: " + step + "; currentStep: " + currentStep +
"; message: " + message + "; totalSteps: " + totalSteps);
}
percentage = currentStep / totalSteps;
if (percentage > 1.0) {
percentage = 1.0;
}
progressListener.onAction(progressPhase.name(), step.name(), percentage, message);
}
});
}
}
public void setProgressListener(ProgressListener progressListener) {
this.progressListener = progressListener;
}
public void setTotalSteps(int totalSteps) {
this.totalSteps = totalSteps;
}
}

View File

@ -0,0 +1,9 @@
package com.truphone.lpad.progress;
public interface ProgressListener {
void onAction(String phase,
String step,
Double percentage,
String message);
}

View File

@ -0,0 +1,62 @@
package com.truphone.lpad.progress;
public enum ProgressStep {
ENABLE_PROFILE_PROFILE_ENABLED,
ENABLE_PROFILE_PROFILE_NOT_ENABLED,
ENABLE_PROFILE_ENABLING_PROFILE,
ENABLE_PROFILE_CONVERTING_RESPONSE,
ENABLE_PROFILE_TRIGGERED_PROFILE_SWITCH,
DISABLE_PROFILE_DISABLING_PROFILE,
DISABLE_PROFILE_DISABLED,
DISABLE_PROFILE_NOT_DISABLED,
DISABLE_PROFILE_CONVERTING_RESPONSE,
DISABLE_PROFILE_TRIGGERED_PROFILE_SWITCH,
DELETE_PROFILE_DELETING_PROFILE,
DELETE_PROFILE_NOT_DELETED,
DELETE_PROFILE_DELETED,
DELETE_PROFILE_CONVERTING_RESPONSE,
MEMORY_RESET_SUCCESS,
MEMORY_RESET_RESETING,
DOWNLOAD_PROFILE_RETRIEVING_EUICC_ADDRESS,
DOWNLOAD_PROFILE_CONVERTING_EUICC_CONFIGURED_ADDRESS,
DOWNLOAD_PROFILE_CONVERTED_EUICC_ADDRESS,
DOWNLOAD_PROFILE_GET_EUICC_INFO,
DOWNLOAD_PROFILE_CONVERTING_EUICC_INFO,
DOWNLOAD_PROFILE_CONVERTED_EUICC_INFO,
DOWNLOAD_PROFILE_GET_EUICC_CHALLENGE,
DOWNLOAD_PROFILE_CONVERTING_EUICC_CHALLENGE,
DOWNLOAD_PROFILE_CONVERTED_EUICC_CHALLENGE,
DOWNLOAD_PROFILE_INITIATE_AUTHENTICATION,
DOWNLOAD_PROFILE_INITIATED_AUTHENTICATION,
DOWNLOAD_PROFILE_AUTHENTICATE_WITH_EUICC,
DOWNLOAD_PROFILE_AUTHENTICATED_WITH_EUICC,
DOWNLOAD_PROFILE_AUTHENTICATE_CLIENT,
DOWNLOAD_PROFILE_AUTHENTICATED_CLIENT,
DOWNLOAD_PROFILE_PREPARE_DOWNLOAD,
DOWNLOAD_PROFILE_PREPARED_DOWNLOAD,
DOWNLOAD_PROFILE_GET_BOUND_PROFILE_PACKAGE,
DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE_RETRIEVED,
DOWNLOAD_PROFILE_GENERATING_SBPP,
DOWNLOAD_PROFILE_GENERATED_SBPP,
DOWNLOAD_PROFILE_GENERATING_SBPP_APDUS,
DOWNLOAD_PROFILE_GENERATED_SBPP_APDUS,
DOWNLOAD_PROFILE_LOADING_SBPP,
DOWNLOAD_PROFILE_INITIALIZE_SECURE_CHANNEL,
DOWNLOAD_PROFILE_CONFIGURE_ISDPA,
DOWNLOAD_PROFILE_STORE_METADATA,
DOWNLOAD_PROFILE_REPLACE_SESSIONS_KEYS,
DOWNLOAD_PROFILE_BOUND_PROFILE_PACKAGE,
DOWNLOAD_PROFILE_INSTALLED,
DOWNLOAD_PROFILE_APDU_TRANSMITTED,
ALLOCATE_PROFILE_ALLOCATING,
ALLOCATE_PROFILE_ALLOCATED,
GET_EID_RETRIEVING,
GET_EID_CONVERTING,
GET_EID_CONVERTED
}

View File

@ -0,0 +1,119 @@
package com.truphone.lpad.worker;
import com.truphone.es9plus.AllocateProfileResponse;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.util.LogStub;
import org.apache.commons.lang3.StringUtils;
import com.truphone.lpad.LpadWorker;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang3.NotImplementedException;
/**
* Worker containing all logic to allocate a profile for a MCC with a specific EID
*/
public class AllocateProfileWorker implements LpadWorker<LpadWorkerExchange<AllocateProfileWorker.AllocateProfileInputParams>, String> {
private static final Logger LOG = Logger.getLogger(AllocateProfileWorker.class.getName());
private final Progress progress;
private final Es9PlusImpl es9PlusImpl;
/**
* @param progress Progress Bar
* @param es9PlusImpl RSP29 Client
*/
public AllocateProfileWorker(final Progress progress,
final Es9PlusImpl es9PlusImpl) {
inputValidation(progress == null, "Progress must not be null");
inputValidation(es9PlusImpl == null, "Es9PlusImpl must not be null");
this.progress = progress;
this.es9PlusImpl = es9PlusImpl;
}
/**
* Allocates the Protected Profile Packages to specified EIDs based on given MCC
*
* @param lpadWorkerExchange Exchange that must contain in its body the {@link AllocateProfileInputParams}
* @return Activation Code Token
*/
public String run(final LpadWorkerExchange<AllocateProfileInputParams> lpadWorkerExchange) {
// inputValidation(lpadWorkerExchange == null, "Input params to invoke Allocate Profile must not be null");
// inputValidation(lpadWorkerExchange.getBody() == null, "Input params must have body defined");
// inputValidation(StringUtils.isBlank(lpadWorkerExchange.getBody().getEid()), "EID must not be null/empty");
// inputValidation(StringUtils.isBlank(lpadWorkerExchange.getBody().getMcc()), "MCC must not be null/empty");
//
// progress.setTotalSteps(2);
// progress.stepExecuted(ProgressStep.ALLOCATE_PROFILE_ALLOCATING, "allocateProfile allocating...");
//
// logDebug(" - Allocating profile for MCC: " + lpadWorkerExchange.getBody().getMcc()
// + " and EID: " + lpadWorkerExchange.getBody().getEid());
//
// AllocateProfileResponse allocateProfileResponse
// = es9PlusImpl.allocateProfile(lpadWorkerExchange.getBody().getEid(), lpadWorkerExchange.getBody().getMcc());
//
// if (allocateProfileResponse != null) {
// progress.stepExecuted(ProgressStep.ALLOCATE_PROFILE_ALLOCATED, "allocateProfile allocated!");
//
// logDebug(" - Allocate Profile Response: " + allocateProfileResponse);
//
// return allocateProfileResponse.getAcToken();
// } else {
// logDebug(" - No matching id returned from profile broker, please check profiles are available");
//
// throw new RuntimeException("Unable to allocate profile");
// }
throw new NotImplementedException("Not implemented");
}
private void logDebug(final String errorMessage) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + errorMessage);
}
}
private void inputValidation(final boolean invalidCondition, final String errorMessage) {
if (invalidCondition) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + errorMessage);
throw new IllegalArgumentException(errorMessage);
}
}
/**
* This class is responsible to gather the mandatory params to allocate a profile, which are:
* <ul>
* <li>mcc: Mobile country code</li>
* <li>eid: eUICC-ID</li>
* </ul>
*/
public class AllocateProfileInputParams {
private final String mcc;
private final String eid;
/**
* Input params to allocate the Protected Profile Packages
*
* @param mcc Mobile country code
* @param eid eUICC-ID
*/
public AllocateProfileInputParams(final String mcc, final String eid) {
this.mcc = mcc;
this.eid = eid;
}
String getMcc() {
return mcc;
}
String getEid() {
return eid;
}
}
}

View File

@ -0,0 +1,162 @@
package com.truphone.lpad.worker;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.LpadWorker;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.DeleteProfileResponse;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DeleteProfileWorker implements LpadWorker<LpadWorkerExchange<DeleteProfileWorker.DeleteProfileInputParams>, String> {
private static final Logger LOG = Logger.getLogger(DeleteProfileWorker.class.getName());
private final Progress progress;
private final ApduChannel apduChannel;
static final String PROFILE_RESULT_SUCCESS = "0";
/**
* @param progress Progress Bar
* @param apduChannel aPDU Channel
*/
public DeleteProfileWorker(Progress progress, ApduChannel apduChannel) {
inputValidation(progress == null, "Progress must not be null");
inputValidation(apduChannel == null, "ApduChannel must not be null");
this.progress = progress;
this.apduChannel = apduChannel;
}
/**
* Deletes the Profile from the ICC and converts the response to be readable
*
* @param lpadWorkerExchange Exchange that must contain in its body the {@link DeleteProfileInputParams}
* @return Delete response Code
*/
public String run(final LpadWorkerExchange<DeleteProfileInputParams> lpadWorkerExchange) {
inputValidation(lpadWorkerExchange == null, "Input params to invoke Delete Profile must not be null");
inputValidation(lpadWorkerExchange.getBody() == null, "Input params must have body defined");
inputValidation(StringUtils.isBlank(lpadWorkerExchange.getBody().getIccid()), "ICCID must not be null/empty");
String iccid = lpadWorkerExchange.getBody().getIccid(); // Get ICCID From Body
String eResponse = transmitDeleteProfile(iccid, progress);
return convertDeleteProfile(iccid, progress, eResponse);
}
/**
* Converts the response from the transmission, checks if there are errors in the transmission
*
* @param iccid Integrated Circuit Card ID
* @param progress Progress Bar
* @param eResponse Response from transmitDeleteProfile
* @return Delete response Code
*/
private String convertDeleteProfile(String iccid, Progress progress, String eResponse) {
progress.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
DeleteProfileResponse deleteProfileResponse = new DeleteProfileResponse();
try {
InputStream is = new ByteArrayInputStream(Hex.decodeHex(eResponse.toCharArray()));
deleteProfileResponse.decode(is);
logDebug(" - Delete response: " + deleteProfileResponse);
if (PROFILE_RESULT_SUCCESS.equals(deleteProfileResponse.getDeleteResult().toString())) {
logDebug(" - iccid: " + iccid + " profile deleted");
logDebug(" - iccid: " + iccid + " Refreshing SIM card on Delete.");
apduChannel.sendStatus();
progress.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
} else {
progress.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
LOG.info(LogStub.getInstance().getTag() + " - iccid:" + iccid + " profile not deleted");
}
return deleteProfileResponse.getDeleteResult().toString();
} catch (IOException ioe) {
LOG.severe(LogStub.getInstance().getTag() + " - iccid:" + iccid + " profile failed to be deleted");
throw new RuntimeException("Unable to delete profile: " + iccid + ", response: " + eResponse);
} catch (DecoderException e) {
LOG.severe(LogStub.getInstance().getTag() + " - " + e.getMessage());
LOG.severe(LogStub.getInstance().getTag() + " - iccid: " + iccid + " profile failed to be deleted. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to delete profile: " + iccid + ", response: " + eResponse);
}
}
/**
* Transmits the action to deletes the profile for the specific ICC
*
* @param iccid Integrated Circuit Card ID
* @param progress Progress Bar
* @return
*/
private String transmitDeleteProfile(String iccid, Progress progress) {
progress.setTotalSteps(3);
progress.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
logDebug(" - Deleting profile: " + iccid);
String apdu = ApduUtils.deleteProfileApdu(iccid);
logDebug(" - Delete profile apdu: " + apdu);
String eResponse = apduChannel.transmitAPDU(apdu);
logDebug(" - Delete Response: " + eResponse);
return eResponse;
}
private void logDebug(final String errorMessage) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + errorMessage);
}
}
private void inputValidation(final boolean invalidCondition, final String errorMessage) {
if (invalidCondition) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + errorMessage);
throw new IllegalArgumentException(errorMessage);
}
}
/**
* This class is responsible to gather the mandatory params to delete a profile, which are:
* <ul>
* <li>iccid: Integrated Circuit Card ID</li>
* </ul>
*/
public class DeleteProfileInputParams {
private final String iccid;
/**
* Input params to allocate the Protected Profile Packages
*
* @param iccid Integrated Circuit Card ID
*/
public DeleteProfileInputParams(final String iccid) {
this.iccid = iccid;
}
String getIccid() {
return iccid;
}
}
}

View File

@ -0,0 +1,109 @@
package com.truphone.lpad.worker;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpad.LpadWorker;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.rsp.dto.asn1.rspdefinitions.GetEuiccDataResponse;
import com.truphone.util.LogStub;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class GetEidLpadWorker implements LpadWorker<LpadWorkerExchange<String>, String> {
private static final Logger LOG = Logger.getLogger(GetEidLpadWorker.class.getName());
private final Progress progress;
private final ApduChannel apduChannel;
public GetEidLpadWorker(final Progress progress,
final ApduChannel apduChannel) {
inputValidation(progress == null, "received an invalid progress: " + progress);
inputValidation(apduChannel == null, "received an invalid apduChannel: " + apduChannel);
this.progress = progress;
this.apduChannel = apduChannel;
}
/**
* Gets the EID from the eUICC, using its apdu
*
* @param lpadWorkerExchange Exchange that must contain in its body the APDU related with the EID which we want to obtain
* @return The EID from the eUICC, using its APDU
*/
public String run(final LpadWorkerExchange<String> lpadWorkerExchange) {
progress.setTotalSteps(3);
progress.stepExecuted(ProgressStep.GET_EID_RETRIEVING, "getEID retrieving...");
inputValidation(lpadWorkerExchange == null, "Lpa dWorker Exchange must be provided");
inputValidation(StringUtils.isBlank(lpadWorkerExchange.getBody()), "EID APDU must be provided");
logDebug("EID APDU: " + lpadWorkerExchange);
String eidapduResponseStr = apduChannel.transmitAPDU(lpadWorkerExchange.getBody());
logDebug("Response: " + eidapduResponseStr);
return convertGetEuiccData(eidapduResponseStr, progress);
}
private String convertGetEuiccData(final String eidapduResponseStr,
final Progress progress) {
progress.stepExecuted(ProgressStep.GET_EID_CONVERTING, "getEID converting...");
inputValidation(StringUtils.isBlank(eidapduResponseStr), "received an invalid eidapduResponseStr: " + eidapduResponseStr);
GetEuiccDataResponse eidResponse = new GetEuiccDataResponse();
try {
logDebug("Decoding response: " + eidapduResponseStr);
InputStream is = new ByteArrayInputStream(Hex.decodeHex(eidapduResponseStr.toCharArray()));
logDebug("Decoding with GetEuiccDataResponse");
eidResponse.decode(is, true);
logDebug("EID is: " + eidResponse.getEidValue().toString());
progress.stepExecuted(ProgressStep.GET_EID_CONVERTED, "getEID converted...");
return eidResponse.getEidValue().toString();
} catch (DecoderException e) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + e.getMessage(), e);
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - Unable to retrieve EID. Exception in Decoder:" + e.getMessage());
throw new RuntimeException("Unable to retrieve EID");
} catch (IOException ioe) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + ioe.getMessage(), ioe);
throw new RuntimeException("Invalid EID response, unable to retrieve EID");
}
}
private void logDebug(final String errorMessage) {
if (LogStub.getInstance().isDebugEnabled()) {
LogStub.getInstance().logDebug(LOG, LogStub.getInstance().getTag() + " - " + errorMessage);
}
}
private void inputValidation(final boolean invalidCondition, final String errorMessage) {
if (invalidCondition) {
LOG.log(Level.SEVERE, LogStub.getInstance().getTag() + " - " + errorMessage);
throw new IllegalArgumentException(errorMessage);
}
}
}

View File

@ -0,0 +1,25 @@
package com.truphone.lpad.worker;
/**
* Message used within LPAD Workers containing all necessary data
*
* @param <T> Data to be used on LPAD Workers operations
*/
public class LpadWorkerExchange<T> implements WorkerExchange<T> {
private final T body;
public LpadWorkerExchange(final T body) {
this.body = body;
}
/**
* Get data to be used on LPAD Workers operations
*
* @return The data to be used on LPAD Workers operations
*/
@Override
public T getBody() {
return this.body;
}
}

View File

@ -0,0 +1,14 @@
package com.truphone.lpad.worker;
/**
* Message used within Workers containing all necessary data
* @param <T> Data to be used on Workers operations
*/
public interface WorkerExchange<T> {
/**
* Get data to be used on Workers operations
*
* @return The data to be used on Workers operations
*/
T getBody();
}

View File

@ -0,0 +1,73 @@
package com.truphone.util;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LogStub {
private static LogStub instance;
private Level logLevel;
private String tag;
private boolean androidLog;
private LogStub() {
logLevel = Level.ALL;
tag = "";
androidLog = false;
}
public static LogStub getInstance() {
if (instance == null) {
instance = new LogStub();
}
return instance;
}
public void setLogLevel(Level logLevel) {
this.logLevel = logLevel;
}
public boolean isDebugEnabled() {
return logLevel.intValue() <= Level.FINE.intValue();
}
private boolean isTraceEnabled() {
return logLevel.intValue() <= Level.FINEST.intValue();
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public void setAndroidLog(boolean androidLog) {
this.androidLog = androidLog;
}
private boolean isAndroidLog() {
return androidLog;
}
public void logDebug(Logger logger, String message) {
logger.info(message);
// if (isAndroidLog()) {
// logger.info(message);
// } else {
// //logger.fine(message);
// System.out.println(message);
// }
}
}

View File

@ -0,0 +1,31 @@
package com.truphone.util;
import java.util.Properties;
public class PropUtil {
public static String getMandatoryProperty(final Properties props,
final String key) {
if (!props.containsKey(key)) {
throw new IllegalArgumentException("mandatory property missing: "
+ key);
}
return props.getProperty(key);
}
public static int getIntProperty(final Properties props, final String key,
final int defaultValue) {
if (props.containsKey(key)) {
try {
return Integer.decode(props.getProperty(key));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"syntax error in int property: " + key, e);
}
} else {
return defaultValue;
}
}
}

View File

@ -0,0 +1,22 @@
package com.truphone.util;
public class TLVBean {
private String taglen;
private String value;
public TLVBean(String taglen, String value) {
super();
this.taglen = taglen;
this.value = value;
}
public String getTaglen() {
return taglen;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,36 @@
package com.truphone.util;
public class TextUtil {
private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
/**
* Converts the given byte array to its hex representation.
*
* @param data The byte array to convert.
* @return Hex-encoded data as a string.
* @see #toHexString(byte[], int, int)
*/
public static String toHexString(byte[] data) {
return data == null ? null : toHexString(data, 0, data.length);
}
/**
* Converts the given byte array slice to its hex representation.
*
* @param data The byte array to convert.
* @param offset Slice start.
* @param length Slice length.
* @return Hex-encoded data as a string.
*/
public static String toHexString(final byte[] data, int offset, int length) {
final char[] result = new char[length << 1];
length += offset;
for (int i = 0; offset < length; ++offset) {
result[i++] = HEX_DIGITS[(data[offset] >>> 4) & 0x0F];
result[i++] = HEX_DIGITS[data[offset] & 0x0F];
}
return new String(result);
}
}

View File

@ -0,0 +1,50 @@
package com.truphone.util;
public class ToTLV {
public static String toTLV(String tag,String input){
if("".equals(tag))return toTLV(input);
return tag+toTLV(input);
}
public static String integerToTLV(String tag,int input){
if("".equals(tag))return integerToTLV(input);
return tag+integerToTLV(input);
}
public static String integerToTLV(int input) {
String tlv;
if(input<=127){
tlv=String.format("01%02X", input);
}else{
tlv=String.format("02%04X", input);
}
return tlv;
}
public static String toTLV(String input) {
int inputLen = input.length()/2;
String strInputLenString = toHex(String.valueOf(inputLen));
if (inputLen > 65535) {
input = "83" + strInputLenString + input;
} else if (inputLen > 255) {
input = "82" + strInputLenString + input;
} else if(inputLen > 127) {
input = "81" + strInputLenString + input;
} else {
input = strInputLenString + input;
}
return input;
}
private static String toHex(String num) {
String hex = Integer.toHexString(Integer.valueOf(num));
if (hex.length() % 2 != 0) {
hex = "0" + hex;
}
return hex.toUpperCase();
}
}

View File

@ -0,0 +1,29 @@
package com.truphone.util;
public class Tools {
public static String itoa(int value, int len) {
String result = Integer.toHexString(value).toUpperCase();
int rLen = result.length();
len = 2 * len;
if (rLen > len) {
return result.substring(rLen - len, rLen);
}
if (rLen == len) {
return result;
}
StringBuffer strBuff = new StringBuffer(result);
for (int i = 0; i < len - rLen; i++) {
strBuff.insert(0, '0');
}
return strBuff.toString();
}
public static String toHex(String num) {
String hex = Integer.toHexString(Integer.valueOf(num));
if (hex.length() % 2 != 0) {
hex = "0" + hex;
}
return hex.toUpperCase();
}
}

View File

@ -0,0 +1,52 @@
package com.truphone.util;
public class Util {
public static String byteToHexString(byte b) {
StringBuffer s = new StringBuffer();
if ((b & 0xFF) < 16)
s.append("0");
s.append(Integer.toHexString(b & 0xFF).toUpperCase());
return s.toString();
}
public static String byteArrayToHexString(byte[] buffer, String separator) {
StringBuffer s = new StringBuffer();
int i = 0;
for (i = 0; i < buffer.length; i++) {
s.append(byteToHexString(buffer[i]) + separator);
}
if (s.length() > 0) {
s.delete(s.length() - separator.length(), s.length());
}
return s.toString();
}
public static byte[] hexStringToByteArray(String s) {
if (s == null)
return null;
s = s.replaceAll(" ", "").replaceAll(":", "").replaceAll("0x", "").replaceAll("0X", "");
if (s.length() % 2 != 0)
throw new IllegalArgumentException("The length cannot be odd.");
byte[] output = new byte[s.length() / 2];
for (int i = 0; i < s.length(); i += 2)
output[(i / 2)] = ((byte) Integer.parseInt(s.substring(i, i + 2), 16));
return output;
}
public static String ASCIIToHex(String s) {
String ret = "";
if (s != null) {
byte[] buffer = s.getBytes();
ret = byteArrayToHexString(buffer, "");
}
return ret;
}
}

View File

@ -0,0 +1,619 @@
PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
-- EXPORTS ALL --
-- IMPORTS NONE --
-- UNIVERSAL Types defined in 1993 and 1998 ASN.1
-- and required by this specification
-- UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
-- UniversalString is defined in ASN.1:1993
-- BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
-- BMPString is the subtype of UniversalString and models
-- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
-- UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
-- The content of this type conforms to RFC 2279.
-- PKIX specific OIDs
id-pkix OBJECT IDENTIFIER ::=
{ iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) pkix(7) }
-- PKIX arcs
id-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
-- arc for private certificate extensions
id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
-- arc for policy qualifier types
id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
-- arc for extended key purpose OIDS
id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
-- arc for access descriptors
-- policyQualifierIds for Internet policy qualifiers
id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
-- OID for CPS qualifier
id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
-- OID for user notice qualifier
-- access descriptor definitions
id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
id-ad-timeStamping OBJECT IDENTIFIER ::= { id-ad 3 }
id-ad-caRepository OBJECT IDENTIFIER ::= { id-ad 5 }
-- attribute data types
Attribute ::= SEQUENCE {
type AttributeType,
values SET OF AttributeValue }
-- at least one value is required
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY
AttributeTypeAndValue ::= SEQUENCE {
type AttributeType,
value AttributeValue }
-- suggested naming attributes: Definition of the following
-- information object set may be augmented to meet local
-- requirements. Note that deleting members of the set may
-- prevent interoperability with conforming implementations.
-- presented in pairs: the AttributeType followed by the
-- type definition for the corresponding AttributeValue
--Arc for standard naming attributes
id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
-- Naming attributes of type X520name
id-at-name AttributeType ::= { id-at 41 }
id-at-surname AttributeType ::= { id-at 4 }
id-at-givenName AttributeType ::= { id-at 42 }
id-at-initials AttributeType ::= { id-at 43 }
id-at-generationQualifier AttributeType ::= { id-at 44 }
X520name ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-name)),
printableString PrintableString (SIZE (1..ub-name)),
universalString UniversalString (SIZE (1..ub-name)),
utf8String UTF8String (SIZE (1..ub-name)),
bmpString BMPString (SIZE (1..ub-name)) }
-- Naming attributes of type X520CommonName
id-at-commonName AttributeType ::= { id-at 3 }
X520CommonName ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-common-name)),
printableString PrintableString (SIZE (1..ub-common-name)),
universalString UniversalString (SIZE (1..ub-common-name)),
utf8String UTF8String (SIZE (1..ub-common-name)),
bmpString BMPString (SIZE (1..ub-common-name)) }
-- Naming attributes of type X520LocalityName
id-at-localityName AttributeType ::= { id-at 7 }
X520LocalityName ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-locality-name)),
printableString PrintableString (SIZE (1..ub-locality-name)),
universalString UniversalString (SIZE (1..ub-locality-name)),
utf8String UTF8String (SIZE (1..ub-locality-name)),
bmpString BMPString (SIZE (1..ub-locality-name)) }
-- Naming attributes of type X520StateOrProvinceName
id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
X520StateOrProvinceName ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-state-name)),
printableString PrintableString (SIZE (1..ub-state-name)),
universalString UniversalString (SIZE (1..ub-state-name)),
utf8String UTF8String (SIZE (1..ub-state-name)),
bmpString BMPString (SIZE(1..ub-state-name)) }
-- Naming attributes of type X520OrganizationName
id-at-organizationName AttributeType ::= { id-at 10 }
X520OrganizationName ::= CHOICE {
teletexString TeletexString
(SIZE (1..ub-organization-name)),
printableString PrintableString
(SIZE (1..ub-organization-name)),
universalString UniversalString
(SIZE (1..ub-organization-name)),
utf8String UTF8String
(SIZE (1..ub-organization-name)),
bmpString BMPString
(SIZE (1..ub-organization-name)) }
-- Naming attributes of type X520OrganizationalUnitName
id-at-organizationalUnitName AttributeType ::= { id-at 11 }
X520OrganizationalUnitName ::= CHOICE {
teletexString TeletexString
(SIZE (1..ub-organizational-unit-name)),
printableString PrintableString
(SIZE (1..ub-organizational-unit-name)),
universalString UniversalString
(SIZE (1..ub-organizational-unit-name)),
utf8String UTF8String
(SIZE (1..ub-organizational-unit-name)),
bmpString BMPString
(SIZE (1..ub-organizational-unit-name)) }
-- Naming attributes of type X520Title
id-at-title AttributeType ::= { id-at 12 }
X520Title ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-title)),
printableString PrintableString (SIZE (1..ub-title)),
universalString UniversalString (SIZE (1..ub-title)),
utf8String UTF8String (SIZE (1..ub-title)),
bmpString BMPString (SIZE (1..ub-title)) }
-- Naming attributes of type X520dnQualifier
id-at-dnQualifier AttributeType ::= { id-at 46 }
X520dnQualifier ::= PrintableString
-- Naming attributes of type X520countryName (digraph from IS 3166)
id-at-countryName AttributeType ::= { id-at 6 }
X520countryName ::= PrintableString (SIZE (2))
-- Naming attributes of type X520SerialNumber
id-at-serialNumber AttributeType ::= { id-at 5 }
X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
-- Naming attributes of type X520Pseudonym
id-at-pseudonym AttributeType ::= { id-at 65 }
X520Pseudonym ::= CHOICE {
teletexString TeletexString (SIZE (1..ub-pseudonym)),
printableString PrintableString (SIZE (1..ub-pseudonym)),
universalString UniversalString (SIZE (1..ub-pseudonym)),
utf8String UTF8String (SIZE (1..ub-pseudonym)),
bmpString BMPString (SIZE (1..ub-pseudonym)) }
-- Naming attributes of type DomainComponent (from RFC 2247)
id-domainComponent AttributeType ::=
{ 0 9 2342 19200300 100 1 25 }
DomainComponent ::= IA5String
-- Legacy attributes
pkcs-9 OBJECT IDENTIFIER ::=
{ iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
id-emailAddress AttributeType ::= { pkcs-9 1 }
EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
-- naming data types --
Name ::= CHOICE { -- only one possibility for now --
rdnSequence RDNSequence }
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
DistinguishedName ::= RDNSequence
RelativeDistinguishedName ::=
SET SIZE (1 .. MAX) OF AttributeTypeAndValue
-- Directory string type --
DirectoryString ::= CHOICE {
teletexString TeletexString (SIZE (1..MAX)),
printableString PrintableString (SIZE (1..MAX)),
universalString UniversalString (SIZE (1..MAX)),
utf8String UTF8String (SIZE (1..MAX)),
bmpString BMPString (SIZE (1..MAX)) }
-- certificate and CRL specific structures begin here
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
extensions [3] Extensions OPTIONAL
-- If present, version MUST be v3 -- }
Version ::= INTEGER { v1(0), v2(1), v3(2) }
CertificateSerialNumber ::= INTEGER
Validity ::= SEQUENCE {
notBefore Time,
notAfter Time }
Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime }
UniqueIdentifier ::= BIT STRING
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING }
-- CRL structures
CertificateList ::= SEQUENCE {
tbsCertList TBSCertList,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING }
TBSCertList ::= SEQUENCE {
version Version OPTIONAL,
-- if present, MUST be v2
signature AlgorithmIdentifier,
issuer Name,
thisUpdate Time,
nextUpdate Time OPTIONAL,
revokedCertificates SEQUENCE OF SEQUENCE {
userCertificate CertificateSerialNumber,
revocationDate Time,
crlEntryExtensions Extensions OPTIONAL
-- if present, MUST be v2
} OPTIONAL,
crlExtensions [0] Extensions OPTIONAL }
-- if present, MUST be v2
-- Version, Time, CertificateSerialNumber, and Extensions were
-- defined earlier for use in the certificate structure
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL }
-- contains a value of the type
-- registered for use with the
-- algorithm object identifier value
-- X.400 address syntax starts here
ORAddress ::= SEQUENCE {
built-in-standard-attributes BuiltInStandardAttributes,
built-in-domain-defined-attributes
BuiltInDomainDefinedAttributes OPTIONAL,
-- see also teletex-domain-defined-attributes
extension-attributes ExtensionAttributes OPTIONAL }
-- Built-in Standard Attributes
BuiltInStandardAttributes ::= SEQUENCE {
country-name CountryName OPTIONAL,
administration-domain-name AdministrationDomainName OPTIONAL,
network-address [0] IMPLICIT NetworkAddress OPTIONAL,
-- see also extended-network-address
terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
private-domain-name [2] PrivateDomainName OPTIONAL,
organization-name [3] IMPLICIT OrganizationName OPTIONAL,
-- see also teletex-organization-name
numeric-user-identifier [4] IMPLICIT NumericUserIdentifier
OPTIONAL,
personal-name [5] IMPLICIT PersonalName OPTIONAL,
-- see also teletex-personal-name
organizational-unit-names [6] IMPLICIT OrganizationalUnitNames
OPTIONAL }
-- see also teletex-organizational-unit-names
CountryName ::= [APPLICATION 1] CHOICE {
x121-dcc-code NumericString
(SIZE (ub-country-name-numeric-length)),
iso-3166-alpha2-code PrintableString
(SIZE (ub-country-name-alpha-length)) }
AdministrationDomainName ::= [APPLICATION 2] CHOICE {
numeric NumericString (SIZE (0..ub-domain-name-length)),
printable PrintableString (SIZE (0..ub-domain-name-length)) }
NetworkAddress ::= X121Address -- see also extended-network-address
X121Address ::= NumericString (SIZE (1..ub-x121-address-length))
TerminalIdentifier ::= PrintableString (SIZE
(1..ub-terminal-id-length))
PrivateDomainName ::= CHOICE {
numeric NumericString (SIZE (1..ub-domain-name-length)),
printable PrintableString (SIZE (1..ub-domain-name-length)) }
OrganizationName ::= PrintableString
(SIZE (1..ub-organization-name-length))
-- see also teletex-organization-name
NumericUserIdentifier ::= NumericString
(SIZE (1..ub-numeric-user-id-length))
PersonalName ::= SET {
surname [0] IMPLICIT PrintableString
(SIZE (1..ub-surname-length)),
given-name [1] IMPLICIT PrintableString
(SIZE (1..ub-given-name-length)) OPTIONAL,
initials [2] IMPLICIT PrintableString
(SIZE (1..ub-initials-length)) OPTIONAL,
generation-qualifier [3] IMPLICIT PrintableString
(SIZE (1..ub-generation-qualifier-length))
OPTIONAL }
-- see also teletex-personal-name
OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
OF OrganizationalUnitName
-- see also teletex-organizational-unit-names
OrganizationalUnitName ::= PrintableString (SIZE
(1..ub-organizational-unit-name-length))
-- Built-in Domain-defined Attributes
BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
(1..ub-domain-defined-attributes) OF
BuiltInDomainDefinedAttribute
BuiltInDomainDefinedAttribute ::= SEQUENCE {
type PrintableString (SIZE
(1..ub-domain-defined-attribute-type-length)),
value PrintableString (SIZE
(1..ub-domain-defined-attribute-value-length)) }
-- Extension Attributes
ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
ExtensionAttribute
ExtensionAttribute ::= SEQUENCE {
extension-attribute-type [0] IMPLICIT INTEGER
(0..ub-extension-attributes),
extension-attribute-value [1]
ANY DEFINED BY extension-attribute-type }
-- Extension types and attribute values
common-name INTEGER ::= 1
CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
teletex-common-name INTEGER ::= 2
TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
teletex-organization-name INTEGER ::= 3
TeletexOrganizationName ::=
TeletexString (SIZE (1..ub-organization-name-length))
teletex-personal-name INTEGER ::= 4
TeletexPersonalName ::= SET {
surname [0] IMPLICIT TeletexString
(SIZE (1..ub-surname-length)),
given-name [1] IMPLICIT TeletexString
(SIZE (1..ub-given-name-length)) OPTIONAL,
initials [2] IMPLICIT TeletexString
(SIZE (1..ub-initials-length)) OPTIONAL,
generation-qualifier [3] IMPLICIT TeletexString
(SIZE (1..ub-generation-qualifier-length))
OPTIONAL }
teletex-organizational-unit-names INTEGER ::= 5
TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
(1..ub-organizational-units) OF TeletexOrganizationalUnitName
TeletexOrganizationalUnitName ::= TeletexString
(SIZE (1..ub-organizational-unit-name-length))
pds-name INTEGER ::= 7
PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))
physical-delivery-country-name INTEGER ::= 8
PhysicalDeliveryCountryName ::= CHOICE {
x121-dcc-code NumericString (SIZE
(ub-country-name-numeric-length)),
iso-3166-alpha2-code PrintableString
(SIZE (ub-country-name-alpha-length)) }
postal-code INTEGER ::= 9
PostalCode ::= CHOICE {
numeric-code NumericString (SIZE (1..ub-postal-code-length)),
printable-code PrintableString (SIZE (1..ub-postal-code-length)) }
physical-delivery-office-name INTEGER ::= 10
PhysicalDeliveryOfficeName ::= PDSParameter
physical-delivery-office-number INTEGER ::= 11
PhysicalDeliveryOfficeNumber ::= PDSParameter
extension-OR-address-components INTEGER ::= 12
ExtensionORAddressComponents ::= PDSParameter
physical-delivery-personal-name INTEGER ::= 13
PhysicalDeliveryPersonalName ::= PDSParameter
physical-delivery-organization-name INTEGER ::= 14
PhysicalDeliveryOrganizationName ::= PDSParameter
extension-physical-delivery-address-components INTEGER ::= 15
ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter
unformatted-postal-address INTEGER ::= 16
UnformattedPostalAddress ::= SET {
printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines)
OF PrintableString (SIZE (1..ub-pds-parameter-length))
OPTIONAL,
teletex-string TeletexString
(SIZE (1..ub-unformatted-address-length)) OPTIONAL }
street-address INTEGER ::= 17
StreetAddress ::= PDSParameter
post-office-box-address INTEGER ::= 18
PostOfficeBoxAddress ::= PDSParameter
poste-restante-address INTEGER ::= 19
PosteRestanteAddress ::= PDSParameter
unique-postal-name INTEGER ::= 20
UniquePostalName ::= PDSParameter
local-postal-attributes INTEGER ::= 21
LocalPostalAttributes ::= PDSParameter
PDSParameter ::= SET {
printable-string PrintableString
(SIZE(1..ub-pds-parameter-length)) OPTIONAL,
teletex-string TeletexString
(SIZE(1..ub-pds-parameter-length)) OPTIONAL }
extended-network-address INTEGER ::= 22
ExtendedNetworkAddress ::= CHOICE {
e163-4-address SEQUENCE {
number [0] IMPLICIT NumericString
(SIZE (1..ub-e163-4-number-length)),
sub-address [1] IMPLICIT NumericString
(SIZE (1..ub-e163-4-sub-address-length))
OPTIONAL },
psap-address [0] IMPLICIT PresentationAddress }
PresentationAddress ::= SEQUENCE {
pSelector [0] EXPLICIT OCTET STRING OPTIONAL,
sSelector [1] EXPLICIT OCTET STRING OPTIONAL,
tSelector [2] EXPLICIT OCTET STRING OPTIONAL,
nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }
terminal-type INTEGER ::= 23
TerminalType ::= INTEGER {
telex (3),
teletex (4),
g3-facsimile (5),
g4-facsimile (6),
ia5-terminal (7),
videotex (8) }
-- Extension Domain-defined Attributes
teletex-domain-defined-attributes INTEGER ::= 6
TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
(1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute
TeletexDomainDefinedAttribute ::= SEQUENCE {
type TeletexString
(SIZE (1..ub-domain-defined-attribute-type-length)),
value TeletexString
(SIZE (1..ub-domain-defined-attribute-value-length)) }
-- specifications of Upper Bounds MUST be regarded as mandatory
-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
-- Upper Bounds
-- Upper Bounds
ub-name INTEGER ::= 32768
ub-common-name INTEGER ::= 64
ub-locality-name INTEGER ::= 128
ub-state-name INTEGER ::= 128
ub-organization-name INTEGER ::= 64
ub-organizational-unit-name INTEGER ::= 64
ub-title INTEGER ::= 64
ub-serial-number INTEGER ::= 64
ub-match INTEGER ::= 128
ub-emailaddress-length INTEGER ::= 255
ub-common-name-length INTEGER ::= 64
ub-country-name-alpha-length INTEGER ::= 2
ub-country-name-numeric-length INTEGER ::= 3
ub-domain-defined-attributes INTEGER ::= 4
ub-domain-defined-attribute-type-length INTEGER ::= 8
ub-domain-defined-attribute-value-length INTEGER ::= 128
ub-domain-name-length INTEGER ::= 16
ub-extension-attributes INTEGER ::= 256
ub-e163-4-number-length INTEGER ::= 15
ub-e163-4-sub-address-length INTEGER ::= 40
ub-generation-qualifier-length INTEGER ::= 3
ub-given-name-length INTEGER ::= 16
ub-initials-length INTEGER ::= 5
ub-integer-options INTEGER ::= 256
ub-numeric-user-id-length INTEGER ::= 32
ub-organization-name-length INTEGER ::= 64
ub-organizational-unit-name-length INTEGER ::= 32
ub-organizational-units INTEGER ::= 4
ub-pds-name-length INTEGER ::= 16
ub-pds-parameter-length INTEGER ::= 30
ub-pds-physical-address-lines INTEGER ::= 6
ub-postal-code-length INTEGER ::= 16
ub-pseudonym INTEGER ::= 128
ub-surname-length INTEGER ::= 40
ub-terminal-id-length INTEGER ::= 24
ub-unformatted-address-length INTEGER ::= 180
ub-x121-address-length INTEGER ::= 16
-- Note - upper bounds on string types, such as TeletexString, are
-- measured in characters. Excepting PrintableString or IA5String, a
-- significantly greater number of octets will be required to hold
-- such a value. As a minimum, 16 octets, or twice the specified
-- upper bound, whichever is the larger, should be allowed for
-- TeletexString. For UTF8String or UniversalString at least four
-- times the upper bound should be allowed.
END

View File

@ -0,0 +1,387 @@
--
-- ASN.1 module found by ./crfc2asn1.pl in rfc3280.txt at line 5850
--
PKIX1Implicit88 { iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19) }
DEFINITIONS IMPLICIT TAGS ::=
BEGIN
-- EXPORTS ALL --
IMPORTS
id-pe, id-kp, id-qt-unotice, id-qt-cps,
ORAddress, Name, RelativeDistinguishedName,
CertificateSerialNumber, Attribute, DirectoryString
FROM PKIX1Explicit88 { iso(1) identified-organization(3)
dod(6) internet(1) security(5) mechanisms(5) pkix(7)
id-mod(0) id-pkix1-explicit(18) };
-- ISO arc for standard certificate and CRL extensions
id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29}
-- authority key identifier OID and syntax
id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
AuthorityKeyIdentifier ::= SEQUENCE {
keyIdentifier [0] KeyIdentifier OPTIONAL,
authorityCertIssuer [1] GeneralNames OPTIONAL,
authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
-- authorityCertIssuer and authorityCertSerialNumber MUST both
-- be present or both be absent
KeyIdentifier ::= OCTET STRING
-- subject key identifier OID and syntax
id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 }
SubjectKeyIdentifier ::= KeyIdentifier
-- key usage extension OID and syntax
id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
KeyUsage ::= BIT STRING {
digitalSignature (0),
nonRepudiation (1),
keyEncipherment (2),
dataEncipherment (3),
keyAgreement (4),
keyCertSign (5),
cRLSign (6),
encipherOnly (7),
decipherOnly (8) }
-- private key usage period extension OID and syntax
id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 }
PrivateKeyUsagePeriod ::= SEQUENCE {
notBefore [0] GeneralizedTime OPTIONAL,
notAfter [1] GeneralizedTime OPTIONAL }
-- either notBefore or notAfter MUST be present
-- certificate policies extension OID and syntax
id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
PolicyInformation ::= SEQUENCE {
policyIdentifier CertPolicyId,
policyQualifiers SEQUENCE SIZE (1..MAX) OF
PolicyQualifierInfo OPTIONAL }
CertPolicyId ::= OBJECT IDENTIFIER
PolicyQualifierInfo ::= SEQUENCE {
policyQualifierId PolicyQualifierId,
qualifier ANY DEFINED BY policyQualifierId }
-- Implementations that recognize additional policy qualifiers MUST
-- augment the following definition for PolicyQualifierId
PolicyQualifierId ::=
OBJECT IDENTIFIER -- ( id-qt-cps | id-qt-unotice )
-- CPS pointer qualifier
CPSuri ::= IA5String
-- user notice qualifier
UserNotice ::= SEQUENCE {
noticeRef NoticeReference OPTIONAL,
explicitText DisplayText OPTIONAL}
NoticeReference ::= SEQUENCE {
organization DisplayText,
noticeNumbers SEQUENCE OF INTEGER }
DisplayText ::= CHOICE {
ia5String IA5String (SIZE (1..200)),
visibleString VisibleString (SIZE (1..200)),
bmpString BMPString (SIZE (1..200)),
utf8String UTF8String (SIZE (1..200)) }
-- policy mapping extension OID and syntax
id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 }
PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
issuerDomainPolicy CertPolicyId,
subjectDomainPolicy CertPolicyId }
-- subject alternative name extension OID and syntax
id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 }
SubjectAltName ::= GeneralNames
GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
GeneralName ::= CHOICE {
otherName [0] AnotherName,
rfc822Name [1] IA5String,
dNSName [2] IA5String,
x400Address [3] ORAddress,
directoryName [4] Name,
ediPartyName [5] EDIPartyName,
uniformResourceIdentifier [6] IA5String,
iPAddress [7] OCTET STRING,
registeredID [8] OBJECT IDENTIFIER }
-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
AnotherName ::= SEQUENCE {
type-id OBJECT IDENTIFIER,
value [0] EXPLICIT ANY DEFINED BY type-id }
EDIPartyName ::= SEQUENCE {
nameAssigner [0] DirectoryString OPTIONAL,
partyName [1] DirectoryString }
-- issuer alternative name extension OID and syntax
id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 }
IssuerAltName ::= GeneralNames
id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 }
SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
-- basic constraints extension OID and syntax
id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
BasicConstraints ::= SEQUENCE {
cA BOOLEAN DEFAULT FALSE,
pathLenConstraint INTEGER (0..MAX) OPTIONAL }
-- name constraints extension OID and syntax
id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 }
NameConstraints ::= SEQUENCE {
permittedSubtrees [0] GeneralSubtrees OPTIONAL,
excludedSubtrees [1] GeneralSubtrees OPTIONAL }
GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
GeneralSubtree ::= SEQUENCE {
base GeneralName,
minimum [0] BaseDistance DEFAULT 0,
maximum [1] BaseDistance OPTIONAL }
BaseDistance ::= INTEGER (0..MAX)
-- policy constraints extension OID and syntax
id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
PolicyConstraints ::= SEQUENCE {
requireExplicitPolicy [0] SkipCerts OPTIONAL,
inhibitPolicyMapping [1] SkipCerts OPTIONAL }
SkipCerts ::= INTEGER (0..MAX)
-- CRL distribution points extension OID and syntax
id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31}
CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
DistributionPoint ::= SEQUENCE {
distributionPoint [0] DistributionPointName OPTIONAL,
reasons [1] ReasonFlags OPTIONAL,
cRLIssuer [2] GeneralNames OPTIONAL }
DistributionPointName ::= CHOICE {
fullName [0] GeneralNames,
nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
ReasonFlags ::= BIT STRING {
unused (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
privilegeWithdrawn (7),
aACompromise (8) }
-- extended key usage extension OID and syntax
id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}
ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
KeyPurposeId ::= OBJECT IDENTIFIER
-- permit unspecified key uses
anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
-- extended key purpose OIDs
id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
-- inhibit any policy OID and syntax
id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 }
InhibitAnyPolicy ::= SkipCerts
-- freshest (delta)CRL extension OID and syntax
id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 }
FreshestCRL ::= CRLDistributionPoints
-- authority info access
id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
AuthorityInfoAccessSyntax ::=
SEQUENCE SIZE (1..MAX) OF AccessDescription
AccessDescription ::= SEQUENCE {
accessMethod OBJECT IDENTIFIER,
accessLocation GeneralName }
-- subject info access
id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 }
SubjectInfoAccessSyntax ::=
SEQUENCE SIZE (1..MAX) OF AccessDescription
-- CRL number extension OID and syntax
id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
CRLNumber ::= INTEGER (0..MAX)
-- issuing distribution point extension OID and syntax
id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
IssuingDistributionPoint ::= SEQUENCE {
distributionPoint [0] DistributionPointName OPTIONAL,
onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
onlySomeReasons [3] ReasonFlags OPTIONAL,
indirectCRL [4] BOOLEAN DEFAULT FALSE,
onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }
BaseCRLNumber ::= CRLNumber
-- CRL reasons extension OID and syntax
id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
CRLReason ::= ENUMERATED {
unspecified (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
removeFromCRL (8),
privilegeWithdrawn (9),
aACompromise (10) }
-- certificate issuer CRL entry extension OID and syntax
id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
CertificateIssuer ::= GeneralNames
-- hold instruction extension OID and syntax
id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
HoldInstructionCode ::= OBJECT IDENTIFIER
-- ANSI x9 holdinstructions
-- ANSI x9 arc holdinstruction arc
holdInstruction OBJECT IDENTIFIER ::=
{joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}
-- ANSI X9 holdinstructions referenced by this standard
id-holdinstruction-none OBJECT IDENTIFIER ::=
{holdInstruction 1} -- deprecated
id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
{holdInstruction 2}
id-holdinstruction-reject OBJECT IDENTIFIER ::=
{holdInstruction 3}
-- invalidity date CRL entry extension OID and syntax
id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
InvalidityDate ::= GeneralizedTime
END

View File

@ -0,0 +1,785 @@
RSPDefinitions {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1) spec-version(1) version-two(2)}
DEFINITIONS
AUTOMATIC TAGS
EXTENSIBILITY IMPLIED ::=
BEGIN
IMPORTS Certificate, CertificateList, Time FROM PKIX1Explicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18)}
SubjectKeyIdentifier FROM PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19)};
id-rsp OBJECT IDENTIFIER ::= {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1)}
-- Basic types, for size constraints
Octet8 ::= OCTET STRING (SIZE(8))
Octet16 ::= OCTET STRING (SIZE(16))
OctetTo16 ::= OCTET STRING (SIZE(1..16))
Octet32 ::= OCTET STRING (SIZE(32))
Octet1 ::= OCTET STRING(SIZE(1))
Octet2 ::= OCTET STRING (SIZE(2))
VersionType ::= OCTET STRING(SIZE(3)) -- major/minor/revision version are coded as binary value on byte 1/2/3, e.g. '02 00 0C' for v2.0.12.
Iccid ::= [APPLICATION 26] OCTET STRING (SIZE(10)) -- ICCID as coded in EFiccid, corresponding tag is '5A'
RemoteOpId ::= [2] INTEGER {installBoundProfilePackage(1)}
TransactionId ::= OCTET STRING (SIZE(1..16))
-- Definition of EUICCInfo1 --------------------------
GetEuiccInfo1Request ::= [32] SEQUENCE { -- Tag 'BF20'
}
EUICCInfo1 ::= [32] SEQUENCE { -- Tag 'BF20'
svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification
euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier -- List of CI Public Key Identifier supported on the eUICC for signature creation
}
-- Definition of EUICCInfo2 --------------------------
GetEuiccInfo2Request ::= [34] SEQUENCE { -- Tag 'BF22'
}
EUICCInfo2 ::= [34] SEQUENCE { -- Tag 'BF22'
profileVersion [1] VersionType, -- SIMAlliance Profile package version supported
svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
euiccFirmwareVer [3] VersionType, -- eUICC Firmware version
extCardResource [4] OCTET STRING, -- Extended Card Resource Information according to ETSI TS 102 226
uiccCapability [5] UICCCapability,
javacardVersion [6] VersionType OPTIONAL,
globalplatformVersion [7] VersionType OPTIONAL,
rspCapability [8] RspCapability,
euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification
euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifier supported on the eUICC for signature creation
euiccCategory [11] INTEGER {
other(0),
basicEuicc(1),
mediumEuicc(2),
contactlessEuicc(3)
} OPTIONAL,
forbiddenProfilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
ppVersion VersionType, -- Protection Profile version
sasAcreditationNumber UTF8String (SIZE(0..64)),
certificationDataObject [12] CertificationDataObject OPTIONAL
}
-- Definition of RspCapability
RspCapability ::= BIT STRING {
additionalProfile(0), -- at least one more Profile can be installed
crlSupport(1), -- CRL
rpmSupport(2), -- Remote Profile Management
testProfileSupport (3) -- support for test profile
}
-- Definition of CertificationDataObject
CertificationDataObject ::= SEQUENCE {
platformLabel UTF8String, -- Platform_Label as defined in GlobalPlatform DLOA specification [57]
discoveryBaseURL UTF8String -- Discovery Base URL of the SE default DLOA Registrar as defined in GlobalPlatform DLOA specification [57]
}
CertificateInfo ::= BIT STRING {
reserved(0), -- eUICC has a CERT.EUICC.ECDSA in GlobalPlatform format. The use of this bit is deprecated.
certSigningX509(1), -- eUICC has a CERT.EUICC.ECDSA in X.509 format
rfu2(2),
rfu3(3),
reserved2(4), -- Handling of Certificate in GlobalPlatform format. The use of this bit is deprecated.
certVerificationX509(5)-- Handling of Certificate in X.509 format
}
-- Definition of UICCCapability
UICCCapability ::= BIT STRING {
/* Sequence is derived from ServicesList[] defined in SIMalliance PEDefinitions*/
contactlessSupport(0), -- Contactless (SWP, HCI and associated APIs)
usimSupport(1), -- USIM as defined by 3GPP
isimSupport(2), -- ISIM as defined by 3GPP
csimSupport(3), -- CSIM as defined by 3GPP2
akaMilenage(4), -- Milenage as AKA algorithm
akaCave(5), -- CAVE as authentication algorithm
akaTuak128(6), -- TUAK as AKA algorithm with 128 bit key length
akaTuak256(7), -- TUAK as AKA algorithm with 256 bit key length
rfu1(8), -- reserved for further algorithms
rfu2(9), -- reserved for further algorithms
gbaAuthenUsim(10), -- GBA authentication in the context of USIM
gbaAuthenISim(11), -- GBA authentication in the context of ISIM
mbmsAuthenUsim(12), -- MBMS authentication in the context of USIM
eapClient(13), -- EAP client
javacard(14), -- Javacard support
multos(15), -- Multos support
multipleUsimSupport(16), -- Multiple USIM applications are supported within the same Profile
multipleIsimSupport(17), -- Multiple ISIM applications are supported within the same Profile
multipleCsimSupport(18) -- Multiple CSIM applications are supported within the same Profile
}
-- Definition of DeviceInfo
DeviceInfo ::= SEQUENCE {
tac Octet8,
deviceCapabilities DeviceCapabilities,
imei Octet8 OPTIONAL
}
DeviceCapabilities ::= SEQUENCE { -- Highest fully supported release for each definition
-- The device SHALL set all the capabilities it supports
gsmSupportedRelease VersionType OPTIONAL,
utranSupportedRelease VersionType OPTIONAL,
cdma2000onexSupportedRelease VersionType OPTIONAL,
cdma2000hrpdSupportedRelease VersionType OPTIONAL,
cdma2000ehrpdSupportedRelease VersionType OPTIONAL,
eutranSupportedRelease VersionType OPTIONAL,
contactlessSupportedRelease VersionType OPTIONAL,
rspCrlSupportedVersion VersionType OPTIONAL,
rspRpmSupportedVersion VersionType OPTIONAL
}
ProfileInfoListRequest ::= [45] SEQUENCE { -- Tag 'BF2D'
searchCriteria [0] CHOICE {
isdpAid [APPLICATION 15] OctetTo16, -- AID of the ISD-P, tag '4F'
iccid Iccid, -- ICCID, tag '5A'
profileClass [21] ProfileClass -- Tag '95'
} OPTIONAL,
tagList [APPLICATION 28] OCTET STRING OPTIONAL -- tag '5C'
}
-- Definition of ProfileInfoList
ProfileInfoListResponse ::= [45] CHOICE { -- Tag 'BF2D'
profileInfoListOk SEQUENCE OF ProfileInfo,
profileInfoListError ProfileInfoListError
}
ProfileInfo ::= [PRIVATE 3] SEQUENCE { -- Tag 'E3'
iccid Iccid OPTIONAL,
isdpAid [APPLICATION 15] OctetTo16 OPTIONAL, -- AID of the ISD-P containing the Profile, tag '4F'
profileState [112] ProfileState OPTIONAL, -- Tag '9F70'
profileNickname [16] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '90'
serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91'
profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92'
iconType [19] IconType OPTIONAL, -- Tag '93'
icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94', see condition in ES10c:GetProfilesInfo
profileClass [21] ProfileClass DEFAULT operational, -- Tag '95'
notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL, -- Tag 'B6'
profileOwner [23] OperatorID OPTIONAL, -- Tag 'B7'
dpProprietaryData [24] DpProprietaryData OPTIONAL, -- Tag 'B8'
profilePolicyRules [25] PprIds OPTIONAL -- Tag '99'
}
PprIds ::= BIT STRING {-- Definition of Profile Policy Rules identifiers
pprUpdateControl(0), -- defines how to update PPRs via ES6
ppr1(1), -- Indicator for PPR1 'Disabling of this Profile is not allowed'
ppr2(2), -- Indicator for PPR2 'Deletion of this Profile is not allowed'
ppr3(3) -- Indicator for PPR3 'Deletion of this Profile is required upon its successful disabling'
}
OperatorID ::= SEQUENCE {
mccMnc OCTET STRING (SIZE(3)), -- MCC and MNC coded as defined in 3GPP TS 24.008 [32]
gid1 OCTET STRING OPTIONAL, -- referring to content of EF GID1 (file identifier '6F3E') as defined in 3GPP TS 31.102 [54]
gid2 OCTET STRING OPTIONAL -- referring to content of EF GID2 (file identifier '6F3F') as defined in 3GPP TS 31.102 [54]
}
ProfileInfoListError ::= INTEGER {incorrectInputValues(1), undefinedError(127)}
-- Definition of StoreMetadata request
StoreMetadataRequest ::= [37] SEQUENCE { -- Tag 'BF25'
iccid Iccid,
serviceProviderName [17] UTF8String (SIZE(0..32)), -- Tag '91'
profileName [18] UTF8String (SIZE(0..64)), -- Tag '92' (corresponds to 'Short Description' defined in SGP.21 [2])
iconType [19] IconType OPTIONAL, -- Tag '93' (JPG or PNG)
icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94'(Data of the icon. Size 64 x 64 pixel. This field SHALL only be present if iconType is present)
profileClass [21] ProfileClass OPTIONAL, -- Tag '95' (default if absent: 'operational')
notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL,
profileOwner [23] OperatorID OPTIONAL, -- Tag 'B7'
profilePolicyRules [25] PprIds OPTIONAL -- Tag '99'
}
NotificationEvent ::= BIT STRING {
notificationInstall (0),
notificationEnable(1),
notificationDisable(2),
notificationDelete(3)
}
NotificationConfigurationInformation ::= SEQUENCE {
profileManagementOperation NotificationEvent,
notificationAddress UTF8String -- FQDN to forward the notification
}
IconType ::= INTEGER {jpg(0), png(1)}
ProfileState ::= INTEGER {disabled(0), enabled(1)}
ProfileClass ::= INTEGER {test(0), provisioning(1), operational(2)}
-- Definition of UpdateMetadata request
UpdateMetadataRequest ::= [42] SEQUENCE { -- Tag 'BF2A'
serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91'
profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92'
iconType [19] IconType OPTIONAL, -- Tag '93'
icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94'
profilePolicyRules [25] PprIds OPTIONAL -- Tag '99'
}
-- Definition of data objects for command PrepareDownload -------------------------
PrepareDownloadRequest ::= [33] SEQUENCE { -- Tag 'BF21'
smdpSigned2 SmdpSigned2, -- Signed information
smdpSignature2 [APPLICATION 55] OCTET STRING, -- DP_Sign1, tag '5F37'
hashCc Octet32 OPTIONAL, -- Hash of confirmation code
smdpCertificate Certificate -- CERT.DPpb.ECDSA
}
SmdpSigned2 ::= SEQUENCE {
transactionId [0] TransactionId, -- The TransactionID generated by the SM DP+
ccRequiredFlag BOOLEAN, --Indicates if the Confirmation Code is required
bppEuiccOtpk [APPLICATION 73] OCTET STRING OPTIONAL -- otPK.EUICC.ECKA already used for binding the BPP, tag '5F49'
}
PrepareDownloadResponse ::= [33] CHOICE { -- Tag 'BF21'
downloadResponseOk PrepareDownloadResponseOk,
downloadResponseError PrepareDownloadResponseError
}
PrepareDownloadResponseOk ::= SEQUENCE {
euiccSigned2 EUICCSigned2, -- Signed information
euiccSignature2 [APPLICATION 55] OCTET STRING -- tag '5F37'
}
EUICCSigned2 ::= SEQUENCE {
transactionId [0] TransactionId,
euiccOtpk [APPLICATION 73] OCTET STRING, -- otPK.EUICC.ECKA, tag '5F49'
hashCc Octet32 OPTIONAL -- Hash of confirmation code
}
PrepareDownloadResponseError ::= SEQUENCE {
transactionId [0] TransactionId,
downloadErrorCode DownloadErrorCode
}
DownloadErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2), unsupportedCurve(3), noSessionContext(4), invalidTransactionId(5), undefinedError(127)}
-- Definition of data objects for command AuthenticateServer--------------------
AuthenticateServerRequest ::= [56] SEQUENCE { -- Tag 'BF38'
serverSigned1 ServerSigned1, -- Signed information
serverSignature1 [APPLICATION 55] OCTET STRING, -- tag ?5F37?
euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- CI Public Key Identifier to be used
serverCertificate Certificate, -- RSP Server Certificate CERT.XXauth.ECDSA
ctxParams1 CtxParams1
}
ServerSigned1 ::= SEQUENCE {
transactionId [0] TransactionId, -- The Transaction ID generated by the RSP Server
euiccChallenge [1] Octet16, -- The eUICC Challenge
serverAddress [3] UTF8String, -- The RSP Server address
serverChallenge [4] Octet16 -- The RSP Server Challenge
}
CtxParams1 ::= CHOICE {
ctxParamsForCommonAuthentication CtxParamsForCommonAuthentication -- New contextual data objects may be defined for extensibility
}
CtxParamsForCommonAuthentication ::= SEQUENCE {
matchingId UTF8String OPTIONAL,-- The MatchingId could be the Activation code token or EventID or empty
deviceInfo DeviceInfo -- The Device information
}
AuthenticateServerResponse ::= [56] CHOICE { -- Tag 'BF38'
authenticateResponseOk AuthenticateResponseOk,
authenticateResponseError AuthenticateResponseError
}
AuthenticateResponseOk ::= SEQUENCE {
euiccSigned1 EuiccSigned1, -- Signed information
euiccSignature1 [APPLICATION 55] OCTET STRING, --EUICC_Sign1, tag 5F37
euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM
eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI
}
EuiccSigned1 ::= SEQUENCE {
transactionId [0] TransactionId,
serverAddress [3] UTF8String,
serverChallenge [4] Octet16, -- The RSP Server Challenge
euiccInfo2 [34] EUICCInfo2,
ctxParams1 CtxParams1
}
AuthenticateResponseError ::= SEQUENCE {
transactionId [0] TransactionId,
authenticateErrorCode AuthenticateErrorCode
}
AuthenticateErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2), unsupportedCurve(3), noSessionContext(4), invalidOid(5), euiccChallengeMismatch(6), ciPKUnknown(7), undefinedError(127)}
-- Definition of Cancel Session------------------------------
CancelSessionRequest ::= [65] SEQUENCE { -- Tag 'BF41'
transactionId TransactionId, -- The TransactionID generated by the RSP Server
reason CancelSessionReason
}
CancelSessionReason ::= INTEGER {endUserRejection(0), postponed(1), timeout(2), pprNotAllowed(3)}
CancelSessionResponse ::= [65] CHOICE { -- Tag 'BF41'
cancelSessionResponseOk CancelSessionResponseOk,
cancelSessionResponseError INTEGER {invalidTransactionId(5), undefinedError(127)}
}
CancelSessionResponseOk ::= SEQUENCE {
euiccCancelSessionSigned EuiccCancelSessionSigned, -- Signed information
euiccCancelSessionSignature [APPLICATION 55] OCTET STRING -- tag '5F37
}
EuiccCancelSessionSigned ::= SEQUENCE {
transactionId TransactionId,
smdpOid OBJECT IDENTIFIER, -- SM-DP+ OID as contained in CERT.DPauth.ECDSA
reason CancelSessionReason
}
-- Definition of Bound Profile Package --------------------------
BoundProfilePackage ::= [54] SEQUENCE { -- Tag 'BF36'
initialiseSecureChannelRequest [35] InitialiseSecureChannelRequest, -- Tag 'BF23'
firstSequenceOf87 [0] SEQUENCE OF [7] OCTET STRING, -- sequence of '87' TLVs
sequenceOf88 [1] SEQUENCE OF [8] OCTET STRING, -- sequence of '88' TLVs
secondSequenceOf87 [2] SEQUENCE OF [7] OCTET STRING OPTIONAL, -- sequence of '87' TLVs
sequenceOf86 [3] SEQUENCE OF [6] OCTET STRING -- sequence of '86' TLVs
}
-- Definition of Get eUICC Challenge --------------------------
GetEuiccChallengeRequest ::= [46] SEQUENCE { -- Tag 'BF2E'
}
GetEuiccChallengeResponse ::= [46] SEQUENCE { -- Tag 'BF2E'
euiccChallenge Octet16 -- random eUICC challenge
}
-- Definition of Profile Installation Resulceipt
ProfileInstallationResult ::= [55] SEQUENCE { -- Tag 'BF37'
profileInstallationResultData [39] ProfileInstallationResultData,
euiccSignPIR EuiccSignPIR
}
ProfileInstallationResultData ::= [39] SEQUENCE { -- Tag 'BF27'
transactionId[0] TransactionId, -- The TransactionID generated by the SM-DP+
notificationMetadata[47] NotificationMetadata,
smdpOid OBJECT IDENTIFIER OPTIONAL, -- SM-DP+ OID (same value as in CERT.DPpb.ECDSA)
finalResult [2] CHOICE {
successResult SuccessResult,
errorResult ErrorResult
}
}
EuiccSignPIR ::= [APPLICATION 55] OCTET STRING -- Tag '5F37', eUICC?s signature
SuccessResult ::= SEQUENCE {
aid [APPLICATION 15] OCTET STRING (SIZE (5..16)), -- AID of ISD-P
simaResponse OCTET STRING -- contains (multiple) 'EUICCResponse' as defined in [5]
}
ErrorResult ::= SEQUENCE {
bppCommandId BppCommandId,
errorReason ErrorReason,
simaResponse OCTET STRING OPTIONAL -- contains (multiple) 'EUICCResponse' as defined in [5]
}
BppCommandId ::= INTEGER {initialiseSecureChannel(0), configureISDP(1), storeMetadata(2), storeMetadata2(3), replaceSessionKeys(4), loadProfileElements(5)}
ErrorReason ::= INTEGER {
incorrectInputValues(1),
invalidSignature(2),
invalidTransactionId(3),
unsupportedCrtValues(4),
unsupportedRemoteOperationType(5),
unsupportedProfileClass(6),
scp03tStructureError(7),
scp03tSecurityError(8),
installFailedDueToIccidAlreadyExistsOnEuicc(9), installFailedDueToInsufficientMemoryForProfile(10),
installFailedDueToInterruption(11),
installFailedDueToPEProcessingError (12),
installFailedDueToIccidMismatch(13),
testProfileInstallFailedDueToInvalidNaaKey(14),
pprNotAllowed(15),
installFailedDueToUnknownError(127)
}
ListNotificationRequest ::= [40] SEQUENCE { -- Tag 'BF28'
profileManagementOperation [1] NotificationEvent OPTIONAL
}
ListNotificationResponse ::= [40] CHOICE { -- Tag 'BF28'
notificationMetadataList SEQUENCE OF NotificationMetadata,
listNotificationsResultError INTEGER {undefinedError(127)}
}
NotificationMetadata ::= [47] SEQUENCE { -- Tag 'BF2F'
seqNumber [0] INTEGER,
profileManagementOperation [1] NotificationEvent, --Only one bit set to 1
notificationAddress UTF8String, -- FQDN to forward the notification
iccid Iccid OPTIONAL
}
-- Definition of Profile Nickname Information
SetNicknameRequest ::= [41] SEQUENCE { -- Tag 'BF29'
iccid Iccid,
profileNickname [16] UTF8String (SIZE(0..64))
}
SetNicknameResponse ::= [41] SEQUENCE { -- Tag 'BF29'
setNicknameResult INTEGER {ok(0), iccidNotFound (1), undefinedError(127)}
}
id-rsp-cert-objects OBJECT IDENTIFIER ::= { id-rsp cert-objects(2)}
id-rspExt OBJECT IDENTIFIER ::= {id-rsp-cert-objects 0}
id-rspRole OBJECT IDENTIFIER ::= {id-rsp-cert-objects 1}
-- Definition of OIDs for role identification
id-rspRole-ci OBJECT IDENTIFIER ::= {id-rspRole 0}
id-rspRole-euicc OBJECT IDENTIFIER ::= {id-rspRole 1}
id-rspRole-eum OBJECT IDENTIFIER ::= {id-rspRole 2}
id-rspRole-dp-tls OBJECT IDENTIFIER ::= {id-rspRole 3}
id-rspRole-dp-auth OBJECT IDENTIFIER ::= {id-rspRole 4}
id-rspRole-dp-pb OBJECT IDENTIFIER ::= {id-rspRole 5}
id-rspRole-ds-tls OBJECT IDENTIFIER ::= {id-rspRole 6}
id-rspRole-ds-auth OBJECT IDENTIFIER ::= {id-rspRole 7}
--Definition of data objects for InitialiseSecureChannel Request
InitialiseSecureChannelRequest ::= [35] SEQUENCE { -- Tag 'BF23'
remoteOpId RemoteOpId, -- Remote Operation Type Identifier (value SHALL be set to installBoundProfilePackage)
transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
controlRefTemplate[6] IMPLICIT ControlRefTemplate, -- Control Reference Template (Key Agreement). Current specification considers a subset of CRT specified in GlobalPlatform Card Specification [8], section 6.4.2.3 for the Mutual Authentication Data Field
smdpOtpk [APPLICATION 73] OCTET STRING, ---otPK.DP.ECKA as specified in GlobalPlatform Card Specification [8] section 6.4.2.3 for ePK.OCE.ECKA, tag '5F49'
smdpSign [APPLICATION 55] OCTET STRING -- SM-DP's signature, tag '5F37'
}
ControlRefTemplate ::= SEQUENCE {
keyType[0] Octet1, -- Key type according to GlobalPlatform Card Specification [8] Table 11-16, AES= '88', Tag '80'
keyLen[1] Octet1, --Key length in number of bytes. For current specification key length SHALL by 0x10 bytes, Tag '81'
hostId[4] OctetTo16 -- Host ID value , Tag '84'
}
--Definition of data objects for ConfigureISDPRequest
ConfigureISDPRequest ::= [36] SEQUENCE { -- Tag 'BF24'
dpProprietaryData [24] DpProprietaryData OPTIONAL -- Tag 'B8'
}
DpProprietaryData ::= SEQUENCE { -- maximum size including tag and length field: 128 bytes
dpOid OBJECT IDENTIFIER -- OID in the tree of the SM-DP+ that created the Profile
-- additional data objects defined by the SM-DP+ MAY follow
}
-- Definition of request message for command ReplaceSessionKeys
ReplaceSessionKeysRequest ::= [38] SEQUENCE { -- tag 'BF26'
/*The new initial MAC chaining value*/
initialMacChainingValue OCTET STRING,
/*New session key value for encryption/decryption (PPK-ENC)*/
ppkEnc OCTET STRING,
/*New session key value of the session key C-MAC computation/verification (PPK-MAC)*/
ppkCmac OCTET STRING
}
-- Definition of data objects for RetrieveNotificationsList
RetrieveNotificationsListRequest ::= [43] SEQUENCE { -- Tag 'BF2B'
searchCriteria CHOICE {
seqNumber [0] INTEGER,
profileManagementOperation [1] NotificationEvent
} OPTIONAL
}
RetrieveNotificationsListResponse ::= [43] CHOICE { -- Tag 'BF2B'
notificationList SEQUENCE OF PendingNotification,
notificationsListResultError INTEGER {noResultAvailable(1), undefinedError(127)}
}
PendingNotification ::= CHOICE {
profileInstallationResult [55] ProfileInstallationResult, -- tag 'BF37'
otherSignedNotification OtherSignedNotification
}
OtherSignedNotification ::= SEQUENCE {
tbsOtherNotification NotificationMetadata,
euiccNotificationSignature [APPLICATION 55] OCTET STRING, -- eUICC signature of tbsOtherNotification, Tag '5F37'
euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM
eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI
}
-- Definition of notificationSent
NotificationSentRequest ::= [48] SEQUENCE { -- Tag 'BF30'
seqNumber [0] INTEGER
}
NotificationSentResponse ::= [48] SEQUENCE { -- Tag 'BF30'
deleteNotificationStatus INTEGER {ok(0), nothingToDelete(1), undefinedError(127)}
}
-- Definition of Enable Profile --------------------------
EnableProfileRequest ::= [49] SEQUENCE { -- Tag 'BF31'
profileIdentifier CHOICE {
isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
iccid Iccid -- ICCID, tag '5A'
},
refreshFlag BOOLEAN -- indicating whether REFRESH is required
}
EnableProfileResponse ::= [49] SEQUENCE { -- Tag 'BF31'
enableResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInDisabledState(2), disallowedByPolicy(3), wrongProfileReenabling(4), undefinedError(127)}
}
-- Definition of Disable Profile --------------------------
DisableProfileRequest ::= [50] SEQUENCE { -- Tag 'BF32'
profileIdentifier CHOICE {
isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
iccid Iccid -- ICCID, tag '5A'
},
refreshFlag BOOLEAN -- indicating whether REFRESH is required
}
DisableProfileResponse ::= [50] SEQUENCE { -- Tag 'BF32'
disableResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInEnabledState(2), disallowedByPolicy(3), undefinedError(127)}
}
-- Definition of Delete Profile --------------------------
DeleteProfileRequest ::= [51] CHOICE { -- Tag 'BF33'
isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
iccid Iccid -- ICCID, tag '5A'
}
DeleteProfileResponse ::= [51] SEQUENCE { -- Tag 'BF33'
deleteResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInDisabledState(2), disallowedByPolicy(3), undefinedError(127)}
}
-- Definition of Memory Reset --------------------------
EuiccMemoryResetRequest ::= [52] SEQUENCE { -- Tag 'BF34'
resetOptions [2] BIT STRING {
deleteOperationalProfiles(0),
deleteFieldLoadedTestProfiles(1),
resetDefaultSmdpAddress(2)}
}
EuiccMemoryResetResponse ::= [52] SEQUENCE { -- Tag 'BF34'
resetResult INTEGER {ok(0), nothingToDelete(1), undefinedError(127)}
}
-- Definition of Get EID --------------------------
GetEuiccDataRequest ::= [62] SEQUENCE { -- Tag 'BF3E'
tagList [APPLICATION 28] Octet1 -- tag '5C', the value SHALL be set to '5A'
}
GetEuiccDataResponse ::= [62] SEQUENCE { -- Tag 'BF3E'
eidValue [APPLICATION 26] Octet16 -- tag '5A'
}
-- Definition of Get Rat
GetRatRequest ::= [67] SEQUENCE { -- Tag ' BF43'
-- No input data
}
GetRatResponse ::= [67] SEQUENCE { -- Tag 'BF43'
rat RulesAuthorisationTable
}
RulesAuthorisationTable ::= SEQUENCE OF ProfilePolicyAuthorisationRule
ProfilePolicyAuthorisationRule ::= SEQUENCE {
pprIds PprIds,
allowedOperators SEQUENCE OF OperatorID,
pprFlags BIT STRING {consentRequired(0)}
}
-- Definition of data structure command for loading a CRL
LoadCRLRequest ::= [53] SEQUENCE { -- Tag 'BF35'
-- A CRL-A
crl CertificateList
}
-- Definition of data structure response for loading a CRL
LoadCRLResponse ::= [53] CHOICE { -- Tag 'BF35'
loadCRLResponseOk LoadCRLResponseOk,
loadCRLResponseError LoadCRLResponseError
}
LoadCRLResponseOk ::= SEQUENCE {
missingParts SEQUENCE OF SEQUENCE {
number INTEGER (0..MAX)
} OPTIONAL
}
LoadCRLResponseError ::= INTEGER {invalidSignature(1), invalidCRLFormat(2), notEnoughMemorySpace(3), verificationKeyNotFound(4), undefinedError(127)}
-- Definition of the extension for Certificate Expiration Date
id-rsp-expDate OBJECT IDENTIFIER ::= {id-rspExt 1}
ExpirationDate ::= Time
-- Definition of the extension id for total partial-CRL number
id-rsp-totalPartialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 2}
TotalPartialCrlNumber ::= INTEGER
-- Definition of the extension id for the partial-CRL number
id-rsp-partialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 3}
PartialCrlNumber ::= INTEGER
-- Definition for ES9+ ASN.1 Binding --------------------------
RemoteProfileProvisioningRequest ::= [2] CHOICE { -- Tag 'A2'
initiateAuthenticationRequest [57] InitiateAuthenticationRequest, -- Tag 'BF39'
authenticateClientRequest [59] AuthenticateClientRequest, -- Tag 'BF3B'
getBoundProfilePackageRequest [58] GetBoundProfilePackageRequest, -- Tag 'BF3A'
cancelSessionRequestEs9 [65] CancelSessionRequestEs9, -- Tag 'BF41'
handleNotification [61] HandleNotification -- tag 'BF3D'
}
RemoteProfileProvisioningResponse ::= [2] CHOICE { -- Tag 'A2'
initiateAuthenticationResponse [57] InitiateAuthenticationResponse, -- Tag 'BF39'
authenticateClientResponseEs9 [59] AuthenticateClientResponseEs9, -- Tag 'BF3B'
getBoundProfilePackageResponse [58] GetBoundProfilePackageResponse, -- Tag 'BF3A'
cancelSessionResponseEs9 [65] CancelSessionResponseEs9, -- Tag 'BF41'
authenticateClientResponseEs11 [64] AuthenticateClientResponseEs11 -- Tag 'BF40'
}
InitiateAuthenticationRequest ::= [57] SEQUENCE { -- Tag 'BF39'
euiccChallenge [1] Octet16, -- random eUICC challenge
smdpAddress [3] UTF8String,
euiccInfo1 EUICCInfo1
}
InitiateAuthenticationResponse ::= [57] CHOICE { -- Tag 'BF39'
initiateAuthenticationOk InitiateAuthenticationOkEs9,
initiateAuthenticationError INTEGER {
invalidDpAddress(1),
euiccVersionNotSupportedByDp(2),
ciPKNotSupported(3)
}
}
InitiateAuthenticationOkEs9 ::= SEQUENCE {
transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
serverSigned1 ServerSigned1, -- Signed information
serverSignature1 [APPLICATION 55] OCTET STRING, -- Server_Sign1, tag '5F37'
euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- The curve CI Public Key to be used as required by ES10b.AuthenticateServer
serverCertificate Certificate
}
AuthenticateClientRequest ::= [59] SEQUENCE { -- Tag 'BF3B'
transactionId [0] TransactionId,
authenticateServerResponse [56] AuthenticateServerResponse -- This is the response from ES10b.AuthenticateServer
}
AuthenticateClientResponseEs9 ::= [59] CHOICE { -- Tag 'BF3B'
authenticateClientOk AuthenticateClientOk,
authenticateClientError INTEGER {
eumCertificateInvalid(1),
eumCertificateExpired(2),
euiccCertificateInvalid(3),
euiccCertificateExpired(4),
euiccSignatureInvalid(5),
matchingIdRefused(6),
eidMismatch(7),
noEligibleProfile(8),
ciPKUnknown(9),
invalidTransactionId(10),
undefinedError(127)
}
}
AuthenticateClientOk ::= SEQUENCE {
transactionId [0] TransactionId,
profileMetaData [37] StoreMetadataRequest,
prepareDownloadRequest [33] PrepareDownloadRequest
}
GetBoundProfilePackageRequest ::= [58] SEQUENCE { -- Tag 'BF3A'
transactionId [0] TransactionId,
prepareDownloadResponse [33] PrepareDownloadResponse
}
GetBoundProfilePackageResponse ::= [58] CHOICE { -- Tag 'BF3A'
getBoundProfilePackageOk GetBoundProfilePackageOk,
getBoundProfilePackageError INTEGER {
euiccSignatureInvalid(1),
confirmationCodeMissing(2),
confirmationCodeRefused(3),
confirmationCodeRetriesExceeded(4),
invalidTransactionId(95),
undefinedError(127)
}
}
GetBoundProfilePackageOk ::= SEQUENCE {
transactionId [0] TransactionId,
boundProfilePackage [54] BoundProfilePackage
}
HandleNotification ::= [61] SEQUENCE { -- Tag 'BF3D'
pendingNotification PendingNotification
}
CancelSessionRequestEs9 ::= [65] SEQUENCE { -- Tag 'BF41'
transactionId TransactionId,
cancelSessionResponse CancelSessionResponse -- data structure defined for ES10b.CancelSession function
}
CancelSessionResponseEs9 ::= [65] CHOICE { -- Tag 'BF41'
cancelSessionOk CancelSessionOk,
cancelSessionError INTEGER {
invalidTransactionId(1),
euiccSignatureInvalid(2),
undefinedError(127)
}
}
CancelSessionOk ::= SEQUENCE { -- This function has no output data
}
EuiccConfiguredAddressesRequest ::= [60] SEQUENCE { -- Tag 'BF3C'
}
EuiccConfiguredAddressesResponse ::= [60] SEQUENCE { -- Tag 'BF3C'
defaultDpAddress UTF8String OPTIONAL, -- Default SM-DP+ address as an FQDN
rootDsAddress UTF8String -- Root SM-DS address as an FQDN
}
ISDRProprietaryApplicationTemplate ::= [PRIVATE 0] SEQUENCE { -- Tag 'E0'
svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
lpaeSupport BIT STRING {
lpaeUsingCat(0), -- LPA in the eUICC using Card Application Toolkit
lpaeUsingScws(1) -- LPA in the eUICC using Smartcard Web Server
} OPTIONAL
}
LpaeActivationRequest ::= [66] SEQUENCE { -- Tag 'BF42'
lpaeOption BIT STRING {
activateCatBasedLpae(0), -- LPAe with LUIe based on CAT
activateScwsBasedLpae(1) -- LPAe with LUIe based on SCWS
}
}
LpaeActivationResponse ::= [66] SEQUENCE { -- Tag 'BF42'
lpaeActivationResult INTEGER {ok(0), notSupported(1)}
}
SetDefaultDpAddressRequest ::= [63] SEQUENCE { -- Tag 'BF3F'
defaultDpAddress UTF8String -- Default SM-DP+ address as an FQDN
}
SetDefaultDpAddressResponse ::= [63] SEQUENCE { -- Tag 'BF3F'
setDefaultDpAddressResult INTEGER { ok (0), undefinedError (127)}
}
AuthenticateClientResponseEs11 ::= [64] CHOICE { -- Tag 'BF40'
authenticateClientOk AuthenticateClientOkEs11,
authenticateClientError INTEGER {
eumCertificateInvalid(1),
eumCertificateExpired(2),
euiccCertificateInvalid(3),
euiccCertificateExpired(4),
euiccSignatureInvalid(5),
eventIdUnknown(6),
invalidTransactionId(7),
undefinedError(127)
}
}
AuthenticateClientOkEs11 ::= SEQUENCE {
transactionId TransactionId,
eventEntries SEQUENCE OF EventEntries
}
EventEntries ::= SEQUENCE {
eventId UTF8String,
rspServerAddress UTF8String
}
END

View File

@ -0,0 +1,122 @@
package com.truphone.lpad.worker;
import com.truphone.es9plus.AllocateProfileResponse;
import com.truphone.es9plus.Es9PlusImpl;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.util.LogStub;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.logging.Level;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.internal.verification.VerificationModeFactory.times;
public class AllocateProfileWorkerTest {
// private AllocateProfileWorker allocateProfileWorker;
//
// @Mock
// private Progress mockProgress;
// @Mock
// private Es9PlusImpl mockEs9PlusImpl;
//
// @Before
// public void setUp() {
// MockitoAnnotations.initMocks(this);
// allocateProfileWorker = new AllocateProfileWorker(mockProgress, mockEs9PlusImpl);
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionProgressIsNull() {
// new AllocateProfileWorker(null, mockEs9PlusImpl);
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenRsp29ModuleIsNull() {
// new AllocateProfileWorker(mockProgress, null);
// }
//
// @Test
// public void shouldAllocateAProfileForAValidMcc() {
//
//// String mcc = "351";
//// String eid = "2";
//// String acToken = "token";
////
//// AllocateProfileResponse mockAllocateProfileResponse = mock(AllocateProfileResponse.class);
//// when(mockAllocateProfileResponse.getAcToken())
//// .thenReturn(acToken);
////
//// when(mockEs9PlusImpl.allocateProfile(eid, mcc))
//// .thenReturn(mockAllocateProfileResponse);
////
//// String run = allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams(mcc, eid)));
////
//// assertEquals(acToken, run);
//// verify(mockProgress, times(1))
//// .setTotalSteps(2);
//// verify(mockProgress, times(1))
//// .stepExecuted(ProgressStep.ALLOCATE_PROFILE_ALLOCATING, "allocateProfile allocating...");
//// verify(mockProgress, times(1))
//// .stepExecuted(ProgressStep.ALLOCATE_PROFILE_ALLOCATED, "allocateProfile allocated!");
// }
//
// @Test(expected = RuntimeException.class)
// public void shouldThrowRuntimeExceptionWhenRspEs29ModuleReturnsANullAllocateProfileResponse() {
// LogStub.getInstance().setLogLevel(Level.FINEST);
//
// String mcc = "351";
// String eid = "2";
//
// when(mockEs9PlusImpl.allocateProfile(eid, mcc))
// .thenReturn(null);
//
// allocateProfileWorker
// = new AllocateProfileWorker(mockProgress, mockEs9PlusImpl);
//
// allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams(mcc, eid)));
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenAllocateProfileInputParamsIsNull() {
// allocateProfileWorker.run(null);
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenMccIsNull() {
//
// allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams(null, "eid")));
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenMccIsEmpty() {
//
// allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams("", "eid")));
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenEidIsNull() {
//
// allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams("mcc", null)));
// }
//
// @Test(expected = IllegalArgumentException.class)
// public void shouldThrowIllegalArgumentExceptionWhenEidIsEmpty() {
//
// allocateProfileWorker.run(buildLpadWorkerExchange(buildAllocateProfileInputParams("mcc", "")));
// }
//
// private AllocateProfileWorker.AllocateProfileInputParams buildAllocateProfileInputParams(final String mcc, final String eid) {
// return allocateProfileWorker. new AllocateProfileInputParams(mcc, eid);
// }
//
// private LpadWorkerExchange<AllocateProfileWorker.AllocateProfileInputParams> buildLpadWorkerExchange(final AllocateProfileWorker.AllocateProfileInputParams allocateProfileInputParams) {
// return new LpadWorkerExchange<>(allocateProfileInputParams);
// }
}

View File

@ -0,0 +1,213 @@
package com.truphone.lpad.worker;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.util.ToTLV;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
public class DeleteProfileWorkerTest {
private DeleteProfileWorker deleteProfileWorker;
@Mock
private Progress mockProgress;
@Mock
private ApduChannel mockApduChannel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
deleteProfileWorker = new DeleteProfileWorker(mockProgress, mockApduChannel);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionProgressIsNull() {
new DeleteProfileWorker(null, mockApduChannel);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenApduChannelIsNull() {
new DeleteProfileWorker(mockProgress, null);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenDeleteProfileInputParamsIsNull() {
deleteProfileWorker.run(null);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenDeleteProfileInputParamsBodyIsNull() {
deleteProfileWorker.run(null);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenICCIDIsNull() {
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(null)));
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenICCIDIsEmpty() {
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams("")));
}
@Test(expected = RuntimeException.class)
public void theTransmissionFailedResponseWrongContent(){
String iccid = "89445035401458888888";
String eResponse = "TEST";
when(mockApduChannel.transmitAPDU(anyString())).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test(expected = RuntimeException.class)
public void theTransmissionFailedResponseEmpty(){
String iccid = "89445035401458888888";
String eResponse = "";
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test
public void theTransmissionResponseOk(){
String iccid = "89445035401458888888";
String eResponse = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "00"));
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockApduChannel, times(1)).sendStatus();
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test
public void theTransmissionFailedIccidOrAidNotFound(){
String iccid = "89445035401458888888";
String eResponse = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "01"));
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockApduChannel, times(0)).sendStatus();
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test
public void theTransmissionFailedProfileNotInDisabledState(){
String iccid = "89445035401458888888";
String eResponse = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "02"));
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockApduChannel, times(0)).sendStatus();
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test
public void theTransmissionFailedDisallowedByPolicy(){
String iccid = "89445035401458888888";
String eResponse = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "03"));
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockApduChannel, times(0)).sendStatus();
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
@Test
public void theTransmissionFailedUndefinedError(){
String iccid = "89445035401458888888";
String eResponse = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "7F")); //7F
when(mockApduChannel.transmitAPDU(any(String.class))).thenReturn(eResponse);
deleteProfileWorker.run(buildLpadWorkerExchange(buildDeleteProfileInputParams(iccid)));
verify(mockProgress, times(1)).setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETING_PROFILE, iccid + " delete profile");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_CONVERTING_RESPONSE, "Converting response");
verify(mockApduChannel, times(0)).sendStatus();
verify(mockProgress, times(0))
.stepExecuted(ProgressStep.DELETE_PROFILE_DELETED, iccid + " deleted successfully");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.DELETE_PROFILE_NOT_DELETED, iccid + " profile not deleted");
}
private DeleteProfileWorker.DeleteProfileInputParams buildDeleteProfileInputParams(final String iccid) {
return deleteProfileWorker. new DeleteProfileInputParams(iccid);
}
private LpadWorkerExchange<DeleteProfileWorker.DeleteProfileInputParams> buildLpadWorkerExchange(final DeleteProfileWorker.DeleteProfileInputParams deleteProfileInputParams) {
return new LpadWorkerExchange<>(deleteProfileInputParams);
}
}

View File

@ -0,0 +1,111 @@
package com.truphone.lpad.worker;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.apdu.ApduUtils;
import com.truphone.lpad.progress.Progress;
import com.truphone.lpad.progress.ProgressStep;
import com.truphone.util.LogStub;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.logging.Level;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
public class GetEidLpadWorkerTest {
private GetEidLpadWorker getIdWorker;
@Mock
private Progress mockProgress;
@Mock
private ApduChannel mockApduChannel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
getIdWorker = new GetEidLpadWorker(mockProgress, mockApduChannel);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenProgressIsNull() {
new GetEidLpadWorker(null, mockApduChannel);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenApduChannelIsNull() {
new GetEidLpadWorker(mockProgress, null);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenTransmitAPDUReturnNull() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(null);
getIdWorker.run(buildStringLpadWorkerExchange(ApduUtils.getEIDApdu()));
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowIllegalArgumentExceptionWhenTransmitAPDUReturnEmpty() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("");
getIdWorker.run(buildStringLpadWorkerExchange(ApduUtils.getEIDApdu()));
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenIdentifierDoesNotMatch() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("A0A40000027F");
getIdWorker.run(buildStringLpadWorkerExchange(ApduUtils.getEIDApdu()));
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenDecodeFails() {
LogStub.getInstance().setLogLevel(Level.FINEST);
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("asdasdasd");
getIdWorker.run(buildStringLpadWorkerExchange(ApduUtils.getEIDApdu()));
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenEidApduIsNull() {
getIdWorker.run(buildStringLpadWorkerExchange(null));
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenEidApduIsEmpty() {
getIdWorker.run(buildStringLpadWorkerExchange(""));
}
@Test
public void shouldGetEidData() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("bf3e125a10890440500010006800000000000001709000");
String eidData = getIdWorker.run(buildStringLpadWorkerExchange(ApduUtils.getEIDApdu()));
assertEquals("89044050001000680000000000000170", eidData);
verify(mockProgress, times(1))
.setTotalSteps(3);
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.GET_EID_RETRIEVING, "getEID retrieving...");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.GET_EID_CONVERTING, "getEID converting...");
verify(mockProgress, times(1))
.stepExecuted(ProgressStep.GET_EID_CONVERTED, "getEID converted...");
}
private LpadWorkerExchange<String> buildStringLpadWorkerExchange(final String eidApdu) {
return new LpadWorkerExchange<>(eidApdu);
}
}

View File

@ -0,0 +1,82 @@
package integration;
import com.github.tomakehurst.wiremock.common.ConsoleNotifier;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import integration.utils.ReferenceData;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.LocalProfileAssistant;
import com.truphone.lpa.impl.LocalProfileAssistantImpl;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
public class AllocateProfileTest {
private LocalProfileAssistant localProfileAssistant;
// @Mock
// private ApduChannel mockApduChannel;
//
// @ClassRule
// public static WireMockRule wireMockRule = new WireMockRule(WireMockConfiguration.options().port(8090).httpsPort(8443).notifier(new ConsoleNotifier(true)));
//
// @Before
// public void setUp() {
// MockitoAnnotations.initMocks(this);
//
// localProfileAssistant = new LocalProfileAssistantImpl(this.mockApduChannel);
// }
//
// @Test
// public void shouldReturnAcToken() {
// wireMockRule.stubFor(post(urlMatching("/custom/profile/"))
// .withHeader("Content-type", equalTo("application/x-www-form-urlencoded"))
// .withHeader("User-Agent", equalTo("gsma-rsp-com.truphone.lpad"))
// .withHeader("X-Admin-Protocol", equalTo("gsma/rsp/v2.2.0"))
// .withRequestBody(containing("eid=89044050001000680000000000000170&mcc=351"))
// .willReturn(aResponse().withStatus(200).withBody("$1$rsp.truphone.com$2")));
//
// when(mockApduChannel.transmitAPDU(anyString()))
// .thenReturn(ReferenceData.VALID_EID);
//
// Assert.assertEquals("2", localProfileAssistant.allocateProfile("351"));
// }
//
// @Test(expected = RuntimeException.class)
// public void shouldThrowRuntimeExceptionWhenRspServerRespondesWithEmpty() {
// wireMockRule.stubFor(post(urlMatching("/custom/profile/"))
// .withHeader("Content-type", equalTo("application/x-www-form-urlencoded"))
// .withHeader("User-Agent", equalTo("gsma-rsp-com.truphone.lpad"))
// .withHeader("X-Admin-Protocol", equalTo("gsma/rsp/v2.2.0"))
// .withRequestBody(containing("eid=89044050001000680000000000000170&mcc=351"))
// .willReturn(aResponse().withStatus(200).withBody("x")));
//
// when(mockApduChannel.transmitAPDU(anyString()))
// .thenReturn(ReferenceData.VALID_EID);
//
// localProfileAssistant.allocateProfile("351");
// }
//
//
// @Test(expected = RuntimeException.class)
// public void shouldThrowRuntimeExceptionWhenRspServerRespondesWithStatusDifferentOf2xx() {
// wireMockRule.stubFor(post(urlMatching("/custom/profile/"))
// .withHeader("Content-type", equalTo("application/x-www-form-urlencoded"))
// .withHeader("User-Agent", equalTo("gsma-rsp-com.truphone.lpad"))
// .withHeader("X-Admin-Protocol", equalTo("gsma/rsp/v2.2.0"))
// .withRequestBody(containing("eid=89044050001000680000000000000170&mcc=351"))
// .willReturn(aResponse().withStatus(400).withBody("x")));
//
// when(mockApduChannel.transmitAPDU(anyString()))
// .thenReturn(ReferenceData.VALID_EID);
//
// localProfileAssistant.allocateProfile("351");
// }
}

View File

@ -0,0 +1,104 @@
package integration;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.LocalProfileAssistant;
import com.truphone.lpa.impl.LocalProfileAssistantImpl;
import com.truphone.lpad.progress.Progress;
import com.truphone.util.ToTLV;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
public class DeleteProfileTest {
private LocalProfileAssistant localProfileAssistant;
@Mock
private ApduChannel mockApduChannel;
@Mock
private Progress mockProgress;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
localProfileAssistant = new LocalProfileAssistantImpl(this.mockApduChannel);
}
@Test
public void shouldResponseOk() {
String response = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "00"));
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(response);
assertEquals("0", this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress));
}
@Test
public void shouldFailedIccidOrAidNotFound() {
String response = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "01"));
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(response);
assertEquals("1", this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress));
}
@Test
public void shouldFailedProfileNotInDisabledState() {
String response = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "02"));
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(response);
assertEquals("2", this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress));
}
@Test
public void shouldFailedDisallowedByPolicy() {
String response = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "03"));
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(response);
assertEquals("3", this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress));
}
@Test
public void shouldFailedUndefinedError() {
String response = ToTLV.toTLV("BF33", ToTLV.toTLV("80", "7F"));
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(response);
assertEquals("127", this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress));
}
@Test(expected = RuntimeException.class)
public void shouldFailedReturnStringWrong() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("randomstring");
this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress);
}
@Test(expected = RuntimeException.class)
public void shouldFailedReturnEmptyString() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("");
this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress);
}
@Test(expected = RuntimeException.class)
public void shouldFailedReturnNullString() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(null);
this.localProfileAssistant.deleteProfile("89445035401458888888", mockProgress);
}
}

View File

@ -0,0 +1,72 @@
package integration;
import integration.utils.ReferenceData;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.truphone.lpa.ApduChannel;
import com.truphone.lpa.LocalProfileAssistant;
import com.truphone.lpa.impl.LocalProfileAssistantImpl;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
public class GetEidTest {
private LocalProfileAssistant localProfileAssistant;
@Mock
private ApduChannel mockApduChannel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
localProfileAssistant = new LocalProfileAssistantImpl(this.mockApduChannel);
}
@Test
public void shouldReturnEid() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(ReferenceData.VALID_EID);
assertEquals("89044050001000680000000000000170", this.localProfileAssistant.getEID());
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenApduChannelRespondsWithNonHexadecimalValue() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("asdasd");
assertEquals("89044050001000680000000000000170", this.localProfileAssistant.getEID());
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenApduChannelRespondsWithAnInvalidEID() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("dfcd8f12a77c264a0ce4");
assertEquals("89044050001000680000000000000170", this.localProfileAssistant.getEID());
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenApduChannelRespondsWithNull() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn(null);
assertEquals("89044050001000680000000000000170", this.localProfileAssistant.getEID());
}
@Test(expected = RuntimeException.class)
public void shouldThrowRuntimeExceptionWhenApduChannelRespondsWithEmpty() {
when(mockApduChannel.transmitAPDU(any(String.class)))
.thenReturn("");
assertEquals("89044050001000680000000000000170", this.localProfileAssistant.getEID());
}
}

View File

@ -0,0 +1,6 @@
package integration.utils;
public interface ReferenceData {
String VALID_EID = "bf3e125a10890440500010006800000000000001709000";
}

View File

@ -13,4 +13,4 @@ dependencyResolutionManagement {
} }
} }
rootProject.name = "OpenEUICC" rootProject.name = "OpenEUICC"
include ':app' include ':app', ':libs:lpad-sm-dp-plus-connector'