Q: install in keychain = SecItemAdd() correct? With a class of kSecClassIdentity? And I'd send in a persistent reference, write to disk, and pull it back up to refer to this identity in the future?
Q: Now on to usage... imagine the following scenario: peer A initiates a connection to peer B, both peers have already added the embedded root certificate to their trusted roots.
[inStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
[outStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:NO], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:YES], kCFStreamSSLValidatesCertificateChain,
kCFNull,kCFStreamSSLPeerName,
nil];
CFReadStreamSetProperty((CFReadStreamRef)inStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty((CFWriteStreamRef)outStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
Not sure about kCFStreamSSLPeerName above... I'm ignoring it because there are no valid domains in this case, and my trust is boiling down to the custom root already installed and trusted. A now waits to hear back from B.
Over at B, I'm doing this when the listener gets streams to the requesting end at A:
[inStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
[outStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kCFStreamSSLAllowsExpiredCertificates,
[NSNumber numberWithBool:NO], kCFStreamSSLAllowsAnyRoot,
[NSNumber numberWithBool:YES], kCFStreamSSLValidatesCertificateChain,
kCFNull,kCFStreamSSLPeerName,
[self.session sslIdentityAndCertificates], kCFStreamSSLCertificates,
[NSNumber numberWithBool:YES], kCFStreamSSLIsServer,
nil];
CFReadStreamSetProperty((CFReadStreamRef)inStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
CFWriteStreamSetProperty((CFWriteStreamRef)outStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
The sslIdentityAndCertificates method fetches the identity from the keychain and packages the needed components up in the required array for setting the property on the stream. In the process of negotiating the secure connection, the identity data makes its way over to A...
At A the peer evaluates trust by comparing down to the root certificate, which is trusted internally by the app.
Q: I do *not* override the TLS chain validation, correct? It should all work, if configured as above...
Please let me know if I'm headed off track in any regard, and thanks again for your help!
John