PKI: Chains, Trust Anchors, and Pinning on Mobile
What this domain covers
PKI questions on eMAPT focus on how a mobile OS decides to trust a server certificate and what that means for interception testing. You are expected to trace a chain, name the fields that decide the outcome, and explain why installing a proxy CA frequently fails.
Chain validation rules
- A certificate is only as trusted as the path from leaf to a trust anchor in the platform store. Every link's signature, validity window, and issuer/subject match must verify.
- X.509 v3 extensions drive the decision:
basicConstraints CA:TRUE(withpathLenConstraint) for issuers,keyUsage keyCertSign, andextendedKeyUsage serverAuthfor TLS servers. - Hostname checking uses
subjectAltName, notcommonName. Wildcards match one leftmost label only (*.example.comcoversapi.example.com, nota.b.example.com). - Revocation uses CRL or OCSP when the client is configured for it; mobile stacks commonly soft-fail, so a revoked certificate may still be accepted.
Platform behaviour
Android 7+ apps with targetSdk 24 or higher do not trust user-installed CAs unless a network security config explicitly opts in with <certificates src="user"/>. iOS relies on ATS plus the system trust store; a user-installed root must also be enabled for full trust in Settings, and pinning can override trust entirely.
Worked example
An app calls https://api.example.com. The server sends a leaf with SAN api.example.com and an intermediate; the root is already in the device store. Validation passes signature, dates, EKU, and SAN. The app additionally pins the leaf's SPKI SHA-256. You install your proxy CA, so the chain now validates against your root-but the pin comparison fails and the handshake aborts. The correct conclusion is pinning, not a broken chain: the fix is to hook or patch the pinning check, not to reinstall the CA. If instead the app rejected your root before any pin check, the cause would be the Android trust-store rule above.
Traps that cost marks
- Assuming a user CA is honoured on modern Android.
- Checking CN instead of SAN.
- Ignoring EKU or
basicConstraintswhen building a test chain. - Pinning the leaf certificate when rotation is planned; SPKI pinning with backup pins is the safer design.
- Treating "signed by a trusted root" as the end of validation when hostname and EKU still apply.
TLS: Handshake Anatomy and Mobile Trust Decisions
Scope
TLS questions test whether you can read a handshake, identify what actually provides confidentiality and forward secrecy, and explain mobile trust failures in terms of platform APIs rather than guesswork.
Handshake and cipher suites
- TLS 1.2 flow: ClientHello (versions, cipher suites, SNI, ALPN) → ServerHello, Certificate, ServerKeyExchange (ECDHE parameters), ServerHelloDone; then key exchange, ChangeCipherSpec, Finished.
- TLS 1.3 reduces this to a single round trip, removes RSA key transport, CBC modes, and static DH, and encrypts the server certificate after ServerHello. Only (EC)DHE and PSK-based establishment remain.
- A cipher suite name encodes key exchange, authentication, bulk cipher, and hash, for example
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Forward secrecy comes from ephemeral ECDHE keys, not from the bulk cipher. - Resumption uses session IDs or tickets in 1.2 and PSK in 1.3. Early (0-RTT) data is replayable and should not carry state-changing requests.
Mobile trust controls
Android offers the network security config, custom TrustManager implementations, and OkHttp CertificatePinner. iOS offers ATS keys such as NSAllowsArbitraryLoads and NSExceptionDomains, plus URLSession authentication challenges that can override default validation.
Worked example
A targetSdk 29 app is proxied with a user-installed Burp CA. Every HTTPS request fails with a chain error. Reasoning: targetSdk 24 or higher excludes user CAs unless the config adds <certificates src="user"/>. You repackage the APK with a permissive config and most traffic flows, but one host still fails. Because a global trust-all patch would have cleared that host too, the remaining failure points to a pin on that specific host rather than to trust-store policy.
Traps that cost marks
- Trusting user CAs by default on Android 7 and later.
- Equating "TLS 1.3" with "strong"-1.3 still permits AES-128.
- Missing a hostname verifier that returns true, which accepts any certificate name.
- Blaming pinning before checking network security config or ATS exceptions.
- Forgetting that chain validation and hostname validation are two separate checks that fail differently.
Applied Cryptography: Spotting Broken Crypto in Mobile Apps
Scope
Applied cryptography questions ask you to recognise broken primitives in decompiled code and to recommend the correct algorithm, mode, and key storage for a mobile app. Answers are judged on mode choice, key management, and randomness sources.
Rules that decide answers
- Confidentiality with integrity means AEAD: AES-GCM or ChaCha20-Poly1305. CBC alone is malleable and needs encrypt-then-MAC; ECB is deterministic and leaks plaintext structure.
- GCM nonces must be unique per key. Reuse allows recovery of the authentication key, so a static IV in source is a finding.
- Passwords go through a slow KDF-PBKDF2 with high iteration counts, scrypt, or Argon2-with a per-user salt. A bare SHA-256 is fast and unsuitable.
- HMAC-SHA-256 authenticates messages; a plain hash is not a MAC.
- RSA needs OAEP padding for new designs, not PKCS#1 v1.5. ECDSA requires a unique nonce per signature.
- Randomness must come from
SecureRandomorSecRandomCopyBytes, neverjava.util.RandomorMath.random. - Keys belong in Android Keystore or iOS Keychain, ideally hardware-backed and non-exportable.
Worked example
Decompiling an APK reveals Cipher.getInstance("AES/ECB/PKCS5Padding") with the key read from a string constant. Reasoning: ECB encrypts identical plaintext blocks identically, so a captured token or database file reveals patterns and block boundaries; and because the key ships inside the DEX, anyone with the APK can decrypt everything. That is two findings-mode and key management-not one. The fix is AES-GCM with a fresh random 96-bit nonce per message and a Keystore-generated, non-exportable key.
Traps that cost marks
- Calling Base64 encoding "encryption".
- Assuming string obfuscation protects a hardcoded key from static analysis.
- Choosing SHA-256 for password storage because it is "strong"-it is simply fast.
- Believing HTTPS protects data at rest in SharedPreferences, SQLite, or plists.
- Reusing an IV because it looks random, or deriving one from a timestamp.
- Trusting custom or home-grown crypto instead of standard constructions.