diff --git a/app-common/src/main/AndroidManifest.xml b/app-common/src/main/AndroidManifest.xml
index a9c61d3..be37bf4 100644
--- a/app-common/src/main/AndroidManifest.xml
+++ b/app-common/src/main/AndroidManifest.xml
@@ -6,8 +6,7 @@
-
+
diff --git a/app-common/src/main/res/raw/symantec_gsma_rspv2_root_ci1 b/app-common/src/main/res/raw/symantec_gsma_rspv2_root_ci1
deleted file mode 100644
index d9b7113..0000000
--- a/app-common/src/main/res/raw/symantec_gsma_rspv2_root_ci1
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN CERTIFICATE-----
-MIICSTCCAe+gAwIBAgIQbmhWeneg7nyF7hg5Y9+qejAKBggqhkjOPQQDAjBEMRgw
-FgYDVQQKEw9HU00gQXNzb2NpYXRpb24xKDAmBgNVBAMTH0dTTSBBc3NvY2lhdGlv
-biAtIFJTUDIgUm9vdCBDSTEwIBcNMTcwMjIyMDAwMDAwWhgPMjA1MjAyMjEyMzU5
-NTlaMEQxGDAWBgNVBAoTD0dTTSBBc3NvY2lhdGlvbjEoMCYGA1UEAxMfR1NNIEFz
-c29jaWF0aW9uIC0gUlNQMiBSb290IENJMTBZMBMGByqGSM49AgEGCCqGSM49AwEH
-A0IABJ1qutL0HCMX52GJ6/jeibsAqZfULWj/X10p/Min6seZN+hf5llovbCNuB2n
-unLz+O8UD0SUCBUVo8e6n9X1TuajgcAwgb0wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
-EwEB/wQFMAMBAf8wEwYDVR0RBAwwCogIKwYBBAGC6WAwFwYDVR0gAQH/BA0wCzAJ
-BgdngRIBAgEAME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9nc21hLWNybC5zeW1h
-dXRoLmNvbS9vZmZsaW5lY2EvZ3NtYS1yc3AyLXJvb3QtY2kxLmNybDAdBgNVHQ4E
-FgQUgTcPUSXQsdQI1MOyMubSXnlb6/swCgYIKoZIzj0EAwIDSAAwRQIgIJdYsOMF
-WziPK7l8nh5mu0qiRiVf25oa9ullG/OIASwCIQDqCmDrYf+GziHXBOiwJwnBaeBO
-aFsiLzIEOaUuZwdNUw==
------END CERTIFICATE-----
diff --git a/app-common/src/main/res/xml/network_security_config.xml b/app-common/src/main/res/xml/network_security_config.xml
deleted file mode 100644
index 2d4e014..0000000
--- a/app-common/src/main/res/xml/network_security_config.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/EuiccInfo2.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/EuiccInfo2.kt
index b7769e7..e69c7ff 100644
--- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/EuiccInfo2.kt
+++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/EuiccInfo2.kt
@@ -9,4 +9,6 @@ data class EuiccInfo2(
val ppVersion: String,
val freeNvram: Int,
val freeRam: Int,
+ val euiccCiPKIdListForSigning: Array,
+ val euiccCiPKIdListForVerification: Array,
)
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/HttpInterface.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/HttpInterface.kt
index f693374..49d6cc0 100644
--- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/HttpInterface.kt
+++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/HttpInterface.kt
@@ -1,5 +1,7 @@
package net.typeblog.lpac_jni
+import javax.net.ssl.TrustManager
+
/*
* Should reflect euicc_http_interface in lpac/euicc/interface.h
*/
@@ -25,4 +27,8 @@ interface HttpInterface {
}
fun transmit(url: String, tx: ByteArray, headers: Array): HttpResponse
+ // The LPA is supposed to pass in a list of pkIds supported by the eUICC.
+ // HttpInterface is responsible for providing TrustManager implementations that
+ // validate based on certificates corresponding to these pkIds
+ fun usePublicKeyIds(pkids: Array)
}
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt
index d84ae95..bfad50c 100644
--- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt
+++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/HttpInterfaceImpl.kt
@@ -2,14 +2,20 @@ package net.typeblog.lpac_jni.impl
import android.util.Log
import net.typeblog.lpac_jni.HttpInterface
-import java.net.HttpURLConnection
import java.net.URL
+import java.security.SecureRandom
+import javax.net.ssl.HttpsURLConnection
+import javax.net.ssl.SSLContext
+import javax.net.ssl.TrustManager
+import javax.net.ssl.TrustManagerFactory
class HttpInterfaceImpl: HttpInterface {
companion object {
private const val TAG = "HttpInterfaceImpl"
}
+ private lateinit var trustManagers: Array
+
override fun transmit(
url: String,
tx: ByteArray,
@@ -17,8 +23,17 @@ class HttpInterfaceImpl: HttpInterface {
): HttpInterface.HttpResponse {
Log.d(TAG, "transmit(url = $url)")
+ val parsedUrl = URL(url)
+ if (parsedUrl.protocol != "https") {
+ throw IllegalArgumentException("SM-DP+ servers must use the HTTPS protocol")
+ }
+
try {
- val conn = URL(url).openConnection() as HttpURLConnection
+ val sslContext = SSLContext.getInstance("TLS")
+ sslContext.init(null, trustManagers, SecureRandom())
+
+ val conn = parsedUrl.openConnection() as HttpsURLConnection
+ conn.sslSocketFactory = sslContext.socketFactory
conn.requestMethod = "POST"
conn.doInput = true
conn.doOutput = true
@@ -40,4 +55,11 @@ class HttpInterfaceImpl: HttpInterface {
throw e
}
}
+
+ override fun usePublicKeyIds(pkids: Array) {
+ val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply {
+ init(keyIdToKeystore(pkids))
+ }
+ trustManagers = trustManagerFactory.trustManagers
+ }
}
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt
index 5dabf28..7412f00 100644
--- a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt
+++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/LocalProfileAssistantImpl.kt
@@ -26,6 +26,9 @@ class LocalProfileAssistantImpl(
if (LpacJni.es10xInit(contextHandle) < 0) {
throw IllegalArgumentException("Failed to initialize LPA")
}
+
+ val pkids = euiccInfo2?.euiccCiPKIdListForVerification ?: arrayOf(DEFAULT_PKID_GSMA_RSP2_ROOT_CI1)
+ httpInterface.usePublicKeyIds(pkids)
}
private fun tryReconnect(timeoutMillis: Long) = runBlocking {
diff --git a/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/RootCertificates.kt b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/RootCertificates.kt
new file mode 100644
index 0000000..ec094aa
--- /dev/null
+++ b/libs/lpac-jni/src/main/java/net/typeblog/lpac_jni/impl/RootCertificates.kt
@@ -0,0 +1,148 @@
+package net.typeblog.lpac_jni.impl
+
+import java.io.ByteArrayInputStream
+import java.security.KeyStore
+import java.security.cert.CertificateException
+import java.security.cert.CertificateFactory
+
+const val DEFAULT_PKID_GSMA_RSP2_ROOT_CI1 = "81370f5125d0b1d408d4c3b232e6d25e795bebfb"
+
+internal fun keyIdToKeystore(keyIds: Array): KeyStore {
+ val ret = KeyStore.getInstance(KeyStore.getDefaultType())
+ ret.load(null, null)
+ keyIds.forEach {
+ if (it !in KNOWN_CI_CERTS) throw CertificateException("Unknown CI cert ID $it")
+ ByteArrayInputStream(KNOWN_CI_CERTS[it]!!.toByteArray()).use { stream ->
+ val cf = CertificateFactory.getInstance("X.509")
+ ret.setCertificateEntry(it, cf.generateCertificate(stream))
+ }
+ }
+ return ret
+}
+
+// ref:
+internal val KNOWN_CI_CERTS = hashMapOf(
+ // GSM Association - RSP2 Root CI1 (CA: DigiCert)
+ // Specs: SGP.21 and SGP.22 version 2 and version 3
+ "81370f5125d0b1d408d4c3b232e6d25e795bebfb" to """
+ -----BEGIN CERTIFICATE-----
+ MIICSTCCAe+gAwIBAgIQbmhWeneg7nyF7hg5Y9+qejAKBggqhkjOPQQDAjBEMRgw
+ FgYDVQQKEw9HU00gQXNzb2NpYXRpb24xKDAmBgNVBAMTH0dTTSBBc3NvY2lhdGlv
+ biAtIFJTUDIgUm9vdCBDSTEwIBcNMTcwMjIyMDAwMDAwWhgPMjA1MjAyMjEyMzU5
+ NTlaMEQxGDAWBgNVBAoTD0dTTSBBc3NvY2lhdGlvbjEoMCYGA1UEAxMfR1NNIEFz
+ c29jaWF0aW9uIC0gUlNQMiBSb290IENJMTBZMBMGByqGSM49AgEGCCqGSM49AwEH
+ A0IABJ1qutL0HCMX52GJ6/jeibsAqZfULWj/X10p/Min6seZN+hf5llovbCNuB2n
+ unLz+O8UD0SUCBUVo8e6n9X1TuajgcAwgb0wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
+ EwEB/wQFMAMBAf8wEwYDVR0RBAwwCogIKwYBBAGC6WAwFwYDVR0gAQH/BA0wCzAJ
+ BgdngRIBAgEAME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9nc21hLWNybC5zeW1h
+ dXRoLmNvbS9vZmZsaW5lY2EvZ3NtYS1yc3AyLXJvb3QtY2kxLmNybDAdBgNVHQ4E
+ FgQUgTcPUSXQsdQI1MOyMubSXnlb6/swCgYIKoZIzj0EAwIDSAAwRQIgIJdYsOMF
+ WziPK7l8nh5mu0qiRiVf25oa9ullG/OIASwCIQDqCmDrYf+GziHXBOiwJwnBaeBO
+ aFsiLzIEOaUuZwdNUw==
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ // OISITE GSMA CI G1 (CA: WISeKey)
+ // Specs: SGP.21 and SGP.22 version 3
+ "4c27967ad20c14b391e9601e41e604ad57c0222f" to """
+ -----BEGIN CERTIFICATE-----
+ MIIB9zCCAZ2gAwIBAgIUSpBSCCDYPOEG/IFHUCKpZ2pIAQMwCgYIKoZIzj0EAwIw
+ QzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRpb24xGTAXBgNV
+ BAMMEE9JU1RFIEdTTUEgQ0kgRzEwIBcNMjQwMTE2MjMxNzM5WhgPMjA1OTAxMDcy
+ MzE3MzhaMEMxCzAJBgNVBAYTAkNIMRkwFwYDVQQKDBBPSVNURSBGb3VuZGF0aW9u
+ MRkwFwYDVQQDDBBPSVNURSBHU01BIENJIEcxMFkwEwYHKoZIzj0CAQYIKoZIzj0D
+ AQcDQgAEvZ3s3PFC4NgrCcCMmHJ6DJ66uzAHuLcvjJnOn+TtBNThS7YHLDyHCa2v
+ 7D+zTP+XTtgqgcLoB56Gha9EQQQ4xKNtMGswDwYDVR0TAQH/BAUwAwEB/zAQBgNV
+ HREECTAHiAVghXQFDjAXBgNVHSABAf8EDTALMAkGB2eBEgECAQAwHQYDVR0OBBYE
+ FEwnlnrSDBSzkelgHkHmBK1XwCIvMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQD
+ AgNIADBFAiBVcywTj017jKpAQ+gwy4MqK2hQvzve6lkvQkgSP6ykHwIhAI0KFwCD
+ jnPbmcJsG41hUrWNlf+IcrMvFuYii0DasBNi
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ // Symantec RSP Test Root CA (CA: DigiCert)
+ "665a1433d67c1a2c5db8b52c967f10a057ba5cb2" to """
+ -----BEGIN CERTIFICATE-----
+ MIICkDCCAjagAwIBAgIQPfCO5OYL+cdbbx2ETDO7DDAKBggqhkjOPQQDAjBoMR0w
+ GwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjFHMEUGA1UEAxM+U3ltYW50ZWMg
+ Q29ycG9yYXRpb24gUlNQIFRlc3QgUm9vdCBDQSAtIEZvciBUZXN0IFB1cnBvc2Vz
+ IE9ubHkwHhcNMTcwNzExMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjBoMR0wGwYDVQQK
+ ExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjFHMEUGA1UEAxM+U3ltYW50ZWMgQ29ycG9y
+ YXRpb24gUlNQIFRlc3QgUm9vdCBDQSAtIEZvciBUZXN0IFB1cnBvc2VzIE9ubHkw
+ WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQlbEYt9PTmdWcaX5WC68SYTFyZcbBN
+ vFpJW6bZQpERlMIAuzEpgscbTDccHtNpDqJwMqZXCO7ebCmRLyI6jqe3o4HBMIG+
+ MA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBcGA1UdIAEB/wQNMAsw
+ CQYHZ4ESAQIBADBPBgNVHR8ESDBGMESgQqBAhj5odHRwOi8vcGtpLWNybC5zeW1h
+ dXRoLmNvbS9TeW1hbnRlY1JTUFRlc3RSb290Q0EvTGF0ZXN0Q1JMLmNybDASBgNV
+ HREECzAJiAcrBgEEAYMJMB0GA1UdDgQWBBRmWhQz1nwaLF24tSyWfxCgV7pcsjAK
+ BggqhkjOPQQDAgNIADBFAiAQ1quTqcexvDnKvmAkqoQP09QMXAXxlCyma82NtrYq
+ UQIhAP/W6pRamBGhSliV+EancgbZj+VoOkKdj0o7sP/cKdhZ
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ // GSMA Test CI
+ // Specs: SGP.26 v1
+ "f54172bdf98a95d65cbeb88a38a1c11d800a85c3" to """
+ -----BEGIN CERTIFICATE-----
+ MIICVjCCAfugAwIBAgIJALh086v6bETTMAoGCCqGSM49BAMCMEkxFTATBgNVBAMM
+ DEdTTUEgVGVzdCBDSTERMA8GA1UECwwIVEVTVENFUlQxEDAOBgNVBAoMB1JTUFRF
+ U1QxCzAJBgNVBAYTAklUMCAXDTE3MDIwMTE1Mzk0MloYDzIwNTIwMjAxMTUzOTQy
+ WjBJMRUwEwYDVQQDDAxHU01BIFRlc3QgQ0kxETAPBgNVBAsMCFRFU1RDRVJUMRAw
+ DgYDVQQKDAdSU1BURVNUMQswCQYDVQQGEwJJVDBZMBMGByqGSM49AgEGCCqGSM49
+ AwEHA0IABJQGV6Zz3CiPidUuqKR3BJknkfnDSwA25jPi0MupRU1l2zLrF5gXmdLy
+ Q4juK5XBCUVGyXkBzq66llCRmi4g0imjgckwgcYwHQYDVR0OBBYEFPVBcr35ipXW
+ XL64ijihwR2ACoXDMA8GA1UdEwEB/wQFMAMBAf8wFwYDVR0gAQH/BA0wCzAJBgdn
+ gRIBAgEAMA4GA1UdDwEB/wQEAwIBBjAOBgNVHREEBzAFiAOINwEwWwYDVR0fBFQw
+ UjAnoCWgI4YhaHR0cDovL2NpLnRlc3QuZ3NtYS5jb20vQ1JMLUEuY3JsMCegJaAj
+ hiFodHRwOi8vY2kudGVzdC5nc21hLmNvbS9DUkwtQi5jcmwwCgYIKoZIzj0EAwID
+ SQAwRgIhAJHyUclxU7nPhTeadItXKkloUkVWxH8z62l7VZEswPLSAiEA3OSec/NJ
+ 7NBZEO+d9raahnq/OJ3Ia4QRtN/hlpFQ9fk=
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ "c0bc70ba36929d43b467ff57570530e57ab8fcd8" to """
+ -----BEGIN CERTIFICATE-----
+ MIICVTCCAfygAwIBAgIJALh086v6bETTMAoGCCqGSM49BAMCMEkxFTATBgNVBAMM
+ DEdTTUEgVGVzdCBDSTERMA8GA1UECwwIVEVTVENFUlQxEDAOBgNVBAoMB1JTUFRF
+ U1QxCzAJBgNVBAYTAklUMCAXDTE3MDQxOTEwMzQzOFoYDzIwNTIwNDE4MTAzNDM4
+ WjBJMRUwEwYDVQQDDAxHU01BIFRlc3QgQ0kxETAPBgNVBAsMCFRFU1RDRVJUMRAw
+ DgYDVQQKDAdSU1BURVNUMQswCQYDVQQGEwJJVDBaMBQGByqGSM49AgEGCSskAwMC
+ CAEBBwNCAAQnh7TVbtgkqea+BOGIf2uYuv64x2P1KDf3ARPpNk7dvhObwMfefhaP
+ HlzQwYU0/FBk5k9obcUzJ8p/Hc6oWimUo4HJMIHGMB0GA1UdDgQWBBTAvHC6NpKd
+ Q7Rn/1dXBTDlerj82DAPBgNVHRMBAf8EBTADAQH/MBcGA1UdIAEB/wQNMAswCQYH
+ Z4ESAQIBADAOBgNVHQ8BAf8EBAMCAQYwDgYDVR0RBAcwBYgDiDcBMFsGA1UdHwRU
+ MFIwJ6AloCOGIWh0dHA6Ly9jaS50ZXN0LmdzbWEuY29tL0NSTC1BLmNybDAnoCWg
+ I4YhaHR0cDovL2NpLnRlc3QuZ3NtYS5jb20vQ1JMLUIuY3JsMAoGCCqGSM49BAMC
+ A0cAMEQCIAbGw59auXFdcsVl3PX/O/7z+3DvCuM6BzZmkTWG0O+SAiAWskTrRp8q
+ L1hrwcMgtLZDG4902UH38YMrQyVSsWHfog==
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ // Test CI
+ // Specs: SGP.26 v3
+ "34eecf13156518d48d30bdf06853404d115f955d" to """
+ -----BEGIN CERTIFICATE-----
+ MIIB4zCCAYqgAwIBAgIBADAKBggqhkjOPQQDAjBEMRAwDgYDVQQDDAdUZXN0IENJ
+ MREwDwYDVQQLDAhURVNUQ0VSVDEQMA4GA1UECgwHUlNQVEVTVDELMAkGA1UEBhMC
+ SVQwIBcNMjMwNTMxMTI1MDI4WhgPMjA1ODA1MzAxMjUwMjhaMEQxEDAOBgNVBAMM
+ B1Rlc3QgQ0kxETAPBgNVBAsMCFRFU1RDRVJUMRAwDgYDVQQKDAdSU1BURVNUMQsw
+ CQYDVQQGEwJJVDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLlQW4kHaMJSrAK4
+ nVKjGIgKWYxick+Y1x0MKO/Bsb3+KxMdnAObkPZjLosKlKCnH2bHUHhqRyDDSc2Y
+ 9+wB6A6jazBpMB0GA1UdDgQWBBQ07s8TFWUY1I0wvfBoU0BNEV+VXTAOBgNVHQ8B
+ Af8EBAMCAQYwFwYDVR0gAQH/BA0wCzAJBgdngRIBAgEAMA8GA1UdEwEB/wQFMAMB
+ Af8wDgYDVR0RBAcwBYgDiDcBMAoGCCqGSM49BAMCA0cAMEQCIEuYVB+bwdn5Z6sL
+ eKFS07FnvHY03QqDm8XYxdjDAxZuAiBneNr+fBYeqDulQWfrGXFLDTbsFBENNdDj
+ jvcHgHpATQ==
+ -----END CERTIFICATE-----
+ """.trimIndent(),
+ "2209f61cd9ec5c9c854e787341ff83ecf9776a5b" to """
+ -----BEGIN CERTIFICATE-----
+ MIIB5DCCAYugAwIBAgIBADAKBggqhkjOPQQDAjBEMRAwDgYDVQQDDAdUZXN0IENJ
+ MREwDwYDVQQLDAhURVNUQ0VSVDEQMA4GA1UECgwHUlNQVEVTVDELMAkGA1UEBhMC
+ SVQwIBcNMjMwNjAyMTMwNTQzWhgPMjA1ODA2MDExMzA1NDNaMEQxEDAOBgNVBAMM
+ B1Rlc3QgQ0kxETAPBgNVBAsMCFRFU1RDRVJUMRAwDgYDVQQKDAdSU1BURVNUMQsw
+ CQYDVQQGEwJJVDBaMBQGByqGSM49AgEGCSskAwMCCAEBBwNCAASF7cCXanl/xSJe
+ PwIeEUeZk4zPPM3iE16JbpOWPqPXaJwGmMKvHwQlRxiLtPWrRBalgkzrr4RgYIqD
+ aTcnvxoFo2swaTAdBgNVHQ4EFgQUIgn2HNnsXJyFTnhzQf+D7Pl3alswDgYDVR0P
+ AQH/BAQDAgEGMBcGA1UdIAEB/wQNMAswCQYHZ4ESAQIBADAPBgNVHRMBAf8EBTAD
+ AQH/MA4GA1UdEQQHMAWIA4g3ATAKBggqhkjOPQQDAgNHADBEAiBLLHbhrIvy1Cue
+ 7lDUlQZY2EOK7/I/o2CQO0pj76OqzQIgTQ+kE02RPbMuflDbXKRuVDKFvfZ/vHEW
+ QKvBPWehIXI=
+ -----END CERTIFICATE-----
+ """.trimIndent()
+)
\ No newline at end of file
diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c
index 44f5e93..4c3393a 100644
--- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c
+++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.c
@@ -53,7 +53,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
euicc_info2_class = (*env)->FindClass(env, "net/typeblog/lpac_jni/EuiccInfo2");
euicc_info2_class = (*env)->NewGlobalRef(env, euicc_info2_class);
- euicc_info2_constructor = (*env)->GetMethodID(env, euicc_info2_class, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V");
+ euicc_info2_constructor = (*env)->GetMethodID(env, euicc_info2_class, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II[Ljava/lang/String;[Ljava/lang/String;)V");
const char _unused[1];
empty_string = (*env)->NewString(env, _unused, 0);
@@ -262,12 +262,16 @@ JNIEXPORT jobject JNICALL
Java_net_typeblog_lpac_1jni_LpacJni_es10cexGetEuiccInfo2(JNIEnv *env, jobject thiz, jlong handle) {
struct euicc_ctx *ctx = (struct euicc_ctx *) handle;
struct es10cex_euiccinfo2 * info;
+ jobjectArray euiccCiPKIdListForVerification = NULL;
+ jobjectArray euiccCiPKIdListForSigning = NULL;
jstring sas_accreditation_number = NULL;
jstring global_platform_version = NULL;
jstring euicc_firmware_version = NULL;
jstring profile_version = NULL;
jstring pp_version = NULL;
jobject ret = NULL;
+ char **curr = NULL;
+ int count = 0;
if (es10cex_get_euiccinfo2(ctx, &info) < 0)
goto out;
@@ -278,12 +282,26 @@ Java_net_typeblog_lpac_1jni_LpacJni_es10cexGetEuiccInfo2(JNIEnv *env, jobject th
sas_accreditation_number = toJString(env, info->sasAcreditationNumber);
pp_version = toJString(env, info->ppVersion);
+ count = LPAC_JNI_NULL_TERM_LIST_COUNT(info->euiccCiPKIdListForSigning, curr);
+ euiccCiPKIdListForSigning = (*env)->NewObjectArray(env, count, string_class, NULL);
+ LPAC_JNI_NULL_TERM_LIST_FOREACH(info->euiccCiPKIdListForSigning, curr, {
+ (*env)->SetObjectArrayElement(env, euiccCiPKIdListForSigning, i, toJString(env, *curr));
+ });
+
+ count = LPAC_JNI_NULL_TERM_LIST_COUNT(info->euiccCiPKIdListForVerification, curr);
+ euiccCiPKIdListForVerification = (*env)->NewObjectArray(env, count, string_class, NULL);
+ LPAC_JNI_NULL_TERM_LIST_FOREACH(info->euiccCiPKIdListForVerification, curr, {
+ (*env)->SetObjectArrayElement(env, euiccCiPKIdListForVerification, i, toJString(env, *curr));
+ });
+
ret = (*env)->NewObject(env, euicc_info2_class, euicc_info2_constructor,
profile_version, euicc_firmware_version,
global_platform_version,
sas_accreditation_number, pp_version,
info->extCardResource.freeNonVolatileMemory,
- info->extCardResource.freeVolatileMemory);
+ info->extCardResource.freeVolatileMemory,
+ euiccCiPKIdListForSigning,
+ euiccCiPKIdListForVerification);
out:
(*env)->DeleteLocalRef(env, profile_version);
diff --git a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
index e0e2109..e60c465 100644
--- a/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
+++ b/libs/lpac-jni/src/main/jni/lpac-jni/lpac-jni.h
@@ -28,6 +28,21 @@ struct lpac_jni_ctx {
#define LPAC_JNI_LINKED_LIST_COUNT(list, curr) \
(__LPAC_JNI_LINKED_LIST_FOREACH(list, curr, {}, i))
+#define __LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body, after) { \
+ int i = 0; \
+ curr = list; \
+ while (*curr != NULL) { \
+ body; \
+ curr++; \
+ i++; \
+ }; \
+ after; \
+}
+#define LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body) \
+ __LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, body, {})
+#define LPAC_JNI_NULL_TERM_LIST_COUNT(list, curr) \
+ (__LPAC_JNI_NULL_TERM_LIST_FOREACH(list, curr, {}, i))
+
extern JavaVM *jvm;
extern jclass string_class;