Download raw body.
[UPDATE] security/veracrypt 1.25.9 -> 1.26.29 + improvements
Hello,
Please find attached a patch updating security/veracrypt from 1.25.9 to
1.26.29, including native OpenBSD privilege elevation and FFS support.
Upstream source:
https://launchpad.net/veracrypt/trunk/1.26.29/+download/
The main OpenBSD-specific changes are:
- Replace sudo with doas for the privileged core service.
- Support restricted doas.conf rules allowing only --core-service.
- Handle password authentication through a private pseudoterminal,
without exposing credentials through argv or the environment.
- Add native FFS creation using /sbin/newfs through a restricted
privileged service request.
- Preserve FAT as the default for noninteractive volume creation.
- Remove the obsolete coreutils dependency and add pcsc-lite.
- Fix reproducible-build date handling with OpenBSD's awk.
- Update distinfo, PLIST, patches, documentation and the desktop icon.
- Enable the upstream cryptographic self-tests through make test.
The doas implementation supports password authentication and retries
after incorrect credentials. The FFS formatter validates the target vnd
device before requesting the privileged operation.
I built, packaged, installed and tested VeraCrypt 1.26.29 on OpenBSD
8.0-current amd64.
The cryptographic self-tests passed, including when executed by an
unprivileged user.
I also verified restricted doas permissions, password authentication,
FFS volume creation, mounting, writing, reading, unmounting and
remounting. File integrity was confirmed using SHA256, and fsck_ffs
reported no errors.
The existing FAT creation and mounting behavior was also tested
successfully.
These tests uncovered and helped resolve several privilege-related
problems that were not apparent when running as root.
Testing was limited to the CLI and regular file-backed volumes on amd64.
The GUI builds but has not been tested interactively. Other
architectures, physical devices, hidden volumes and smartcards remain
untested.
I would particularly appreciate review of the privilege elevation
changes and additional testing on other architectures.
Thank you for your time and consideration.
Best regards,
David.
Index: security/veracrypt/Makefile
===================================================================
RCS file: /cvs/ports/security/veracrypt/Makefile,v
diff -u -p -u -r1.8 Makefile
--- security/veracrypt/Makefile 17 Dec 2024 05:49:59 -0000 1.8
+++ security/veracrypt/Makefile 14 Oct 2026 19:04:23 -0000
@@ -2,23 +2,22 @@ BROKEN-sparc64= relocation truncated to
COMMENT= free open source disk encryption software
-V= 1.25.9
+V= 1.26.29
DISTNAME= VeraCrypt_${V}_Source
PKGNAME= veracrypt-${V}
CATEGORIES= security
HOMEPAGE= https://www.veracrypt.fr/
-REVISION= 1
MAINTAINER= Tietoturvamies <main@tietoturvamies.fi>
# Apache2
-PERMIT_PACKAGE= yes
+PERMIT_PACKAGE= Yes
SITES= https://launchpad.net/veracrypt/trunk/${V}/+download/
EXTRACT_SUFX= .tar.bz2
FIX_EXTRACT_PERMISSIONS=Yes
-# C++11
+# C++14
COMPILER= base-clang ports-gcc
CXXFLAGS_base-clang = -std=c++14
@@ -26,16 +25,16 @@ CXXFLAGS_base-clang = -std=c++14
WANTLIB += ${COMPILER_LIBCXX} c m fuse wx_baseu-3.2 wx_gtk3u_core-3.2
BUILD_DEPENDS= devel/yasm \
- sysutils/coreutils
+ security/pcsc-lite
LIB_DEPENDS= x11/wxWidgets
RUN_DEPENDS= devel/desktop-file-utils \
- security/sudo
+ security/pcsc-lite
WRKDIST= ${WRKDIR}/src
USE_GMAKE= Yes
-ALL_TARGET=
+ALL_TARGET=
MAKE_FLAGS= VERBOSE=1 \
NOTEST=1 \
CC="${CC}" \
@@ -43,7 +42,6 @@ MAKE_FLAGS= VERBOSE=1 \
PORT_CFLAGS="${CFLAGS}" \
PORT_CXXFLAGS="${CXXFLAGS}"
-NO_TEST= Yes
.if ${MACHINE_ARCH:Mi386}
MAKE_ENV+= LFLAGS=-Wl,-z,notext
@@ -52,13 +50,16 @@ MAKE_ENV+= LFLAGS=-Wl,-z,notext
pre-configure:
${SUBST_CMD} ${WRKSRC}/Setup/FreeBSD/veracrypt.desktop
+do-test:
+ ${WRKSRC}/Main/veracrypt --text --test
+
do-install:
${INSTALL_PROGRAM} ${WRKSRC}/Main/veracrypt ${PREFIX}/bin
${INSTALL_DATA_DIR} ${PREFIX}/share/applications
${INSTALL_DATA} ${WRKSRC}/Setup/FreeBSD/veracrypt.desktop \
${PREFIX}/share/applications
${INSTALL_DATA_DIR} ${PREFIX}/share/pixmaps/
- ${INSTALL_DATA} ${WRKSRC}/Resources/Icons/VeraCrypt-48x48.xpm \
- ${PREFIX}/share/pixmaps/veracrypt.xpm
+ ${INSTALL_DATA} ${WRKSRC}/Resources/Icons/VeraCrypt-48x48.png \
+ ${PREFIX}/share/pixmaps/veracrypt.png
.include <bsd.port.mk>
Index: security/veracrypt/distinfo
===================================================================
RCS file: /cvs/ports/security/veracrypt/distinfo,v
diff -u -p -u -r1.2 distinfo
--- security/veracrypt/distinfo 14 Mar 2022 11:07:46 -0000 1.2
+++ security/veracrypt/distinfo 14 Oct 2026 19:04:23 -0000
@@ -1,2 +1,2 @@
-SHA256 (VeraCrypt_1.25.9_Source.tar.bz2) = drbhgYS8IaQdKUn/Y9ch1JBUpxbO/zpL13tcNRC3lK8=
-SIZE (VeraCrypt_1.25.9_Source.tar.bz2) = 24438846
+SHA256 (VeraCrypt_1.26.29_Source.tar.bz2) = YIJnMeKYK0vSMeOTDoWkQ5EWljhnGhsgDFGPjItGyyo=
+SIZE (VeraCrypt_1.26.29_Source.tar.bz2) = 36302144
Index: security/veracrypt/patches/patch-Makefile
===================================================================
RCS file: /cvs/ports/security/veracrypt/patches/patch-Makefile,v
diff -u -p -u -r1.3 patch-Makefile
--- security/veracrypt/patches/patch-Makefile 14 Mar 2022 11:07:46 -0000 1.3
+++ security/veracrypt/patches/patch-Makefile 14 Oct 2026 19:04:23 -0000
@@ -4,16 +4,16 @@
Index: Makefile
--- Makefile.orig
+++ Makefile
-@@ -47,7 +47,7 @@ export CFLAGS := -Wall
+@@ -50,7 +50,7 @@
export CXXFLAGS := -Wall -Wno-unused-parameter
- C_CXX_FLAGS := -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES -I$(BASE_DIR) -I$(BASE_DIR)/Crypto
+ C_CXX_FLAGS := -MMD -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES -I$(BASE_DIR) -I$(BASE_DIR)/Crypto -DARGON2_NO_THREADS -I$(BASE_DIR)/Crypto/Argon2/include
export ASFLAGS := -D __GNUC__ -D __YASM__
-export LFLAGS :=
+export LFLAGS ?=
+ export PKG_CONFIG ?= pkg-config
export PKG_CONFIG_PATH ?= /usr/local/lib/pkgconfig
-
-@@ -109,7 +109,7 @@ endif
+@@ -111,7 +111,7 @@
ifeq "$(TC_BUILD_CONFIG)" "Release"
@@ -22,7 +22,7 @@ Index: Makefile
export WX_BUILD_DIR ?= $(BASE_DIR)/wxrelease
WX_CONFIGURE_FLAGS += --disable-debug_flag --disable-debug_gdb --disable-debug_info
-@@ -441,8 +441,8 @@ endif
+@@ -585,8 +585,8 @@
#------ Common configuration ------
@@ -32,4 +32,4 @@ Index: Makefile
+CXXFLAGS := $(C_CXX_FLAGS) $(CXXFLAGS) $(TC_EXTRA_CXXFLAGS) $(PORT_CXXFLAGS)
LFLAGS := $(LFLAGS) $(TC_EXTRA_LFLAGS)
- WX_CONFIGURE_FLAGS += --enable-unicode -disable-shared --disable-dependency-tracking --enable-exceptions --enable-std_string --enable-dataobj --enable-mimetype
+ #------ Reproducible build configuration ------
Index: security/veracrypt/patches/patch-Setup_FreeBSD_veracrypt_desktop
===================================================================
RCS file: /cvs/ports/security/veracrypt/patches/patch-Setup_FreeBSD_veracrypt_desktop,v
diff -u -p -u -r1.2 patch-Setup_FreeBSD_veracrypt_desktop
--- security/veracrypt/patches/patch-Setup_FreeBSD_veracrypt_desktop 11 Mar 2022 19:54:08 -0000 1.2
+++ security/veracrypt/patches/patch-Setup_FreeBSD_veracrypt_desktop 14 Oct 2026 19:04:23 -0000
@@ -1,12 +1,15 @@
+Point the desktop launcher at the executable installed under TRUEPREFIX
+rather than the upstream /usr/bin path.
+
Index: Setup/FreeBSD/veracrypt.desktop
--- Setup/FreeBSD/veracrypt.desktop.orig
+++ Setup/FreeBSD/veracrypt.desktop
-@@ -3,7 +3,7 @@ Encoding=UTF-8
- Name=VeraCrypt
- GenericName=VeraCrypt
- Comment=VeraCrypt
--Exec=/usr/bin/veracrypt
-+Exec=${TRUEPREFIX}/bin/veracrypt
+@@ -4,7 +4,7 @@
+ GenericName=VeraCrypt volume manager
+ Comment=Create and mount VeraCrypt encrypted volumes
Icon=veracrypt
+-Exec=/usr/bin/veracrypt %f
++Exec=${TRUEPREFIX}/bin/veracrypt %f
+ Categories=Security;Utility;Filesystem
+ Keywords=encryption,filesystem
Terminal=false
- Type=Application
Index: security/veracrypt/pkg/PLIST
===================================================================
RCS file: /cvs/ports/security/veracrypt/pkg/PLIST,v
diff -u -p -u -r1.2 PLIST
--- security/veracrypt/pkg/PLIST 11 Mar 2022 19:54:08 -0000 1.2
+++ security/veracrypt/pkg/PLIST 14 Oct 2026 19:04:23 -0000
@@ -1,5 +1,6 @@
@bin bin/veracrypt
share/applications/veracrypt.desktop
+share/doc/pkg-readmes/${PKGSTEM}
share/pixmaps/
-share/pixmaps/veracrypt.xpm
+share/pixmaps/veracrypt.png
@tag update-desktop-database
Index: security/veracrypt/patches/patch-Build_Tools_source_date_epoch_sh
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Build_Tools_source_date_epoch_sh
@@ -0,0 +1,20 @@
+Continue the month_number ternary expression explicitly: OpenBSD's awk
+does not accept a bare newline after ':' as a line continuation, so the
+release date could not be derived from Common/Tcdefs.h.
+
+Index: Build/Tools/source_date_epoch.sh
+--- Build/Tools/source_date_epoch.sh.orig
++++ Build/Tools/source_date_epoch.sh
+@@ -60,9 +60,9 @@
+ RELEASE_EPOCH=$(awk '
+ function leap(y) { return ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) }
+ function month_number(name) {
+- return (name == "January" ? 1 : name == "February" ? 2 : name == "March" ? 3 :
+- name == "April" ? 4 : name == "May" ? 5 : name == "June" ? 6 :
+- name == "July" ? 7 : name == "August" ? 8 : name == "September" ? 9 :
++ return (name == "January" ? 1 : name == "February" ? 2 : name == "March" ? 3 : \
++ name == "April" ? 4 : name == "May" ? 5 : name == "June" ? 6 : \
++ name == "July" ? 7 : name == "August" ? 8 : name == "September" ? 9 : \
+ name == "October" ? 10 : name == "November" ? 11 : name == "December" ? 12 : 0);
+ }
+ function mdays(m, y) { return (m == 2 ? 28 + leap(y) : (m == 4 || m == 6 || m == 9 || m == 11 ? 30 : 31)) }
Index: security/veracrypt/patches/patch-Common_Tcdefs_h
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Common_Tcdefs_h
@@ -0,0 +1,16 @@
+Set TC_STR_RELEASE_DATE to June 9, 2026, matching TC_RELEASE_DATE_DAY
+and the upstream "Set release date to June 9th 2026" commit. The awk
+helper in Build/Tools/source_date_epoch.sh requires both dates to agree.
+
+Index: Common/Tcdefs.h
+--- Common/Tcdefs.h.orig
++++ Common/Tcdefs.h
+@@ -73,7 +73,7 @@
+ #define VERSION_NUM 0x0126
+
+ // Release date
+-#define TC_STR_RELEASE_DATE L"June 8, 2026"
++#define TC_STR_RELEASE_DATE L"June 9, 2026"
+ #define TC_RELEASE_DATE_YEAR 2026
+ #define TC_RELEASE_DATE_MONTH 6
+ #define TC_RELEASE_DATE_DAY 9
Index: security/veracrypt/patches/patch-Core_Unix_CoreServiceRequest_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreServiceRequest_cpp
@@ -0,0 +1,42 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Core/Unix/CoreServiceRequest.cpp.orig
++++ Core/Unix/CoreServiceRequest.cpp
+@@ -245,6 +245,27 @@
+ }
+ #endif
+
++#ifdef TC_OPENBSD
++ void ExecuteOpenBSDFFSFormatterRequest::Deserialize (shared_ptr <Stream> stream)
++ {
++ CoreServiceRequest::Deserialize (stream);
++ Serializer sr (stream);
++ Device = sr.DeserializeWString ("Device");
++ }
++
++ bool ExecuteOpenBSDFFSFormatterRequest::RequiresElevation () const
++ {
++ return !Core->HasAdminPrivileges();
++ }
++
++ void ExecuteOpenBSDFFSFormatterRequest::Serialize (shared_ptr <Stream> stream) const
++ {
++ CoreServiceRequest::Serialize (stream);
++ Serializer sr (stream);
++ sr.Serialize ("Device", wstring (Device));
++ }
++#endif
++
+ // MountVolumeRequest
+ void MountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
+ {
+@@ -326,6 +347,9 @@
+ TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSectorSizeRequest);
+ TC_SERIALIZER_FACTORY_ADD_CLASS (GetDeviceSizeRequest);
+ TC_SERIALIZER_FACTORY_ADD_CLASS (GetHostDevicesRequest);
++#ifdef TC_OPENBSD
++ TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteOpenBSDFFSFormatterRequest);
++#endif
+ TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeRequest);
+ TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerRequest);
+ }
Index: security/veracrypt/patches/patch-Core_Unix_CoreServiceRequest_h
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreServiceRequest_h
@@ -0,0 +1,22 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Core/Unix/CoreServiceRequest.h.orig
++++ Core/Unix/CoreServiceRequest.h
+@@ -142,6 +142,17 @@
+ };
+ #endif
+
++#ifdef TC_OPENBSD
++ struct ExecuteOpenBSDFFSFormatterRequest : CoreServiceRequest
++ {
++ ExecuteOpenBSDFFSFormatterRequest () { }
++ ExecuteOpenBSDFFSFormatterRequest (const DevicePath &devicePath) : Device (devicePath) { }
++ TC_SERIALIZABLE (ExecuteOpenBSDFFSFormatterRequest);
++ virtual bool RequiresElevation () const;
++ DevicePath Device;
++ };
++#endif
++
+ struct MountVolumeRequest : CoreServiceRequest
+ {
+ MountVolumeRequest () { }
Index: security/veracrypt/patches/patch-Core_Unix_CoreServiceResponse_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreServiceResponse_cpp
@@ -0,0 +1,32 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Core/Unix/CoreServiceResponse.cpp.orig
++++ Core/Unix/CoreServiceResponse.cpp
+@@ -100,6 +100,17 @@
+ }
+ #endif
+
++#ifdef TC_OPENBSD
++ void ExecuteOpenBSDFFSFormatterResponse::Deserialize (shared_ptr <Stream> stream)
++ {
++ }
++
++ void ExecuteOpenBSDFFSFormatterResponse::Serialize (shared_ptr <Stream> stream) const
++ {
++ Serializable::Serialize (stream);
++ }
++#endif
++
+ // MountVolumeResponse
+ void MountVolumeResponse::Deserialize (shared_ptr <Stream> stream)
+ {
+@@ -133,6 +144,9 @@
+ #ifdef TC_MACOSX
+ TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteMacOSXAPFSFormatterResponse);
+ #endif
++#ifdef TC_OPENBSD
++ TC_SERIALIZER_FACTORY_ADD_CLASS (ExecuteOpenBSDFFSFormatterResponse);
++#endif
+ TC_SERIALIZER_FACTORY_ADD_CLASS (MountVolumeResponse);
+ TC_SERIALIZER_FACTORY_ADD_CLASS (SetFileOwnerResponse);
+ }
Index: security/veracrypt/patches/patch-Core_Unix_CoreServiceResponse_h
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreServiceResponse_h
@@ -0,0 +1,18 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Core/Unix/CoreServiceResponse.h.orig
++++ Core/Unix/CoreServiceResponse.h
+@@ -77,6 +77,13 @@
+ };
+ #endif
+
++#ifdef TC_OPENBSD
++ struct ExecuteOpenBSDFFSFormatterResponse : CoreServiceResponse
++ {
++ TC_SERIALIZABLE (ExecuteOpenBSDFFSFormatterResponse);
++ };
++#endif
++
+ struct MountVolumeResponse : CoreServiceResponse
+ {
+ MountVolumeResponse () { }
Index: security/veracrypt/patches/patch-Core_Unix_CoreService_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreService_cpp
@@ -0,0 +1,392 @@
+Use doas with rules restricted to --core-service and a private authentication
+terminal. Keep its slave on stderr across doas closefrom(), forward one
+password response, and detach the elevated worker before releasing the tty.
+Format OpenBSD FFS through a restricted privileged service request.
+
+--- Core/Unix/CoreService.cpp.orig
++++ Core/Unix/CoreService.cpp
+@@ -14,6 +14,15 @@
+ #include <fcntl.h>
+ #include <sys/wait.h>
+ #include <stdio.h>
++#ifdef TC_OPENBSD
++#include <errno.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <termios.h>
++#include <unistd.h>
++#endif
+ #include "Platform/FileStream.h"
+ #include "Platform/MemoryStream.h"
+ #include "Platform/Serializable.h"
+@@ -28,6 +37,24 @@
+
+ namespace VeraCrypt
+ {
++#ifdef TC_OPENBSD
++ // doas(1) reads the password from its controlling terminal. A private
++ // pseudoterminal is used for that, so the elevated process does not need
++ // a terminal of its own and the password entered in the user interface
++ // can be forwarded without exposing it on the command line or in the
++ // environment.
++ static int DoasAuthTerminalFd = -1;
++
++ static void CloseDoasAuthTerminal ()
++ {
++ if (DoasAuthTerminalFd != -1)
++ {
++ close (DoasAuthTerminalFd);
++ DoasAuthTerminalFd = -1;
++ }
++ }
++#endif
++
+ #ifdef TC_MACOSX
+ static bool IsMacOSXDevicePathWithPrefix (const string &path, const string &prefix)
+ {
+@@ -111,6 +138,10 @@
+ {
+ try
+ {
++#ifdef TC_OPENBSD
++ // Detach the elevated worker before releasing its auth terminal.
++ throw_sys_if (setsid () == -1);
++#endif
+ int f = open ("/dev/null", 0);
+ throw_sys_sub_if (f == -1, "/dev/null");
+ throw_sys_if (dup2 (f, STDERR_FILENO) == -1);
+@@ -149,6 +180,10 @@
+
+ void CoreService::ProcessRequests (int inputFD, int outputFD)
+ {
++#ifdef TC_OPENBSD
++ finally_do ({ CloseDoasAuthTerminal (); });
++#endif
++
+ try
+ {
+ Core = move_ptr(CoreDirect);
+@@ -273,6 +308,34 @@
+ }
+ #endif
+
++#ifdef TC_OPENBSD
++ ExecuteOpenBSDFFSFormatterRequest *formatRequest = dynamic_cast <ExecuteOpenBSDFFSFormatterRequest*> (request.get());
++ if (formatRequest)
++ {
++ string device = formatRequest->Device;
++ if (device.size() != 10 || device.compare (0, 8, "/dev/vnd") != 0
++ || device[8] < '0' || device[8] > '3' || device[9] != 'c')
++ throw ParameterIncorrect (SRC_POS);
++
++ // Format only a VeraCrypt virtual device without a mounted
++ // filesystem, never an arbitrary host disk or active filesystem.
++ bool mountedVolumeFound = false;
++ foreach (shared_ptr <VolumeInfo> volume, Core->GetMountedVolumes())
++ {
++ if (volume->VirtualDevice == formatRequest->Device && volume->MountPoint.IsEmpty())
++ mountedVolumeFound = true;
++ }
++ if (!mountedVolumeFound)
++ throw ParameterIncorrect (SRC_POS);
++
++ list <string> arguments;
++ arguments.push_back ("/dev/r" + device.substr (5));
++ Process::Execute ("/sbin/newfs", arguments);
++ ExecuteOpenBSDFFSFormatterResponse().Serialize (outputStream);
++ continue;
++ }
++#endif
++
+ // MountVolumeRequest
+ MountVolumeRequest *mountRequest = dynamic_cast <MountVolumeRequest*> (request.get());
+ if (mountRequest)
+@@ -372,6 +435,14 @@
+ {
+ ExecuteMacOSXAPFSFormatterRequest request (devicePath, userId, groupId);
+ SendRequest <ExecuteMacOSXAPFSFormatterResponse> (request);
++ }
++#endif
++
++#ifdef TC_OPENBSD
++ void CoreService::RequestExecuteOpenBSDFFSFormatter (const DevicePath &devicePath)
++ {
++ ExecuteOpenBSDFFSFormatterRequest request (devicePath);
++ SendRequest <ExecuteOpenBSDFFSFormatterResponse> (request);
+ }
+ #endif
+
+@@ -408,6 +479,7 @@
+ {
+ // Test if the user has an active "sudo" session.
+ bool authCheckDone = false;
++#ifndef TC_OPENBSD
+ if (!Core->GetUseDummySudoPassword ())
+ {
+ // We are using -n to avoid prompting the user for a password.
+@@ -452,6 +524,9 @@
+ request.FastElevation = false;
+ }
+ }
++#endif
++ // On OpenBSD, test the actual service with doas -n. A rule
++ // restricted to --core-service need not allow /usr/bin/true.
+
+ try
+ {
+@@ -507,6 +582,36 @@
+
+ void CoreService::StartElevated (const CoreServiceRequest &request)
+ {
++#ifdef TC_OPENBSD
++ CloseDoasAuthTerminal();
++
++ int authTerminalFd = -1;
++ string authTerminalPath;
++ bool authTerminalKept = false;
++
++ finally_do_arg2 (int *, &authTerminalFd, bool *, &authTerminalKept,
++ {
++ if (!*finally_arg2 && *finally_arg != -1)
++ {
++ close (*finally_arg);
++ *finally_arg = -1;
++ }
++ });
++
++ if (!request.FastElevation)
++ {
++ authTerminalFd = posix_openpt (O_RDWR | O_NOCTTY);
++ throw_sys_sub_if (authTerminalFd == -1, "posix_openpt");
++ throw_sys_if (fcntl (authTerminalFd, F_SETFD, FD_CLOEXEC) == -1);
++ throw_sys_if (grantpt (authTerminalFd) == -1);
++ throw_sys_if (unlockpt (authTerminalFd) == -1);
++
++ char *slavePath = ptsname (authTerminalFd);
++ throw_sys_sub_if (slavePath == nullptr, "ptsname");
++ authTerminalPath = slavePath;
++ }
++#endif
++
+ unique_ptr <Pipe> inPipe (new Pipe());
+ unique_ptr <Pipe> outPipe (new Pipe());
+ Pipe errPipe;
+@@ -522,7 +627,11 @@
+ {
+ // Throw exception if sudo is not found in secure locations
+ std::string errorMsg;
++#ifdef TC_OPENBSD
++ string sudoPath = Process::FindSystemBinary("doas", errorMsg);
++#else
+ string sudoPath = Process::FindSystemBinary("sudo", errorMsg);
++#endif
+ if (sudoPath.empty())
+ throw SystemException(SRC_POS, errorMsg);
+
+@@ -551,7 +660,54 @@
+ throw_sys_if (dup2 (outPipe->GetWriteFD(), STDOUT_FILENO) == -1);
+ throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1);
+
++#ifdef TC_OPENBSD
++ const char *args[8];
++
++ if (!authTerminalPath.empty())
++ {
++ throw_sys_if (setsid () == -1);
++
++ int authFd = open (authTerminalPath.c_str(), O_RDWR);
++ throw_sys_sub_if (authFd == -1, authTerminalPath);
++
++ // Keep the admin password out of the terminal echo.
++ struct termios tios;
++ throw_sys_if (tcgetattr (authFd, &tios) == -1);
++ {
++ tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN);
++ tios.c_iflag &= ~(BRKINT | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
++ tios.c_cc[VMIN] = 1;
++ tios.c_cc[VTIME] = 0;
++ throw_sys_if (tcsetattr (authFd, TCSANOW, &tios) == -1);
++ }
++
++ if (ioctl (authFd, TIOCSCTTY, 0) == -1 && errno != EINVAL)
++ {
++ close (authFd);
++ throw SystemException (SRC_POS, "TIOCSCTTY");
++ }
++
++ // doas closes descriptors above stderr before authentication.
++ // Keep the slave on stderr so /dev/tty remains available.
++ throw_sys_if (dup2 (authFd, STDERR_FILENO) == -1);
++ close (authFd);
++
++ args[0] = sudoPath.c_str();
++ args[1] = appPath.c_str();
++ args[2] = TC_CORE_SERVICE_CMDLINE_OPTION;
++ args[3] = nullptr;
++ }
++ else
++ {
++ args[0] = sudoPath.c_str();
++ args[1] = "-n";
++ args[2] = appPath.c_str();
++ args[3] = TC_CORE_SERVICE_CMDLINE_OPTION;
++ args[4] = nullptr;
++ }
++#else
+ const char *args[] = { sudoPath.c_str(), "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr };
++#endif
+ execvp (args[0], ((char* const*) args));
+ throw SystemException (SRC_POS, args[0]);
+ }
+@@ -601,9 +757,13 @@
+ #if defined(TC_LINUX )
+ Thread::Sleep (1000); // wait 1 second for the forked sudo to start
+ #endif
++#ifndef TC_OPENBSD
+ if (write (inPipe->GetWriteFD(), &adminPassword.front(), adminPassword.size())) { } // Errors ignored
+-
+- burn (&adminPassword.front(), adminPassword.size());
++#endif
++ finally_do_arg (vector <char> *, &adminPassword,
++ {
++ burn (&finally_arg->front(), finally_arg->size());
++ });
+
+ throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
+ throw_sys_if (fcntl (errPipe.GetReadFD(), F_SETFL, O_NONBLOCK) == -1);
+@@ -611,11 +771,77 @@
+ char buffer[4096];
+ vector <char> errOutput;
+ errOutput.reserve (4096);
++#ifdef TC_OPENBSD
++ vector <char> authOutput;
++#endif
+
+ Poller poller (outPipe->GetReadFD(), errPipe.GetReadFD());
+ int status, waitRes;
+ int exitCode = 1;
+
++#ifdef TC_OPENBSD
++ if (authTerminalFd != -1)
++ {
++ throw_sys_if (fcntl (authTerminalFd, F_SETFL, O_NONBLOCK) == -1);
++ Poller authPoller (outPipe->GetReadFD(), errPipe.GetReadFD(), authTerminalFd);
++ bool passwordSent = false;
++
++ while ((waitRes = waitpid (forkedPid, &status, WNOHANG)) == 0)
++ {
++ list <int> ready;
++ try
++ {
++ ready = authPoller.WaitForData (timeout);
++ }
++ catch (TimeOut&)
++ {
++ kill (forkedPid, SIGTERM);
++ close (authTerminalFd);
++ authTerminalFd = -1;
++ waitpid (forkedPid, &status, 0);
++ throw ElevationFailed (SRC_POS, "doas", 1, "Authentication timed out");
++ }
++
++ foreach (int fd, ready)
++ {
++ ssize_t bytesRead = read (fd, buffer, sizeof (buffer));
++ if (bytesRead <= 0)
++ continue;
++
++ if (fd == errPipe.GetReadFD())
++ errOutput.insert (errOutput.end(), buffer, buffer + bytesRead);
++
++ if (fd == authTerminalFd)
++ {
++ authOutput.insert (authOutput.end(), buffer, buffer + bytesRead);
++ if (!passwordSent)
++ {
++ // readpassphrase has opened the terminal and printed its prompt.
++ size_t sent = 0;
++ while (sent < adminPassword.size())
++ {
++ ssize_t n = write (authTerminalFd, &adminPassword[sent], adminPassword.size() - sent);
++ if (n < 0 && errno == EINTR)
++ continue;
++ throw_sys_if (n <= 0);
++ sent += n;
++ }
++ burn (&adminPassword.front(), adminPassword.size());
++ passwordSent = true;
++ }
++ else if (string (authOutput.begin(), authOutput.end()).find ("Authentication failed") != string::npos)
++ {
++ // Let the frontend request a new password, rather than leaving
++ // doas waiting for another response on its private terminal.
++ kill (forkedPid, SIGTERM);
++ }
++ }
++ }
++ }
++ }
++ else
++#endif
++ {
+ try
+ {
+ do
+@@ -667,11 +893,17 @@
+ Thread thread;
+ thread.Start (new WaitFunctor (forkedPid));
+
++#ifdef TC_OPENBSD
++ throw ElevationFailed (SRC_POS, "doas", 1, "");
++#else
+ throw ElevationFailed (SRC_POS, "sudo", 1, "");
++#endif
+ }
+
+ waitRes = waitpid (forkedPid, &status, 0);
+ }
++ }
++
+ }
+
+ if (!errOutput.empty())
+@@ -700,11 +932,19 @@
+ if (!errOutput.empty())
+ strErrOutput.insert (strErrOutput.begin(), errOutput.begin(), errOutput.end());
+
++#ifdef TC_OPENBSD
++ strErrOutput.insert (strErrOutput.end(), authOutput.begin(), authOutput.end());
++ if (strErrOutput.find (" tty") != string::npos)
++ strErrOutput += "\nTo allow VeraCrypt to elevate privileges, add an appropriate rule for it to '/etc/doas.conf'.";
++
++ throw ElevationFailed (SRC_POS, "doas", exitCode, strErrOutput);
++#else
+ // sudo may require a tty even if -S is used
+ if (strErrOutput.find (" tty") != string::npos)
+ strErrOutput += "\nTo enable use of 'sudo' by applications without a terminal window, please disable 'requiretty' option in '/etc/sudoers'. Newer versions of sudo automatically determine whether a terminal is required ('requiretty' option is obsolete).";
+
+ throw ElevationFailed (SRC_POS, "sudo", exitCode, strErrOutput);
++#endif
+ }
+
+ throw_sys_if (fcntl (outPipe->GetReadFD(), F_SETFL, 0) == -1);
+@@ -718,6 +958,17 @@
+
+ AdminInputPipe = move_ptr(inPipe);
+ AdminOutputPipe = move_ptr(outPipe);
++
++#ifdef TC_OPENBSD
++ if (authTerminalFd != -1)
++ {
++ // Keep the authentication terminal open for the lifetime of the
++ // elevated service. Closing the master would hang up the service.
++ authTerminalKept = true;
++ DoasAuthTerminalFd = authTerminalFd;
++ authTerminalFd = -1;
++ }
++#endif
+ }
+
+ void CoreService::Stop ()
Index: security/veracrypt/patches/patch-Core_Unix_CoreService_h
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_Unix_CoreService_h
@@ -0,0 +1,14 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Core/Unix/CoreService.h.orig
++++ Core/Unix/CoreService.h
+@@ -39,6 +39,9 @@
+ static const char *GetMacOSXAPFSFormatterPath ();
+ static void RequestExecuteMacOSXAPFSFormatter (const DevicePath &devicePath, uint64 userId, uint64 groupId);
+ #endif
++#ifdef TC_OPENBSD
++ static void RequestExecuteOpenBSDFFSFormatter (const DevicePath &devicePath);
++#endif
+ static shared_ptr <VolumeInfo> RequestMountVolume (MountOptions &options);
+ static void RequestSetFileOwner (const FilesystemPath &path, const UserId &owner);
+ static void SetAdminPasswordCallback (shared_ptr <GetStringFunctor> functor) { AdminPasswordCallback = functor; }
Index: security/veracrypt/patches/patch-Core_VolumeCreator_h
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Core_VolumeCreator_h
@@ -0,0 +1,34 @@
+Represent FFS as the OpenBSD native filesystem and select /sbin/newfs
+for its formatter.
+
+Index: Core/VolumeCreator.h
+--- Core/VolumeCreator.h.orig
++++ Core/VolumeCreator.h
+@@ -55,7 +55,8 @@
+ Btrfs,
+ MacOsExt,
+ APFS,
+- UFS
++ UFS,
++ FFS
+ };
+
+ static Enum GetPlatformNative ()
+@@ -68,6 +69,8 @@
+ return VolumeCreationOptions::FilesystemType::MacOsExt;
+ #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
+ return VolumeCreationOptions::FilesystemType::UFS;
++#elif defined (TC_OPENBSD)
++ return VolumeCreationOptions::FilesystemType::FFS;
+ #else
+ return VolumeCreationOptions::FilesystemType::FAT;
+ #endif
+@@ -90,6 +93,8 @@
+ case VolumeCreationOptions::FilesystemType::APFS: return "newfs_apfs";
+ #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
+ case VolumeCreationOptions::FilesystemType::UFS: return "newfs" ;
++ #elif defined (TC_OPENBSD)
++ case VolumeCreationOptions::FilesystemType::FFS: return "/sbin/newfs" ;
+ #endif
+ default: return NULL;
+ }
Index: security/veracrypt/patches/patch-Main_CommandLineInterface_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Main_CommandLineInterface_cpp
@@ -0,0 +1,15 @@
+Accept FFS as an explicit filesystem selection on the OpenBSD CLI.
+
+Index: Main/CommandLineInterface.cpp
+--- Main/CommandLineInterface.cpp.orig
++++ Main/CommandLineInterface.cpp
+@@ -415,6 +415,9 @@
+ ArgFilesystem = VolumeCreationOptions::FilesystemType::NTFS;
+ else if (str.IsSameAs (L"exFAT", false))
+ ArgFilesystem = VolumeCreationOptions::FilesystemType::exFAT;
++#elif defined (TC_OPENBSD)
++ else if (str.IsSameAs (L"FFS", false))
++ ArgFilesystem = VolumeCreationOptions::FilesystemType::FFS;
+ #endif
+ else
+ throw_err (LangString["UNKNOWN_OPTION"] + L": " + str);
Index: security/veracrypt/patches/patch-Main_Forms_VolumeCreationWizard_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Main_Forms_VolumeCreationWizard_cpp
@@ -0,0 +1,32 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Main/Forms/VolumeCreationWizard.cpp.orig
++++ Main/Forms/VolumeCreationWizard.cpp
+@@ -17,6 +17,9 @@
+ #include <unistd.h>
+ #include <sys/statvfs.h> // header for statvfs
+ #include "Platform/Unix/Process.h"
++#endif
++#ifdef TC_OPENBSD
++#include "Core/Unix/CoreService.h"
+ #endif
+ #include "Core/RandomNumberGenerator.h"
+ #include "Core/VolumeCreator.h"
+@@ -869,7 +872,7 @@
+ bool useElevatedAPFSFormatter = UseElevatedMacOSXAPFSFormatter (fsFormatter);
+ if (!useElevatedAPFSFormatter)
+ PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners);
+-#else
++#elif !defined(TC_OPENBSD)
+ UserId origDeviceOwner ((uid_t) -1);
+
+ try
+@@ -926,6 +929,8 @@
+ SetCreationProgressText (StringFormatter (LangString["FORMAT_STAGE_CREATING_FILESYSTEM"], fsFormatter));
+ #ifdef TC_MACOSX
+ ExecuteMacOSXFilesystemFormatter (fsFormatter, args);
++#elif defined(TC_OPENBSD)
++ CoreService::RequestExecuteOpenBSDFFSFormatter (virtualDevice);
+ #else
+ Process::Execute (fsFormatter, args);
+ #endif
Index: security/veracrypt/patches/patch-Main_Forms_VolumeFormatOptionsWizardPage_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Main_Forms_VolumeFormatOptionsWizardPage_cpp
@@ -0,0 +1,23 @@
+Offer FFS in the OpenBSD GUI filesystem selector and restore that
+selection when displaying existing creation options.
+
+Index: Main/Forms/VolumeFormatOptionsWizardPage.cpp
+--- Main/Forms/VolumeFormatOptionsWizardPage.cpp.orig
++++ Main/Forms/VolumeFormatOptionsWizardPage.cpp
+@@ -52,6 +52,8 @@
+ FilesystemTypeChoice->Append (L"APFS", (void *) VolumeCreationOptions::FilesystemType::APFS);
+ #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
+ FilesystemTypeChoice->Append (L"UFS", (void *) VolumeCreationOptions::FilesystemType::UFS);
++#elif defined (TC_OPENBSD)
++ FilesystemTypeChoice->Append (L"FFS", (void *) VolumeCreationOptions::FilesystemType::FFS);
+ #endif
+
+ if (!disable32bitFilesystems && filesystemSize <= TC_MAX_FAT_SECTOR_COUNT * sectorSize)
+@@ -94,6 +96,7 @@
+ case VolumeCreationOptions::FilesystemType::MacOsExt: FilesystemTypeChoice->SetStringSelection (L"Mac OS Extended"); break;
+ case VolumeCreationOptions::FilesystemType::APFS: FilesystemTypeChoice->SetStringSelection (L"APFS"); break;
+ case VolumeCreationOptions::FilesystemType::UFS: FilesystemTypeChoice->SetStringSelection (L"UFS"); break;
++ case VolumeCreationOptions::FilesystemType::FFS: FilesystemTypeChoice->SetStringSelection (L"FFS"); break;
+
+ default:
+ throw ParameterIncorrect (SRC_POS);
Index: security/veracrypt/patches/patch-Main_TextUserInterface_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Main_TextUserInterface_cpp
@@ -0,0 +1,55 @@
+Run OpenBSD FFS formatting through the elevated core service.
+
+--- Main/TextUserInterface.cpp.orig
++++ Main/TextUserInterface.cpp
+@@ -24,6 +24,9 @@
+ #include "Common/Token.h"
+ #include "Common/SecurityToken.h"
+ #include "Common/EMVToken.h"
++#ifdef TC_OPENBSD
++#include "Core/Unix/CoreService.h"
++#endif
+ #include "Core/RandomNumberGenerator.h"
+ #include "Application.h"
+ #ifdef TC_MACOSX
+@@ -930,7 +933,13 @@
+ {
+ if (Preferences.NonInteractive)
+ {
++#ifdef TC_OPENBSD
++ // Preserve the historical OpenBSD batch default. Native FFS
++ // formatting requires elevation, so scripts should opt in.
++ options->Filesystem = VolumeCreationOptions::FilesystemType::FAT;
++#else
+ options->Filesystem = VolumeCreationOptions::FilesystemType::GetPlatformNative();
++#endif
+ }
+ else
+ {
+@@ -971,6 +980,8 @@
+ }
+ #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
+ ShowInfo (wxString::Format (L" %li) %s", filesystems.size() + 1, "UFS")); filesystems.push_back (VolumeCreationOptions::FilesystemType::UFS);
++#elif defined (TC_OPENBSD)
++ ShowInfo (wxString::Format (L" %li) %s", filesystems.size() + 1, "FFS")); filesystems.push_back (VolumeCreationOptions::FilesystemType::FFS);
+ #endif
+
+ ssize_t defaultFilesystem = fatAvailable ? 2 : 1;
+@@ -1132,7 +1143,7 @@
+ bool useElevatedAPFSFormatter = UseElevatedMacOSXAPFSFormatter (fsFormatter);
+ if (!useElevatedAPFSFormatter)
+ PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners);
+-#else
++#elif !defined(TC_OPENBSD)
+ UserId origDeviceOwner ((uid_t) -1);
+
+ try
+@@ -1188,6 +1199,8 @@
+
+ #ifdef TC_MACOSX
+ ExecuteMacOSXFilesystemFormatter (fsFormatter, args);
++#elif defined(TC_OPENBSD)
++ CoreService::RequestExecuteOpenBSDFFSFormatter (virtualDevice);
+ #else
+ Process::Execute (fsFormatter, args);
+ #endif
Index: security/veracrypt/patches/patch-Main_UserInterface_cpp
===================================================================
--- /dev/null
+++ security/veracrypt/patches/patch-Main_UserInterface_cpp
@@ -0,0 +1,18 @@
+Name doas in OpenBSD elevation failures to match the core service
+launcher, retaining sudo diagnostics on other platforms.
+
+Index: Main/UserInterface.cpp
+--- Main/UserInterface.cpp.orig
++++ Main/UserInterface.cpp
+@@ -40,7 +40,11 @@
+ public:
+ virtual void operator() (string &str)
+ {
++#ifdef TC_OPENBSD
++ throw ElevationFailed (SRC_POS, "doas", 1, "");
++#else
+ throw ElevationFailed (SRC_POS, "sudo", 1, "");
++#endif
+ }
+ };
+
Index: security/veracrypt/pkg/README
===================================================================
--- /dev/null
+++ security/veracrypt/pkg/README
@@ -0,0 +1,35 @@
++-------------------------------------------------------------------------------
+| Running ${PKGSTEM} on OpenBSD
++-------------------------------------------------------------------------------
+
+Privilege elevation
+===================
+
+VeraCrypt runs its privileged core service through doas(1). Add a rule to
+/etc/doas.conf before mounting, creating or formatting volumes:
+
+ permit :wheel cmd ${TRUEPREFIX}/bin/veracrypt args --core-service
+
+This rule permits only the privileged core service used internally by
+VeraCrypt. Run the normal CLI or GUI as your own user. Do not use
+"permit nopass" unless you accept passwordless elevation for every user
+allowed by the rule.
+
+The core service is used for operations that require root privileges, such as
+configuring vnd(4) loop devices, mounting and unmounting filesystems,
+changing ownership of mount points and device nodes, and running newfs(8)
+when an OpenBSD FFS filesystem is created inside a volume.
+
+Filesystem creation
+===================
+
+OpenBSD FFS filesystems can be created inside a new volume by selecting the
+"FFS" filesystem in the volume creation wizard or by passing
+"--filesystem=FFS" on the command line. The filesystem is created with
+newfs(8) on the raw vnd(4) character device through the elevated core
+service. Changing device ownership alone is insufficient: reading the disk
+label requires privileged ioctls on OpenBSD.
+
+Noninteractive creation retains FAT as its default. Request FFS explicitly
+with --filesystem=FFS. Without a passwordless doas rule, use interactive mode
+so VeraCrypt can request your account password.
Index: security/veracrypt/patches/patch-Core_Unix_OpenBSD_CoreOpenBSD_cpp
===================================================================
--- security/veracrypt/patches/patch-Core_Unix_OpenBSD_CoreOpenBSD_cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-The -c option is no more. https://github.com/veracrypt/VeraCrypt/pull/1002
-
-Index: Core/Unix/OpenBSD/CoreOpenBSD.cpp
---- Core/Unix/OpenBSD/CoreOpenBSD.cpp.orig
-+++ Core/Unix/OpenBSD/CoreOpenBSD.cpp
-@@ -69,8 +69,6 @@ namespace VeraCrypt
- if (freeVnd == -1)
- throw "couldn't find free vnd";
-
-- args.push_back ("-c");
--
- stringstream freePath;
- freePath << "vnd" << freeVnd;
- args.push_back (freePath.str());
[UPDATE] security/veracrypt 1.25.9 -> 1.26.29 + improvements