-
Notifications
You must be signed in to change notification settings - Fork 502
Description
[iOS SCEP] “The Certification Authority does not have the required capability” (iOS 18, iPhone 16)
When installing a SCEP profile on iOS, I get:
Profile Installation Failed → The Certification Authority does not have the required capability.
However, GetCACaps appears to include the expected capabilities (notably SubjectAltName).
Environment
CA: smallstep/step-ca:latest
Edge: nginx:1.27-alpine (Docker Compose)
SCEP provisioner: my_scep
Edge host: :9001
Device: iPhone 16 (small), iOS 18
Expected
SCEP profile (RSA 2048, KeyUsage=5, with SAN) installs successfully and the device identity certificate is issued.
ERROR
Profile install fails with:
The Certification Authority does not have the required capability.
Minimal Repro Steps
Start CA: docker-compose up -d step-ca
Generate edge TLS + SCEP provisioner + profiles (Challenge embedded):
scripts/make_profiles.sh my_scep 9001
On iOS: install CA-only profile and set Full Trust.
Install SCEP-only (or All-in-one) profile → error above.
Diagnostics / Observations
GetCACaps from the same NGINX endpoint (both classic and versioned path) claims to include SubjectAltName.
The CA root is installed on the device and set to Full Trust.
Potential formatting/header issue: GetCACaps body looks comma-separated, appears duplicated sometimes, and ends with a trailing '%'. iOS may expect newline-separated tokens, strict Content-Type, and no trailing characters.
Logs (sanitized; domain redacted)
step-ca access logs:
time="2025-09-23T18:36:17Z" level=info duration="29.178µs" duration-ns=29178 fields.time="2025-09-23T18:36:17Z" method=GET name=ca path=/health protocol=HTTP/2.0 referer= remote-address=172.18.0.1 request-id=b845be99-8ce1-4269-bbef-c1fdf8847c1d size=16 status=200 user-agent=curl/7.81.0 user-id=
time="2025-09-23T18:36:17Z" level=info duration="18.726µs" duration-ns=18726 fields.time="2025-09-23T18:36:17Z" method=GET name=ca path="/scep/my_scep?operation=GetCACaps" protocol=HTTP/1.1 referer= remote-address=172.18.0.3 request-id=bf6e9f73-4bd2-413d-a6a5-97836ebb71eb size=97 status=200 user-agent=curl/7.81.0 user-id=
time="2025-09-23T18:36:17Z" level=info duration="21.103µs" duration-ns=21103 fields.time="2025-09-23T18:36:17Z" method=GET name=ca path="/scep/my_scep?operation=GetCACaps" protocol=HTTP/1.1 referer= remote-address=172.18.0.3 request-id=330defb6-a1df-4213-ae9b-d120d015106d size=97 status=200 user-agent=curl/7.81.0 user-id=
curl -sk "https://:9001/scep/my_scep?operation=GetCACaps"
curl -sk "https://:9001/scep/v123/my_scep?operation=GetCACaps"
SCEPStandard,POSTPKIOperation,SHA-1,SHA-256,SHA-512,DES3,AES,Renewal,GetNextCACert,SubjectAltNameSCEPStandard,POSTPKIOperation,SHA-1,SHA-256,SHA-512,DES3,AES,Renewal,GetNextCACert,SubjectAltName
SCEPStandard,POSTPKIOperation,SHA-1,SHA-256,SHA-512,DES3,AES,Renewal,GetNextCACert,SubjectAltName
Does iOS require GetCACaps to be newline-separated (one token per line) with no trailing characters (e.g., '%') and a strict Content-Type: text/plain?
Could the duplicated, comma-separated list (and trailing '%') cause iOS to conclude the CA lacks the required capability even though SubjectAltName is present?
Are there known iOS constraints on exact casing or ordering of capabilities, or on response headers/redirect behavior for GetCACaps, GetCACert, or PKIOperation?
Safari's 'Not Secure' warning is expected for a private/enterprise CA. The CA root is installed and marked as Fully Trusted on the device.