瀏覽代碼

import LPA library implementation from TruPhone

Converted to gradle build and updated a bunch of dependencies.
Peter Cai 3 年之前
父節點
當前提交
9ca4ce2798
共有 100 個文件被更改,包括 7773 次插入4 次删除
  1. 1 0
      .gitignore
  2. 3 1
      .idea/compiler.xml
  3. 3 0
      .idea/gradle.xml
  4. 1 1
      .idea/misc.xml
  5. 1 1
      app/build.gradle
  6. 55 0
      libs/lpad-sm-dp-plus-connector/.classpath
  7. 23 0
      libs/lpad-sm-dp-plus-connector/.project
  8. 6 0
      libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.core.resources.prefs
  9. 2 0
      libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.jdt.apt.core.prefs
  10. 9 0
      libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.jdt.core.prefs
  11. 4 0
      libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.m2e.core.prefs
  12. 36 0
      libs/lpad-sm-dp-plus-connector/build.gradle
  13. 170 0
      libs/lpad-sm-dp-plus-connector/pom.xml
  14. 59 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/AllocateProfileResponse.java
  15. 216 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/Es9PlusImpl.java
  16. 122 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/HttpRSPClient.java
  17. 26 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/HttpResponse.java
  18. 10 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/LpaUtils.java
  19. 4 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/MsgBody.java
  20. 12 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/MsgType.java
  21. 28 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/AuthenticateClientReq.java
  22. 37 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/CancelSessionReq.java
  23. 53 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/ConfirmOrderReq.java
  24. 45 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/DownloadOrderReq.java
  25. 28 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/GetBoundProfilePackageReq.java
  26. 74 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/HandleDownloadProgressInfoReq.java
  27. 19 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/HandleNotificationReq.java
  28. 37 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/InitiateAuthenticationReq.java
  29. 19 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/ReleaseProfileReq.java
  30. 12 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/base/RequestMsgBody.java
  31. 63 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/AuthenticateClientResp.java
  32. 8 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/CancelSessionResp.java
  33. 34 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/ConfirmOrderResp.java
  34. 17 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/DownloadOrderResp.java
  35. 26 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/GetBoundProfilePackageResp.java
  36. 8 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/HandleDownloadProgressInfoResp.java
  37. 8 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/HandleNotificationResp.java
  38. 64 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/InitiateAuthenticationResp.java
  39. 8 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/ReleaseProfileResp.java
  40. 33 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/FunctionExecutionStatus.java
  41. 19 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/HeaderResp.java
  42. 24 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/NotificationPointStatus.java
  43. 16 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/ResponseMsgBody.java
  44. 64 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/StatusCodeData.java
  45. 15 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/ApduChannel.java
  46. 5 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/ApduTransmittedListener.java
  47. 40 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/LocalProfileAssistant.java
  48. 362 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/ApduUtils.java
  49. 17 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/NotificationType.java
  50. 275 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/ProfileUtil.java
  51. 42 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/AuthenticateClientSmDp.java
  52. 101 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/DisableProfileWorker.java
  53. 77 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/DownloadProfileWorker.java
  54. 106 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/EnableProfileWorker.java
  55. 57 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/GetSMDPAddressWorker.java
  56. 193 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/HandleNotificationsWorker.java
  57. 123 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/InitialAuthenticationKeys.java
  58. 95 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/ListProfilesWorker.java
  59. 142 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/LocalProfileAssistantImpl.java
  60. 12 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/ProfileKey.java
  61. 50 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/SetSMDPAddressWorker.java
  62. 57 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/SmdsRetrieveEventsWorker.java
  63. 61 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/ApduTransmitter.java
  64. 290 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/AuthenticatingPhaseWorker.java
  65. 16 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/CloseResources.java
  66. 94 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/ConnectingPhaseWorker.java
  67. 85 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/DownloadPhaseWorker.java
  68. 115 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/GeneratePhaseWorker.java
  69. 249 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/InstallationPhaseWorker.java
  70. 9 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/SbppApdu.java
  71. 132 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/DownloadProgress.java
  72. 61 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/DownloadProgressPhase.java
  73. 5 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/ProgressPhase.java
  74. 17 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/LpadWorker.java
  75. 68 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/Progress.java
  76. 9 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/ProgressListener.java
  77. 62 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/ProgressStep.java
  78. 119 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/AllocateProfileWorker.java
  79. 162 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/DeleteProfileWorker.java
  80. 109 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/GetEidLpadWorker.java
  81. 25 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/LpadWorkerExchange.java
  82. 14 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/WorkerExchange.java
  83. 73 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/LogStub.java
  84. 31 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/PropUtil.java
  85. 22 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/TLVBean.java
  86. 36 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/TextUtil.java
  87. 50 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/ToTLV.java
  88. 29 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/Tools.java
  89. 52 0
      libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/Util.java
  90. 619 0
      libs/lpad-sm-dp-plus-connector/src/main/resources/PKIXExplicit88.asn
  91. 387 0
      libs/lpad-sm-dp-plus-connector/src/main/resources/PKIXImplicit88.asn
  92. 785 0
      libs/lpad-sm-dp-plus-connector/src/main/resources/rsp.asn
  93. 122 0
      libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/AllocateProfileWorkerTest.java
  94. 213 0
      libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/DeleteProfileWorkerTest.java
  95. 111 0
      libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/GetEidLpadWorkerTest.java
  96. 82 0
      libs/lpad-sm-dp-plus-connector/src/test/java/integration/AllocateProfileTest.java
  97. 104 0
      libs/lpad-sm-dp-plus-connector/src/test/java/integration/DeleteProfileTest.java
  98. 72 0
      libs/lpad-sm-dp-plus-connector/src/test/java/integration/GetEidTest.java
  99. 6 0
      libs/lpad-sm-dp-plus-connector/src/test/java/integration/utils/ReferenceData.java
  100. 1 1
      settings.gradle

