[ios] kCFStreamErrorDomainSSL error -9806

Error Log

Error Domain=kCFStreamErrorDomainSSL Code=-9806 “The operation couldn’t be completed. (kCFStreamErrorDomainSSL error -9806.)” UserInfo=0x7f7fc9c4bf10 {NSLocalizedRecoverySuggestion=Error code definition can be found in Apple’s SecureTransport.h

Environment

reliance telecom (India very bad network)

I was able to see SSL packet only. (normal case : TLS 1.2 packet should be occurred )

Cause

GCDAsyncSocket errSSLClosedAbort

- (OSStatus)sslWriteWithBuffer:(const void *)buffer length:(size_t *)bufferLength

- (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength

- (void)doReadData
    if (result == errSSLClosedGraceful || result == errSSLClosedAbort)
    {
        // We've reached the end of the stream.
        // Handle this the same way we would an EOF from the socket.
        socketEOF = YES;
        sslErrCode = result;
    }
// 
- (void)doReadEOF
        if ((flags & kStartingReadTLS) || (flags & kStartingWriteTLS))
	{
		// We received an EOF during or prior to startTLS.
		// The SSL/TLS handshake is now impossible, so this is an unrecoverable situation.
		
		shouldDisconnect = YES;
		
		if ([self usingSecureTransportForTLS])
		{
			error = [self sslError:errSSLClosedAbort];
		}
	}

Hypothesis

1. SSL TLS connection (handshake) may be unstable.

2. Server Client Protocol Error.
-> always failed

3. Firewall (TLS -> SSL?)

4. Heavy TLS hand-shake
(remove Server Key Exchange packet, client embed server enc_key)

5. Server did not support TLS 1.2 in past days

Solution

I have tried to find a solution

Reference

GCDAsyncSocket
TLS handshake
TLS Detail(MS)
SSL and TLS (IBM Knowledge Center)
SecureTransport.h
/*************************************************
 *** OSStatus values unique to SecureTransport ***
 *************************************************/

/*
    Note: the comments that appear after these errors are used to create SecErrorMessages.strings.
    The comments must not be multi-line, and should be in a form meaningful to an end user. If
    a different or additional comment is needed, it can be put in the header doc format, or on a
    line that does not start with errZZZ.
*/

enum {
	errSSLProtocol				= -9800,	/* SSL protocol error */
	errSSLNegotiation			= -9801,	/* Cipher Suite negotiation failure */
	errSSLFatalAlert			= -9802,	/* Fatal alert */
	errSSLWouldBlock			= -9803,	/* I/O would block (not fatal) */
    errSSLSessionNotFound 		= -9804,	/* attempt to restore an unknown session */
    errSSLClosedGraceful 		= -9805,	/* connection closed gracefully */
    errSSLClosedAbort 			= -9806,	/* connection closed via error */
    errSSLXCertChainInvalid 	= -9807,	/* invalid certificate chain */
    errSSLBadCert				= -9808,	/* bad certificate format */
	errSSLCrypto				= -9809,	/* underlying cryptographic error */
	errSSLInternal				= -9810,	/* Internal error */
	errSSLModuleAttach			= -9811,	/* module attach failure */
    errSSLUnknownRootCert		= -9812,	/* valid cert chain, untrusted root */
    errSSLNoRootCert			= -9813,	/* cert chain not verified by root */
	errSSLCertExpired			= -9814,	/* chain had an expired cert */
	errSSLCertNotYetValid		= -9815,	/* chain had a cert not yet valid */
	errSSLClosedNoNotify		= -9816,	/* server closed session with no notification */
	errSSLBufferOverflow		= -9817,	/* insufficient buffer provided */
	errSSLBadCipherSuite		= -9818,	/* bad SSLCipherSuite */
	
	/* fatal errors detected by peer */
	errSSLPeerUnexpectedMsg		= -9819,	/* unexpected message received */
	errSSLPeerBadRecordMac		= -9820,	/* bad MAC */
	errSSLPeerDecryptionFail	= -9821,	/* decryption failed */
	errSSLPeerRecordOverflow	= -9822,	/* record overflow */
	errSSLPeerDecompressFail	= -9823,	/* decompression failure */
	errSSLPeerHandshakeFail		= -9824,	/* handshake failure */
	errSSLPeerBadCert			= -9825,	/* misc. bad certificate */
	errSSLPeerUnsupportedCert	= -9826,	/* bad unsupported cert format */
	errSSLPeerCertRevoked		= -9827,	/* certificate revoked */
	errSSLPeerCertExpired		= -9828,	/* certificate expired */
	errSSLPeerCertUnknown		= -9829,	/* unknown certificate */
	errSSLIllegalParam			= -9830,	/* illegal parameter */
	errSSLPeerUnknownCA 		= -9831,	/* unknown Cert Authority */
	errSSLPeerAccessDenied		= -9832,	/* access denied */
	errSSLPeerDecodeError		= -9833,	/* decoding error */
	errSSLPeerDecryptError		= -9834,	/* decryption error */
	errSSLPeerExportRestriction	= -9835,	/* export restriction */
	errSSLPeerProtocolVersion	= -9836,	/* bad protocol version */
	errSSLPeerInsufficientSecurity = -9837,	/* insufficient security */
	errSSLPeerInternalError		= -9838,	/* internal error */
	errSSLPeerUserCancelled		= -9839,	/* user canceled */
	errSSLPeerNoRenegotiation	= -9840,	/* no renegotiation allowed */

	/* non-fatal result codes */
	errSSLServerAuthCompleted	= -9841,	/* server cert is valid, or was ignored if verification disabled */
	errSSLClientCertRequested	= -9842,	/* server has requested a client cert */

	/* more errors detected by us */
	errSSLHostNameMismatch		= -9843,	/* peer host name mismatch */
	errSSLConnectionRefused		= -9844,	/* peer dropped connection before responding */
	errSSLDecryptionFail		= -9845,	/* decryption failure */
	errSSLBadRecordMac			= -9846,	/* bad MAC */
	errSSLRecordOverflow		= -9847,	/* record overflow */
	errSSLBadConfiguration		= -9848,	/* configuration error */
	errSSLLast					= -9849		/* end of range, to be deleted */
};

[생각의 정리] 빈 수레

회사 동료와 선배들이 작성한 코드를 보면
내가 무엇을 모르는지 무엇이 부족한지 느낀다.

그들은 본인들이 잘 한다고 생각 하지 않는다. (프라이드는 있지만 겸손하다)
약을 팔지 않는다. 실용적이다.

하지만 입만 요란한 사람은
문제가 생겼을 때 한발 뒤로 물러난다.

그리고 문제가 있을 때
불만과 불평만 할 뿐 문제를 적극적으로 해결하려고 하지 않는다.

제대로 공부 하지 않는다…
자신이 아는 것에 대해서만 앵무세 처럼 반복 할 뿐이다

게다가 본인이 어리석은지 인지하지 못한다…
자존심은 강하고 남의 조언을 듣지 않는다.

남의 말을 옮기는 것은 누구나 할 수 있다.
Deep learning을 해야 나만의 철학과 도메인에 대한 내공이 생긴다.

나도 빈 수레였던 시절이 있었던 것 같다.