Hey there,
Setup:
I am writing an app for iOS 7 that implements a Client-Server architecture (one
iPhone acts as server the other iPhone acts as client). Therefore I am using
CFStream and SSL/TLS to make the connection suitable secure.
Problem:
Now the connection as well as SSL/TLS are working great but now I want to
specify the ciphers that are used by SSL/TLS and here I get stuck. The
procedure is as follows:
I get the ssl context from the stream before it opens on both server- and
client side
I read all the enabled ciphers
I intersect the enabled ciphers with those I want to have in the end
Then I set the enabled ciphers to be exactly that intersection (which is
non-zero)
Errors?
Strange is, that I do not get any return values that could indicate a coding
error. The only thing that happens is, that I get a stream error and of course
no connection at all.
Code:
Here is my code. I do set the ssl properties before the stream opens on both
client- (Before sending connection request by opening the stream) and server
side (handleConnect).
——————8<——————————
- (bool)setSSLpropertiesForStreamsIn:(NSInputStream*)readStream
andOut:(NSOutputStream*)writeStream
withServerRole:(BOOL)isServer
{
if (!_ssl) {
return YES;
}
// Setting streams to use TLS
[readStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
[writeStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL
forKey:NSStreamSocketSecurityLevelKey];
// Get our identity
SecIdentityRef identityRef;
SecCertificateRef certificate;
BOOL status = [self getP2PConnectionCertificate:&certificate
andIdentity:&identityRef];
if (!status) {
NSLog(@"Unable to obtain certificate and identity!");
return NO;
}
// Setting properties. Atm every certificate is accepted and no hostname
will be checked
NSArray *certificates = [NSArray arrayWithObjects:(__bridge
id)identityRef,(__bridge id)certificate, nil];
NSDictionary *settings = @{(NSString
*)kCFStreamPropertyShouldCloseNativeSocket: [NSNumber
numberWithBool:YES],
(NSString
*)kCFStreamSSLValidatesCertificateChain: [NSNumber
numberWithBool:NO],
(NSString
*)kCFStreamSSLAllowsExpiredCertificates: [NSNumber
numberWithBool:YES],
(NSString *)kCFStreamSSLAllowsExpiredRoots:
[NSNumber numberWithBool:YES],
(NSString *)kCFStreamSSLAllowsAnyRoot:
[NSNumber numberWithBool:YES],
(NSString *)kCFStreamSSLCertificates:
certificates,
(NSString *)kCFStreamSSLIsServer:
[NSNumber numberWithBool:isServer],
(NSString *)kCFStreamSSLLevel:
(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL
};
// Apply properties.
bool success1 = CFReadStreamSetProperty ((CFReadStreamRef) readStream,
kCFStreamPropertySSLSettings, (CFTypeRef)settings);
bool success2 = CFWriteStreamSetProperty((CFWriteStreamRef) writeStream,
kCFStreamPropertySSLSettings, (CFTypeRef)settings);
// Now change the ciphers to those that we want
// Get SSLContext to access the ssl properties
CFDataRef socketSSLContextData = (CFDataRef)
CFReadStreamCopyProperty((CFReadStreamRef) readStream,
kCFStreamPropertySocketSSLContext);
SSLContextRef sslContext;
CFDataGetBytes(socketSSLContextData, CFRangeMake(0, sizeof(SSLContextRef)),
(UInt8*)&sslContext);
// Get enabled ciphers
size_t numCiphers = 0;
SSLGetNumberEnabledCiphers(sslContext, &numCiphers);
SSLCipherSuite *enabledCiphers = (SSLCipherSuite
*)malloc(sizeof(SSLCipherSuite) * numCiphers);
SSLGetEnabledCiphers(sslContext, enabledCiphers, &numCiphers);
// Converting to NSSet for better performance
SSLCipherSuite *targetCiphers[41] = {
TLS_ECDH_ECDSA_WITH_NULL_SHA ,
TLS_ECDH_ECDSA_WITH_RC4_128_SHA ,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA ,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA ,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA ,
TLS_ECDHE_ECDSA_WITH_NULL_SHA ,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA ,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA ,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ,
TLS_ECDH_RSA_WITH_NULL_SHA ,
TLS_ECDH_RSA_WITH_RC4_128_SHA ,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA ,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA ,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA ,
TLS_ECDHE_RSA_WITH_NULL_SHA ,
TLS_ECDHE_RSA_WITH_RC4_128_SHA ,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA ,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA ,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ,
TLS_ECDH_anon_WITH_NULL_SHA ,
TLS_ECDH_anon_WITH_RC4_128_SHA ,
TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA ,
TLS_ECDH_anon_WITH_AES_128_CBC_SHA ,
TLS_ECDH_anon_WITH_AES_256_CBC_SHA ,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 ,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 ,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 ,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 ,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 ,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 ,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 ,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 ,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 ,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 ,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 ,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 };
NSMutableSet *setOfTargetCiphers = [[NSMutableSet alloc] init];
for (int i = 0; i < 41; i++)
[setOfTargetCiphers addObject:[NSNumber
numberWithInt:targetCiphers[i]]];
NSMutableSet *setOfEnabledCiphers = [[NSMutableSet alloc] init];
for (int i = 0; i < numCiphers; i++)
[setOfEnabledCiphers addObject:[NSNumber
numberWithInt:enabledCiphers[i]]];
// Compute intersection set to get possible values for the connection
[setOfEnabledCiphers intersectSet:setOfTargetCiphers]; // Removes from the
set of enabled ciphers those that are not in the set of target ciphers
// Set the remaining setOfEnabledCiphers to be the only enabled ciphers in
the ssl connection
int numberOfLeftCiphers = [setOfEnabledCiphers count];
SSLCipherSuite *ciphers = (SSLCipherSuite
*)malloc(numberOfLeftCiphers * sizeof(SSLCipherSuite));
for (NSNumber* numberOfCipher in setOfEnabledCiphers) {
ciphers[numberOfLeftCiphers-1] = [numberOfCipher intValue];
numberOfLeftCiphers -= 1;
}
OSStatus osStatus = SSLSetEnabledCiphers(sslContext, ciphers, 1);
if (osStatus != noErr)
NSLog(@"Unable to set the accepted chiphers to the SSL context!");
// Check for success
if ((success1 & success2) && !_invalid) {
NSLog(@"SSL/TLS settings for streams are set.");
NSLog(@"SSL/TLS settings were set for server: %i", isServer);
}
return (success1 & success2);
}
——————>8——————————
Can anybody help me here please? Any help is very appreciated.
Kind regards,
Bastian
signature.asc
Description: Message signed with OpenPGP using GPGMail
_______________________________________________ Cocoa-dev mailing list ([email protected]) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to [email protected]