+ 1 - 0
.gitignore

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

+ 3 - 1
.idea/compiler.xml

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

+ 3 - 0
.idea/gradle.xml

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

+ 1 - 1
.idea/misc.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <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" />
   </component>
   <component name="ProjectType">

+ 1 - 1
app/build.gradle

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

+ 55 - 0
libs/lpad-sm-dp-plus-connector/.classpath

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

+ 23 - 0
libs/lpad-sm-dp-plus-connector/.project

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

+ 6 - 0
libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.core.resources.prefs

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

+ 2 - 0
libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.jdt.apt.core.prefs

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

+ 9 - 0
libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.jdt.core.prefs

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

+ 4 - 0
libs/lpad-sm-dp-plus-connector/.settings/org.eclipse.m2e.core.prefs

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

+ 36 - 0
libs/lpad-sm-dp-plus-connector/build.gradle

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

+ 170 - 0
libs/lpad-sm-dp-plus-connector/pom.xml

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

+ 59 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/AllocateProfileResponse.java

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

+ 216 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/Es9PlusImpl.java

@@ -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);
+    }
+}

+ 122 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/HttpRSPClient.java

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

+ 26 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/HttpResponse.java

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

+ 10 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/LpaUtils.java

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

+ 4 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/MsgBody.java

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

+ 12 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/MsgType.java

@@ -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();
+}

+ 28 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/AuthenticateClientReq.java

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

+ 37 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/CancelSessionReq.java

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

+ 53 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/ConfirmOrderReq.java

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

+ 45 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/DownloadOrderReq.java

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

+ 28 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/GetBoundProfilePackageReq.java

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

+ 74 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/HandleDownloadProgressInfoReq.java

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

+ 19 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/HandleNotificationReq.java

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

+ 37 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/InitiateAuthenticationReq.java

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

+ 19 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/ReleaseProfileReq.java

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

+ 12 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/request/base/RequestMsgBody.java

@@ -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 {
+    }
+}

+ 63 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/AuthenticateClientResp.java

@@ -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 + '\'' +
+                '}';
+    }
+}

+ 8 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/CancelSessionResp.java

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

+ 34 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/ConfirmOrderResp.java

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

+ 17 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/DownloadOrderResp.java

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

+ 26 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/GetBoundProfilePackageResp.java

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

+ 8 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/HandleDownloadProgressInfoResp.java

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

+ 8 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/HandleNotificationResp.java

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

+ 64 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/InitiateAuthenticationResp.java

@@ -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 + '\'' +
+                '}';
+    }
+}

+ 8 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/ReleaseProfileResp.java

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

+ 33 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/FunctionExecutionStatus.java

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

+ 19 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/HeaderResp.java

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

+ 24 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/NotificationPointStatus.java

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

