iOS: SSL Handshake over bluetooth - ios

I'm trying to do a SSL Handshake over Bluetooth. I've been trying to use the Secure Transport API (https://developer.apple.com/documentation/security/secure_transport) to achieve this:
func sslHandshake() {
guard let sslContext = SSLCreateContext(kCFAllocatorDefault, .clientSide, .streamType) else {
return
}
SSLSetIOFuncs(sslContext, { (connection, data, dataLength) -> OSStatus in
//Read
return noErr
}) { (connection, data, dataLength) -> OSStatus in
//Write
writeToPeripheral(data)
return noErr
}
SSLHandshake(sslContext)
}
I've been able to write the client hello data to the bluetooth peripheral without a problem. But before I can write the server hello that I get from the peripheral, the SSL handshake fails and when I try doing a SSLRead I get an error -9806.
Is there a way I can avoid the handshake from failing so I can write the server hello, cert and other stuff for the handshake?

Related

GRPC-Swift Send HTTPProtocolVersion from Client

I'm trying GRPC-Swift for Client-Server application.
I'm using GRPC-Swift for both Client and Server
Client is an iPhone application, which I tried with iPhone Simulator.
I followed this link for Client-side streaming RPC.
When I send message to Server from Client, I got the following error message in the console from Server,
error io.grpc.server_channel_call : unable to determine http version
From the Server in the
HTTPProtocolSwitcher.swift
inside the function func channelRead(context: ChannelHandlerContext, data: NIOAny), it is checking for HTTPProtocolVersion, and it is missing.
How to send the HTTPVersion from the Client code?
Update:
Client Code
import GRPC
import NIO
class HTTPClient {
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
private var channel: ClientConnection?
private var client: ChatGuide_ChatGuideClient?
private var clientCall: ClientStreamingCall<ChatGuide_TextMessage, ChatGuide_TextMessage>?
func connect(host: String, port: Int) throws {
let channel = ClientConnection.secure(group: self.group)
.connect(host: host, port: port)
self.channel = channel
self.client = ChatGuide_ChatGuideClient(channel: channel)
}
func disconnect() {
do {
self.clientCall?.sendEnd(promise: nil)
_ = try self.clientCall?.status.wait()
try self.group.syncShutdownGracefully()
} catch let error {
print("\(type(of: self)): Could not shutdown gracefully -", error.localizedDescription)
}
}
func initiateClient() {
let timeAmount = TimeAmount.minutes(1)
let timeLimit = TimeLimit.timeout(timeAmount)
let options = CallOptions(timeLimit: timeLimit)
let call = self.client?.chat(callOptions: options)
call?.response.whenSuccess { (message) in
print("\(type(of: self)): Message from server -", message.text)
}
call?.response.whenFailure { (error) in
print("\(type(of: self)): Response error -", error.localizedDescription)
}
self.clientCall = call
}
func send(text: String) {
if self.clientCall == nil {
self.initiateClient()
}
let message = ChatGuide_TextMessage.with {
$0.text = text
}
self.clientCall?.sendMessage(message, promise: nil)
}
}
Hey Vignesh,
I am currently learning gRPC-Swift myself, so I hope I will be of service and not muck things further.
However, it looks to me that you are not configuring the HTTP/1.x layer in order to transfer Protobuf packets, if you take a look at the HTTP1ToGRPCServerCodec.swift file Here
I think you will have a much clearer idea of how to adjust your code, I am sorry I can't provide more details, however not being too sure myself without further testing and reviewing the codebase.
Best regards and keep me posted if indeed i was helpful,
cheers
From the Server I have initiated insecure Server as,
let server = Server.insecure(group: self.group)
From the Client I have initiated secure ClientConnection as,
let channel = ClientConnection.secure(group: self.group)
And I got this clarification from here
So I made the ClientConnection also insecure as,
let channel = ClientConnection.insecure(group: self.group)
And after this it is working now.

Ktor client IOS and self-signed certificate

I'm using Ktor and Kotlin/native in iOS in an iOS app that accesses an internal dev server. The dev server uses a certificate issued by an internal CA which is not publicly trusted.
When trying to access the server with the following code :
internal suspend fun performHttp(url : String)
{
// URL is a self signed HTTPS: request
val client = HttpClient(Ios)
val response = client.get<String>(url)
println(response)
}
it throws the following exception :
TIC SSL Trust Error [32:0x281956dc0]: 3:0
esri2[470:136341] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)
esri2[470:136341] Task <F3CC4C40-0231-4E58-97F3-F457D5A18BB0>.<1> HTTP load failed (error code: -1202 [3:-9807])
esri2[470:136417] Task <F3CC4C40-0231-4E58-97F3-F457D5A18BB0>.<1> finished with error - code: -1202
esri2[470:136211] Task <F3CC4C40-0231-4E58-97F3-F457D5A18BB0>.<1> load failed with error Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “server1.internal.lan” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
"<cert(0x12b094e00) s: server1.internal.lan i: Internal-Issuing-CA2>",
How do I convince Ktor that it should access this URL, or ignore untrusted certs? Yes, I know that one should not ignore untrusted certs, but this is a lab test.
Ktor iOS engine offers the ability to configure the underlying NSURLSession with the help of IosClientEngineConfig.kt.
With it you can configure (amongst other things) a ChallengeHandler by setting the block for handleChallenge in the config like this:
val client = HttpClient(Ios) {
engine {
handleChallenge(TrustSelfSignedCertificate())
}
}
Then you need to implement a class in Kotlin something like this:
internal data class TrustSelfSignedCertificate internal constructor(
private val validateTrust: Boolean = true
) : ChallengeHandler {
override fun invoke(
session: NSURLSession,
task: NSURLSessionTask,
challenge: NSURLAuthenticationChallenge,
completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Unit
) {
val hostname = challenge.protectionSpace.host
val serverTrust = challenge.protectionSpace.serverTrust
var result: SecTrustResultType = 0u
memScoped {
val nativeResult = alloc<SecTrustResultTypeVar>()
nativeResult.value = result
SecTrustEvaluate(serverTrust!!, nativeResult.ptr)
}
val serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)
val serverCertificateData = SecCertificateCopyData(serverCertificate)
val data = CFDataGetBytePtr(serverCertificateData)
val size = CFDataGetLength(serverCertificateData)
val cert1 = NSData.dataWithBytes(data, size.toULong())
val pathToCert = NSBundle.mainBundle.pathForResource("myOwnCert", "cer")
val localCertificate: NSData = NSData.dataWithContentsOfFile(pathToCert!!)!!
if (localCertificate == cert1) {
completionHandler(
NSURLSessionAuthChallengeUseCredential,
NSURLCredential.create(serverTrust)
)
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, null)
}
}
}
Also, don't forget to put you certificate as a file "myOwnCert.cer" into you iOS project (maybe on the top-level).
NOTE
Ktor with iOS engine does not respect/use NSApptransportSecurity.
The code is based on this answers.
With the help of this blog-post.

Swift - unable to connect to open hotspot

I'm attempting to connect to an open Wi-Fi network using the NEHotspotConfigurationManager without any luck. I've ensured my app has the proper Hotspot Configuration Entitlement and I'm running on a device that is > iOS 11.
Here is the code I'm using to connect to the open network.
// MARK: - Connect to Hotspot
#available(iOS 11.0, *)
func connectToHotspot(completion: #escaping APConnectionStatusHandler) {
let configuration = NEHotspotConfiguration.init(ssid: Constants.hotspotSSID)
configuration.joinOnce = true
NEHotspotConfigurationManager.shared.apply(NEHotspotConfiguration.init()) { connectionError in
if let error = connectionError {
debugPrint("Failed to automatically connect to \(Constants.hotspotSSID)")
debugPrint(error)
completion(false, error.localizedDescription)
}
else {
debugPrint("Automatically connected to \(Constants.hotspotSSID)")
completion(true, nil)
}
}
}
connectionError is populated every time I run this with:
Domain=NEHotspotConfigurationErrorDomain Code=1 "invalid SSID."
I'm unable to find any information on what exactly this error message means. The network shows up in the list of networks for the device I'm using. I'm spelling it correctly and the error message is the same regardless of what SSID string I use.
Any recommendations?
Maybe you shouldn't use Constant.hotspotSSID.
According to the afore-mentioned, I cannot identify what is the 'Constant' or which data type it is.
Here is my thought, try this:
let yourSSID: String = "SSID"
let configuration = NEHotspotConfiguration.init(ssid: yourSSID)
configuration.joinOnce = true
NEHotspotConfigurationManager.shared.apply(configuration) {
(error) in
if error != nil {
print("Connect-> Failure!")
} else {
print("Connect-> Success!")
}
}

iOS App crashes when the service is closed

I've been writing an app with Swift 4 and it communicates with a service via RESTful API.
I have found some helpful code examples and everything works well as the service is running.
However, I could not handle the situation that the service is closed. I have tried try/catch blocks but they did not work well. Please check the code below firstly. It's the part of the communication. Basically it sends an email address to the service and gets a response as an activation code.
URLSession.shared.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in
guard error == nil else {
// Some code
return
}
guard let responseData = data else {
// Some code
return
}
do {
guard let activation_response = try JSONSerialization.jsonObject(with: responseData, options: [])
as? [String: Any] else {
// Some code
return
}
guard let activation_code = activation_response["activation_code"] as? String else {
// Some code
return
}
// Some code, here, if it works fine.
} catch {
// Some code
return
}
}.resume()
When the service is closed, simply it will throw an error such as TCP connection failed. How can I handle it?
The error I get is something like below:
TheApp[4184:399699] TIC TCP Conn Failed [1:0x604000166600]: 1:61 Err(61)
2018-01-02 20:35:04.930874+0300 TheApp[4184:399699] Task <5ED49B16-BFDC-45A5-85F5-095C4FC4D84D>.<1> HTTP load failed (error code: -1004 [1:61])
2018-01-02 20:35:04.934352+0300 TheApp[4184:399698] Task <5ED49B16-BFDC-45A5-85F5-095C4FC4D84D>.<1> finished with error - code: -1004
It throws an exception and I can not catch it. I could not find how to do it. Thank you very much in advance for your help.

How to connect using Socket-IO-Swift on a self-signed certificate?

I use the framework Socket.IO-cleint-swift. Below is the code for creating and connecting:
let socket = SocketIOClient.init(socketURL: URL(string: "https://ts4.steelsea.net:8080")!, config: [.log(true), .forcePolling(true),.secure(true),.selfSigned(true)])
socket.on("connect") {data, ack in
print("socket connected")
}
socket.on("currentAmount") {data, ack in
if let cur = data[0] as? Double {
socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in
socket.emit("update", ["amount": cur + 2.50])
}
ack.with("Got your currentAmount", "dude")
}
}
socket.connect()
Below is an error:
ERROR SocketIOClient: The certificate for this server is invalid. You
might be connecting to a server that is pretending to be
“ts4.steelsea.net” which could put your confidential information at
risk.
I can not figure out how to confirm this certificate to me.
This is connected with insecure connection with the server. And that is why Socket.IO is sending you error.
If you would like to silent this error you can try to drop secure(true) and selfSigned(true) configs.

Resources