Skip to content
This repository was archived by the owner on Dec 27, 2019. It is now read-only.
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
8 changes: 8 additions & 0 deletions contrib/examples/windows-pipe/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CC := x86_64-w64-mingw32-gcc
CFLAGS ?= -O3
CFLAGS += -Wall
enumerate-and-get.exe: enumerate-and-get.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $<
clean:
rm -f enumerate-and-get.exe
.PHONY: clean
5 changes: 5 additions & 0 deletions contrib/examples/windows-pipe/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Connecting to the Windows tunnel service
========================================

Porting wg(8) to Windows will require a bit of work. So, in the meantime,
here's a small example of how to enumerate and connect to the named pipe.
128 changes: 128 additions & 0 deletions contrib/examples/windows-pipe/enumerate-and-get.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015-2019 Jason A. Donenfeld <[email protected]>. All Rights Reserved.
*/

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <stdbool.h>

static HANDLE open_wireguard_pipe(const char *name)
{
char fname[0x1000];
HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token, pipe_handle;
PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
BOOL ret;
DWORD pid = 0, last_error;
TOKEN_PRIVILEGES privileges = {
.PrivilegeCount = 1,
.Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
};

if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid)) {
fprintf(stderr, "Error: LookupPrivilegeValue: 0x%lx\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
if (!ImpersonateSelf(SecurityImpersonation)) {
fprintf(stderr, "Error: ImpersonateSelf: 0x%lx\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token)) {
fprintf(stderr, "Error: OpenThreadToken: 0x%lx\n", GetLastError());
return INVALID_HANDLE_VALUE;
}
if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) {
fprintf(stderr, "Error: AdjustTokenPrivileges: 0x%lx\n", GetLastError());
CloseHandle(thread_token);
return INVALID_HANDLE_VALUE;
}
CloseHandle(thread_token);

process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (process_snapshot == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Error: CreateToolhelp32Snapshot: 0x%lx\n", GetLastError());
RevertToSelf();
return INVALID_HANDLE_VALUE;
}
for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) {
if (!strcasecmp(entry.szExeFile, "winlogon.exe")) {
pid = entry.th32ProcessID;
break;
}
}
CloseHandle(process_snapshot);
if (!pid) {
fprintf(stderr, "Error: unable to find winlogon.exe\n");
RevertToSelf();
return INVALID_HANDLE_VALUE;
}

winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!winlogon_process) {
fprintf(stderr, "Error: OpenProcess: 0x%lx\n", GetLastError());
RevertToSelf();
return INVALID_HANDLE_VALUE;
}

if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token)) {
fprintf(stderr, "Error: OpenProcessToken: 0x%lx\n", GetLastError());
CloseHandle(winlogon_process);
RevertToSelf();
return INVALID_HANDLE_VALUE;
}
CloseHandle(winlogon_process);

if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) {
fprintf(stderr, "Error: DuplicateToken: 0x%lx\n", GetLastError());
CloseHandle(winlogon_token);
RevertToSelf();
return INVALID_HANDLE_VALUE;
}
CloseHandle(winlogon_token);

if (!SetThreadToken(NULL, duplicated_token)) {
fprintf(stderr, "Error: SetThreadToken: 0x%lx\n", GetLastError());
CloseHandle(duplicated_token);
RevertToSelf();
return INVALID_HANDLE_VALUE;
}
CloseHandle(duplicated_token);

snprintf(fname, sizeof(fname), "\\\\.\\pipe\\WireGuard\\%s", name);
pipe_handle = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
last_error = GetLastError();
RevertToSelf();
if (pipe_handle == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error: CreateFile: 0x%lx\n", last_error);
return pipe_handle;
}

