refactor: Trust SM-DP+ TLS certs based on euiccCiPKIdListForVerification
All checks were successful
/ build-debug (push) Successful in 4m39s
All checks were successful
/ build-debug (push) Successful in 4m39s
Unfortunately, because there is no way to access the certificate itself from the eUICC, we have to hard-code known & supported certificates still. However, this approach makes sure that only those certificates listed by the eUICC are trusted during their SM-DP+ sessions. Were these added directly as part of the Android security config, then all certificates would be blindly trusted for all SM-DP+ sessions (and even normal TLS connections if the app were to make them). As a result we can now trust more known certificates, including GSMA Test CIs. These are hard-coded as a hash map.
This commit is contained in:
parent
252000660a
commit
c033ef5ba9
|
@ -6,8 +6,7 @@
|
|||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<application>
|
||||
<activity
|
||||
android:name="im.angry.openeuicc.ui.SettingsActivity"
|
||||
android:label="@string/pref_settings" />
|
||||
|
|
|
@ -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-----
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<trust-anchors>
|
||||
<certificates src="@raw/symantec_gsma_rspv2_root_ci1"/>
|
||||
<certificates src="system"/>
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
|
@ -9,4 +9,6 @@ data class EuiccInfo2(
|
|||
val ppVersion: String,
|
||||
val freeNvram: Int,
|
||||
val freeRam: Int,
|
||||
val euiccCiPKIdListForSigning: Array<String>,
|
||||
val euiccCiPKIdListForVerification: Array<String>,
|
||||
)
|
|
@ -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<String>): 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<String>)
|
||||
}
|
|
@ -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<TrustManager>
|
||||
|
||||
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<String>) {
|
||||
val trustManagerFactory = TrustManagerFactory.getInstance("PKIX").apply {
|
||||
init(keyIdToKeystore(pkids))
|
||||
}
|
||||
trustManagers = trustManagerFactory.trustManagers
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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<String>): 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: <https://euicc-manual.septs.app/docs/pki/ci/>
|
||||
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()
|
||||
)
|
|
@ -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, "<init>", "(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, "<init>", "(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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue