Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ let package = Package(
.define("_GNU_SOURCE"),
.define("_POSIX_C_SOURCE", to: "200112L"),
.define("_DARWIN_C_SOURCE"),
// Disable assembly on Windows as SPM doesn't support .S files on Windows
.define("OPENSSL_NO_ASM", .when(platforms: [.windows])),
]
),
.target(
Expand Down
18 changes: 9 additions & 9 deletions Sources/CNIOBoringSSL/crypto/thread_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,18 @@ static void NTAPI thread_local_destructor(PVOID module, DWORD reason,
//
// Force a reference to _tls_used to make the linker create the TLS directory
// if it's not already there. (E.g. if __declspec(thread) is not used). Force
// a reference to p_thread_callback_boringssl to prevent whole program
// a reference to CNIOBoringSSL_p_thread_callback_boringssl to prevent whole program
// optimization from discarding the variable.
//
// Note, in the prefixed build, |p_thread_callback_boringssl| may be a macro.
// Note, in the prefixed build, |CNIOBoringSSL_p_thread_callback_boringssl| may be a macro.
#define STRINGIFY(x) #x
#define EXPAND_AND_STRINGIFY(x) STRINGIFY(x)
#ifdef _WIN64
__pragma(comment(linker, "/INCLUDE:_tls_used")) __pragma(comment(
linker, "/INCLUDE:" EXPAND_AND_STRINGIFY(p_thread_callback_boringssl)))
linker, "/INCLUDE:" EXPAND_AND_STRINGIFY(CNIOBoringSSL_p_thread_callback_boringssl)))
#else
__pragma(comment(linker, "/INCLUDE:__tls_used")) __pragma(comment(
linker, "/INCLUDE:_" EXPAND_AND_STRINGIFY(p_thread_callback_boringssl)))
linker, "/INCLUDE:_" EXPAND_AND_STRINGIFY(CNIOBoringSSL_p_thread_callback_boringssl)))
#endif

