Imported Upstream version 5.2.0.175

Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-06-07 13:16:24 +00:00
parent 4bdbaf4a88
commit 966bba02bb
8776 changed files with 346420 additions and 149650 deletions

View File

@@ -4,8 +4,8 @@ project(CoreFX)
set(CMAKE_MACOSX_RPATH ON)
set(CMAKE_INSTALL_PREFIX $ENV{__CMakeBinDir})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_C_FLAGS "-std=c11")
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(VERSION_FILE_PATH "${CMAKE_BINARY_DIR}/../../version.c")
@@ -52,6 +52,10 @@ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
endif ()
add_compile_options(-mthumb)
add_compile_options(-mfpu=vfpv3)
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
add_definitions(-DBIT32=1)
add_definitions(-D_ARM_)
add_definitions(-D_FILE_OFFSET_BITS=64)
endif ()
string(TOUPPER ${CMAKE_BUILD_TYPE} UPPERCASE_CMAKE_BUILD_TYPE)
@@ -86,7 +90,11 @@ if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${CLR_SANITIZE_LINK_FLAGS} -Wl,--gc-sections")
endif ()
elseif (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE)
add_compile_options (-O3)
if (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l AND DEFINED ENV{CROSSCOMPILE})
add_compile_options (-O1)
else()
add_compile_options (-O3)
endif()
add_definitions(-DNDEBUG)
else ()
message(FATAL_ERROR "Unknown build type. Set CMAKE_BUILD_TYPE to DEBUG or RELEASE.")
@@ -147,7 +155,7 @@ if (NOT WIN32)
else (CMAKE_SYSTEM_NAME STREQUAL Darwin)
# Ensure that objcopy is present
if(DEFINED ENV{CROSSCOMPILE})
if(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL i686)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l OR CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL i686 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
find_program(OBJCOPY ${TOOLCHAIN}-objcopy)
else()
message(FATAL_ERROR "Only AMD64, X86, ARM64 and ARM are supported")

View File

@@ -1,6 +1,11 @@
#pragma once
#cmakedefine PAL_UNIX_NAME @PAL_UNIX_NAME@
#cmakedefine01 HAVE_LSEEK64
#cmakedefine01 HAVE_MMAP64
#cmakedefine01 HAVE_FTRUNCATE64
#cmakedefine01 HAVE_POSIX_FADVISE64
#cmakedefine01 HAVE_FLOCK64
#cmakedefine01 HAVE_STAT64
#cmakedefine01 HAVE_PIPE2
#cmakedefine01 HAVE_STAT_BIRTHTIME
@@ -16,8 +21,6 @@
#cmakedefine01 HAVE_POSIX_ADVISE
#cmakedefine01 PRIORITY_REQUIRES_INT_WHO
#cmakedefine01 KEVENT_REQUIRES_INT_PARAMS
#cmakedefine01 HAVE_IN6_U
#cmakedefine01 HAVE_U6_ADDR
#cmakedefine01 HAVE_IOCTL
#cmakedefine01 HAVE_TIOCGWINSZ
#cmakedefine01 HAVE_SCHED_GETAFFINITY
@@ -27,6 +30,7 @@
#cmakedefine01 HAVE_PRIVATE_FDS_BITS
#cmakedefine01 HAVE_STATFS
#cmakedefine01 HAVE_EPOLL
#cmakedefine01 HAVE_ACCEPT_4
#cmakedefine01 HAVE_KQUEUE
#cmakedefine01 HAVE_SENDFILE_4
#cmakedefine01 HAVE_SENDFILE_6
@@ -64,6 +68,15 @@
#cmakedefine01 HAVE_HEIMDAL_HEADERS
#cmakedefine01 HAVE_NSGETENVIRON
#cmakedefine01 HAVE_CRT_EXTERNS_H
#cmakedefine01 HAVE_GETDOMAINNAME
#cmakedefine01 HAVE_UNAME
#cmakedefine01 HAVE_FUTIMES
#cmakedefine01 HAVE_FUTIMENS
#cmakedefine01 HAVE_MKSTEMPS
#cmakedefine01 HAVE_MKSTEMP
#cmakedefine01 IPV6MR_INTERFACE_UNSIGNED
#cmakedefine01 BIND_ADDRLEN_UNSIGNED
#cmakedefine01 INOTIFY_RM_WATCH_WD_UNSIGNED
// Mac OS X has stat64, but it is deprecated since plain stat now
// provides the same 64-bit aware struct when targeting OS X > 10.5

View File

