Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

liveans
Copy link
Member

@liveans liveans commented Jun 25, 2025

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 stephentoub, wfurt, rzikm, a team and Copilot June 25, 2025 11:45
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jun 25, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

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
File Description
src/tasks/LibraryBuilder/Templates/CMakeLists.txt.template Link CLI library builder against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template Link Apple app builder target against Network framework
src/tasks/AppleAppBuilder/Templates/CMakeLists-librarymode.txt.template Link Apple library‐mode builder against Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.m Implement TLS handshake and I/O callbacks using Network framework
src/native/libs/System.Net.Security.Native.Apple/pal_networkframework.h Declare C API for Network Framework TLS functions
src/native/libs/System.Net.Security.Native.Apple/extra_libs.cmake Find and append Network framework to native link list
src/native/libs/System.Net.Security.Native.Apple/entrypoints.c Register native TLS entrypoints for DllImport
src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt Add and configure System.Net.Security.Native.Apple targets
src/native/libs/CMakeLists.txt Include System.Net.Security.Native.Apple in native build when targeting Apple
src/mono/msbuild/apple/build/AppleBuild.targets Add Network framework to Mono Apple app linker args
src/libraries/System.Net.Security/src/System.Net.Security.csproj Include new Interop.OSX files in library project
src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs Managed interop for Network Framework TLS operations
src/libraries/Common/src/Interop/OSX/Interop.Network.cs Managed retain/release wrappers for Network Framework objects
src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs Define library constants for AppleNetworkNative and NetworkFramework
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets Add 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);

@liveans liveans requested review from filipnavara and simonrozsival and removed request for simonrozsival June 25, 2025 11:53
Co-authored-by: Radek Zikmund <32671551+rzikm@users.noreply.github.com>
@liveans
Copy link
Member Author

liveans commented Jun 28, 2025

/azp run runtime-nativeaot-outerloop

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@teo-tsirpanis teo-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
Copy link
Contributor

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

throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;
Copy link
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
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
Member

Choose a reason for hiding this comment

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

We have only

private const int OSStatus_writErr = -20;
private const int OSStatus_readErr = -19;
private const int OSStatus_noErr = 0;
private const int OSStatus_errSSLWouldBlock = -9803;
private const int InitialBufferSize = 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
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
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
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 ?

// 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
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
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
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
Copy link
Member

rzikm commented Jul 1, 2025

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 wfurt July 1, 2025 13:48
@rzikm rzikm self-assigned this Jul 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants