Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c062e18
Native Interop Layer
liveans Jun 16, 2025
ecba3f7
Native Layer Compilation fix for Mono + NativeAOT + templates
liveans Jun 16, 2025
bf130f3
First shape of new native + interop
liveans Jun 25, 2025
0dcc599
Newlines at the end of files
liveans Jun 25, 2025
44b3597
Default constructor ownsHandle to true
liveans Jun 25, 2025
3cbcea7
Delete couple of unsafe keyword in Interop
liveans Jun 25, 2025
3defe85
Update src/native/libs/System.Net.Security.Native.Apple/pal_networkfr…
liveans Jun 25, 2025
57a7069
Merge branch 'main' into network_framework_integration_native_interop
liveans Jun 25, 2025
c1a2b6b
Fix PlatformManifestFileEntry
liveans Jun 25, 2025
0977679
Review feedback
liveans Jun 25, 2025
fe343b0
Apply suggestions from code review
liveans Jun 26, 2025
0fff060
Update src/libraries/Common/src/Interop/OSX/Interop.Network.Tls.cs
liveans Jun 26, 2025
3441093
Review feedbacks
liveans Jun 28, 2025
3e547c5
Merge branch 'main' into network_framework_integration_native_interop
liveans Jun 28, 2025
25b8950
Further review feedback
liveans Jun 28, 2025
91238c5
Add new library name to nativeaot build target file
liveans Jun 28, 2025
a250b67
Merge branch 'main' into network_framework_integration_native_interop
liveans Jun 28, 2025
beb5f93
Merge System.Net.Security.Native.Apple with System.Security.Cryptogra…
rzikm Jul 1, 2025
0ab06b2
fixup! Merge System.Net.Security.Native.Apple with System.Security.Cr…
rzikm Jul 1, 2025
39bef6d
Shared OSStatus
rzikm Jul 1, 2025
8267454
Correctly release some handles
rzikm Jul 1, 2025
4bf6eb9
Remove printf
rzikm Jul 1, 2025
f771ea9
Add comments
rzikm Jul 1, 2025
6ab3942
Fix build
rzikm Jul 2, 2025
cc950a1
Merge branch 'main' into network_framework_integration_native_interop
liveans Jul 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<NativeFramework Include="CoreFoundation" />
<NativeFramework Include="CryptoKit" />
<NativeFramework Include="Foundation" />
<NativeFramework Include="Network" />
<NativeFramework Include="Security" />
<!-- The library builds don't reference the GSS API on tvOS builds. -->
<NativeFramework Condition="!$(_targetOS.StartsWith('tvos'))" Include="GSS" />
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/Common/src/Interop/OSX/Interop.Libraries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ internal static partial class Libraries
internal const string OpenLdap = "libldap.dylib";
internal const string SystemConfigurationLibrary = "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration";
internal const string AppleCryptoNative = "libSystem.Security.Cryptography.Native.Apple";
internal const string AppleNetworkNative = "libSystem.Net.Security.Native.Apple";
internal const string NetworkFramework = "/System/Library/Frameworks/Network.framework/Network";
internal const string MsQuic = "libmsquic.dylib";
}
}
18 changes: 18 additions & 0 deletions src/libraries/Common/src/Interop/OSX/Interop.Network.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class NetworkFramework
{
// Network Framework reference counting functions
[LibraryImport(Libraries.NetworkFramework, EntryPoint = "nw_retain")]
internal static partial IntPtr Retain(IntPtr obj);

[LibraryImport(Libraries.NetworkFramework, EntryPoint = "nw_release")]
internal static partial void Release(IntPtr obj);
}
}
153 changes: 153 additions & 0 deletions src/libraries/Common/src/Interop/OSX/Interop.NetworkTls.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
// TLS 1.3 specific Network Framework implementation for macOS
internal static partial class NetworkFramework
{
internal static partial class Tls
{
// Core TLS functions for Network Framework integration
[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwInit")]
[return: MarshalAs(UnmanagedType.I4)]
internal static unsafe partial bool Init(delegate* unmanaged<IntPtr, StatusUpdates, IntPtr, IntPtr, void> statusCallback,
delegate* unmanaged<IntPtr, byte*, void**, int> readCallback,
delegate* unmanaged<IntPtr, byte*, void**, int> writeCallback);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwCreateContext")]
internal static partial SafeNetworkFrameworkHandle CreateContext([MarshalAs(UnmanagedType.I4)] bool isServer);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwSetTlsOptions", StringMarshalling = StringMarshalling.Utf8)]
private static partial int SetTlsOptions(SafeNetworkFrameworkHandle connection, IntPtr gcHandle,
string targetName, Span<byte> alpnBuffer, int alpnLength,
SslProtocols minTlsProtocol, SslProtocols maxTlsProtocol);

internal static int SetTlsOptions(SafeNetworkFrameworkHandle nwHandle, IntPtr gcHandle, string targetName, List<SslApplicationProtocol>? applicationProtocols, SslProtocols minTlsVersion, SslProtocols maxTlsVersion)
{
int alpnLength = GetAlpnProtocolListSerializedLength(applicationProtocols);
Span<byte> alpn = alpnLength <= 256 ? stackalloc byte[256].Slice(0, alpnLength) : new byte[alpnLength];
SerializeAlpnProtocolList(applicationProtocols, alpn);

return SetTlsOptions(nwHandle, gcHandle, targetName, alpn, alpnLength, minTlsVersion, maxTlsVersion);
}

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwStartTlsHandshake")]
internal static partial int StartTlsHandshake(SafeNetworkFrameworkHandle connection, IntPtr gcHandle);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwProcessInputData")]
internal static unsafe partial int ProcessInputData(SafeNetworkFrameworkHandle connection,
SafeNetworkFrameworkHandle framer,
byte* buffer, int bufferLength);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwSendToConnection")]
internal static unsafe partial int SendToConnection(SafeNetworkFrameworkHandle connection, IntPtr gcHandle,
void* buffer, int bufferLength);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwReadFromConnection")]
internal static partial int ReadFromConnection(SafeNetworkFrameworkHandle connection, IntPtr gcHandle);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwCancelConnection")]
internal static partial int CancelConnection(SafeNetworkFrameworkHandle connection);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwGetConnectionInfo")]
internal static unsafe partial int GetConnectionInfo(SafeNetworkFrameworkHandle connection,
out SslProtocols pProtocol, out TlsCipherSuite pCipherSuiteOut,
ref void* negotiatedAlpn, out uint alpnLength);

[LibraryImport(Interop.Libraries.AppleNetworkNative, EntryPoint = "AppleNetNative_NwCopyCertChain")]
internal static partial int CopyCertChain(SafeNetworkFrameworkHandle connection,
out SafeCFArrayHandle certificates,
out int count);

internal static int GetAlpnProtocolListSerializedLength(List<SslApplicationProtocol>? applicationProtocols)
{
if (applicationProtocols is null)
{
return 0;
}

int protocolSize = 0;

foreach (SslApplicationProtocol protocol in applicationProtocols)
{
if (protocol.Protocol.Length == 0 || protocol.Protocol.Length > byte.MaxValue)
{
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;
}

return protocolSize;
}

private static void SerializeAlpnProtocolList(List<SslApplicationProtocol>? applicationProtocols, Span<byte> buffer)
{
if (applicationProtocols is null)
{
return;
}

Debug.Assert(GetAlpnProtocolListSerializedLength(applicationProtocols) == buffer.Length);

int offset = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
buffer[offset++] = (byte)protocol.Protocol.Length;
protocol.Protocol.Span.CopyTo(buffer.Slice(offset));
offset += protocol.Protocol.Length;
buffer[offset++] = 0;
}
}
}
// Status enumeration for Network Framework TLS operations
internal enum StatusUpdates
{
UnknownError = 0,
FramerStart = 1,
FramerStop = 2,
HandshakeFinished = 3,
HandshakeFailed = 4,
ConnectionReadFinished = 100,
ConnectionWriteFinished = 101,
ConnectionWriteFailed = 102,
ConnectionCancelled = 103,
}

internal enum OSStatus
{
NoError = 0,
ReadError = -19,
WriteError = -20,
EOFError = -39,
SecUserCanceled = -128,
WouldBlock = -9803
}
}

// Safe handle classes for Network Framework TLS resources
internal sealed class SafeNetworkFrameworkHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeNetworkFrameworkHandle() : base(ownsHandle: true) { }

public SafeNetworkFrameworkHandle(IntPtr handle, bool ownsHandle) : base(ownsHandle)
{
SetHandle(NetworkFramework.Retain(handle));
}

protected override bool ReleaseHandle()
{
NetworkFramework.Release(handle);
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@
Link="Common\Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.Ssl.cs" />
<Compile Include="$(CommonPath)Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.X509Chain.cs"
Link="Common\Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.X509Chain.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.Network.cs"
Link="Common\Interop\OSX\Interop.Network.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.NetworkTls.cs"
Link="Common\Interop\OSX\Interop.NetworkTls.cs" />
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeCreateHandle.OSX.cs"
Link="Common\Microsoft\Win32\SafeHandles\SafeCreateHandle.OSX.cs" />
<Compile Include="System\Net\CertificateValidationPal.OSX.cs" />
Expand Down
1 change: 1 addition & 0 deletions src/mono/msbuild/apple/build/AppleBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<_CommonLinkerArgs Include="-lswiftCore" />
<_CommonLinkerArgs Include="-lswiftFoundation" />
<_CommonLinkerArgs Include="-framework Foundation" />
<_CommonLinkerArgs Include="-framework Network" />
<_CommonLinkerArgs Include="-framework Security" />
<_CommonLinkerArgs Include="-framework CryptoKit" />
<_CommonLinkerArgs Include="-framework UIKit" />
Expand Down
1 change: 1 addition & 0 deletions src/native/libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,6 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI)

if (CLR_CMAKE_TARGET_APPLE)
add_subdirectory(System.Security.Cryptography.Native.Apple)
add_subdirectory(System.Net.Security.Native.Apple)
endif ()
endif ()
50 changes: 50 additions & 0 deletions src/native/libs/System.Net.Security.Native.Apple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
project(System.Net.Security.Native.Apple C)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

add_compile_options(-Wno-deprecated-declarations)

include(${CMAKE_CURRENT_LIST_DIR}/extra_libs.cmake)
append_extra_networking_apple_libs(NATIVE_LIBS_EXTRA)

set(NATIVENETWORKING_SOURCES
pal_networkframework.m
entrypoints.c
)

if (GEN_SHARED_LIB)
add_library(System.Net.Security.Native.Apple
SHARED
${NATIVENETWORKING_SOURCES}
${VERSION_FILE_PATH}
)
endif()

add_library(System.Net.Security.Native.Apple-Static
STATIC
${NATIVENETWORKING_SOURCES}
)

set_target_properties(System.Net.Security.Native.Apple-Static PROPERTIES OUTPUT_NAME System.Net.Security.Native.Apple CLEAN_DIRECT_OUTPUT 1)

if (GEN_SHARED_LIB)
target_link_libraries(System.Net.Security.Native.Apple
PRIVATE
${NATIVE_LIBS_EXTRA}
)

add_custom_command(TARGET System.Net.Security.Native.Apple POST_BUILD
COMMENT "Verifying System.Net.Security.Native.Apple entry points"
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../verify-entrypoints.sh
$<TARGET_FILE:System.Net.Security.Native.Apple>
${CMAKE_CURRENT_SOURCE_DIR}/entrypoints.c
${CMAKE_NM}
VERBATIM
)
endif()

if (GEN_SHARED_LIB)
install_with_stripped_symbols (System.Net.Security.Native.Apple PROGRAMS .)
endif()

install (TARGETS System.Net.Security.Native.Apple-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs)
28 changes: 28 additions & 0 deletions src/native/libs/System.Net.Security.Native.Apple/entrypoints.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include <minipal/entrypoints.h>

// Include System.Net.Security.Native.Apple headers
#include "pal_networkframework.h"

static const Entry s_netSecurityAppleNative[] =
{
DllImportEntry(AppleNetNative_NwInit)
DllImportEntry(AppleNetNative_NwCreateContext)
DllImportEntry(AppleNetNative_NwSetTlsOptions)
DllImportEntry(AppleNetNative_NwStartTlsHandshake)
DllImportEntry(AppleNetNative_NwProcessInputData)
DllImportEntry(AppleNetNative_NwSendToConnection)
DllImportEntry(AppleNetNative_NwReadFromConnection)
DllImportEntry(AppleNetNative_NwCancelConnection)
DllImportEntry(AppleNetNative_NwGetConnectionInfo)
DllImportEntry(AppleNetNative_NwCopyCertChain)
};

EXTERN_C const void* NetSecurityAppleResolveDllImport(const char* name);

EXTERN_C const void* NetSecurityAppleResolveDllImport(const char* name)
{
return minipal_resolve_dllimport(s_netSecurityAppleNative, ARRAY_SIZE(s_netSecurityAppleNative), name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function(append_extra_networking_apple_libs NativeLibsExtra)
find_library(COREFOUNDATION CoreFoundation)
find_library(SECURITY Security)
find_library(NETWORK Network)
find_library(FOUNDATION Foundation)

set(${NativeLibsExtra} ${${NativeLibsExtra}} ${COREFOUNDATION} ${SECURITY} ${NETWORK} ${FOUNDATION} PARENT_SCOPE)
endfunction()
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma once

#include "pal_compiler.h"
#include <pal_ssl_types.h>
#include <stdint.h>
#include <stddef.h>
#include <sys/types.h> // for intptr_t

#ifdef __OBJC__
#import <Network/Network.h>
#else
#include <Network/Network.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

// Handshake state enumeration matching other Apple SSL implementations
typedef enum
{
PAL_TlsHandshakeState_Unknown = 0,
PAL_TlsHandshakeState_Complete = 1,
PAL_TlsHandshakeState_WouldBlock = 2,
PAL_TlsHandshakeState_ServerAuthCompleted = 3,
PAL_TlsHandshakeState_ClientAuthCompleted = 4,
PAL_TlsHandshakeState_ClientCertRequested = 5,
PAL_TlsHandshakeState_ClientHelloReceived = 6,
} PAL_TlsHandshakeState;

// Status update enumeration for TLS operations
typedef enum
{
PAL_NwStatusUpdates_UnknownError = 0,
PAL_NwStatusUpdates_FramerStart = 1,
PAL_NwStatusUpdates_FramerStop = 2,
PAL_NwStatusUpdates_HandshakeFinished = 3,
PAL_NwStatusUpdates_HandshakeFailed = 4,

PAL_NwStatusUpdates_ConnectionReadFinished = 100,
PAL_NwStatusUpdates_ConnectionWriteFinished = 101,
PAL_NwStatusUpdates_ConnectionWriteFailed = 102,
PAL_NwStatusUpdates_ConnectionCancelled = 103,
} PAL_NwStatusUpdates;

// Callback type definitions that match the implementation usage
typedef void (*StatusUpdateCallback)(size_t context, PAL_NwStatusUpdates status, size_t data1, size_t data2);
typedef int32_t (*ReadCallback)(void* context, uint8_t* buffer, size_t* length);
typedef int32_t (*WriteCallback)(void* context, uint8_t* buffer, size_t length);

// Only TLS-specific Network Framework functions are exported
PALEXPORT nw_connection_t AppleNetNative_NwCreateContext(int32_t isServer);
PALEXPORT int32_t AppleNetNative_NwStartTlsHandshake(nw_connection_t connection, size_t gcHandle);
PALEXPORT int32_t AppleNetNative_NwInit(StatusUpdateCallback statusFunc, ReadCallback readFunc, WriteCallback writeFunc);
PALEXPORT int32_t AppleNetNative_NwSendToConnection(nw_connection_t connection, size_t gcHandle, uint8_t* buffer, int length);
PALEXPORT int32_t AppleNetNative_NwReadFromConnection(nw_connection_t connection, size_t gcHandle);
PALEXPORT int32_t AppleNetNative_NwProcessInputData(nw_connection_t connection, nw_framer_t framer, const uint8_t * data, int dataLength);
PALEXPORT int32_t AppleNetNative_NwSetTlsOptions(nw_connection_t connection, size_t gcHandle, char* targetName, const uint8_t* alpnBuffer, int alpnLength, PAL_SslProtocol minTlsProtocol, PAL_SslProtocol maxTlsProtocol);
PALEXPORT int32_t AppleNetNative_NwGetConnectionInfo(nw_connection_t connection, PAL_SslProtocol* pProtocol, uint16_t* pCipherSuiteOut, const char** negotiatedAlpn, uint32_t* alpnLength);
PALEXPORT int32_t AppleNetNative_NwCopyCertChain(nw_connection_t connection, CFArrayRef* certificates, int* count);
PALEXPORT int32_t AppleNetNative_NwCancelConnection(nw_connection_t connection);

#ifdef __cplusplus
}
#endif
Loading
Loading