import Foundation import Security import Testing @testable import ClientTLS // B4 · Pins the hand-written PKCS#10 encoder against an EXTERNAL known-good // vector (OpenSSL) plus the two boundary behaviours the structural tests in // CertificateSigningRequestTests don't reach: a signer that hands back a // non-X9.63 public key, and a subject long enough to need a long-form DER // length. `verifyCsrPoPEc` re-serializes `CertificationRequestInfo` server-side // before checking the PoP, so a single byte of drift breaks enrollment. @Test("CertificationRequestInfo is byte-identical to OpenSSL's for the same key + subject") func csrRequestInfoMatchesOpenSSLVector() throws { // Arrange — the exact key OpenSSL used for the embedded vector. let signer = try KnownGoodCSR.fixedKey() // Act let der = try CertificateSigningRequest.der( subjectCommonName: KnownGoodCSR.subjectCommonName, signer: signer ) // Assert — the signed half must match OpenSSL byte for byte. let parsed = try #require(parseCSR(der)) #expect(parsed.certificationRequestInfoDER == KnownGoodCSR.certificationRequestInfoDER) } @Test("the vector's self-signature verifies over the exact CertificationRequestInfo bytes") func csrVectorSignatureVerifies() throws { // Arrange let signer = try KnownGoodCSR.fixedKey() let der = try CertificateSigningRequest.der( subjectCommonName: KnownGoodCSR.subjectCommonName, signer: signer ) let bytes = [UInt8](der) let outer = try #require(TestDER.read(bytes, at: 0)) let parts = TestDER.children(bytes, outer) let signature = Data(bytes[(parts[2].valueStart + 1)..? let verified = SecKeyVerifySignature( publicKey, .ecdsaSignatureMessageX962SHA256, KnownGoodCSR.certificationRequestInfoDER as CFData, signature as CFData, &error ) // Assert #expect(verified, "\(String(describing: error?.takeRetainedValue()))") } @Test("a signer whose public key is not a 65-byte uncompressed point is rejected") func csrRejectsNonX963PublicKey() { // Arrange — a compressed (33-byte) point: valid EC, wrong encoding for SPKI. let compressed = Data([0x02] + [UInt8](repeating: 0x11, count: 32)) let signer = StubSigner(publicKey: compressed) // Act / Assert — must fail BEFORE signing (no PoP over a bogus SPKI). #expect(throws: CertificateSigningRequest.CSRError.invalidPublicKey) { _ = try CertificateSigningRequest.der(subjectCommonName: "device", signer: signer) } #expect(signer.signCallCount == 0) } @Test("a subject long enough to need a 2-byte DER length still round-trips") func csrLongSubjectUsesLongFormLength() throws { // Arrange — 300 chars pushes CertificationRequestInfo past 255 bytes, so its // length must be encoded long-form as 0x82 . let longCommonName = String(repeating: "d", count: 300) let signer = try KnownGoodCSR.fixedKey() // Act let der = try CertificateSigningRequest.der( subjectCommonName: longCommonName, signer: signer ) // Assert let parsed = try #require(parseCSR(der)) #expect(parsed.subjectCommonName == longCommonName) let infoBytes = [UInt8](parsed.certificationRequestInfoDER) #expect(infoBytes[1] == 0x82) // long form, two length bytes let declaredLength = Int(infoBytes[2]) << 8 | Int(infoBytes[3]) #expect(declaredLength == infoBytes.count - 4) // minimal + accurate } // MARK: - Helpers /// A `P256HardwareKey` that returns a caller-chosen public key and records /// whether it was ever asked to sign. private final class StubSigner: P256HardwareKey, @unchecked Sendable { private let publicKey: Data private let lock = NSLock() private var signCalls = 0 init(publicKey: Data) { self.publicKey = publicKey } var signCallCount: Int { lock.withLock { signCalls } } func publicKeyX963() throws -> Data { publicKey } func sign(_ message: Data) throws -> Data { lock.withLock { signCalls += 1 } return Data([0x30, 0x00]) } }