private static void TraceCallback(void *userData, UnityTls.unitytls_tlsctx *ctx, byte *traceMessage, size_t traceMessageLen) { var message = Encoding.UTF8.GetString(traceMessage, (int)traceMessageLen); Console.Write(message); }
private static void CertificateCallback(void *userData, UnityTls.unitytls_tlsctx *ctx, byte *cn, size_t cnLen, UnityTls.unitytls_x509name *caList, size_t caListLen, UnityTls.unitytls_x509list_ref *chain, UnityTls.unitytls_key_ref *key, UnityTls.unitytls_errorstate *errorState) { var handle = (GCHandle)(IntPtr)userData; var context = (UnityTlsContext)handle.Target; context.CertificateCallback(ctx, cn, cnLen, caList, caListLen, chain, key, errorState); }
private void CertificateCallback(UnityTls.unitytls_tlsctx *ctx, byte *cn, size_t cnLen, UnityTls.unitytls_x509name *caList, size_t caListLen, UnityTls.unitytls_x509list_ref *chain, UnityTls.unitytls_key_ref *key, UnityTls.unitytls_errorstate *errorState) { try { if (remoteCertificate == null) { throw new TlsException(AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server."); } localClientCertificate = SelectClientCertificate(null); if (localClientCertificate == null) { *chain = new UnityTls.unitytls_x509list_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; *key = new UnityTls.unitytls_key_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; } else { // Need to create native objects for client chain/key. Need to keep them cached. // Make sure we don't have old native objects still around. UnityTls.NativeInterface.unitytls_x509list_free(requestedClientCertChain); UnityTls.NativeInterface.unitytls_key_free(requestedClientKey); ExtractNativeKeyAndChainFromManagedCertificate(localClientCertificate, errorState, out requestedClientCertChain, out requestedClientKey); *chain = UnityTls.NativeInterface.unitytls_x509list_get_ref(requestedClientCertChain, errorState); *key = UnityTls.NativeInterface.unitytls_key_get_ref(requestedClientKey, errorState); } Unity.Debug.CheckAndThrow(*errorState, "Failed to retrieve certificates on request.", AlertDescription.HandshakeFailure); } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); if (lastException == null) { lastException = ex; } } }
public override void Shutdown() { if (Settings != null && Settings.SendCloseNotify) { var err = UnityTls.NativeInterface.unitytls_errorstate_create(); UnityTls.NativeInterface.unitytls_tlsctx_notify_close(tlsContext, &err); } // Destroy native UnityTls objects UnityTls.NativeInterface.unitytls_x509list_free(requestedClientCertChain); UnityTls.NativeInterface.unitytls_key_free(requestedClientKey); UnityTls.NativeInterface.unitytls_tlsctx_free(tlsContext); tlsContext = null; hasContext = false; }
public UnityTlsContext( MobileAuthenticatedStream parent, MonoSslAuthenticationOptions opts) : base(parent, opts) { // Need GCHandle to get a consistent pointer to this instance handle = GCHandle.Alloc(this); var errorState = UnityTls.NativeInterface.unitytls_errorstate_create(); // Map selected protocols as best as we can. var protocolRange = new UnityTls.unitytls_tlsctx_protocolrange { min = UnityTlsConversions.GetMinProtocol(EnabledProtocols), max = UnityTlsConversions.GetMaxProtocol(EnabledProtocols) }; readCallback = ReadCallback; writeCallback = WriteCallback; var callbacks = new UnityTls.unitytls_tlsctx_callbacks { write = writeCallback, read = readCallback, data = (void *)(IntPtr)handle }; if (opts.ServerMode) { ExtractNativeKeyAndChainFromManagedCertificate(opts.ServerCertificate, &errorState, out var serverCerts, out var serverPrivateKey); try { var serverCertsRef = UnityTls.NativeInterface.unitytls_x509list_get_ref(serverCerts, &errorState); var serverKeyRef = UnityTls.NativeInterface.unitytls_key_get_ref(serverPrivateKey, &errorState); Unity.Debug.CheckAndThrow(errorState, "Failed to parse server key/certificate"); tlsContext = UnityTls.NativeInterface.unitytls_tlsctx_create_server(protocolRange, callbacks, serverCertsRef.handle, serverKeyRef.handle, &errorState); if (opts.ClientCertificateRequired) { UnityTls.unitytls_x509list *clientAuthCAList = null; try { clientAuthCAList = UnityTls.NativeInterface.unitytls_x509list_create(&errorState); var clientAuthCAListRef = UnityTls.NativeInterface.unitytls_x509list_get_ref(clientAuthCAList, &errorState); UnityTls.NativeInterface.unitytls_tlsctx_server_require_client_authentication(tlsContext, clientAuthCAListRef, &errorState); } finally { UnityTls.NativeInterface.unitytls_x509list_free(clientAuthCAList); } } } finally { UnityTls.NativeInterface.unitytls_x509list_free(serverCerts); UnityTls.NativeInterface.unitytls_key_free(serverPrivateKey); } } else { var targetHostUtf8 = Encoding.UTF8.GetBytes(opts.TargetHost); fixed(byte *targetHostUtf8Ptr = targetHostUtf8) { tlsContext = UnityTls.NativeInterface.unitytls_tlsctx_create_client(protocolRange, callbacks, targetHostUtf8Ptr, (size_t)targetHostUtf8.Length, &errorState); } certificateCallback = CertificateCallback; UnityTls.NativeInterface.unitytls_tlsctx_set_certificate_callback(tlsContext, certificateCallback, (void *)(IntPtr)handle, &errorState); } verifyCallback = VerifyCallback; UnityTls.NativeInterface.unitytls_tlsctx_set_x509verify_callback(tlsContext, verifyCallback, (void *)(IntPtr)handle, &errorState); Unity.Debug.CheckAndThrow(errorState, "Failed to create UnityTls context"); #pragma warning disable CS0162 // Disable unreachable code warning if (ActivateTracing) { traceCallback = TraceCallback; UnityTls.NativeInterface.unitytls_tlsctx_set_trace_callback(tlsContext, traceCallback, null, &errorState); Unity.Debug.CheckAndThrow(errorState, "Failed to set trace callback"); } #pragma warning restore CS0162 // Reenable unreachable code warning. hasContext = true; }