[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations - #117016

Closed
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop
Closed

[OSX][TLS 1.3] Network Framework Native Layer + Interop Classes Implementations#117016
liveans wants to merge 25 commits into
dotnet:mainfrom
liveans:network_framework_integration_native_interop

Conversation

@liveans

Copy link
Copy Markdown
Contributor

This is the initial part of #1979. Follow-up PRs will handle integration with the PAL layer and the SslStream layer.
I'm splitting the changes into multiple PRs to simplify the review process.

And this PR starting to replace #104835 PoC PR, most of the parts are untouched and directly copy from that PR. Mostly restructured stuff into different library + different interop file.

I'm going to iterate feature progressively, once we merge this, I'm going to create the next PR for PAL + SslStream integration layer.

@liveans
liveans requested review from a team, Copilot, rzikm, stephentoub and wfurtJune 25, 2025 11:45
@github-actionsgithub-actionsBot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Initial implementation of a native Network Framework layer and corresponding managed interop code to support TLS 1.3 on macOS.

  • Updated build scripts to link against Apple’s Network framework
  • Added pal_networkframework C API and entrypoints for TLS operations via Network Framework
  • Introduced Interop.Network and Interop.NetworkTls for managed interop and updated project files

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.templateLink CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.templateLink Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.templateLink Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.mImplement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.hDeclare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmakeFind and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.cRegister native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txtAdd and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txtInclude System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targetsAdd Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csprojInclude new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.csManaged interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.csManaged retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.csDefine library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targetsAdd Network framework to NativeAOT Unix build targets
Comments suppressed due to low confidence (4)

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m:18

  • AppleNetNative_NwCreateContext currently hardcodes the endpoint to "127.0.0.1:42". Consider accepting host and port parameters or providing a separate function to configure the endpoint rather than using placeholder values.
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer)

src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs:1

  • The new NetworkFramework TLS interop code is not accompanied by any unit tests. Consider adding tests for ALPN serialization, native call success paths, and error handling.
// Licensed to the .NET Foundation under one or more agreements.

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:57

  • Public functions in this header lack parameter and return-value documentation. Consider adding doc comments to clarify expected behavior, ownership, and possible error codes.
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);

src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h:60

  • The declaration of AppleNetNative_NwProcessInputData includes the nw_framer_t framer parameter, but the header signature in this diff does not match the implementation. Ensure the header and implementation signatures align to avoid compilation errors.
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Ahmet Ibrahim Aksoyand others added 2 commits June 25, 2025 13:48
@liveans
liveans requested review from filipnavara and simonrozsival and removed request for simonrozsivalJune 25, 2025 11:53
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
Comment threadsrc/libraries/System.Net.Security/src/System.Net.Security.csproj Outdated
Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Outdated
@liveans

Copy link
Copy Markdown
ContributorAuthor

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanisteo-tsirpanis added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Jun 28, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props Outdated
Comment threadsrc/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we should put cap somewhere and throw some meaningful exception. I'm wondering if schannel or openssl also have some limits. (could be done as follow-up IMHO)

ConnectionCancelled = 103,
}

internal enum OSStatus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we already have the OSStatus somewhere...? I would thins most of them are pretty general.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have only

privateconstintOSStatus_writErr=-20;
privateconstintOSStatus_readErr=-19;
privateconstintOSStatus_noErr=0;
privateconstintOSStatus_errSSLWouldBlock=-9803;
privateconstintInitialBufferSize=2048;

Not sure what the best place for the shared definition would be, maybe Interop.AppleCrypto.OSStatus.

framer_options = nw_framer_copy_options(framer);

NSNumber* num = nw_framer_options_copy_object_value(framer_options, "GCHANDLE");
assert(num != NULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it its up to use to manage it. I think the assert is ok to let us know if our assumptions are wrong. at least in the early stages.

[num getValue:&ptr];
size_t size = message_length;

nw_framer_parse_output(framer, 1, message_length, NULL, ^size_t(uint8_t *buffer, size_t buffer_length, bool is_complete2) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitL I would rename is_complete2 to is_complete

};

static nw_framer_cleanup_handler_t framer_cleanup_handler = ^(nw_framer_t framer) {
(void)framer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes me wonder if we missed something. But if we did not, maybe we don't even need the empty handler. Any thoughts on this @filipnavara ?

Comment threadsrc/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Outdated
// The endpoint values (127.0.0.1:42) are arbitrary - they just need to be
// syntactically and semantically valid since the connection is never established.
nw_parameters_t nw_parameters = nw_parameters_create_secure_udp(NW_PARAMETERS_DISABLE_PROTOCOL, NW_PARAMETERS_DEFAULT_CONFIGURATION);
nw_endpoint_t nw_endpoint = nw_endpoint_create_host("127.0.0.1", "42");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if something is already bound on port 42? Like another .NET process?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nothing. There is no real socket. we just need to create some nw_endpoint.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, since this is create_host, maybe we can simply put in some text @liveans instead of using something that looks valid.

@rzikm

rzikm commented Jul 1, 2025

Copy link
Copy Markdown
Member

I am taking this over to land it in main ASAP while liveans is on vacation. I addressed most of the comments, I also have some Ideas how to move this forward, but will keep them for the followup PRs, PTAL

@rzikm
rzikm requested a review from wfurtJuly 1, 2025 13:48
@rzikmrzikm self-assigned this Jul 2, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@liveans@rzikm@vcsjones@filipnavara@stephentoub@teo-tsirpanis@MichalStrehovsky@wfurt