+ 16 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/ResponseMsgBody.java

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

+ 64 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/es9plus/message/response/base/StatusCodeData.java

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

+ 15 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/ApduChannel.java

@@ -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);
+}

+ 5 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/ApduTransmittedListener.java

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

+ 40 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/LocalProfileAssistant.java

@@ -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();
+}

+ 362 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/ApduUtils.java

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

+ 17 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/NotificationType.java

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

+ 275 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/apdu/ProfileUtil.java

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

+ 42 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/AuthenticateClientSmDp.java

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

+ 101 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/DisableProfileWorker.java

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

+ 77 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/DownloadProfileWorker.java

@@ -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);
+    }
+}

+ 106 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/EnableProfileWorker.java

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

+ 57 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/GetSMDPAddressWorker.java

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

+ 193 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/HandleNotificationsWorker.java

@@ -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());
+        }
+    }
+}

+ 123 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/InitialAuthenticationKeys.java

@@ -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 + '\'' +
+                '}';
+    }
+}

+ 95 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/ListProfilesWorker.java

@@ -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);
+    }
+}

+ 142 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/LocalProfileAssistantImpl.java

@@ -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();
+    }
+}

+ 12 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/ProfileKey.java

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

+ 50 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/SetSMDPAddressWorker.java

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

+ 57 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/SmdsRetrieveEventsWorker.java

@@ -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;
+//    }
+}

+ 61 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/ApduTransmitter.java

@@ -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);
+    }
+}

+ 290 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/AuthenticatingPhaseWorker.java

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

+ 16 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/CloseResources.java

@@ -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) {
+            }
+        }
+    }
+}

+ 94 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/ConnectingPhaseWorker.java

@@ -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);
+        }
+    }
+}

+ 85 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/DownloadPhaseWorker.java

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

+ 115 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/GeneratePhaseWorker.java

@@ -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);
+            }
+        }
+    }
+}

+ 249 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/InstallationPhaseWorker.java

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

+ 9 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/impl/download/SbppApdu.java

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

+ 132 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/DownloadProgress.java

@@ -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());
+    }
+}

+ 61 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/DownloadProgressPhase.java

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

+ 5 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpa/progress/ProgressPhase.java

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

+ 17 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/LpadWorker.java

@@ -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);
+}

+ 68 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/Progress.java

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

+ 9 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/ProgressListener.java

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

+ 62 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/progress/ProgressStep.java

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

+ 119 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/AllocateProfileWorker.java

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

+ 162 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/DeleteProfileWorker.java

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

+ 109 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/GetEidLpadWorker.java

@@ -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);
+        }
+    }
+}

+ 25 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/LpadWorkerExchange.java

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

+ 14 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/lpad/worker/WorkerExchange.java

@@ -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();
+}

+ 73 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/LogStub.java

@@ -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);
+//        }
+    }
+}

+ 31 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/PropUtil.java

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

+ 22 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/TLVBean.java

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

+ 36 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/TextUtil.java

@@ -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);
+    }
+
+}

+ 50 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/ToTLV.java

@@ -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();
+	}
+}

+ 29 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/Tools.java

@@ -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();
+    }
+}

+ 52 - 0
libs/lpad-sm-dp-plus-connector/src/main/java/com/truphone/util/Util.java

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

+ 619 - 0
libs/lpad-sm-dp-plus-connector/src/main/resources/PKIXExplicit88.asn

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

+ 387 - 0
libs/lpad-sm-dp-plus-connector/src/main/resources/PKIXImplicit88.asn

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

+ 785 - 0
libs/lpad-sm-dp-plus-connector/src/main/resources/rsp.asn

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

+ 122 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/AllocateProfileWorkerTest.java

@@ -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);
+//    }
+}

+ 213 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/DeleteProfileWorkerTest.java

@@ -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);
+    }
+
+
+}

+ 111 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/com/truphone/lpad/worker/GetEidLpadWorkerTest.java

@@ -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);
+    }
+}

+ 82 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/integration/AllocateProfileTest.java

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

+ 104 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/integration/DeleteProfileTest.java

@@ -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);
+    }
+
+}

+ 72 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/integration/GetEidTest.java

@@ -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());
+    }
+}

+ 6 - 0
libs/lpad-sm-dp-plus-connector/src/test/java/integration/utils/ReferenceData.java

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

+ 1 - 1
settings.gradle

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