// .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are
Expand All @@ -141,7 +141,7 @@ __pragma(comment(linker, "/INCLUDE:__tls_used")) __pragma(comment(
//
// See VC\crt\src\tlssup.c for reference.

// The linker must not discard p_thread_callback_boringssl. (We force a
// The linker must not discard CNIOBoringSSL_p_thread_callback_boringssl. (We force a
// reference to this variable with a linker /INCLUDE:symbol pragma to ensure
// that.) If this variable is discarded, the OnThreadExit function will never
// be called.
Expand All @@ -153,10 +153,10 @@ __pragma(comment(linker, "/INCLUDE:__tls_used")) __pragma(comment(
// When defining a const variable, it must have external linkage to be sure
// the linker doesn't discard it.
extern "C" {
extern const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl;
extern const PIMAGE_TLS_CALLBACK CNIOBoringSSL_p_thread_callback_boringssl;
}
// clang-format on
const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor;
const PIMAGE_TLS_CALLBACK CNIOBoringSSL_p_thread_callback_boringssl = thread_local_destructor;
// Reset the default section.
#pragma const_seg()

Expand All @@ -165,10 +165,10 @@ const PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor;
#pragma data_seg(".CRT$XLC")
// clang-format off
extern "C" {
extern PIMAGE_TLS_CALLBACK p_thread_callback_boringssl;
extern PIMAGE_TLS_CALLBACK CNIOBoringSSL_p_thread_callback_boringssl;
}
// clang-format on
PIMAGE_TLS_CALLBACK p_thread_callback_boringssl = thread_local_destructor;
PIMAGE_TLS_CALLBACK CNIOBoringSSL_p_thread_callback_boringssl = thread_local_destructor;
// Reset the default section.
#pragma data_seg()

Expand Down
33 changes: 33 additions & 0 deletions Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,39 @@

#define BORINGSSL_PREFIX CNIOBoringSSL

// On Windows, prevent conflicts between winsock.h and winsock2.h
// Also prevent min/max macro conflicts with std::numeric_limits
#if defined(_WIN32) || defined(_WIN64)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_ // Prevent winsock.h from being included
#endif
#include <winsock2.h>
#include <ws2tcpip.h>

// Undefine Windows CryptoAPI macros that conflict with BoringSSL types
// wincrypt.h defines these as LPCSTR constants for CertGetNameString
#ifdef X509_NAME
#undef X509_NAME
#endif
#ifdef X509_EXTENSIONS
#undef X509_EXTENSIONS
#endif
#ifdef X509_CERT_PAIR
#undef X509_CERT_PAIR
#endif
#ifdef X509_NAME_VALUE
#undef X509_NAME_VALUE
#endif
#ifdef PKCS7_SIGNER_INFO
#undef PKCS7_SIGNER_INFO
#endif
#endif

// This file should be the first included by all BoringSSL headers.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

; 32-bit Windows adds underscores to C functions, while 64-bit Windows does not.
%ifidn __OUTPUT_FORMAT__, win32
%xdefine _p_thread_callback_boringssl BORINGSSL_PREFIX %+ _p_thread_callback_boringssl
%xdefine _ACCESS_DESCRIPTION_free _ %+ BORINGSSL_PREFIX %+ _ACCESS_DESCRIPTION_free
%xdefine _ACCESS_DESCRIPTION_new _ %+ BORINGSSL_PREFIX %+ _ACCESS_DESCRIPTION_new
%xdefine _AES_CMAC _ %+ BORINGSSL_PREFIX %+ _AES_CMAC
Expand Down Expand Up @@ -3994,6 +3995,7 @@
%xdefine _x509v3_hex_to_bytes _ %+ BORINGSSL_PREFIX %+ _x509v3_hex_to_bytes
%xdefine _x509v3_looks_like_dns_name _ %+ BORINGSSL_PREFIX %+ _x509v3_looks_like_dns_name
%else
%xdefine p_thread_callback_boringssl BORINGSSL_PREFIX %+ _p_thread_callback_boringssl
%xdefine ACCESS_DESCRIPTION_free BORINGSSL_PREFIX %+ _ACCESS_DESCRIPTION_free
%xdefine ACCESS_DESCRIPTION_new BORINGSSL_PREFIX %+ _ACCESS_DESCRIPTION_new
%xdefine AES_CMAC BORINGSSL_PREFIX %+ _AES_CMAC
Expand Down
2 changes: 2 additions & 0 deletions Sources/NIOSSL/ByteBufferBIO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import Musl
import Glibc
#elseif canImport(Bionic)
import Bionic
#elseif os(Windows)
import WinSDK
#else
#error("unsupported os")
#endif
Expand Down
2 changes: 2 additions & 0 deletions Sources/NIOSSL/IdentityVerification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import Musl
import Glibc
#elseif canImport(Android)
import Android
#elseif os(Windows)
import WinSDK
#else
#error("unsupported os")
#endif
Expand Down
2 changes: 2 additions & 0 deletions Sources/NIOSSL/NIOSSLClientHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import Musl
import Glibc
#elseif canImport(Android)
import Android
#elseif os(Windows)
import WinSDK
#else
#error("unsupported os")
#endif
Expand Down
21 changes: 19 additions & 2 deletions Sources/NIOSSL/PosixPort.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import Musl
import Glibc
#elseif canImport(Android)
import Android
#elseif os(Windows)
import ucrt
import WinSDK
#else
#error("unsupported os")
#endif
Expand All @@ -41,12 +44,14 @@ internal typealias FILEPointer = UnsafeMutablePointer<FILE>
#endif

private let sysFopen = fopen
private let sysMlock = mlock
private let sysMunlock = munlock
private let sysFclose = fclose
private let sysStat = { @Sendable in stat($0, $1) }
#if !os(Windows)
private let sysMlock = mlock
private let sysMunlock = munlock
private let sysLstat = lstat
private let sysReadlink = readlink
#endif

// MARK:- Copied code from SwiftNIO
private func isUnacceptableErrno(_ code: CInt) -> Bool {
Expand All @@ -65,7 +70,11 @@ internal func wrapSyscall<T: FixedWidthInteger>(where function: String = #functi
while true {
let res = try body()
if res == -1 {
#if os(Windows)
let err = Int32(bitPattern: GetLastError())
#else
let err = errno
#endif
if err == EINTR {
continue
}
Expand All @@ -84,7 +93,11 @@ internal func wrapErrorIsNullReturnCall<T>(
) throws -> T {
while true {
guard let res = try body() else {
#if os(Windows)
let err = Int32(bitPattern: GetLastError())
#else
let err = errno
#endif
if err == EINTR {
continue
}
Expand Down Expand Up @@ -113,6 +126,7 @@ internal enum Posix {
}
}

#if !os(Windows)
@inline(never)
internal static func readlink(
path: UnsafePointer<Int8>,
Expand All @@ -123,6 +137,7 @@ internal enum Posix {
sysReadlink(path, buf, bufSize)
}
}
#endif

@inline(never)
@discardableResult
Expand All @@ -132,6 +147,7 @@ internal enum Posix {
}
}

#if !os(Windows)
@inline(never)
@discardableResult
internal static func lstat(path: UnsafePointer<Int8>, buf: UnsafeMutablePointer<stat>) throws -> Int32 {
Expand All @@ -155,4 +171,5 @@ internal enum Posix {
sysMunlock(addr, len)
}
}
#endif
}
2 changes: 2 additions & 0 deletions Sources/NIOSSL/SSLCallbacks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import Musl
import Glibc
#elseif canImport(Bionic)
import Bionic
#elseif os(Windows)
import WinSDK
#else
#error("unsupported os")
#endif
Expand Down
4 changes: 3 additions & 1 deletion Sources/NIOSSL/SSLCertificate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import Musl
import Glibc
#elseif canImport(Bionic)
import Bionic
#elseif os(Windows)
import WinSDK
#else
#error("unsupported os")
#endif
Expand Down Expand Up @@ -427,7 +429,7 @@ extension NIOSSLCertificate {
var dataPtr: UnsafeMutablePointer<CChar>? = nil
let length = CNIOBoringSSL_BIO_get_mem_data(bio, &dataPtr)

guard let bytes = dataPtr.map({ UnsafeRawBufferPointer(start: $0, count: length) }) else {
guard let bytes = dataPtr.map({ UnsafeRawBufferPointer(start: $0, count: .init(length)) }) else {
fatalError("Failed to map bytes from a certificate")
}

Expand Down
33 changes: 31 additions & 2 deletions Sources/NIOSSL/SSLContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import Musl
import Glibc
#elseif canImport(Android)
import Android
#elseif os(Windows)
import ucrt
import WinSDK
#else
#error("unsupported os")
#endif
Expand All @@ -45,8 +48,8 @@ internal enum FileSystemObject {
return nil
}

#if os(Android) && arch(arm)
return (statObj.st_mode & UInt32(S_IFDIR)) != 0 ? .directory : .file
#if (os(Android) && arch(arm)) || os(Windows)
return (UInt32(statObj.st_mode) & UInt32(S_IFDIR)) != 0 ? .directory : .file
#else
return (statObj.st_mode & S_IFDIR) != 0 ? .directory : .file
#endif
Expand Down Expand Up @@ -788,13 +791,15 @@ extension NIOSSLContext {

// Check if the element is a symlink. If it is not, return false.
var buffer = stat()
#if !os(Windows) // Windows has no symlinks
let _ = try Posix.lstat(path: path, buf: &buffer)
// Check the mode to make sure this is a symlink
#if os(Android) && arch(arm)
if (buffer.st_mode & UInt32(S_IFMT)) != UInt32(S_IFLNK) { return false }
#else
if (buffer.st_mode & S_IFMT) != S_IFLNK { return false }
#endif
#endif

// Return true at this point because the file format is considered to be in rehash format and a symlink.
// Rehash format being "%08lx.%d" or HHHHHHHH.D
Expand Down Expand Up @@ -919,16 +924,35 @@ internal class DirectoryContents: Sequence, IteratorProtocol {
// Otherwise an OpaquePointer needs to be used to account for the non-defined type in glibc.
#if canImport(Darwin)
let dir: UnsafeMutablePointer<DIR>
#elseif os(Windows)
var fileData = WIN32_FIND_DATA()
var dir: HANDLE? = nil
#else
let dir: OpaquePointer
#endif

init(path: String) {
self.path = path
#if os(Windows)
self.dir = FindFirstFileA(path, &fileData)
#else
self.dir = opendir(path)!
#endif
}

func next() -> String? {
#if os(Windows)
if dir != INVALID_HANDLE_VALUE {
let name = withUnsafePointer(to: &fileData.cFileName) { ptr in
// Pointers to homogeneous tuples in Swift are always bound to both the tuple type and the element type,
// so the assumption below is safe.
let elementPointer = UnsafeRawPointer(ptr).assumingMemoryBound(to: CChar.self)
return String(cString: elementPointer)
}
FindNextFileA(dir, &fileData)
return self.path + name
}
#else
if let dirent: UnsafeMutablePointer<dirent> = readdir(self.dir) {
let name = withUnsafePointer(to: &dirent.pointee.d_name) { (ptr) -> String in
// Pointers to homogeneous tuples in Swift are always bound to both the tuple type and the element type,
Expand All @@ -938,11 +962,16 @@ internal class DirectoryContents: Sequence, IteratorProtocol {
}
return self.path + name
}
#endif
return nil
}

deinit {
#if os(Windows)
FindClose(dir)
#else
closedir(dir)
#endif
}
}

Expand Down
10 changes: 9 additions & 1 deletion Sources/NIOSSL/SSLPKCS12Bundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ extension NIOSSLPKCS12Bundle {

var dataPtr: UnsafeMutablePointer<CChar>? = nil
let length = CNIOBoringSSL_BIO_get_mem_data(bio, &dataPtr)
guard let bytes = dataPtr.map({ UnsafeMutableRawBufferPointer(start: $0, count: length) }) else {
guard let bytes = dataPtr.map({ UnsafeMutableRawBufferPointer(start: $0, count: .init(length)) }) else {
fatalError("Failed to get bytes from private key")
}

Expand All @@ -269,11 +269,19 @@ extension Collection where Element == UInt8 {
bufferPtr.deallocate()
}

#if os(Windows)
// TODO: throw an error on failure
VirtualLock(bufferPtr.baseAddress!, UInt64(bufferPtr.count))
defer {
VirtualUnlock(bufferPtr.baseAddress!, UInt64(bufferPtr.count))
}
#else
try Posix.mlock(addr: bufferPtr.baseAddress!, len: bufferPtr.count)
defer {
// If munlock fails take out the process.
try! Posix.munlock(addr: bufferPtr.baseAddress!, len: bufferPtr.count)
}
#endif

let (_, nextIndex) = bufferPtr.initialize(from: self)
assert(nextIndex == (bufferPtr.endIndex - 1))
Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOSSL/SSLPrivateKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ extension NIOSSLPrivateKey {
var dataPtr: UnsafeMutablePointer<CChar>? = nil
let length = CNIOBoringSSL_BIO_get_mem_data(bio, &dataPtr)

guard let bytes = dataPtr.map({ UnsafeRawBufferPointer(start: $0, count: length) }) else {
guard let bytes = dataPtr.map({ UnsafeRawBufferPointer(start: $0, count: .init(length)) }) else {
fatalError("Failed to map bytes from a private key")
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/NIOSSL/SSLPublicKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ extension NIOSSLPublicKey {
var dataPtr: UnsafeMutablePointer<CChar>? = nil
let length = CNIOBoringSSL_BIO_get_mem_data(bio, &dataPtr)

guard let bytes = dataPtr.map({ UnsafeMutableRawBufferPointer(start: $0, count: length) }) else {
guard let bytes = dataPtr.map({ UnsafeMutableRawBufferPointer(start: $0, count: .init(length)) }) else {
fatalError("Failed to map bytes from a public key")
}

Expand Down
Loading