int main(int argc, char *argv[])
{
WIN32_FIND_DATA find_data;
HANDLE find_handle, pipe_handle;
char tunnel_info[0x10000];
DWORD written;

find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data);
if (find_handle == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error: FindFirstFile: 0x%lx\n", GetLastError());
do {
if (!strncmp("WireGuard\\", find_data.cFileName, 10)) {
printf("name=%s\n", find_data.cFileName + 10);
pipe_handle = open_wireguard_pipe(find_data.cFileName + 10);
if (pipe_handle == INVALID_HANDLE_VALUE)
continue;
if (!WriteFile(pipe_handle, "get=1\n\n", 7, &written, NULL))
continue;
if (!ReadFile(pipe_handle, tunnel_info, sizeof(tunnel_info) - 1, &written, NULL))
continue;
CloseHandle(pipe_handle);
tunnel_info[written] = '\0';
fputs(tunnel_info, stdout);
}
} while (FindNextFile(find_handle, &find_data));

return 0;
}
3 changes: 3 additions & 0 deletions src/compat/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,9 @@ struct __kernel_timespec {
#define skb_probe_transport_header(a) skb_probe_transport_header(a, 0)
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) && !defined(ISRHEL7)
#define ignore_df local_df
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0)
/* Note that all intentional uses of the non-_bh variety need to explicitly
Expand Down
29 changes: 27 additions & 2 deletions src/compat/simd/include/linux/simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <asm/fpu/api.h>
#elif defined(CONFIG_KERNEL_MODE_NEON)
#include <asm/neon.h>
#elif defined(CONFIG_ALTIVEC) || defined(CONFIG_VSX)
#include <asm/switch_to.h>
#include <asm/cputable.h>
#endif

typedef enum {
Expand All @@ -30,13 +33,24 @@ static inline void simd_get(simd_context_t *ctx)

static inline void simd_put(simd_context_t *ctx)
{
if (*ctx & HAVE_SIMD_IN_USE) {
#if defined(CONFIG_X86_64)
if (*ctx & HAVE_SIMD_IN_USE)
kernel_fpu_end();
#elif defined(CONFIG_KERNEL_MODE_NEON)
if (*ctx & HAVE_SIMD_IN_USE)
kernel_neon_end();
#elif defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
disable_kernel_vsx();
preempt_enable();
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
disable_kernel_altivec();
preempt_enable();
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
disable_kernel_fp();
preempt_enable();
}
#endif
}
*ctx = HAVE_NO_SIMD;
}

Expand All @@ -62,6 +76,17 @@ static __must_check inline bool simd_use(simd_context_t *ctx)
kernel_fpu_begin();
#elif defined(CONFIG_KERNEL_MODE_NEON)
kernel_neon_begin();
#elif defined(CONFIG_PPC32) || defined(CONFIG_PPC64)
if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
preempt_disable();
enable_kernel_vsx();
} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
preempt_disable();
enable_kernel_altivec();
} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
preempt_disable();
enable_kernel_fp();
}
#endif
*ctx |= HAVE_SIMD_IN_USE;
return true;
Expand Down
20 changes: 19 additions & 1 deletion src/crypto/Kbuild.include
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ endif
ifeq ($(CONFIG_MIPS)$(CONFIG_64BIT),yy)
CONFIG_ZINC_ARCH_MIPS64 := y
endif
ifeq ($(CONFIG_PPC32),y)
CONFIG_ZINC_ARCH_PPC32 := y
endif
ifeq ($(CONFIG_PPC64),y)
CONFIG_ZINC_ARCH_PPC64 := y
endif

zinc-y += chacha20/chacha20.o
zinc-$(CONFIG_ZINC_ARCH_X86_64) += chacha20/chacha20-x86_64.o
zinc-$(CONFIG_ZINC_ARCH_ARM) += chacha20/chacha20-arm.o chacha20/chacha20-unrolled-arm.o
zinc-$(CONFIG_ZINC_ARCH_ARM64) += chacha20/chacha20-arm64.o
zinc-$(CONFIG_ZINC_ARCH_MIPS) += chacha20/chacha20-mips.o
AFLAGS_chacha20-mips.o += -O2 # This is required to fill the branch delay slots
zinc-$(CONFIG_ZINC_ARCH_PPC32) += chacha20/chacha20-ppc.o
zinc-$(CONFIG_ZINC_ARCH_PPC64) += chacha20/chacha20-ppc.o

zinc-y += poly1305/poly1305.o
zinc-$(CONFIG_ZINC_ARCH_X86_64) += poly1305/poly1305-x86_64.o
Expand All @@ -28,6 +36,8 @@ zinc-$(CONFIG_ZINC_ARCH_ARM64) += poly1305/poly1305-arm64.o
zinc-$(CONFIG_ZINC_ARCH_MIPS) += poly1305/poly1305-mips.o
AFLAGS_poly1305-mips.o += -O2 # This is required to fill the branch delay slots
zinc-$(CONFIG_ZINC_ARCH_MIPS64) += poly1305/poly1305-mips64.o
zinc-$(CONFIG_ZINC_ARCH_PPC32) += poly1305/poly1305-ppc.o
zinc-$(CONFIG_ZINC_ARCH_PPC64) += poly1305/poly1305-ppc.o

zinc-y += chacha20poly1305.o

Expand All @@ -38,12 +48,18 @@ zinc-y += curve25519/curve25519.o
zinc-$(CONFIG_ZINC_ARCH_ARM) += curve25519/curve25519-arm.o

quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $< > $@
cmd_perlasm = $(PERL) $(perlflags-y) $< $(perlargs-y) > $@
$(obj)/%.S: $(src)/%.pl FORCE
$(call if_changed,perlasm)
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
targets := $(patsubst $(kbuild-dir)/%.pl,%.S,$(wildcard $(patsubst %.o,$(kbuild-dir)/crypto/zinc/%.pl,$(zinc-y) $(zinc-m) $(zinc-))))

perlargs-$(CONFIG_ZINC_ARCH_PPC32) += linux32
ifeq ($(CONFIG_ZINC_ARCH_PPC64),y)
perlargs-$(CONFIG_CPU_BIG_ENDIAN) += linux64
perlargs-$(CONFIG_CPU_LITTLE_ENDIAN) += linux64le
endif

# Old kernels don't set this, which causes trouble.
.SECONDARY:

Expand All @@ -54,4 +70,6 @@ ccflags-$(CONFIG_ZINC_ARCH_ARM) += -DCONFIG_ZINC_ARCH_ARM
ccflags-$(CONFIG_ZINC_ARCH_ARM64) += -DCONFIG_ZINC_ARCH_ARM64
ccflags-$(CONFIG_ZINC_ARCH_MIPS) += -DCONFIG_ZINC_ARCH_MIPS
ccflags-$(CONFIG_ZINC_ARCH_MIPS64) += -DCONFIG_ZINC_ARCH_MIPS64
ccflags-$(CONFIG_ZINC_ARCH_PPC32) += -DCONFIG_ZINC_ARCH_PPC32
ccflags-$(CONFIG_ZINC_ARCH_PPC64) += -DCONFIG_ZINC_ARCH_PPC64
ccflags-$(CONFIG_WIREGUARD_DEBUG) += -DCONFIG_ZINC_SELFTEST
66 changes: 66 additions & 0 deletions src/crypto/zinc/chacha20/chacha20-ppc-glue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
* Copyright (C) 2019 Shawn Landden <[email protected]>. All Rights Reserved.
*/