@@ -144,7 +144,7 @@ inline bool DoubleFitsInIntType(double val)
// Modified to track an overflow bit instead of throwing exceptions. In most
// cases the Visual C++ optimizer (Whidbey beta1 - v14.00.40607) is able to
// optimize the bool away completely.
// Note that using a sentinal value (IntMax for example) to represent overflow
// Note that using a sentinel value (IntMax for example) to represent overflow
// actually results in poorer code-gen.
//
// This has also been simplified significantly to remove functionality we

View File

@@ -11,6 +11,7 @@ set(NATIVE_SOURCES
pal_networking.cpp
pal_networkstatistics.cpp
pal_process.cpp
pal_random.cpp
pal_runtimeinformation.cpp
pal_runtimeextensions.cpp
pal_string.cpp
@@ -42,7 +43,7 @@ add_library(System.Native-Static
SET_TARGET_PROPERTIES(System.Native-Static PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES(System.Native-Static PROPERTIES OUTPUT_NAME System.Native CLEAN_DIRECT_OUTPUT 1)
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
if (CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CLR_CMAKE_PLATFORM_ANDROID)
target_link_libraries(System.Native rt)
endif ()

View File

@@ -4,10 +4,12 @@
#include "pal_config.h"
#include "pal_console.h"
#include "pal_io.h"
#include "pal_utilities.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
@@ -430,7 +432,7 @@ static bool InitializeSignalHandling()
// thread. We can't do anything interesting in the signal handler,
// so we instead send a message to another thread that'll do
// the handling work.
if (pipe(g_signalPipe) != 0)
if (SystemNative_Pipe(g_signalPipe, PAL_O_CLOEXEC) != 0)
{
return false;
}

View File

@@ -8,8 +8,8 @@
#include <errno.h>
// ENODATA is not defined on FreeBSD.
#if defined(__FreeBSD__)
// ENODATA is not defined in FreeBSD 10.3 but is defined in 11.0
#if defined(__FreeBSD__) & !defined(ENODATA)
#define ENODATA ENOATTR
#endif
@@ -422,7 +422,7 @@ extern "C" const char* SystemNative_StrErrorR(int32_t platformErrno, char* buffe
}
// The only other valid error codes are 0 for success or EINVAL for
// an unkown error, but in the latter case a reasonable string (e.g
// an unknown error, but in the latter case a reasonable string (e.g
// "Unknown error: 0x123") is returned.
assert(error == 0 || error == EINVAL);
return buffer;

View File

@@ -291,9 +291,16 @@ extern "C" intptr_t SystemNative_ShmOpen(const char* name, int32_t flags, int32_
extern "C" int32_t SystemNative_ShmUnlink(const char* name)
{
#if HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP
int32_t result;
while (CheckInterrupted(result = shm_unlink(name)));
return result;
#else
// Not supported on e.g. Android. Also, prevent a compiler error because name is unused
(void)name;
errno = ENOTSUP;
return -1;
#endif
}
static void ConvertDirent(const dirent& entry, DirectoryEntry* outputEntry)
@@ -563,7 +570,16 @@ extern "C" int32_t SystemNative_FnMatch(const char* pattern, const char* path, F
extern "C" int64_t SystemNative_LSeek(intptr_t fd, int64_t offset, SeekWhence whence)
{
int64_t result;
while (CheckInterrupted(result = lseek(ToFileDescriptor(fd), offset, whence)));
while (CheckInterrupted(
result =
#if HAVE_LSEEK64
lseek64(
#else
lseek(
#endif
ToFileDescriptor(fd),
offset,
whence)));
return result;
}
@@ -577,7 +593,45 @@ extern "C" int32_t SystemNative_Link(const char* source, const char* linkTarget)
extern "C" intptr_t SystemNative_MksTemps(char* pathTemplate, int32_t suffixLength)
{
intptr_t result;
#if HAVE_MKSTEMPS
while (CheckInterrupted(result = mkstemps(pathTemplate, suffixLength)));
#elif HAVE_MKSTEMP
// mkstemps is not available bionic/Android, but mkstemp is
// mkstemp doesn't allow the suffix that msktemps does allow, so we'll need to
// remove that before passing pathTemplate to mkstemp
int32_t pathTemplateLength = static_cast<int32_t>(strlen(pathTemplate));
// pathTemplate must include at least XXXXXX (6 characters) which are not part of
// the suffix
if (suffixLength < 0 || suffixLength > pathTemplateLength - 6)
{
errno = EINVAL;
return -1;
}
// Make mkstemp ignore the suffix by setting the first char of the suffix to \0,
// if there is a suffix
int32_t firstSuffixIndex = 0;
char firstSuffixChar = 0;
if (suffixLength > 0)
{
firstSuffixIndex = pathTemplateLength - suffixLength;
firstSuffixChar = pathTemplate[firstSuffixIndex];
pathTemplate[firstSuffixIndex] = 0;
}
while (CheckInterrupted(result = mkstemp(pathTemplate)));
// Reset the first char of the suffix back to its original value, if there is a suffix
if (suffixLength > 0)
{
pathTemplate[firstSuffixIndex] = firstSuffixChar;
}
#else
#error "Cannot find mkstemps nor mkstemp on this platform"
#endif
return result;
}
@@ -667,7 +721,19 @@ extern "C" void* SystemNative_MMap(void* address,
}
// Use ToFileDescriptorUnchecked to allow -1 to be passed for the file descriptor, since managed code explicitly uses -1
void* ret = mmap(address, static_cast<size_t>(length), protection, flags, ToFileDescriptorUnchecked(fd), offset);
void* ret =
#if HAVE_MMAP64
mmap64(
#else
mmap(
#endif
address,
static_cast<size_t>(length),
protection,
flags,
ToFileDescriptorUnchecked(fd),
offset);
if (ret == MAP_FAILED)
{
return nullptr;
@@ -791,7 +857,15 @@ extern "C" int64_t SystemNative_SysConf(SysConfName name)
extern "C" int32_t SystemNative_FTruncate(intptr_t fd, int64_t length)
{
int32_t result;
while (CheckInterrupted(result = ftruncate(ToFileDescriptor(fd), length)));
while (CheckInterrupted(
result =
#if HAVE_FTRUNCATE64
ftruncate64(
#else
ftruncate(
#endif
ToFileDescriptor(fd),
length)));
return result;
}
@@ -863,7 +937,17 @@ extern "C" int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_
{
#if HAVE_POSIX_ADVISE
int32_t result;
while (CheckInterrupted(result = posix_fadvise(ToFileDescriptor(fd), offset, length, advice)));
while (CheckInterrupted(
result =
#if HAVE_POSIX_FADVISE64
posix_fadvise64(
#else
posix_fadvise(
#endif
ToFileDescriptor(fd),
offset,
length,
advice)));
return result;
#else
// Not supported on this platform. Caller can ignore this failure since it's just a hint.
@@ -1079,15 +1163,28 @@ extern "C" int32_t SystemNative_CopyFile(intptr_t sourceFd, intptr_t destination
// Now that the data from the file has been copied, copy over metadata
// from the source file. First copy the file times.
// If futimes nor futimes are available on this platform, file times will
// not be copied over.
while (CheckInterrupted(ret = fstat_(inFd, &sourceStat)));
if (ret == 0)
{
#if HAVE_FUTIMES
struct timeval origTimes[2];
origTimes[0].tv_sec = sourceStat.st_atime;
origTimes[0].tv_usec = 0;
origTimes[1].tv_sec = sourceStat.st_mtime;
origTimes[1].tv_usec = 0;
while (CheckInterrupted(ret = futimes(outFd, origTimes)));
#elif HAVE_FUTIMENS
// futimes is not a POSIX function, and not available on Android,
// but futimens is
struct timespec origTimes[2];
origTimes[0].tv_sec = static_cast<time_t>(sourceStat.st_atime);
origTimes[0].tv_nsec = 0;
origTimes[1].tv_sec = static_cast<time_t>(sourceStat.st_mtime);
origTimes[1].tv_nsec = 0;
while (CheckInterrupted(ret = futimens(outFd, origTimes)));
#endif
}
if (ret != 0)
{
@@ -1135,7 +1232,13 @@ extern "C" int32_t SystemNative_INotifyRemoveWatch(intptr_t fd, int32_t wd)
assert(wd >= 0);
#if HAVE_INOTIFY
return inotify_rm_watch(ToFileDescriptor(fd), wd);
return inotify_rm_watch(
ToFileDescriptor(fd),
#if INOTIFY_RM_WATCH_WD_UNSIGNED
static_cast<uint32_t>(wd));
#else
wd);
#endif
#else
(void)fd, (void)wd;
errno = ENOTSUP;
@@ -1179,13 +1282,18 @@ extern "C" int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int6
errno = EINVAL;
return -1;
}
#if HAVE_FLOCK64
struct flock64 lockArgs;
#else
struct flock lockArgs;
#endif
lockArgs.l_type = lockType;
lockArgs.l_whence = SEEK_SET;
lockArgs.l_start = offset;
lockArgs.l_len = length;
int32_t ret;
while (CheckInterrupted(ret = fcntl (ToFileDescriptor(fd), F_SETLK, &lockArgs)));
return ret;

View File

@@ -5,6 +5,7 @@
#pragma once
#include "pal_types.h"
#include "pal_errno.h"
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>

View File

@@ -16,6 +16,11 @@
#include <sys/statfs.h>
#include <mntent.h>
#define STRING_BUFFER_SIZE 8192
// Android does not define MNTOPT_RO
#ifndef MNTOPT_RO
#define MNTOPT_RO "r"
#endif
#endif
static int32_t GetMountInfo(MountPointFound onFound)

View File

@@ -31,6 +31,10 @@
#if defined(__APPLE__) && __APPLE__
#include <sys/socketvar.h>
#endif
#if !HAVE_GETDOMAINNAME && HAVE_UNAME
#include <sys/utsname.h>
#include <stdio.h>
#endif
#include <unistd.h>
#include <vector>
#include <pwd.h>
@@ -163,30 +167,14 @@ constexpr T Max(T left, T right)
static void ConvertByteArrayToIn6Addr(in6_addr& addr, const uint8_t* buffer, int32_t bufferLength)
{
#if HAVE_IN6_U
assert(bufferLength == ARRAY_SIZE(addr.__in6_u.__u6_addr8));
memcpy_s(addr.__in6_u.__u6_addr8, ARRAY_SIZE(addr.__in6_u.__u6_addr8), buffer, UnsignedCast(bufferLength));
#elif HAVE_U6_ADDR
assert(bufferLength == ARRAY_SIZE(addr.__u6_addr.__u6_addr8));
memcpy_s(addr.__u6_addr.__u6_addr8, ARRAY_SIZE(addr.__u6_addr.__u6_addr8), buffer, UnsignedCast(bufferLength));
#else
assert(bufferLength == ARRAY_SIZE(addr.s6_addr));
memcpy_s(addr.s6_addr, ARRAY_SIZE(addr.s6_addr), buffer, UnsignedCast(bufferLength));
#endif
}
static void ConvertIn6AddrToByteArray(uint8_t* buffer, int32_t bufferLength, const in6_addr& addr)
{
#if HAVE_IN6_U
assert(bufferLength == ARRAY_SIZE(addr.__in6_u.__u6_addr8));
memcpy_s(buffer, UnsignedCast(bufferLength), addr.__in6_u.__u6_addr8, ARRAY_SIZE(addr.__in6_u.__u6_addr8));
#elif HAVE_U6_ADDR
assert(bufferLength == ARRAY_SIZE(addr.__u6_addr.__u6_addr8));
memcpy_s(buffer, UnsignedCast(bufferLength), addr.__u6_addr.__u6_addr8, ARRAY_SIZE(addr.__u6_addr.__u6_addr8));
#else
assert(bufferLength == ARRAY_SIZE(addr.s6_addr));
memcpy_s(buffer, UnsignedCast(bufferLength), addr.s6_addr, ARRAY_SIZE(addr.s6_addr));
#endif
}
static void ConvertByteArrayToSockAddrIn6(sockaddr_in6& addr, const uint8_t* buffer, int32_t bufferLength)
@@ -915,6 +903,7 @@ extern "C" int32_t SystemNative_GetDomainName(uint8_t* name, int32_t nameLength)
assert(name != nullptr);
assert(nameLength > 0);
#if HAVE_GETDOMAINNAME
#if HAVE_GETDOMAINNAME_SIZET
size_t namelen = UnsignedCast(nameLength);
#else
@@ -922,6 +911,33 @@ extern "C" int32_t SystemNative_GetDomainName(uint8_t* name, int32_t nameLength)
#endif
return getdomainname(reinterpret_cast<char*>(name), namelen);
#elif HAVE_UNAME
// On Android, there's no getdomainname but we can use uname to fetch the domain name
// of the current device
size_t namelen = UnsignedCast(nameLength);
utsname uts;
// If uname returns an error, bail out.
if (uname(&uts) == -1)
{
return -1;
}
// If we don't have enough space to copy the name, bail out.
if (strlen(uts.domainname) >= namelen)
{
errno = EINVAL;
return -1;
}
// Copy the domain name
SafeStringCopy(reinterpret_cast<char*>(name), nameLength, uts.domainname);
return 0;
#else
// GetDomainName is not supported on this platform.
errno = ENOTSUP;
return -1;
#endif
}
extern "C" int32_t SystemNative_GetHostName(uint8_t* name, int32_t nameLength)
@@ -1493,8 +1509,14 @@ extern "C" Error SystemNative_SetIPv6MulticastOption(intptr_t socket, int32_t mu
ipv6_mreq opt;
memset(&opt, 0, sizeof(ipv6_mreq));
opt.ipv6mr_interface = static_cast<unsigned int>(option->InterfaceIndex);
opt.ipv6mr_interface =
#if IPV6MR_INTERFACE_UNSIGNED
static_cast<unsigned int>(option->InterfaceIndex);
#else
option->InterfaceIndex;
#endif
ConvertByteArrayToIn6Addr(opt.ipv6mr_multiaddr, &option->Address.Address[0], NUM_BYTES_IN_IPV6_ADDRESS);
int err = setsockopt(fd, IPPROTO_IP, optionName, &opt, sizeof(opt));
@@ -1730,7 +1752,11 @@ extern "C" Error SystemNative_Accept(intptr_t socket, uint8_t* socketAddress, in
socklen_t addrLen = static_cast<socklen_t>(*socketAddressLen);
int accepted;
#if defined(HAVE_ACCEPT_4) && defined(SOCK_CLOEXEC)
while (CheckInterrupted(accepted = accept4(fd, reinterpret_cast<sockaddr*>(socketAddress), &addrLen, SOCK_CLOEXEC)));
#else
while (CheckInterrupted(accepted = accept(fd, reinterpret_cast<sockaddr*>(socketAddress), &addrLen)));
#endif
if (accepted == -1)
{
*acceptedSocket = -1;
@@ -1752,7 +1778,15 @@ extern "C" Error SystemNative_Bind(intptr_t socket, uint8_t* socketAddress, int3
int fd = ToFileDescriptor(socket);
int err = bind(fd, reinterpret_cast<sockaddr*>(socketAddress), static_cast<socklen_t>(socketAddressLen));
int err = bind(
fd,
reinterpret_cast<sockaddr*>(socketAddress),
#if BIND_ADDRLEN_UNSIGNED
static_cast<socklen_t>(socketAddressLen));
#else
socketAddressLen);
#endif
return err == 0 ? PAL_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
}
@@ -1994,7 +2028,11 @@ static bool TryGetPlatformSocketOption(int32_t socketOptionName, int32_t socketO
optName = IP_DROP_MEMBERSHIP;
return true;
// case PAL_SO_IP_DONTFRAGMENT:
#ifdef IP_MTU_DISCOVER
case PAL_SO_IP_DONTFRAGMENT:
optName = IP_MTU_DISCOVER; // option values will also need to be translated
return true;
#endif
#ifdef IP_ADD_SOURCE_MEMBERSHIP
case PAL_SO_IP_ADD_SOURCE_MEMBERSHIP:
@@ -2156,6 +2194,17 @@ extern "C" Error SystemNative_GetSockOpt(
return SystemNative_ConvertErrorPlatformToPal(errno);
}
#ifdef IP_MTU_DISCOVER
// Handle some special cases for compatibility with Windows
if (socketOptionLevel == PAL_SOL_IP)
{
if (socketOptionName == PAL_SO_IP_DONTFRAGMENT)
{
*optionValue = *optionValue == IP_PMTUDISC_DO ? 1 : 0;
}
}
#endif
assert(optLen <= static_cast<socklen_t>(*optionLen));
*optionLen = static_cast<int32_t>(optLen);
return PAL_SUCCESS;
@@ -2164,7 +2213,7 @@ extern "C" Error SystemNative_GetSockOpt(
extern "C" Error
SystemNative_SetSockOpt(intptr_t socket, int32_t socketOptionLevel, int32_t socketOptionName, uint8_t* optionValue, int32_t optionLen)
{
if (optionLen < 0)
if (optionLen < 0 || optionValue == nullptr)
{
return PAL_EFAULT;
}
@@ -2211,6 +2260,15 @@ SystemNative_SetSockOpt(intptr_t socket, int32_t socketOptionLevel, int32_t sock
return err == 0 ? PAL_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
}
}
#ifdef IP_MTU_DISCOVER
else if (socketOptionLevel == PAL_SOL_IP)
{
if (socketOptionName == PAL_SO_IP_DONTFRAGMENT)
{
*optionValue = *optionValue != 0 ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
}
}
#endif
int optLevel, optName;
if (!TryGetPlatformSocketOption(socketOptionLevel, socketOptionName, optLevel, optName))
@@ -2314,6 +2372,9 @@ extern "C" Error SystemNative_Socket(int32_t addressFamily, int32_t socketType,
return PAL_EPROTONOSUPPORT;
}
#ifdef SOCK_CLOEXEC
platformSocketType |= SOCK_CLOEXEC;
#endif
*createdSocket = socket(platformAddressFamily, platformSocketType, platformProtocolType);
return *createdSocket != -1 ? PAL_SUCCESS : SystemNative_ConvertErrorPlatformToPal(errno);
}

View File

@@ -162,7 +162,7 @@ enum SocketOptionName : int32_t
PAL_SO_IP_MULTICAST_LOOP = 11,
PAL_SO_IP_ADD_MEMBERSHIP = 12,
PAL_SO_IP_DROP_MEMBERSHIP = 13,
// PAL_SO_IP_DONTFRAGMENT = 14,
PAL_SO_IP_DONTFRAGMENT = 14,
PAL_SO_IP_ADD_SOURCE_MEMBERSHIP = 15,
PAL_SO_IP_DROP_SOURCE_MEMBERSHIP = 16,
PAL_SO_IP_BLOCK_SOURCE = 17,

View File

@@ -0,0 +1,111 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
/*
Generate random bytes. The generated bytes are not cryptographically strong.
*/
extern "C" void SystemNative_GetNonCryptographicallySecureRandomBytes(uint8_t* buffer, int32_t bufferLength)
{
assert(buffer != NULL);
int rand_des;
char buf;
long num = 0;
static bool sMissingDevRandom;
static bool sMissingDevURandom;
static bool sInitializedMRand;
int i = 0;
if (i < bufferLength && !sMissingDevRandom)
{
// request non-blocking access to avoid hangs if the /dev/random is exhausted
// or just simply broken
if ((rand_des = open("/dev/random", O_RDONLY | O_NONBLOCK)) == -1)
{
if (errno == ENOENT)
{
sMissingDevRandom = true;
}
// Back off and try /dev/urandom.
}
else
{
for( ; i < bufferLength; i++)
{
if (read(rand_des, &buf, 1) < 1)
{
// the /dev/random pool has been exhausted. Fall back
// to /dev/urandom for the remainder of the buffer.
break;
}
*(buffer + i) ^= buf;
}
close(rand_des);
}
}
if (i < bufferLength && !sMissingDevURandom)
{
if ((rand_des = open("/dev/urandom", O_RDONLY, 0)) == -1)
{
if (errno == ENOENT)
{
sMissingDevURandom = true;
}
// Back off and try mrand48.
}
else
{
for( ; i < bufferLength; i++)
{
if (read(rand_des, &buf, 1) < 1)
{
// Fall back to srand48 for the remainder of the buffer.
break;
}
*(buffer + i) ^= buf;
}
close(rand_des);
}
}
if (!sInitializedMRand)
{
srand48(time(NULL));
sInitializedMRand = true;
}
// always xor srand48 over the whole buffer to get some randomness
// in case /dev/random is not really random
for(i = 0; i < bufferLength; i++)
{
if (i % 4 == 0)
{
num = lrand48();
}
*(buffer + i) ^= num;
num >>= 8;
}
}

View File

@@ -55,6 +55,7 @@ static_assert(PAL_CURLE_OUT_OF_MEMORY == CURLE_OUT_OF_MEMORY, "");
static_assert(PAL_CURLE_OPERATION_TIMEDOUT == CURLE_OPERATION_TIMEDOUT, "");
static_assert(PAL_CURLE_ABORTED_BY_CALLBACK == CURLE_ABORTED_BY_CALLBACK, "");
static_assert(PAL_CURLE_UNKNOWN_OPTION == CURLE_UNKNOWN_OPTION, "");
static_assert(PAL_CURLE_RECV_ERROR == CURLE_RECV_ERROR, "");
static_assert(PAL_CURLE_SEND_FAIL_REWIND == CURLE_SEND_FAIL_REWIND, "");
static_assert(PAL_CURL_HTTP_VERSION_NONE == CURL_HTTP_VERSION_NONE, "");

View File

@@ -74,6 +74,7 @@ enum PAL_CURLcode : int32_t
PAL_CURLE_OPERATION_TIMEDOUT = 28,
PAL_CURLE_ABORTED_BY_CALLBACK = 42,
PAL_CURLE_UNKNOWN_OPTION = 48,
PAL_CURLE_RECV_ERROR = 56,
PAL_CURLE_SEND_FAIL_REWIND = 65,
};

View File

@@ -5,11 +5,24 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_definitions(-DPIC=1)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(SECURITY_LIBRARY Security)
set(NATIVECRYPTO_SOURCES
pal_digest.cpp
pal_ecc.cpp
pal_hmac.cpp
pal_keychain.cpp
pal_random.cpp
pal_rsa.cpp
pal_sec.cpp
pal_seckey.cpp
pal_signverify.cpp
pal_ssl.cpp
pal_symmetric.cpp
pal_trust.cpp
pal_x509.cpp
pal_x509chain.cpp
)
add_library(System.Security.Cryptography.Native.Apple
@@ -22,6 +35,8 @@ add_library(System.Security.Cryptography.Native.Apple
set_target_properties(System.Security.Cryptography.Native.Apple PROPERTIES PREFIX "")
target_link_libraries(System.Security.Cryptography.Native.Apple
${COREFOUNDATION_LIBRARY}
${SECURITY_LIBRARY}
)
install_library_and_symbols (System.Security.Cryptography.Native.Apple)

View File

@@ -74,7 +74,7 @@ extern "C" DigestCtx* AppleCryptoNative_DigestCreate(PAL_HashAlgorithm algorithm
return digestCtx;
}
extern "C" int AppleCryptoNative_DigestUpdate(DigestCtx* ctx, uint8_t* pBuf, int32_t cbBuf)
extern "C" int32_t AppleCryptoNative_DigestUpdate(DigestCtx* ctx, uint8_t* pBuf, int32_t cbBuf)
{
if (cbBuf == 0)
return 1;
@@ -100,12 +100,12 @@ extern "C" int AppleCryptoNative_DigestUpdate(DigestCtx* ctx, uint8_t* pBuf, int
}
}
extern "C" int AppleCryptoNative_DigestFinal(DigestCtx* ctx, uint8_t* pOutput, int32_t cbOutput)
extern "C" int32_t AppleCryptoNative_DigestFinal(DigestCtx* ctx, uint8_t* pOutput, int32_t cbOutput)
{
if (ctx == nullptr || pOutput == nullptr || cbOutput < ctx->cbDigest)
return -1;
int ret = 0;
int32_t ret = 0;
switch (ctx->algorithm)
{

View File

@@ -41,11 +41,11 @@ Apply cbBuf bytes of data from pBuf to the ongoing digest represented in ctx.
Returns 1 on success, 0 on failure, any other value on invalid inputs/state.
*/
extern "C" int AppleCryptoNative_DigestUpdate(DigestCtx* ctx, uint8_t* pBuf, int32_t cbBuf);
extern "C" int32_t AppleCryptoNative_DigestUpdate(DigestCtx* ctx, uint8_t* pBuf, int32_t cbBuf);
/*
Complete the digest in ctx, copying the results to pOutput, and reset ctx for a new digest.
Returns 1 on success, 0 on failure, any other value on invalid inputs/state.
*/
extern "C" int AppleCryptoNative_DigestFinal(DigestCtx* ctx, uint8_t* pOutput, int32_t cbOutput);
extern "C" int32_t AppleCryptoNative_DigestFinal(DigestCtx* ctx, uint8_t* pOutput, int32_t cbOutput);

View File

@@ -0,0 +1,98 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#include "pal_ecc.h"
extern "C" int32_t AppleCryptoNative_EccGenerateKey(
int32_t keySizeBits, SecKeychainRef tempKeychain, SecKeyRef* pPublicKey, SecKeyRef* pPrivateKey, int32_t* pOSStatus)
{
if (pPublicKey != nullptr)
*pPublicKey = nullptr;
if (pPrivateKey != nullptr)
*pPrivateKey = nullptr;
if (pPublicKey == nullptr || pPrivateKey == nullptr || pOSStatus == nullptr)
return kErrorBadInput;
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(nullptr, 2, &kCFTypeDictionaryKeyCallBacks, nullptr);
CFNumberRef cfKeySizeValue = CFNumberCreate(nullptr, kCFNumberIntType, &keySizeBits);
OSStatus status;
if (attributes != nullptr && cfKeySizeValue != nullptr)
{
CFDictionaryAddValue(attributes, kSecAttrKeyType, kSecAttrKeyTypeEC);
CFDictionaryAddValue(attributes, kSecAttrKeySizeInBits, cfKeySizeValue);
CFDictionaryAddValue(attributes, kSecUseKeychain, tempKeychain);
status = SecKeyGeneratePair(attributes, pPublicKey, pPrivateKey);
if (status == noErr)
{
status = ExportImportKey(pPublicKey, kSecItemTypePublicKey);
}
if (status == noErr)
{
status = ExportImportKey(pPrivateKey, kSecItemTypePrivateKey);
}
}
else
{
status = errSecAllocate;
}
if (attributes != nullptr)
CFRelease(attributes);
if (cfKeySizeValue != nullptr)
CFRelease(cfKeySizeValue);
*pOSStatus = status;
return status == noErr;
}
extern "C" uint64_t AppleCryptoNative_EccGetKeySizeInBits(SecKeyRef publicKey)
{
if (publicKey == nullptr)
{
return 0;
}
size_t blockSize = SecKeyGetBlockSize(publicKey);
// This seems to be the expected size of an ECDSA signature for this key.
// But since Apple uses the DER SEQUENCE(r, s) format the signature size isn't
// fixed. It might be trying to encode the biggest the DER value could be:
//
// 256: r is 32 bytes, but maybe one padding byte, so 33.
// s is 32 bytes, but maybe one padding byte, so 33.
// each of those values gets one tag and one length byte
// 35 * 2 is 70 payload bytes for the sequence, so one length byte
// and one tag byte, makes 72.
//
// 384: r,s are 48 bytes, plus padding, length, and tag: 51
// 2 * 51 = 102, requires one length byte and one tag byte, 104.
//
// 521: neither r nor s can have the high bit set, no padding. 66 content bytes
// plus tag and length is 68.
// 2 * 68 is 136, since it's greater than 127 it takes 2 length bytes
// so 136 + 2 + 1 = 139. Looks like they accounted for padding bytes anyways.
//
// This completely needs to be revisited if Apple adds support for "generic" ECC.
//
// Word of caution: While seeking meaning in these numbers I ran across a snippet of code
// which suggests that on iOS (vs macOS) they use a different set of reasoning and produce
// different numbers (they used (8 + 2*thisValue) on iOS for "signature length").
switch (blockSize)
{
case 72:
return 256;
case 104:
return 384;
case 141:
return 521;
}
return 0;
}

View File

@@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#pragma once
#include "pal_seckey.h"
#include <Security/Security.h>
/*
Generate an ECC keypair of the specified size.
Returns 1 on success, 0 on failure. On failure, *pOSStatus should carry the OS failure code.
*/
extern "C" int32_t AppleCryptoNative_EccGenerateKey(int32_t keySizeBits,
SecKeychainRef tempKeychain,
SecKeyRef* pPublicKey,
SecKeyRef* pPrivateKey,
int32_t* pOSStatus);
/*
Get the keysize, in bits, of an ECC key.
Returns the keysize, in bits, of the ECC key, or 0 on error.
*/
extern "C" uint64_t AppleCryptoNative_EccGetKeySizeInBits(SecKeyRef publicKey);

View File

@@ -38,7 +38,7 @@ static CCHmacAlgorithm PalAlgorithmToAppleAlgorithm(PAL_HashAlgorithm algorithm)
}
}
static int GetHmacOutputSize(PAL_HashAlgorithm algorithm)
static int32_t GetHmacOutputSize(PAL_HashAlgorithm algorithm)
{
switch (algorithm)
{
@@ -79,7 +79,7 @@ extern "C" HmacCtx* AppleCryptoNative_HmacCreate(PAL_HashAlgorithm algorithm, in
return hmacCtx;
}
extern "C" int AppleCryptoNative_HmacInit(HmacCtx* ctx, uint8_t* pbKey, int32_t cbKey)
extern "C" int32_t AppleCryptoNative_HmacInit(HmacCtx* ctx, uint8_t* pbKey, int32_t cbKey)
{
if (ctx == nullptr || cbKey < 0)
return 0;
@@ -91,7 +91,7 @@ extern "C" int AppleCryptoNative_HmacInit(HmacCtx* ctx, uint8_t* pbKey, int32_t
return 1;
}
extern "C" int AppleCryptoNative_HmacUpdate(HmacCtx* ctx, uint8_t* pbData, int32_t cbData)
extern "C" int32_t AppleCryptoNative_HmacUpdate(HmacCtx* ctx, uint8_t* pbData, int32_t cbData)
{
if (cbData == 0)
return 1;
@@ -103,7 +103,7 @@ extern "C" int AppleCryptoNative_HmacUpdate(HmacCtx* ctx, uint8_t* pbData, int32
return 1;
}
extern "C" int AppleCryptoNative_HmacFinal(HmacCtx* ctx, uint8_t* pbOutput)
extern "C" int32_t AppleCryptoNative_HmacFinal(HmacCtx* ctx, uint8_t* pbOutput)
{
if (ctx == nullptr || pbOutput == nullptr)
return 0;

Some files were not shown because too many files have changed in this diff Show More