Hardware-backed (StrongBox/TEE) key + PKCS#10 CSR + /device/enroll client in
:api-client, presented via the existing X509KeyManager; renew body {csr}-only;
DeviceKeyProvider seam makes the orchestration JVM-testable. api-client tests +
koverVerify 80% gate pass.
77 lines
3.9 KiB
Plaintext
77 lines
3.9 KiB
Plaintext
// ─────────────────────────────────────────────────────────────────────────────
|
|
// :client-tls-android — the FRAMEWORK half of ClientTLS (plan A11).
|
|
//
|
|
// The ONE key home is AndroidKeyStore: a `.p12` is PARSED via the pure :client-tls
|
|
// half (KeyStore("PKCS12"), import-parse only), then the private key is imported
|
|
// NON-EXPORTABLE into AndroidKeyStore. Tink AEAD (AndroidKeystore master key)
|
|
// encrypts ONLY the cert-chain + metadata blob at rest — never the private key,
|
|
// never the .p12, never the passphrase. A re-reading X509KeyManager presents the
|
|
// AndroidKeyStore key/chain PER handshake so a mid-run import/rotation is used on
|
|
// the NEXT handshake with no relaunch (R4); rotation calls connectionPool.evictAll()
|
|
// on the shared OkHttpClient so pooled/resumed connections drop the old identity.
|
|
//
|
|
// Instrumented tests use the real AndroidKeyStore provider (NOT Robolectric — plan
|
|
// §7), so they only COMPILE here (no emulator) and RUN during device QA.
|
|
//
|
|
// AGP 9 has BUILT-IN Kotlin — apply ONLY com.android.library (adding kotlin.android
|
|
// errors). This module must NOT depend on :transport-okhttp; the :app wiring (A15)
|
|
// bridges IdentityRepository → :transport-okhttp's ClientIdentityProvider seam.
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
plugins {
|
|
id("com.android.library")
|
|
}
|
|
|
|
android {
|
|
namespace = "wang.yaojia.webterm.tlsandroid"
|
|
compileSdk = 36
|
|
defaultConfig {
|
|
minSdk = 29
|
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
}
|
|
testOptions {
|
|
unitTests {
|
|
// The device-enroll orchestration commit logs via android.util.Log — let the JVM unit
|
|
// tests stub it (return 0) instead of throwing "not mocked". The security-critical paths
|
|
// (commit sequencing, error handling) run on the JVM with a software key double.
|
|
isReturnDefaultValues = true
|
|
}
|
|
}
|
|
}
|
|
|
|
kotlin {
|
|
jvmToolchain(17)
|
|
}
|
|
|
|
// JVM (local) unit tests use JUnit 5 (matching the pure modules); AGP's testDebug/ReleaseUnitTest
|
|
// tasks are `Test` tasks, so opt them into the JUnit Platform.
|
|
tasks.withType<Test>().configureEach {
|
|
useJUnitPlatform()
|
|
}
|
|
|
|
dependencies {
|
|
// Pure half: Pkcs12Parse (parse+validate), ClientKeyManagerLogic (alias truth table),
|
|
// CertificateSummary(Reader). `api` so :app sees the shared ParsedClientIdentity/summary types.
|
|
// (No :wire-protocol dep — nothing in src/main references wang.yaojia.webterm.wire*.)
|
|
api(project(":client-tls"))
|
|
// B4 device-enroll: the pure CSR encoder + login/enroll/renew client + HttpTransport seam live in
|
|
// :api-client (JVM-unit-tested); the framework HardwareBackedKey/DeviceEnroller drive them.
|
|
implementation(project(":api-client"))
|
|
implementation(libs.tink.android)
|
|
implementation(libs.okhttp)
|
|
// Mutex serializes the two-store rotation commit (single-commit invariant, A11).
|
|
implementation(libs.kotlinx.coroutines.core)
|
|
|
|
// Instrumented (androidTest) — compile here, run on a device (real AndroidKeyStore).
|
|
androidTestImplementation(libs.androidx.test.ext.junit)
|
|
androidTestImplementation(libs.androidx.test.core)
|
|
androidTestImplementation(libs.androidx.test.runner)
|
|
androidTestImplementation(libs.kotlinx.coroutines.core) // runBlocking for suspend mutators
|
|
|
|
// Local JVM unit tests (src/test) — the DeviceEnroller enroll/commit orchestration driven with a
|
|
// software P-256 key double + the shared FakeHttpTransport (no emulator, no AndroidKeyStore).
|
|
testImplementation(project(":test-support"))
|
|
testImplementation(libs.bundles.unit.test)
|
|
testRuntimeOnly(libs.junit.platform.launcher)
|
|
}
|