asmlinkage void ChaCha20_ctr32_int(u8 *out, const u8 *inp,
size_t len, const u32 key[8],
const u32 counter[4]);
asmlinkage void ChaCha20_ctr32_vmx(u8 *out, const u8 *inp,
size_t len, const u32 key[8],
const u32 counter[4]);
asmlinkage void ChaCha20_ctr32_vsx(u8 *out, const u8 *inp,
size_t len, const u32 key[8],
const u32 counter[4]);
static bool *const chacha20_nobs[] __initconst = { };
static void __init chacha20_fpu_init(void) {}

static inline bool chacha20_arch(struct chacha20_ctx *ctx, u8 *dst,
const u8 *src, size_t len,
simd_context_t *simd_context)
{
void (*ChaCha20SIMD)(u8 *out, const u8 *inp,
size_t len, const u32 key[8],
const u32 counter[4]);

/* SIMD disables preemption, so relax after processing each page. */
BUILD_BUG_ON(PAGE_SIZE < CHACHA20_BLOCK_SIZE ||
PAGE_SIZE % CHACHA20_BLOCK_SIZE);

if (cpu_has_feature(CPU_FTR_VSX_COMP))
ChaCha20SIMD = &ChaCha20_ctr32_vsx;
else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
ChaCha20SIMD = &ChaCha20_ctr32_vmx;
else {
ChaCha20_ctr32_int(dst, src, len, ctx->key, ctx->counter);
return true;
}

for (;;) {
if (len >= CHACHA20_BLOCK_SIZE * 3 && simd_use(simd_context)) {
const size_t bytes = min_t(size_t, len, PAGE_SIZE);

ChaCha20SIMD(dst, src, bytes, ctx->key, ctx->counter);
ctx->counter[0] += (bytes + 63) / 64;
len -= bytes;
if (!len)
break;
dst += bytes;
src += bytes;
simd_relax(simd_context);
} else {
ChaCha20_ctr32_int(dst, src, len, ctx->key, ctx->counter);
ctx->counter[0] += (len + 63) / 64;
return true;
}
}
return true;
}

static inline bool hchacha20_arch(u32 derived_key[CHACHA20_KEY_WORDS],
const u8 nonce[HCHACHA20_NONCE_SIZE],
const u8 key[HCHACHA20_KEY_SIZE],
simd_context_t *simd_context)
{
return false;
}
Loading