commit: 06624ed7867c902e0ca44b5ca381e9d4dc157e14
parent f14538ac33402854509d46e1a7bdaae091c2fb80
Author: Michael Forney <mforney@mforney.org>
Date: Tue, 29 Apr 2025 16:35:44 -0700
openbsd: Update to 7.7
Diffstat:
62 files changed, 3819 insertions(+), 3839 deletions(-)
diff --git a/pkg/openbsd/include/string.h b/pkg/openbsd/include/string.h
@@ -1,5 +1,6 @@
+#define __NEED_mode_t
#include_next <string.h>
char *strcasestr(const char *, const char *);
-void strmode(int, char *);
+void strmode(mode_t, char *);
int timingsafe_memcmp(const void *, const void *, size_t);
int timingsafe_bcmp(const void *, const void *, size_t);
diff --git a/pkg/openbsd/patch/0004-pax-Add-some-includes.patch b/pkg/openbsd/patch/0003-pax-Add-some-includes.patch
diff --git a/pkg/openbsd/patch/0003-pax-Set-listf-to-stderr-in-main.patch b/pkg/openbsd/patch/0003-pax-Set-listf-to-stderr-in-main.patch
@@ -1,34 +0,0 @@
-From e2ca2e2a530e61e8af65dca829aa1fcad5c59a7d Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Mon, 18 Apr 2016 00:13:51 -0700
-Subject: [PATCH] pax: Set listf to stderr in main
-
----
- bin/pax/pax.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/bin/pax/pax.c b/bin/pax/pax.c
-index f6b3634369a..3d50e051075 100644
---- a/bin/pax/pax.c
-+++ b/bin/pax/pax.c
-@@ -93,7 +93,7 @@ char *dirptr; /* destination dir in a copy */
- char *argv0; /* root of argv[0] */
- enum op_mode op_mode; /* what program are we acting as? */
- sigset_t s_mask; /* signal mask for cleanup critical sect */
--FILE *listf = stderr; /* file pointer to print file list to */
-+FILE *listf; /* file pointer to print file list to */
- int listfd = STDERR_FILENO; /* fd matching listf, for sighandler output */
- char *tempfile; /* tempfile to use for mkstemp(3) */
- char *tempbase; /* basename of tempfile to use for mkstemp(3) */
-@@ -224,6 +224,8 @@ main(int argc, char **argv)
- char *tmpdir;
- size_t tdlen;
-
-+ listf = stderr;
-+
- /*
- * Keep a reference to cwd, so we can always come back home.
- */
---
-2.19.0
-
diff --git a/pkg/openbsd/patch/0004-tar-Default-to-stdin.patch b/pkg/openbsd/patch/0004-tar-Default-to-stdin.patch
@@ -0,0 +1,25 @@
+From 7f16d268831910c1d219b8a4f38b364bba34c710 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Mon, 18 Apr 2016 01:16:12 -0700
+Subject: [PATCH] tar: Default to stdin
+
+---
+ bin/pax/options.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/bin/pax/options.c b/bin/pax/options.c
+index cd3f5f6285c..9dd2ea0ce25 100644
+--- a/bin/pax/options.c
++++ b/bin/pax/options.c
+@@ -968,7 +968,7 @@ tar_options(int argc, char **argv)
+ if ((arcname == NULL) || (*arcname == '\0')) {
+ arcname = getenv("TAPE");
+ if ((arcname == NULL) || (*arcname == '\0'))
+- arcname = _PATH_DEFTAPE;
++ arcname = "-";
+ }
+ if ((arcname[0] == '-') && (arcname[1]== '\0'))
+ arcname = NULL;
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0005-tar-Default-to-stdin.patch b/pkg/openbsd/patch/0005-tar-Default-to-stdin.patch
@@ -1,25 +0,0 @@
-From 901940cdf7fc13516ff55e81df0b546eb7c74595 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Mon, 18 Apr 2016 01:16:12 -0700
-Subject: [PATCH] tar: Default to stdin
-
----
- bin/pax/options.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/bin/pax/options.c b/bin/pax/options.c
-index 5db0948858c..dbb4b816c37 100644
---- a/bin/pax/options.c
-+++ b/bin/pax/options.c
-@@ -937,7 +937,7 @@ tar_options(int argc, char **argv)
- if ((arcname == NULL) || (*arcname == '\0')) {
- arcname = getenv("TAPE");
- if ((arcname == NULL) || (*arcname == '\0'))
-- arcname = _PATH_DEFTAPE;
-+ arcname = "-";
- }
- if ((arcname[0] == '-') && (arcname[1]== '\0'))
- arcname = NULL;
---
-2.25.0
-
diff --git a/pkg/openbsd/patch/0006-yacc-Add-some-includes.patch b/pkg/openbsd/patch/0005-yacc-Add-some-includes.patch
diff --git a/pkg/openbsd/patch/0007-diff-Add-missing-includes.patch b/pkg/openbsd/patch/0006-diff-Add-missing-includes.patch
diff --git a/pkg/openbsd/patch/0008-patch-Add-missing-includes.patch b/pkg/openbsd/patch/0007-patch-Add-missing-includes.patch
diff --git a/pkg/openbsd/patch/0009-patch-Avoid-d_namlen.patch b/pkg/openbsd/patch/0008-patch-Avoid-d_namlen.patch
diff --git a/pkg/openbsd/patch/0009-pax-Fix-GNU-long-name-handling-with-short-read.patch b/pkg/openbsd/patch/0009-pax-Fix-GNU-long-name-handling-with-short-read.patch
@@ -0,0 +1,176 @@
+From f88fb1145beac6cce7012b506579d23e0b9826a2 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sat, 3 Dec 2016 20:49:24 -0800
+Subject: [PATCH] pax: Fix GNU long name handling with short read
+
+---
+ bin/pax/ar_subs.c | 66 +++++++++++++++++++++++++++++++++------------
+ bin/pax/buf_subs.c | 4 +--
+ bin/pax/file_subs.c | 25 +----------------
+ 3 files changed, 51 insertions(+), 44 deletions(-)
+
+diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c
+index f018108af59..4c49efa1362 100644
+--- a/bin/pax/ar_subs.c
++++ b/bin/pax/ar_subs.c
+@@ -37,6 +37,7 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
++#include <err.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <signal.h>
+@@ -51,6 +52,7 @@
+ static void wr_archive(ARCHD *, int is_app);
+ static int get_arc(void);
+ static int next_head(ARCHD *);
++static int rd_gnu_string(ARCHD *);
+ extern sigset_t s_mask;
+
+ /*
+@@ -93,16 +95,8 @@ list(void)
+ * step through the archive until the format says it is done
+ */
+ while (next_head(arcn) == 0) {
+- if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+- /*
+- * we need to read, to get the real filename
+- */
+- off_t cnt;
+- if (!rd_wrfile(arcn, arcn->type == PAX_GLF
+- ? -1 : -2, &cnt))
+- (void)rd_skip(cnt + arcn->pad);
++ if (rd_gnu_string(arcn))
+ continue;
+- }
+
+ /*
+ * check for pattern, and user specified options match.
+@@ -245,15 +239,8 @@ extract(void)
+ * says it is done
+ */
+ while (next_head(arcn) == 0) {
+- if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+- /*
+- * we need to read, to get the real filename
+- */
+- if (!rd_wrfile(arcn, arcn->type == PAX_GLF
+- ? -1 : -2, &cnt))
+- (void)rd_skip(cnt + arcn->pad);
++ if (rd_gnu_string(arcn))
+ continue;
+- }
+
+ /*
+ * check for pattern, and user specified options match. When
+@@ -1282,3 +1269,48 @@ get_arc(void)
+ paxwarn(1, "Sorry, unable to determine archive format.");
+ return(-1);
+ }
++
++/*
++ * rd_gnu_string()
++ * Read the file contents into an allocated string if it is a GNU tar
++ * long link/file.
++ * Return:
++ * 1 if gnu string read, 0 otherwise
++ */
++
++static int
++rd_gnu_string(ARCHD *arcn)
++{
++ char **strp;
++
++ switch (arcn->type) {
++ case PAX_GLF:
++ strp = &gnu_name_string;
++ break;
++ case PAX_GLL:
++ strp = &gnu_link_string;
++ break;
++ default:
++ strp = NULL;
++ break;
++ }
++ if (!strp)
++ return 0;
++ /*
++ * we need to read, to get the real filename
++ */
++ if (*strp)
++ err(1, "WARNING! Major Internal Error! GNU hack Failing!");
++ *strp = malloc(arcn->sb.st_size + 1);
++ if (*strp == NULL) {
++ paxwarn(1, "Out of memory");
++ (void)rd_skip(arcn->skip + arcn->pad);
++ } else if (rd_wrbuf(*strp, arcn->sb.st_size) < arcn->sb.st_size) {
++ free(*strp);
++ *strp = NULL;
++ } else {
++ (*strp)[arcn->sb.st_size] = '\0';
++ (void)rd_skip(arcn->pad);
++ }
++ return 1;
++}
+diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c
+index 25dfed5b69b..e3e22a09cc6 100644
+--- a/bin/pax/buf_subs.c
++++ b/bin/pax/buf_subs.c
+@@ -676,9 +676,7 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
+ * pass the blocksize of the file being written to the write routine,
+ * if the size is zero, use the default MINFBSZ
+ */
+- if (ofd < 0)
+- sz = PAXPATHLEN + 1; /* GNU tar long link/file */
+- else if (fstat(ofd, &sb) == 0) {
++ if (fstat(ofd, &sb) == 0) {
+ if (sb.st_blksize > 0)
+ sz = (int)sb.st_blksize;
+ } else
+diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
+index 9f482480a3b..ae0caf29f6c 100644
+--- a/bin/pax/file_subs.c
++++ b/bin/pax/file_subs.c
+@@ -924,7 +924,6 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
+ char *end;
+ int wcnt;
+ char *st = str;
+- char **strp;
+
+ /*
+ * while we have data to process
+@@ -983,29 +982,7 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
+ /*
+ * have non-zero data in this file system block, have to write
+ */
+- switch (fd) {
+- case -1:
+- strp = &gnu_name_string;
+- break;
+- case -2:
+- strp = &gnu_link_string;
+- break;
+- default:
+- strp = NULL;
+- break;
+- }
+- if (strp) {
+- if (*strp)
+- err(1, "WARNING! Major Internal Error! GNU hack Failing!");
+- *strp = malloc(wcnt + 1);
+- if (*strp == NULL) {
+- paxwarn(1, "Out of memory");
+- return(-1);
+- }
+- memcpy(*strp, st, wcnt);
+- (*strp)[wcnt] = '\0';
+- break;
+- } else if (write(fd, st, wcnt) != wcnt) {
++ if (write(fd, st, wcnt) != wcnt) {
+ syswarn(1, errno, "Failed write to file %s", name);
+ return(-1);
+ }
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0010-pax-Fix-GNU-long-name-handling-with-short-read.patch b/pkg/openbsd/patch/0010-pax-Fix-GNU-long-name-handling-with-short-read.patch
@@ -1,176 +0,0 @@
-From ec3fd37495e977af375a98a472d19ae0ccbcd874 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Sat, 3 Dec 2016 20:49:24 -0800
-Subject: [PATCH] pax: Fix GNU long name handling with short read
-
----
- bin/pax/ar_subs.c | 66 +++++++++++++++++++++++++++++++++------------
- bin/pax/buf_subs.c | 4 +--
- bin/pax/file_subs.c | 25 +----------------
- 3 files changed, 51 insertions(+), 44 deletions(-)
-
-diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c
-index e5b0a4ee5d1..f0a55abe2f7 100644
---- a/bin/pax/ar_subs.c
-+++ b/bin/pax/ar_subs.c
-@@ -37,6 +37,7 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/time.h>
-+#include <err.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <signal.h>
-@@ -51,6 +52,7 @@
- static void wr_archive(ARCHD *, int is_app);
- static int get_arc(void);
- static int next_head(ARCHD *);
-+static int rd_gnu_string(ARCHD *);
- extern sigset_t s_mask;
-
- /*
-@@ -93,16 +95,8 @@ list(void)
- * step through the archive until the format says it is done
- */
- while (next_head(arcn) == 0) {
-- if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
-- /*
-- * we need to read, to get the real filename
-- */
-- off_t cnt;
-- if (!rd_wrfile(arcn, arcn->type == PAX_GLF
-- ? -1 : -2, &cnt))
-- (void)rd_skip(cnt + arcn->pad);
-+ if (rd_gnu_string(arcn))
- continue;
-- }
-
- /*
- * check for pattern, and user specified options match.
-@@ -208,15 +202,8 @@ extract(void)
- * says it is done
- */
- while (next_head(arcn) == 0) {
-- if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
-- /*
-- * we need to read, to get the real filename
-- */
-- if (!rd_wrfile(arcn, arcn->type == PAX_GLF
-- ? -1 : -2, &cnt))
-- (void)rd_skip(cnt + arcn->pad);
-+ if (rd_gnu_string(arcn))
- continue;
-- }
-
- /*
- * check for pattern, and user specified options match. When
-@@ -1243,3 +1230,48 @@ get_arc(void)
- paxwarn(1, "Sorry, unable to determine archive format.");
- return(-1);
- }
-+
-+/*
-+ * rd_gnu_string()
-+ * Read the file contents into an allocated string if it is a GNU tar
-+ * long link/file.
-+ * Return:
-+ * 1 if gnu string read, 0 otherwise
-+ */
-+
-+static int
-+rd_gnu_string(ARCHD *arcn)
-+{
-+ char **strp;
-+
-+ switch (arcn->type) {
-+ case PAX_GLF:
-+ strp = &gnu_name_string;
-+ break;
-+ case PAX_GLL:
-+ strp = &gnu_link_string;
-+ break;
-+ default:
-+ strp = NULL;
-+ break;
-+ }
-+ if (!strp)
-+ return 0;
-+ /*
-+ * we need to read, to get the real filename
-+ */
-+ if (*strp)
-+ err(1, "WARNING! Major Internal Error! GNU hack Failing!");
-+ *strp = malloc(arcn->sb.st_size + 1);
-+ if (*strp == NULL) {
-+ paxwarn(1, "Out of memory");
-+ (void)rd_skip(arcn->skip + arcn->pad);
-+ } else if (rd_wrbuf(*strp, arcn->sb.st_size) < arcn->sb.st_size) {
-+ free(*strp);
-+ *strp = NULL;
-+ } else {
-+ (*strp)[arcn->sb.st_size] = '\0';
-+ (void)rd_skip(arcn->pad);
-+ }
-+ return 1;
-+}
-diff --git a/bin/pax/buf_subs.c b/bin/pax/buf_subs.c
-index 68534dcbe25..e84f9e0d3d6 100644
---- a/bin/pax/buf_subs.c
-+++ b/bin/pax/buf_subs.c
-@@ -673,9 +673,7 @@ rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
- * pass the blocksize of the file being written to the write routine,
- * if the size is zero, use the default MINFBSZ
- */
-- if (ofd < 0)
-- sz = PAXPATHLEN + 1; /* GNU tar long link/file */
-- else if (fstat(ofd, &sb) == 0) {
-+ if (fstat(ofd, &sb) == 0) {
- if (sb.st_blksize > 0)
- sz = (int)sb.st_blksize;
- } else
-diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
-index 89b4872988b..8aa3d249923 100644
---- a/bin/pax/file_subs.c
-+++ b/bin/pax/file_subs.c
-@@ -919,7 +919,6 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
- char *end;
- int wcnt;
- char *st = str;
-- char **strp;
-
- /*
- * while we have data to process
-@@ -978,29 +977,7 @@ file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
- /*
- * have non-zero data in this file system block, have to write
- */
-- switch (fd) {
-- case -1:
-- strp = &gnu_name_string;
-- break;
-- case -2:
-- strp = &gnu_link_string;
-- break;
-- default:
-- strp = NULL;
-- break;
-- }
-- if (strp) {
-- if (*strp)
-- err(1, "WARNING! Major Internal Error! GNU hack Failing!");
-- *strp = malloc(wcnt + 1);
-- if (*strp == NULL) {
-- paxwarn(1, "Out of memory");
-- return(-1);
-- }
-- memcpy(*strp, st, wcnt);
-- (*strp)[wcnt] = '\0';
-- break;
-- } else if (write(fd, st, wcnt) != wcnt) {
-+ if (write(fd, st, wcnt) != wcnt) {
- syswarn(1, errno, "Failed write to file %s", name);
- return(-1);
- }
---
-2.26.2
-
diff --git a/pkg/openbsd/patch/0010-pax-Support-xz-compression-with-J-flag.patch b/pkg/openbsd/patch/0010-pax-Support-xz-compression-with-J-flag.patch
@@ -0,0 +1,90 @@
+From c0b84520a7c92b67b195c6ec9ed9185438810380 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sat, 3 Dec 2016 23:50:27 -0800
+Subject: [PATCH] pax: Support xz compression with -J flag
+
+---
+ bin/pax/options.c | 25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+diff --git a/bin/pax/options.c b/bin/pax/options.c
+index 9dd2ea0ce25..63f17f2c1c7 100644
+--- a/bin/pax/options.c
++++ b/bin/pax/options.c
+@@ -156,6 +156,7 @@ static int xz_id(char *_blk, int _size);
+ #define GZIP_CMD "gzip" /* command to run as gzip */
+ #define COMPRESS_CMD "compress" /* command to run as compress */
+ #define BZIP2_CMD "bzip2" /* command to run as bzip2 */
++#define XZ_CMD "xz" /* command to run as xz */
+
+ /*
+ * Format specific routine table
+@@ -312,7 +313,7 @@ pax_options(int argc, char **argv)
+ /*
+ * process option flags
+ */
+- while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
++ while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HJLOPT:U:XYZ0"))
+ != -1) {
+ switch (c) {
+ case 'a':
+@@ -568,6 +569,12 @@ pax_options(int argc, char **argv)
+ Hflag = 1;
+ flg |= CHF;
+ break;
++ case 'J':
++ /*
++ * use xz. Non standard option.
++ */
++ gzip_program = XZ_CMD;
++ break;
+ case 'L':
+ /*
+ * follow symlinks
+@@ -744,7 +751,7 @@ tar_options(int argc, char **argv)
+ * process option flags
+ */
+ while ((c = getoldopt(argc, argv,
+- "b:cef:hjmopqruts:vwxzBC:F:HI:LNOPXZ014578")) != -1) {
++ "b:cef:hjmopqruts:vwxzBC:F:HI:JLNOPXZ014578")) != -1) {
+ switch (c) {
+ case 'b':
+ /*
+@@ -911,6 +918,12 @@ tar_options(int argc, char **argv)
+ incfiles[nincfiles - 1].file = optarg;
+ incfiles[nincfiles - 1].dir = chdname;
+ break;
++ case 'J':
++ /*
++ * use xz. Non standard option.
++ */
++ gzip_program = XZ_CMD;
++ break;
+ case 'L':
+ /*
+ * follow symlinks
+@@ -1194,7 +1207,7 @@ cpio_options(int argc, char **argv)
+ dflag = 1;
+ act = -1;
+ nodirs = 1;
+- while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
++ while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:JLO:SZ6")) != -1)
+ switch (c) {
+ case 'a':
+ /*
+@@ -1378,6 +1391,12 @@ cpio_options(int argc, char **argv)
+ (void)fputs("\n\n", stderr);
+ cpio_usage();
+ break;
++ case 'J':
++ /*
++ * use xz. Non standard option.
++ */
++ gzip_program = XZ_CMD;
++ break;
+ case 'L':
+ /*
+ * follow symbolic links
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0011-pax-Support-xz-compression-with-J-flag.patch b/pkg/openbsd/patch/0011-pax-Support-xz-compression-with-J-flag.patch
@@ -1,90 +0,0 @@
-From 86ce82bfd12c6db2468e3db4afd843cf081f71b2 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Sat, 3 Dec 2016 23:50:27 -0800
-Subject: [PATCH] pax: Support xz compression with -J flag
-
----
- bin/pax/options.c | 25 ++++++++++++++++++++++---
- 1 file changed, 22 insertions(+), 3 deletions(-)
-
-diff --git a/bin/pax/options.c b/bin/pax/options.c
-index 560478f2681..27de25d655b 100644
---- a/bin/pax/options.c
-+++ b/bin/pax/options.c
-@@ -154,6 +154,7 @@ static int xz_id(char *_blk, int _size);
- #define GZIP_CMD "gzip" /* command to run as gzip */
- #define COMPRESS_CMD "compress" /* command to run as compress */
- #define BZIP2_CMD "bzip2" /* command to run as bzip2 */
-+#define XZ_CMD "xz" /* command to run as xz */
-
- /*
- * Format specific routine table
-@@ -300,7 +301,7 @@ pax_options(int argc, char **argv)
- /*
- * process option flags
- */
-- while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HLOPT:U:XYZ0"))
-+ while ((c=getopt(argc,argv,"ab:cdf:ijklno:p:rs:tuvwx:zB:DE:G:HJLOPT:U:XYZ0"))
- != -1) {
- switch (c) {
- case 'a':
-@@ -556,6 +557,12 @@ pax_options(int argc, char **argv)
- Hflag = 1;
- flg |= CHF;
- break;
-+ case 'J':
-+ /*
-+ * use xz. Non standard option.
-+ */
-+ gzip_program = XZ_CMD;
-+ break;
- case 'L':
- /*
- * follow symlinks
-@@ -731,7 +738,7 @@ tar_options(int argc, char **argv)
- * process option flags
- */
- while ((c = getoldopt(argc, argv,
-- "b:cef:hjmopqruts:vwxzBC:HI:LNOPXZ014578")) != -1) {
-+ "b:cef:hjmopqruts:vwxzBC:HI:JLNOPXZ014578")) != -1) {
- switch (c) {
- case 'b':
- /*
-@@ -880,6 +887,12 @@ tar_options(int argc, char **argv)
- incfiles[nincfiles - 1].file = optarg;
- incfiles[nincfiles - 1].dir = chdname;
- break;
-+ case 'J':
-+ /*
-+ * use xz. Non standard option.
-+ */
-+ gzip_program = XZ_CMD;
-+ break;
- case 'L':
- /*
- * follow symlinks
-@@ -1163,7 +1176,7 @@ cpio_options(int argc, char **argv)
- dflag = 1;
- act = -1;
- nodirs = 1;
-- while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
-+ while ((c=getopt(argc,argv,"abcdfijklmoprstuvzABC:E:F:H:I:JLO:SZ6")) != -1)
- switch (c) {
- case 'a':
- /*
-@@ -1347,6 +1360,12 @@ cpio_options(int argc, char **argv)
- (void)fputs("\n\n", stderr);
- cpio_usage();
- break;
-+ case 'J':
-+ /*
-+ * use xz. Non standard option.
-+ */
-+ gzip_program = XZ_CMD;
-+ break;
- case 'L':
- /*
- * follow symbolic links
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0012-setprogname-Explicitly-discard-const-qualifier.patch b/pkg/openbsd/patch/0011-setprogname-Explicitly-discard-const-qualifier.patch
diff --git a/pkg/openbsd/patch/0013-readpassphrase-Support-systems-without-VSTATUS-and-T.patch b/pkg/openbsd/patch/0012-readpassphrase-Support-systems-without-VSTATUS-and-T.patch
diff --git a/pkg/openbsd/patch/0014-Remove-getpass-definition.patch b/pkg/openbsd/patch/0013-Remove-getpass-definition.patch
diff --git a/pkg/openbsd/patch/0014-doas-Port-to-linux-musl.patch b/pkg/openbsd/patch/0014-doas-Port-to-linux-musl.patch
@@ -0,0 +1,581 @@
+From cca6c84b472255c4d015d7d97225791796f61392 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 26 Feb 2017 16:50:55 -0800
+Subject: [PATCH] doas: Port to linux/musl
+
+Remove -a login style option and BSD authentication. Instead, compare
+against shadow file.
+
+Use timestamp files in /run/doas instead of TIOC*VERAUTH to implement
+persist.
+
+Use initgroups/setgid/setuid instead of setusercontext.
+
+Provide UID_MAX and GID_MAX defaults.
+
+Use LOGIN_NAME_MAX instead of _PW_NAME_LEN.
+
+Remove call to closefrom.
+
+Replace calls to errc with err after setting errno.
+
+Call openlog at start to set syslog identity.
+
+Remove unveil/pledge since they aren't supported on Linux.
+
+Simplify handling of PATH in the environment since we don't have
+login.conf with per-user default PATH.
+---
+ usr.bin/doas/doas.1 | 9 ---
+ usr.bin/doas/doas.c | 168 +++++++++++++----------------------------
+ usr.bin/doas/doas.h | 6 +-
+ usr.bin/doas/env.c | 17 ++---
+ usr.bin/doas/parse.y | 1 +
+ usr.bin/doas/persist.c | 133 ++++++++++++++++++++++++++++++++
+ 6 files changed, 198 insertions(+), 136 deletions(-)
+ create mode 100644 usr.bin/doas/persist.c
+
+diff --git a/usr.bin/doas/doas.1 b/usr.bin/doas/doas.1
+index 25827cc7104..3542680faf5 100644
+--- a/usr.bin/doas/doas.1
++++ b/usr.bin/doas/doas.1
+@@ -22,7 +22,6 @@
+ .Sh SYNOPSIS
+ .Nm doas
+ .Op Fl Lns
+-.Op Fl a Ar style
+ .Op Fl C Ar config
+ .Op Fl u Ar user
+ .Ar command
+@@ -67,14 +66,6 @@ The working directory is not changed.
+ .Pp
+ The options are as follows:
+ .Bl -tag -width tenletters
+-.It Fl a Ar style
+-Use the specified authentication style when validating the user,
+-as allowed by
+-.Pa /etc/login.conf .
+-A list of doas-specific authentication methods may be configured by adding an
+-.Sq auth-doas
+-entry in
+-.Xr login.conf 5 .
+ .It Fl C Ar config
+ Parse and check the configuration file
+ .Ar config ,
+diff --git a/usr.bin/doas/doas.c b/usr.bin/doas/doas.c
+index 3999b2e2f64..32532359267 100644
+--- a/usr.bin/doas/doas.c
++++ b/usr.bin/doas/doas.c
+@@ -20,8 +20,6 @@
+ #include <sys/ioctl.h>
+
+ #include <limits.h>
+-#include <login_cap.h>
+-#include <bsd_auth.h>
+ #include <readpassphrase.h>
+ #include <string.h>
+ #include <stdio.h>
+@@ -33,13 +31,22 @@
+ #include <syslog.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <shadow.h>
+
+ #include "doas.h"
+
++#ifndef UID_MAX
++#define UID_MAX 65535
++#endif
++
++#ifndef GID_MAX
++#define GID_MAX 65535
++#endif
++
+ static void __dead
+ usage(void)
+ {
+- fprintf(stderr, "usage: doas [-Lns] [-a style] [-C config] [-u user]"
++ fprintf(stderr, "usage: doas [-Lns] [-C config] [-u user]"
+ " command [arg ...]\n");
+ exit(1);
+ }
+@@ -203,16 +210,28 @@ checkconfig(const char *confpath, int argc, char **argv,
+ }
+
+ static int
+-authuser_checkpass(char *myname, char *login_style)
++verifypasswd(const char *user, const char *pass)
++{
++ struct spwd *sp;
++ char *p1, *p2;
++
++ sp = getspnam(user);
++ if (!sp)
++ return 0;
++ p1 = sp->sp_pwdp;
++ if (p1[0] == '!' || p1[0] == '*')
++ return 0;
++ p2 = crypt(pass, p1);
++ if (!p2)
++ return 0;
++ return strcmp(p1, p2) == 0;
++}
++
++static int
++authuser_checkpass(char *myname)
+ {
+ char *challenge = NULL, *response, rbuf[1024], cbuf[128];
+- auth_session_t *as;
+
+- if (!(as = auth_userchallenge(myname, login_style, "auth-doas",
+- &challenge))) {
+- warnx("Authentication failed");
+- return AUTH_FAILED;
+- }
+ if (!challenge) {
+ char host[HOST_NAME_MAX + 1];
+
+@@ -225,14 +244,12 @@ authuser_checkpass(char *myname, char *login_style)
+ response = readpassphrase(challenge, rbuf, sizeof(rbuf),
+ RPP_REQUIRE_TTY);
+ if (response == NULL && errno == ENOTTY) {
+- syslog(LOG_AUTHPRIV | LOG_NOTICE,
+- "tty required for %s", myname);
++ syslog(LOG_NOTICE, "tty required for %s", myname);
+ errx(1, "a tty is required");
+ }
+- if (!auth_userresponse(as, response, 0)) {
++ if (!verifypasswd(myname, response)) {
+ explicit_bzero(rbuf, sizeof(rbuf));
+- syslog(LOG_AUTHPRIV | LOG_NOTICE,
+- "failed auth for %s", myname);
++ syslog(LOG_NOTICE, "failed auth for %s", myname);
+ warnx("Authentication failed");
+ return AUTH_FAILED;
+ }
+@@ -241,79 +258,36 @@ authuser_checkpass(char *myname, char *login_style)
+ }
+
+ static void
+-authuser(char *myname, char *login_style, int persist)
++authuser(char *myname, int persist)
+ {
+- int i, fd = -1;
++ int i, fd = -1, valid = 0;
+
+- if (persist)
+- fd = open("/dev/tty", O_RDWR);
+- if (fd != -1) {
+- if (ioctl(fd, TIOCCHKVERAUTH) == 0)
++ if (persist) {
++ fd = openpersist(&valid);
++ if (valid)
+ goto good;
+ }
+ for (i = 0; i < AUTH_RETRIES; i++) {
+- if (authuser_checkpass(myname, login_style) == AUTH_OK)
++ if (authuser_checkpass(myname) == AUTH_OK)
+ goto good;
+ }
+ exit(1);
+ good:
+ if (fd != -1) {
+- int secs = 5 * 60;
+- ioctl(fd, TIOCSETVERAUTH, &secs);
++ setpersist(fd);
+ close(fd);
+ }
+ }
+
+-int
+-unveilcommands(const char *ipath, const char *cmd)
+-{
+- char *path = NULL, *p;
+- int unveils = 0;
+-
+- if (strchr(cmd, '/') != NULL) {
+- if (unveil(cmd, "x") != -1)
+- unveils++;
+- goto done;
+- }
+-
+- if (!ipath) {
+- errno = ENOENT;
+- goto done;
+- }
+- path = strdup(ipath);
+- if (!path) {
+- errno = ENOENT;
+- goto done;
+- }
+- for (p = path; p && *p; ) {
+- char buf[PATH_MAX];
+- char *cp = strsep(&p, ":");
+-
+- if (cp) {
+- int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd);
+- if (r >= 0 && r < sizeof buf) {
+- if (unveil(buf, "x") != -1)
+- unveils++;
+- }
+- }
+- }
+-done:
+- free(path);
+- return (unveils);
+-}
+-
+ int
+ main(int argc, char **argv)
+ {
+- const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
+- "/usr/local/bin:/usr/local/sbin";
+ const char *confpath = NULL;
+ char *shargv[] = { NULL, NULL };
+ char *sh;
+- const char *p;
+ const char *cmd;
+ char cmdline[LINE_MAX];
+- char mypwbuf[_PW_BUF_LEN], targpwbuf[_PW_BUF_LEN];
++ char mypwbuf[1024], targpwbuf[1024];
+ struct passwd mypwstore, targpwstore;
+ struct passwd *mypw, *targpw;
+ const struct rule *rule;
+@@ -326,28 +300,20 @@ main(int argc, char **argv)
+ int nflag = 0;
+ char cwdpath[PATH_MAX];
+ const char *cwd;
+- char *login_style = NULL;
+ char **envp;
+
+ setprogname("doas");
+-
+- closefrom(STDERR_FILENO + 1);
++ openlog("doas", 0, LOG_AUTHPRIV);
+
+ uid = getuid();
+
+- while ((ch = getopt(argc, argv, "a:C:Lnsu:")) != -1) {
++ while ((ch = getopt(argc, argv, "C:Lnsu:")) != -1) {
+ switch (ch) {
+- case 'a':
+- login_style = optarg;
+- break;
+ case 'C':
+ confpath = optarg;
+ break;
+ case 'L':
+- i = open("/dev/tty", O_RDWR);
+- if (i != -1)
+- ioctl(i, TIOCCLRVERAUTH);
+- exit(i == -1);
++ exit(clearpersist() != 0);
+ case 'u':
+ if (parseuid(optarg, &target) != 0)
+ errx(1, "unknown user");
+@@ -418,50 +384,30 @@ main(int argc, char **argv)
+ rv = permit(uid, groups, ngroups, &rule, target, cmd,
+ (const char **)argv + 1);
+ if (rv != 0) {
+- syslog(LOG_AUTHPRIV | LOG_NOTICE,
+- "command not permitted for %s: %s", mypw->pw_name, cmdline);
+- errc(1, EPERM, NULL);
++ syslog(LOG_NOTICE, "command not permitted for %s: %s", mypw->pw_name, cmdline);
++ errno = EPERM;
++ err(1, NULL);
+ }
+
+ if (!(rule->options & NOPASS)) {
+ if (nflag)
+ errx(1, "Authentication required");
+
+- authuser(mypw->pw_name, login_style, rule->options & PERSIST);
++ authuser(mypw->pw_name, rule->options & PERSIST);
+ }
+
+- if ((p = getenv("PATH")) != NULL)
+- formerpath = strdup(p);
+- if (formerpath == NULL)
+- formerpath = "";
+-
+- if (unveil(_PATH_LOGIN_CONF, "r") == -1)
+- err(1, "unveil %s", _PATH_LOGIN_CONF);
+- if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
+- err(1, "unveil %s.db", _PATH_LOGIN_CONF);
+- if (unveil(_PATH_LOGIN_CONF_D, "r") == -1)
+- err(1, "unveil %s", _PATH_LOGIN_CONF_D);
+- if (rule->cmd) {
+- if (setenv("PATH", safepath, 1) == -1)
+- err(1, "failed to set PATH '%s'", safepath);
+- }
+- if (unveilcommands(getenv("PATH"), cmd) == 0)
+- goto fail;
+-
+- if (pledge("stdio rpath getpw exec id", NULL) == -1)
+- err(1, "pledge");
+-
+ rv = getpwuid_r(target, &targpwstore, targpwbuf, sizeof(targpwbuf), &targpw);
+ if (rv != 0)
+ err(1, "getpwuid_r failed");
+ if (targpw == NULL)
+ errx(1, "no passwd entry for target");
+
+- if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
+- LOGIN_SETPATH |
+- LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
+- LOGIN_SETUSER | LOGIN_SETENV | LOGIN_SETRTABLE) != 0)
+- errx(1, "failed to set user context for target");
++ if (initgroups(targpw->pw_name, targpw->pw_gid) == -1)
++ err(1, "initgroups");
++ if (setgid(targpw->pw_gid) == -1)
++ err(1, "setgid");
++ if (setuid(targpw->pw_uid) == -1)
++ err(1, "setuid");
+
+ if (pledge("stdio rpath exec", NULL) == -1)
+ err(1, "pledge");
+@@ -475,23 +421,17 @@ main(int argc, char **argv)
+ err(1, "pledge");
+
+ if (!(rule->options & NOLOG)) {
+- syslog(LOG_AUTHPRIV | LOG_INFO,
+- "%s ran command %s as %s from %s",
++ syslog(LOG_INFO, "%s ran command %s as %s from %s",
+ mypw->pw_name, cmdline, targpw->pw_name, cwd);
+ }
+
+ envp = prepenv(rule, mypw, targpw);
+
+- /* setusercontext set path for the next process, so reset it for us */
+ if (rule->cmd) {
+ if (setenv("PATH", safepath, 1) == -1)
+ err(1, "failed to set PATH '%s'", safepath);
+- } else {
+- if (setenv("PATH", formerpath, 1) == -1)
+- err(1, "failed to set PATH '%s'", formerpath);
+ }
+ execvpe(cmd, argv, envp);
+-fail:
+ if (errno == ENOENT)
+ errx(1, "%s: command not found", cmd);
+ err(1, "%s", cmd);
+diff --git a/usr.bin/doas/doas.h b/usr.bin/doas/doas.h
+index ce6a03618ac..363e2626c23 100644
+--- a/usr.bin/doas/doas.h
++++ b/usr.bin/doas/doas.h
+@@ -29,13 +29,17 @@ extern struct rule **rules;
+ extern size_t nrules;
+ extern int parse_error;
+
+-extern const char *formerpath;
++extern const char *safepath;
+
+ struct passwd;
+
+ char **prepenv(const struct rule *, const struct passwd *,
+ const struct passwd *);
+
++int openpersist(int *valid);
++int setpersist(int fd);
++int clearpersist(void);
++
+ #define PERMIT -1
+ #define DENY 2
+
+diff --git a/usr.bin/doas/env.c b/usr.bin/doas/env.c
+index 2d93a4089b6..dc9be691955 100644
+--- a/usr.bin/doas/env.c
++++ b/usr.bin/doas/env.c
+@@ -28,7 +28,7 @@
+
+ #include "doas.h"
+
+-const char *formerpath;
++const char *safepath = "/bin";
+
+ struct envnode {
+ RB_ENTRY(envnode) node;
+@@ -103,7 +103,7 @@ createenv(const struct rule *rule, const struct passwd *mypw,
+ addnode(env, "DOAS_USER", mypw->pw_name);
+ addnode(env, "HOME", targpw->pw_dir);
+ addnode(env, "LOGNAME", targpw->pw_name);
+- addnode(env, "PATH", getenv("PATH"));
++ addnode(env, "PATH", safepath);
+ addnode(env, "SHELL", targpw->pw_shell);
+ addnode(env, "USER", targpw->pw_name);
+
+@@ -200,17 +200,10 @@ fillenv(struct env *env, const char **envlist)
+ /* assign value or inherit from environ */
+ if (eq) {
+ val = eq + 1;
+- if (*val == '$') {
+- if (strcmp(val + 1, "PATH") == 0)
+- val = formerpath;
+- else
+- val = getenv(val + 1);
+- }
++ if (*val == '$')
++ val = getenv(val + 1);
+ } else {
+- if (strcmp(name, "PATH") == 0)
+- val = formerpath;
+- else
+- val = getenv(name);
++ val = getenv(name);
+ }
+ /* at last, we have something to insert */
+ if (val) {
+diff --git a/usr.bin/doas/parse.y b/usr.bin/doas/parse.y
+index 604becb5445..e5fc912a9c4 100644
+--- a/usr.bin/doas/parse.y
++++ b/usr.bin/doas/parse.y
+@@ -20,6 +20,7 @@
+ #include <ctype.h>
+ #include <limits.h>
+ #include <unistd.h>
++#include <stdlib.h>
+ #include <stdint.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+diff --git a/usr.bin/doas/persist.c b/usr.bin/doas/persist.c
+new file mode 100644
+index 00000000000..4ad1bf1efbf
+--- /dev/null
++++ b/usr.bin/doas/persist.c
+@@ -0,0 +1,133 @@
++#include <errno.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <time.h>
++#include <unistd.h>
++
++#include "doas.h"
++
++#define PERSIST_DIR "/run/doas"
++#define PERSIST_TIMEOUT 5 * 60
++
++static int
++ttyid(dev_t *tty)
++{
++ int fd, i;
++ char buf[BUFSIZ], *p;
++ ssize_t n;
++
++ fd = open("/proc/self/stat", O_RDONLY);
++ if (fd == -1)
++ return -1;
++ n = read(fd, buf, sizeof(buf) - 1);
++ if (n >= 0)
++ buf[n] = '\0';
++ /* check that we read the whole file */
++ n = read(fd, buf, 1);
++ close(fd);
++ if (n != 0)
++ return -1;
++ p = strrchr(buf, ')');
++ if (!p)
++ return -1;
++ ++p;
++ /* ttr_nr is the 5th field after executable name, so skip the next 4 */
++ for (i = 0; i < 4; ++i) {
++ p = strchr(++p, ' ');
++ if (!p)
++ return -1;
++ }
++ *tty = strtol(p, &p, 10);
++ if (*p != ' ')
++ return -1;
++ return 0;
++}
++
++static int
++persistpath(char *buf, size_t len)
++{
++ dev_t tty;
++ int n;
++
++ if (ttyid(&tty) < 0)
++ return -1;
++ n = snprintf(buf, len, PERSIST_DIR "/%ju-%ju", (uintmax_t)getuid(), (uintmax_t)tty);
++ if (n < 0 || n >= (int)len)
++ return -1;
++ return 0;
++}
++
++int
++openpersist(int *valid)
++{
++ char path[256];
++ struct stat st;
++ struct timespec ts;
++ int fd;
++
++ if (stat(PERSIST_DIR, &st) < 0) {
++ if (errno != ENOENT)
++ return -1;
++ if (mkdir(PERSIST_DIR, 0700) < 0)
++ return -1;
++ } else if (st.st_uid != 0 || st.st_mode != (S_IFDIR | 0700)) {
++ return -1;
++ }
++ if (persistpath(path, sizeof(path)) < 0)
++ return -1;
++ fd = open(path, O_RDONLY);
++ if (fd == -1) {
++ char tmp[256];
++ struct timespec ts[2] = { { .tv_nsec = UTIME_OMIT }, { 0 } };
++ int n;
++
++ n = snprintf(tmp, sizeof(tmp), PERSIST_DIR "/.tmp-%d", getpid());
++ if (n < 0 || n >= (int)sizeof(tmp))
++ return -1;
++ fd = open(tmp, O_RDONLY | O_CREAT | O_EXCL, 0);
++ if (fd == -1)
++ return -1;
++ if (futimens(fd, ts) < 0 || rename(tmp, path) < 0) {
++ close(fd);
++ unlink(tmp);
++ return -1;
++ }
++ *valid = 0;
++ } else {
++ *valid = clock_gettime(CLOCK_BOOTTIME, &ts) == 0 &&
++ fstat(fd, &st) == 0 &&
++ (ts.tv_sec < st.st_mtim.tv_sec ||
++ (ts.tv_sec == st.st_mtim.tv_sec && ts.tv_nsec < st.st_mtim.tv_nsec)) &&
++ st.st_mtime - ts.tv_sec <= PERSIST_TIMEOUT;
++ }
++ return fd;
++}
++
++int
++setpersist(int fd)
++{
++ struct timespec times[2];
++
++ if (clock_gettime(CLOCK_BOOTTIME, ×[1]) < 0)
++ return -1;
++ times[0].tv_nsec = UTIME_OMIT;
++ times[1].tv_sec += PERSIST_TIMEOUT;
++ return futimens(fd, times);
++}
++
++int
++clearpersist(void)
++{
++ char path[256];
++
++ if (persistpath(path, sizeof(path)) < 0)
++ return -1;
++ if (unlink(path) < 0 && errno != ENOENT)
++ return -1;
++ return 0;
++}
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0015-doas-Port-to-linux-musl.patch b/pkg/openbsd/patch/0015-doas-Port-to-linux-musl.patch
@@ -1,581 +0,0 @@
-From 8fa1e97f6927bf1afddb5923fff3d29c3389817d Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Sun, 26 Feb 2017 16:50:55 -0800
-Subject: [PATCH] doas: Port to linux/musl
-
-Remove -a login style option and BSD authentication. Instead, compare
-against shadow file.
-
-Use timestamp files in /run/doas instead of TIOC*VERAUTH to implement
-persist.
-
-Use initgroups/setgid/setuid instead of setusercontext.
-
-Provide UID_MAX and GID_MAX defaults.
-
-Use LOGIN_NAME_MAX instead of _PW_NAME_LEN.
-
-Remove call to closefrom.
-
-Replace calls to errc with err after setting errno.
-
-Call openlog at start to set syslog identity.
-
-Remove unveil/pledge since they aren't supported on Linux.
-
-Simplify handling of PATH in the environment since we don't have
-login.conf with per-user default PATH.
----
- usr.bin/doas/doas.1 | 9 ---
- usr.bin/doas/doas.c | 168 +++++++++++++----------------------------
- usr.bin/doas/doas.h | 6 +-
- usr.bin/doas/env.c | 17 ++---
- usr.bin/doas/parse.y | 1 +
- usr.bin/doas/persist.c | 133 ++++++++++++++++++++++++++++++++
- 6 files changed, 198 insertions(+), 136 deletions(-)
- create mode 100644 usr.bin/doas/persist.c
-
-diff --git a/usr.bin/doas/doas.1 b/usr.bin/doas/doas.1
-index 25827cc7104..3542680faf5 100644
---- a/usr.bin/doas/doas.1
-+++ b/usr.bin/doas/doas.1
-@@ -22,7 +22,6 @@
- .Sh SYNOPSIS
- .Nm doas
- .Op Fl Lns
--.Op Fl a Ar style
- .Op Fl C Ar config
- .Op Fl u Ar user
- .Ar command
-@@ -67,14 +66,6 @@ The working directory is not changed.
- .Pp
- The options are as follows:
- .Bl -tag -width tenletters
--.It Fl a Ar style
--Use the specified authentication style when validating the user,
--as allowed by
--.Pa /etc/login.conf .
--A list of doas-specific authentication methods may be configured by adding an
--.Sq auth-doas
--entry in
--.Xr login.conf 5 .
- .It Fl C Ar config
- Parse and check the configuration file
- .Ar config ,
-diff --git a/usr.bin/doas/doas.c b/usr.bin/doas/doas.c
-index 8b684d6006c..27d7b01014e 100644
---- a/usr.bin/doas/doas.c
-+++ b/usr.bin/doas/doas.c
-@@ -20,8 +20,6 @@
- #include <sys/ioctl.h>
-
- #include <limits.h>
--#include <login_cap.h>
--#include <bsd_auth.h>
- #include <readpassphrase.h>
- #include <string.h>
- #include <stdio.h>
-@@ -33,13 +31,22 @@
- #include <syslog.h>
- #include <errno.h>
- #include <fcntl.h>
-+#include <shadow.h>
-
- #include "doas.h"
-
-+#ifndef UID_MAX
-+#define UID_MAX 65535
-+#endif
-+
-+#ifndef GID_MAX
-+#define GID_MAX 65535
-+#endif
-+
- static void __dead
- usage(void)
- {
-- fprintf(stderr, "usage: doas [-Lns] [-a style] [-C config] [-u user]"
-+ fprintf(stderr, "usage: doas [-Lns] [-C config] [-u user]"
- " command [arg ...]\n");
- exit(1);
- }
-@@ -200,16 +207,28 @@ checkconfig(const char *confpath, int argc, char **argv,
- }
-
- static int
--authuser_checkpass(char *myname, char *login_style)
-+verifypasswd(const char *user, const char *pass)
-+{
-+ struct spwd *sp;
-+ char *p1, *p2;
-+
-+ sp = getspnam(user);
-+ if (!sp)
-+ return 0;
-+ p1 = sp->sp_pwdp;
-+ if (p1[0] == '!' || p1[0] == '*')
-+ return 0;
-+ p2 = crypt(pass, p1);
-+ if (!p2)
-+ return 0;
-+ return strcmp(p1, p2) == 0;
-+}
-+
-+static int
-+authuser_checkpass(char *myname)
- {
- char *challenge = NULL, *response, rbuf[1024], cbuf[128];
-- auth_session_t *as;
-
-- if (!(as = auth_userchallenge(myname, login_style, "auth-doas",
-- &challenge))) {
-- warnx("Authentication failed");
-- return AUTH_FAILED;
-- }
- if (!challenge) {
- char host[HOST_NAME_MAX + 1];
-
-@@ -222,14 +241,12 @@ authuser_checkpass(char *myname, char *login_style)
- response = readpassphrase(challenge, rbuf, sizeof(rbuf),
- RPP_REQUIRE_TTY);
- if (response == NULL && errno == ENOTTY) {
-- syslog(LOG_AUTHPRIV | LOG_NOTICE,
-- "tty required for %s", myname);
-+ syslog(LOG_NOTICE, "tty required for %s", myname);
- errx(1, "a tty is required");
- }
-- if (!auth_userresponse(as, response, 0)) {
-+ if (!verifypasswd(myname, response)) {
- explicit_bzero(rbuf, sizeof(rbuf));
-- syslog(LOG_AUTHPRIV | LOG_NOTICE,
-- "failed auth for %s", myname);
-+ syslog(LOG_NOTICE, "failed auth for %s", myname);
- warnx("Authentication failed");
- return AUTH_FAILED;
- }
-@@ -238,79 +255,36 @@ authuser_checkpass(char *myname, char *login_style)
- }
-
- static void
--authuser(char *myname, char *login_style, int persist)
-+authuser(char *myname, int persist)
- {
-- int i, fd = -1;
-+ int i, fd = -1, valid = 0;
-
-- if (persist)
-- fd = open("/dev/tty", O_RDWR);
-- if (fd != -1) {
-- if (ioctl(fd, TIOCCHKVERAUTH) == 0)
-+ if (persist) {
-+ fd = openpersist(&valid);
-+ if (valid)
- goto good;
- }
- for (i = 0; i < AUTH_RETRIES; i++) {
-- if (authuser_checkpass(myname, login_style) == AUTH_OK)
-+ if (authuser_checkpass(myname) == AUTH_OK)
- goto good;
- }
- exit(1);
- good:
- if (fd != -1) {
-- int secs = 5 * 60;
-- ioctl(fd, TIOCSETVERAUTH, &secs);
-+ setpersist(fd);
- close(fd);
- }
- }
-
--int
--unveilcommands(const char *ipath, const char *cmd)
--{
-- char *path = NULL, *p;
-- int unveils = 0;
--
-- if (strchr(cmd, '/') != NULL) {
-- if (unveil(cmd, "x") != -1)
-- unveils++;
-- goto done;
-- }
--
-- if (!ipath) {
-- errno = ENOENT;
-- goto done;
-- }
-- path = strdup(ipath);
-- if (!path) {
-- errno = ENOENT;
-- goto done;
-- }
-- for (p = path; p && *p; ) {
-- char buf[PATH_MAX];
-- char *cp = strsep(&p, ":");
--
-- if (cp) {
-- int r = snprintf(buf, sizeof buf, "%s/%s", cp, cmd);
-- if (r >= 0 && r < sizeof buf) {
-- if (unveil(buf, "x") != -1)
-- unveils++;
-- }
-- }
-- }
--done:
-- free(path);
-- return (unveils);
--}
--
- int
- main(int argc, char **argv)
- {
-- const char *safepath = "/bin:/sbin:/usr/bin:/usr/sbin:"
-- "/usr/local/bin:/usr/local/sbin";
- const char *confpath = NULL;
- char *shargv[] = { NULL, NULL };
- char *sh;
-- const char *p;
- const char *cmd;
- char cmdline[LINE_MAX];
-- char mypwbuf[_PW_BUF_LEN], targpwbuf[_PW_BUF_LEN];
-+ char mypwbuf[1024], targpwbuf[1024];
- struct passwd mypwstore, targpwstore;
- struct passwd *mypw, *targpw;
- const struct rule *rule;
-@@ -323,28 +297,20 @@ main(int argc, char **argv)
- int nflag = 0;
- char cwdpath[PATH_MAX];
- const char *cwd;
-- char *login_style = NULL;
- char **envp;
-
- setprogname("doas");
--
-- closefrom(STDERR_FILENO + 1);
-+ openlog("doas", 0, LOG_AUTHPRIV);
-
- uid = getuid();
-
-- while ((ch = getopt(argc, argv, "a:C:Lnsu:")) != -1) {
-+ while ((ch = getopt(argc, argv, "C:Lnsu:")) != -1) {
- switch (ch) {
-- case 'a':
-- login_style = optarg;
-- break;
- case 'C':
- confpath = optarg;
- break;
- case 'L':
-- i = open("/dev/tty", O_RDWR);
-- if (i != -1)
-- ioctl(i, TIOCCLRVERAUTH);
-- exit(i == -1);
-+ exit(clearpersist() != 0);
- case 'u':
- if (parseuid(optarg, &target) != 0)
- errx(1, "unknown user");
-@@ -414,50 +380,30 @@ main(int argc, char **argv)
- cmd = argv[0];
- if (!permit(uid, groups, ngroups, &rule, target, cmd,
- (const char **)argv + 1)) {
-- syslog(LOG_AUTHPRIV | LOG_NOTICE,
-- "command not permitted for %s: %s", mypw->pw_name, cmdline);
-- errc(1, EPERM, NULL);
-+ syslog(LOG_NOTICE, "command not permitted for %s: %s", mypw->pw_name, cmdline);
-+ errno = EPERM;
-+ err(1, NULL);
- }
-
- if (!(rule->options & NOPASS)) {
- if (nflag)
- errx(1, "Authentication required");
-
-- authuser(mypw->pw_name, login_style, rule->options & PERSIST);
-+ authuser(mypw->pw_name, rule->options & PERSIST);
- }
-
-- if ((p = getenv("PATH")) != NULL)
-- formerpath = strdup(p);
-- if (formerpath == NULL)
-- formerpath = "";
--
-- if (unveil(_PATH_LOGIN_CONF, "r") == -1)
-- err(1, "unveil %s", _PATH_LOGIN_CONF);
-- if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
-- err(1, "unveil %s.db", _PATH_LOGIN_CONF);
-- if (unveil(_PATH_LOGIN_CONF_D, "r") == -1)
-- err(1, "unveil %s", _PATH_LOGIN_CONF_D);
-- if (rule->cmd) {
-- if (setenv("PATH", safepath, 1) == -1)
-- err(1, "failed to set PATH '%s'", safepath);
-- }
-- if (unveilcommands(getenv("PATH"), cmd) == 0)
-- goto fail;
--
-- if (pledge("stdio rpath getpw exec id", NULL) == -1)
-- err(1, "pledge");
--
- rv = getpwuid_r(target, &targpwstore, targpwbuf, sizeof(targpwbuf), &targpw);
- if (rv != 0)
- err(1, "getpwuid_r failed");
- if (targpw == NULL)
- errx(1, "no passwd entry for target");
-
-- if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
-- LOGIN_SETPATH |
-- LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
-- LOGIN_SETUSER | LOGIN_SETENV | LOGIN_SETRTABLE) != 0)
-- errx(1, "failed to set user context for target");
-+ if (initgroups(targpw->pw_name, targpw->pw_gid) == -1)
-+ err(1, "initgroups");
-+ if (setgid(targpw->pw_gid) == -1)
-+ err(1, "setgid");
-+ if (setuid(targpw->pw_uid) == -1)
-+ err(1, "setuid");
-
- if (pledge("stdio rpath exec", NULL) == -1)
- err(1, "pledge");
-@@ -471,23 +417,17 @@ main(int argc, char **argv)
- err(1, "pledge");
-
- if (!(rule->options & NOLOG)) {
-- syslog(LOG_AUTHPRIV | LOG_INFO,
-- "%s ran command %s as %s from %s",
-+ syslog(LOG_INFO, "%s ran command %s as %s from %s",
- mypw->pw_name, cmdline, targpw->pw_name, cwd);
- }
-
- envp = prepenv(rule, mypw, targpw);
-
-- /* setusercontext set path for the next process, so reset it for us */
- if (rule->cmd) {
- if (setenv("PATH", safepath, 1) == -1)
- err(1, "failed to set PATH '%s'", safepath);
-- } else {
-- if (setenv("PATH", formerpath, 1) == -1)
-- err(1, "failed to set PATH '%s'", formerpath);
- }
- execvpe(cmd, argv, envp);
--fail:
- if (errno == ENOENT)
- errx(1, "%s: command not found", cmd);
- err(1, "%s", cmd);
-diff --git a/usr.bin/doas/doas.h b/usr.bin/doas/doas.h
-index b98fe353b18..6567625c471 100644
---- a/usr.bin/doas/doas.h
-+++ b/usr.bin/doas/doas.h
-@@ -29,13 +29,17 @@ extern struct rule **rules;
- extern size_t nrules;
- extern int parse_error;
-
--extern const char *formerpath;
-+extern const char *safepath;
-
- struct passwd;
-
- char **prepenv(const struct rule *, const struct passwd *,
- const struct passwd *);
-
-+int openpersist(int *valid);
-+int setpersist(int fd);
-+int clearpersist(void);
-+
- #define PERMIT 1
- #define DENY 2
-
-diff --git a/usr.bin/doas/env.c b/usr.bin/doas/env.c
-index 2d93a4089b6..dc9be691955 100644
---- a/usr.bin/doas/env.c
-+++ b/usr.bin/doas/env.c
-@@ -28,7 +28,7 @@
-
- #include "doas.h"
-
--const char *formerpath;
-+const char *safepath = "/bin";
-
- struct envnode {
- RB_ENTRY(envnode) node;
-@@ -103,7 +103,7 @@ createenv(const struct rule *rule, const struct passwd *mypw,
- addnode(env, "DOAS_USER", mypw->pw_name);
- addnode(env, "HOME", targpw->pw_dir);
- addnode(env, "LOGNAME", targpw->pw_name);
-- addnode(env, "PATH", getenv("PATH"));
-+ addnode(env, "PATH", safepath);
- addnode(env, "SHELL", targpw->pw_shell);
- addnode(env, "USER", targpw->pw_name);
-
-@@ -200,17 +200,10 @@ fillenv(struct env *env, const char **envlist)
- /* assign value or inherit from environ */
- if (eq) {
- val = eq + 1;
-- if (*val == '$') {
-- if (strcmp(val + 1, "PATH") == 0)
-- val = formerpath;
-- else
-- val = getenv(val + 1);
-- }
-+ if (*val == '$')
-+ val = getenv(val + 1);
- } else {
-- if (strcmp(name, "PATH") == 0)
-- val = formerpath;
-- else
-- val = getenv(name);
-+ val = getenv(name);
- }
- /* at last, we have something to insert */
- if (val) {
-diff --git a/usr.bin/doas/parse.y b/usr.bin/doas/parse.y
-index 604becb5445..e5fc912a9c4 100644
---- a/usr.bin/doas/parse.y
-+++ b/usr.bin/doas/parse.y
-@@ -20,6 +20,7 @@
- #include <ctype.h>
- #include <limits.h>
- #include <unistd.h>
-+#include <stdlib.h>
- #include <stdint.h>
- #include <stdarg.h>
- #include <stdio.h>
-diff --git a/usr.bin/doas/persist.c b/usr.bin/doas/persist.c
-new file mode 100644
-index 00000000000..4ad1bf1efbf
---- /dev/null
-+++ b/usr.bin/doas/persist.c
-@@ -0,0 +1,133 @@
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <limits.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <sys/stat.h>
-+#include <sys/types.h>
-+#include <time.h>
-+#include <unistd.h>
-+
-+#include "doas.h"
-+
-+#define PERSIST_DIR "/run/doas"
-+#define PERSIST_TIMEOUT 5 * 60
-+
-+static int
-+ttyid(dev_t *tty)
-+{
-+ int fd, i;
-+ char buf[BUFSIZ], *p;
-+ ssize_t n;
-+
-+ fd = open("/proc/self/stat", O_RDONLY);
-+ if (fd == -1)
-+ return -1;
-+ n = read(fd, buf, sizeof(buf) - 1);
-+ if (n >= 0)
-+ buf[n] = '\0';
-+ /* check that we read the whole file */
-+ n = read(fd, buf, 1);
-+ close(fd);
-+ if (n != 0)
-+ return -1;
-+ p = strrchr(buf, ')');
-+ if (!p)
-+ return -1;
-+ ++p;
-+ /* ttr_nr is the 5th field after executable name, so skip the next 4 */
-+ for (i = 0; i < 4; ++i) {
-+ p = strchr(++p, ' ');
-+ if (!p)
-+ return -1;
-+ }
-+ *tty = strtol(p, &p, 10);
-+ if (*p != ' ')
-+ return -1;
-+ return 0;
-+}
-+
-+static int
-+persistpath(char *buf, size_t len)
-+{
-+ dev_t tty;
-+ int n;
-+
-+ if (ttyid(&tty) < 0)
-+ return -1;
-+ n = snprintf(buf, len, PERSIST_DIR "/%ju-%ju", (uintmax_t)getuid(), (uintmax_t)tty);
-+ if (n < 0 || n >= (int)len)
-+ return -1;
-+ return 0;
-+}
-+
-+int
-+openpersist(int *valid)
-+{
-+ char path[256];
-+ struct stat st;
-+ struct timespec ts;
-+ int fd;
-+
-+ if (stat(PERSIST_DIR, &st) < 0) {
-+ if (errno != ENOENT)
-+ return -1;
-+ if (mkdir(PERSIST_DIR, 0700) < 0)
-+ return -1;
-+ } else if (st.st_uid != 0 || st.st_mode != (S_IFDIR | 0700)) {
-+ return -1;
-+ }
-+ if (persistpath(path, sizeof(path)) < 0)
-+ return -1;
-+ fd = open(path, O_RDONLY);
-+ if (fd == -1) {
-+ char tmp[256];
-+ struct timespec ts[2] = { { .tv_nsec = UTIME_OMIT }, { 0 } };
-+ int n;
-+
-+ n = snprintf(tmp, sizeof(tmp), PERSIST_DIR "/.tmp-%d", getpid());
-+ if (n < 0 || n >= (int)sizeof(tmp))
-+ return -1;
-+ fd = open(tmp, O_RDONLY | O_CREAT | O_EXCL, 0);
-+ if (fd == -1)
-+ return -1;
-+ if (futimens(fd, ts) < 0 || rename(tmp, path) < 0) {
-+ close(fd);
-+ unlink(tmp);
-+ return -1;
-+ }
-+ *valid = 0;
-+ } else {
-+ *valid = clock_gettime(CLOCK_BOOTTIME, &ts) == 0 &&
-+ fstat(fd, &st) == 0 &&
-+ (ts.tv_sec < st.st_mtim.tv_sec ||
-+ (ts.tv_sec == st.st_mtim.tv_sec && ts.tv_nsec < st.st_mtim.tv_nsec)) &&
-+ st.st_mtime - ts.tv_sec <= PERSIST_TIMEOUT;
-+ }
-+ return fd;
-+}
-+
-+int
-+setpersist(int fd)
-+{
-+ struct timespec times[2];
-+
-+ if (clock_gettime(CLOCK_BOOTTIME, ×[1]) < 0)
-+ return -1;
-+ times[0].tv_nsec = UTIME_OMIT;
-+ times[1].tv_sec += PERSIST_TIMEOUT;
-+ return futimens(fd, times);
-+}
-+
-+int
-+clearpersist(void)
-+{
-+ char path[256];
-+
-+ if (persistpath(path, sizeof(path)) < 0)
-+ return -1;
-+ if (unlink(path) < 0 && errno != ENOENT)
-+ return -1;
-+ return 0;
-+}
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0016-pwcache-Don-t-use-fixed-buffer-sizes.patch b/pkg/openbsd/patch/0015-pwcache-Don-t-use-fixed-buffer-sizes.patch
diff --git a/pkg/openbsd/patch/0017-Add-standalone-freezero.patch b/pkg/openbsd/patch/0016-Add-standalone-freezero.patch
diff --git a/pkg/openbsd/patch/0018-m4-Use-hand-written-lexer-to-avoid-cycle-in-bootstra.patch b/pkg/openbsd/patch/0017-m4-Use-hand-written-lexer-to-avoid-cycle-in-bootstra.patch
diff --git a/pkg/openbsd/patch/0018-m4-Use-_Noreturn-instead-of-__dead.patch b/pkg/openbsd/patch/0018-m4-Use-_Noreturn-instead-of-__dead.patch
@@ -0,0 +1,25 @@
+From eb6d8858f8dd92400efaa08680d28515270d4c35 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 10 Apr 2018 16:03:44 -0700
+Subject: [PATCH] m4: Use _Noreturn instead of __dead
+
+---
+ usr.bin/m4/extern.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/usr.bin/m4/extern.h b/usr.bin/m4/extern.h
+index c7defe46c2c..de03e51995e 100644
+--- a/usr.bin/m4/extern.h
++++ b/usr.bin/m4/extern.h
+@@ -112,7 +112,7 @@ extern void usage(void);
+ extern void resizedivs(int);
+ extern size_t buffer_mark(void);
+ extern void dump_buffer(FILE *, size_t);
+-extern void __dead m4errx(int, const char *, ...);
++extern void _Noreturn m4errx(int, const char *, ...);
+
+ extern int obtain_char(struct input_file *);
+ extern void set_input(struct input_file *, FILE *, const char *);
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0020-m4-Add-missing-includes.patch b/pkg/openbsd/patch/0019-m4-Add-missing-includes.patch
diff --git a/pkg/openbsd/patch/0019-m4-Use-_Noreturn-instead-of-__dead.patch b/pkg/openbsd/patch/0019-m4-Use-_Noreturn-instead-of-__dead.patch
@@ -1,25 +0,0 @@
-From 0f0eb43f3d6fb749fac229e3d6c8f74b2c40ece2 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Tue, 10 Apr 2018 16:03:44 -0700
-Subject: [PATCH] m4: Use _Noreturn instead of __dead
-
----
- usr.bin/m4/extern.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/usr.bin/m4/extern.h b/usr.bin/m4/extern.h
-index ea8406b8540..0c07599777d 100644
---- a/usr.bin/m4/extern.h
-+++ b/usr.bin/m4/extern.h
-@@ -113,7 +113,7 @@ extern void usage(void);
- extern void resizedivs(int);
- extern size_t buffer_mark(void);
- extern void dump_buffer(FILE *, size_t);
--extern void __dead m4errx(int, const char *, ...);
-+extern void _Noreturn m4errx(int, const char *, ...);
-
- extern int obtain_char(struct input_file *);
- extern void set_input(struct input_file *, FILE *, const char *);
---
-2.17.0
-
diff --git a/pkg/openbsd/patch/0021-libutil-Add-missing-includes.patch b/pkg/openbsd/patch/0020-libutil-Add-missing-includes.patch
diff --git a/pkg/openbsd/patch/0022-acme-client-Add-missing-includes.patch b/pkg/openbsd/patch/0021-acme-client-Add-missing-includes.patch
diff --git a/pkg/openbsd/patch/0022-rsync-Add-missing-includes.patch b/pkg/openbsd/patch/0022-rsync-Add-missing-includes.patch
@@ -0,0 +1,41 @@
+From 9320adbea46f051b32c93a171dc0d52de8f845c3 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Fri, 14 Jun 2019 12:40:56 -0700
+Subject: [PATCH] rsync: Add missing includes
+
+- stdio.h in socket.c for sscanf
+- stdint.h in extern.h for fixed-width integer types
+- sys/types.h in extern.h for various type definitions
+---
+ usr.bin/rsync/extern.h | 2 ++
+ usr.bin/rsync/socket.c | 1 +
+ 2 files changed, 3 insertions(+)
+
+diff --git a/usr.bin/rsync/extern.h b/usr.bin/rsync/extern.h
+index 5bb23aaa486..55d7bc26ae2 100644
+--- a/usr.bin/rsync/extern.h
++++ b/usr.bin/rsync/extern.h
+@@ -17,6 +17,8 @@
+ #ifndef EXTERN_H
+ #define EXTERN_H
+
++#include <stdint.h>
++#include <sys/types.h>
+ #include <openssl/md4.h>
+
+ /*
+diff --git a/usr.bin/rsync/socket.c b/usr.bin/rsync/socket.c
+index d723d9e7df4..adc4a22cf40 100644
+--- a/usr.bin/rsync/socket.c
++++ b/usr.bin/rsync/socket.c
+@@ -28,6 +28,7 @@
+ #include <poll.h>
+ #include <resolv.h>
+ #include <stdlib.h>
++#include <stdio.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <err.h>
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0023-rsync-Add-missing-includes.patch b/pkg/openbsd/patch/0023-rsync-Add-missing-includes.patch
@@ -1,42 +0,0 @@
-From d423093f8dec64533733deb0762353f68b0adeb2 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Fri, 14 Jun 2019 12:40:56 -0700
-Subject: [PATCH] rsync: Add missing includes
-
-- stdio.h in socket.c for sscanf
-- stdint.h in extern.h for fixed-width integer types
-- sys/types.h in extern.h for various type definitions
----
- usr.bin/rsync/extern.h | 3 +++
- usr.bin/rsync/socket.c | 1 +
- 2 files changed, 4 insertions(+)
-
-diff --git a/usr.bin/rsync/extern.h b/usr.bin/rsync/extern.h
-index 2815f82cf89..a3f2a15b959 100644
---- a/usr.bin/rsync/extern.h
-+++ b/usr.bin/rsync/extern.h
-@@ -17,6 +17,9 @@
- #ifndef EXTERN_H
- #define EXTERN_H
-
-+#include <stdint.h>
-+#include <sys/types.h>
-+
- /*
- * This is the rsync protocol version that we support.
- */
-diff --git a/usr.bin/rsync/socket.c b/usr.bin/rsync/socket.c
-index 953b229afbc..aa95cce9369 100644
---- a/usr.bin/rsync/socket.c
-+++ b/usr.bin/rsync/socket.c
-@@ -28,6 +28,7 @@
- #include <poll.h>
- #include <resolv.h>
- #include <stdlib.h>
-+#include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <err.h>
---
-2.34.1
-
diff --git a/pkg/openbsd/patch/0023-rsync-Use-standard-S_ISVTX-instead-of-S_ISTXT.patch b/pkg/openbsd/patch/0023-rsync-Use-standard-S_ISVTX-instead-of-S_ISTXT.patch
@@ -0,0 +1,34 @@
+From 6e087cd1f746eb636de0ec1769db6b4aac65e666 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Fri, 14 Jun 2019 12:42:15 -0700
+Subject: [PATCH] rsync: Use standard S_ISVTX instead of S_ISTXT
+
+---
+ usr.bin/rsync/receiver.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/usr.bin/rsync/receiver.c b/usr.bin/rsync/receiver.c
+index 256a788b4f0..5dcc33b20fd 100644
+--- a/usr.bin/rsync/receiver.c
++++ b/usr.bin/rsync/receiver.c
+@@ -87,7 +87,7 @@ rsync_set_metadata(struct sess *sess, int newfile,
+ "to user.group: %u.%u", f->path, uid, gid);
+ } else
+ LOG4("%s: updated uid and/or gid", f->path);
+- mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
++ mode &= ~(S_ISVTX | S_ISUID | S_ISGID);
+ }
+
+ /* Conditionally adjust file permissions. */
+@@ -149,7 +149,7 @@ rsync_set_metadata_at(struct sess *sess, int newfile, int rootfd,
+ "to user.group: %u.%u", f->path, uid, gid);
+ } else
+ LOG4("%s: updated uid and/or gid", f->path);
+- mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
++ mode &= ~(S_ISVTX | S_ISUID | S_ISGID);
+ }
+
+ /* Conditionally adjust file permissions. */
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0024-rsync-Avoid-pointer-arithmetic-on-void.patch b/pkg/openbsd/patch/0024-rsync-Avoid-pointer-arithmetic-on-void.patch
@@ -0,0 +1,149 @@
+From 3823d88a12d7c95de2d4b68796b5faa7f550caed Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sat, 15 Jun 2019 20:06:13 -0700
+Subject: [PATCH] rsync: Avoid pointer arithmetic on `void *`
+
+---
+ usr.bin/rsync/blocks.c | 8 ++++----
+ usr.bin/rsync/downloader.c | 2 +-
+ usr.bin/rsync/io.c | 12 ++++++------
+ usr.bin/rsync/sender.c | 5 +++--
+ 4 files changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/usr.bin/rsync/blocks.c b/usr.bin/rsync/blocks.c
+index d1d9b19c31e..8f4bcb532e1 100644
+--- a/usr.bin/rsync/blocks.c
++++ b/usr.bin/rsync/blocks.c
+@@ -163,7 +163,7 @@ blk_find(struct sess *sess, struct blkstat *st,
+ if (!recomp) {
+ fhash = (st->s1 & 0xFFFF) | (st->s2 << 16);
+ } else {
+- fhash = hash_fast(st->map + st->offs, (size_t)osz);
++ fhash = hash_fast((char *)st->map + st->offs, (size_t)osz);
+ st->s1 = fhash & 0xFFFF;
+ st->s2 = fhash >> 16;
+ }
+@@ -176,7 +176,7 @@ blk_find(struct sess *sess, struct blkstat *st,
+ if (st->hint < blks->blksz &&
+ fhash == blks->blks[st->hint].chksum_short &&
+ (size_t)osz == blks->blks[st->hint].len) {
+- hash_slow(st->map + st->offs, (size_t)osz, md, sess);
++ hash_slow((char *)st->map + st->offs, (size_t)osz, md, sess);
+ have_md = 1;
+ if (memcmp(md, blks->blks[st->hint].chksum_long, blks->csum) == 0) {
+ LOG4("%s: found matching hinted match: "
+@@ -209,7 +209,7 @@ blk_find(struct sess *sess, struct blkstat *st,
+ (intmax_t)ent->blk->offs, ent->blk->len);
+
+ if (have_md == 0) {
+- hash_slow(st->map + st->offs, (size_t)osz, md, sess);
++ hash_slow((char *)st->map + st->offs, (size_t)osz, md, sess);
+ have_md = 1;
+ }
+
+@@ -227,7 +227,7 @@ blk_find(struct sess *sess, struct blkstat *st,
+ * block in the sequence.
+ */
+
+- map = st->map + st->offs;
++ map = (char *)st->map + st->offs;
+ st->s1 -= map[0];
+ st->s2 -= osz * map[0];
+
+diff --git a/usr.bin/rsync/downloader.c b/usr.bin/rsync/downloader.c
+index cab6eb23f9f..07ec334f6b4 100644
+--- a/usr.bin/rsync/downloader.c
++++ b/usr.bin/rsync/downloader.c
+@@ -495,7 +495,7 @@ again:
+ sz = tok == p->blk.blksz - 1 ? p->blk.rem : p->blk.len;
+ assert(sz);
+ assert(p->map != MAP_FAILED);
+- buf = p->map + (tok * p->blk.len);
++ buf = (char *)p->map + (tok * p->blk.len);
+
+ /*
+ * Now we read from our block.
+diff --git a/usr.bin/rsync/io.c b/usr.bin/rsync/io.c
+index dc224ae8aed..fcf9e92dbaa 100644
+--- a/usr.bin/rsync/io.c
++++ b/usr.bin/rsync/io.c
+@@ -117,7 +117,7 @@ io_write_blocking(int fd, const void *buf, size_t sz)
+ ERRX("io_write_nonblocking: short write");
+ return 0;
+ }
+- buf += wsz;
++ buf = (char *)buf + wsz;
+ sz -= wsz;
+ }
+
+@@ -156,7 +156,7 @@ io_write_buf(struct sess *sess, int fd, const void *buf, size_t sz)
+ }
+ sess->total_write += wsz;
+ sz -= wsz;
+- buf += wsz;
++ buf = (char *)buf + wsz;
+ }
+
+ return 1;
+@@ -250,7 +250,7 @@ io_read_blocking(int fd, void *buf, size_t sz)
+ ERRX("io_read_nonblocking: short read");
+ return 0;
+ }
+- buf += rsz;
++ buf = (char *)buf + rsz;
+ sz -= rsz;
+ }
+
+@@ -367,7 +367,7 @@ io_read_buf(struct sess *sess, int fd, void *buf, size_t sz)
+ }
+ sz -= rsz;
+ sess->mplex_read_remain -= rsz;
+- buf += rsz;
++ buf = (char *)buf + rsz;
+ sess->total_read += rsz;
+ continue;
+ }
+@@ -463,7 +463,7 @@ io_buffer_buf(void *buf, size_t *bufpos, size_t buflen, const void *val,
+ {
+
+ assert(*bufpos + valsz <= buflen);
+- memcpy(buf + *bufpos, val, valsz);
++ memcpy((char *)buf + *bufpos, val, valsz);
+ *bufpos += valsz;
+ }
+
+@@ -662,7 +662,7 @@ io_unbuffer_buf(const void *buf, size_t *bufpos, size_t bufsz, void *val,
+ {
+
+ assert(*bufpos + valsz <= bufsz);
+- memcpy(val, buf + *bufpos, valsz);
++ memcpy(val, (char *)buf + *bufpos, valsz);
+ *bufpos += valsz;
+ }
+
+diff --git a/usr.bin/rsync/sender.c b/usr.bin/rsync/sender.c
+index c54fbc2dae0..6469e7f27e5 100644
+--- a/usr.bin/rsync/sender.c
++++ b/usr.bin/rsync/sender.c
+@@ -128,7 +128,7 @@ send_up_fsm(struct sess *sess, size_t *phase,
+ return 0;
+ }
+ io_lowbuffer_buf(sess, *wb, &pos, *wbsz,
+- up->stat.map + up->stat.curpos, sz);
++ (char *)up->stat.map + up->stat.curpos, sz);
+
+ up->stat.curpos += sz;
+ if (up->stat.curpos == up->stat.curlen)
+@@ -561,7 +561,8 @@ rsync_sender(struct sess *sess, int fdin,
+ if ((pfd[1].revents & POLLOUT) && wbufsz > 0) {
+ assert(pfd[2].fd == -1);
+ assert(wbufsz - wbufpos);
+- ssz = write(fdout, wbuf + wbufpos, wbufsz - wbufpos);
++ ssz = write(fdout,
++ (char *)wbuf + wbufpos, wbufsz - wbufpos);
+ if (ssz == -1) {
+ ERR("write");
+ goto out;
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0024-rsync-Use-standard-S_ISVTX-instead-of-S_ISTXT.patch b/pkg/openbsd/patch/0024-rsync-Use-standard-S_ISVTX-instead-of-S_ISTXT.patch
@@ -1,34 +0,0 @@
-From d5670219baefe6769a42984abb93e19d8a43dada Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Fri, 14 Jun 2019 12:42:15 -0700
-Subject: [PATCH] rsync: Use standard S_ISVTX instead of S_ISTXT
-
----
- usr.bin/rsync/receiver.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/usr.bin/rsync/receiver.c b/usr.bin/rsync/receiver.c
-index 6e5b01670cd..67510b3e932 100644
---- a/usr.bin/rsync/receiver.c
-+++ b/usr.bin/rsync/receiver.c
-@@ -87,7 +87,7 @@ rsync_set_metadata(struct sess *sess, int newfile,
- "to user.group: %u.%u", f->path, uid, gid);
- } else
- LOG4("%s: updated uid and/or gid", f->path);
-- mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
-+ mode &= ~(S_ISVTX | S_ISUID | S_ISGID);
- }
-
- /* Conditionally adjust file permissions. */
-@@ -148,7 +148,7 @@ rsync_set_metadata_at(struct sess *sess, int newfile, int rootfd,
- "to user.group: %u.%u", f->path, uid, gid);
- } else
- LOG4("%s: updated uid and/or gid", f->path);
-- mode &= ~(S_ISTXT | S_ISUID | S_ISGID);
-+ mode &= ~(S_ISVTX | S_ISUID | S_ISGID);
- }
-
- /* Conditionally adjust file permissions. */
---
-2.34.1
-
diff --git a/pkg/openbsd/patch/0025-Include-sys-sysmacros.h-if-necessary.patch b/pkg/openbsd/patch/0025-Include-sys-sysmacros.h-if-necessary.patch
@@ -0,0 +1,73 @@
+From bf938d0fd70582d8d7942c2f04c2d4209b9b8633 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Mon, 5 Aug 2019 21:42:54 -0700
+Subject: [PATCH] Include sys/sysmacros.h if necessary
+
+---
+ bin/pax/cpio.c | 4 ++++
+ bin/pax/gen_subs.c | 3 +++
+ bin/pax/tar.c | 3 +++
+ usr.bin/rsync/flist.c | 4 ++++
+ 4 files changed, 14 insertions(+)
+
+diff --git a/bin/pax/cpio.c b/bin/pax/cpio.c
+index be0316d8dd9..fbcf032e091 100644
+--- a/bin/pax/cpio.c
++++ b/bin/pax/cpio.c
+@@ -41,6 +41,10 @@
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <stdlib.h>
++#ifndef major
++#include <sys/sysmacros.h>
++#endif
++
+ #include "pax.h"
+ #include "cpio.h"
+ #include "extern.h"
+diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c
+index fcda4d37391..928cfcd3657 100644
+--- a/bin/pax/gen_subs.c
++++ b/bin/pax/gen_subs.c
+@@ -45,6 +45,9 @@
+ #include <unistd.h>
+ #include <utmp.h>
+ #include <vis.h>
++#ifndef major
++#include <sys/sysmacros.h>
++#endif
+
+ #include "pax.h"
+ #include "extern.h"
+diff --git a/bin/pax/tar.c b/bin/pax/tar.c
+index ef22a9fd2d8..a0cbb31b547 100644
+--- a/bin/pax/tar.c
++++ b/bin/pax/tar.c
+@@ -47,6 +47,9 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
++#ifndef major
++#include <sys/sysmacros.h>
++#endif
+
+ #include "pax.h"
+ #include "extern.h"
+diff --git a/usr.bin/rsync/flist.c b/usr.bin/rsync/flist.c
+index cdc9f1da1dd..8832420cce0 100644
+--- a/usr.bin/rsync/flist.c
++++ b/usr.bin/rsync/flist.c
+@@ -16,6 +16,10 @@
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+ #include <sys/stat.h>
++#include <sys/types.h>
++#ifndef major
++#include <sys/sysmacros.h>
++#endif
+
+ #include <assert.h>
+ #include <errno.h>
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0025-rsync-Avoid-pointer-arithmetic-on-void.patch b/pkg/openbsd/patch/0025-rsync-Avoid-pointer-arithmetic-on-void.patch
@@ -1,149 +0,0 @@
-From b93dee95670eccc6a5c34f1f8a3b828998d0da7b Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Sat, 15 Jun 2019 20:06:13 -0700
-Subject: [PATCH] rsync: Avoid pointer arithmetic on `void *`
-
----
- usr.bin/rsync/blocks.c | 8 ++++----
- usr.bin/rsync/downloader.c | 2 +-
- usr.bin/rsync/io.c | 12 ++++++------
- usr.bin/rsync/sender.c | 5 +++--
- 4 files changed, 14 insertions(+), 13 deletions(-)
-
-diff --git a/usr.bin/rsync/blocks.c b/usr.bin/rsync/blocks.c
-index 56790729f27..906733c968e 100644
---- a/usr.bin/rsync/blocks.c
-+++ b/usr.bin/rsync/blocks.c
-@@ -157,7 +157,7 @@ blk_find(struct sess *sess, struct blkstat *st,
- if (!recomp) {
- fhash = (st->s1 & 0xFFFF) | (st->s2 << 16);
- } else {
-- fhash = hash_fast(st->map + st->offs, (size_t)osz);
-+ fhash = hash_fast((char *)st->map + st->offs, (size_t)osz);
- st->s1 = fhash & 0xFFFF;
- st->s2 = fhash >> 16;
- }
-@@ -170,7 +170,7 @@ blk_find(struct sess *sess, struct blkstat *st,
- if (st->hint < blks->blksz &&
- fhash == blks->blks[st->hint].chksum_short &&
- (size_t)osz == blks->blks[st->hint].len) {
-- hash_slow(st->map + st->offs, (size_t)osz, md, sess);
-+ hash_slow((char *)st->map + st->offs, (size_t)osz, md, sess);
- have_md = 1;
- if (memcmp(md, blks->blks[st->hint].chksum_long, blks->csum) == 0) {
- LOG4("%s: found matching hinted match: "
-@@ -203,7 +203,7 @@ blk_find(struct sess *sess, struct blkstat *st,
- (intmax_t)ent->blk->offs, ent->blk->len);
-
- if (have_md == 0) {
-- hash_slow(st->map + st->offs, (size_t)osz, md, sess);
-+ hash_slow((char *)st->map + st->offs, (size_t)osz, md, sess);
- have_md = 1;
- }
-
-@@ -221,7 +221,7 @@ blk_find(struct sess *sess, struct blkstat *st,
- * block in the sequence.
- */
-
-- map = st->map + st->offs;
-+ map = (char *)st->map + st->offs;
- st->s1 -= map[0];
- st->s2 -= osz * map[0];
-
-diff --git a/usr.bin/rsync/downloader.c b/usr.bin/rsync/downloader.c
-index cab6eb23f9f..07ec334f6b4 100644
---- a/usr.bin/rsync/downloader.c
-+++ b/usr.bin/rsync/downloader.c
-@@ -495,7 +495,7 @@ again:
- sz = tok == p->blk.blksz - 1 ? p->blk.rem : p->blk.len;
- assert(sz);
- assert(p->map != MAP_FAILED);
-- buf = p->map + (tok * p->blk.len);
-+ buf = (char *)p->map + (tok * p->blk.len);
-
- /*
- * Now we read from our block.
-diff --git a/usr.bin/rsync/io.c b/usr.bin/rsync/io.c
-index dc224ae8aed..fcf9e92dbaa 100644
---- a/usr.bin/rsync/io.c
-+++ b/usr.bin/rsync/io.c
-@@ -117,7 +117,7 @@ io_write_blocking(int fd, const void *buf, size_t sz)
- ERRX("io_write_nonblocking: short write");
- return 0;
- }
-- buf += wsz;
-+ buf = (char *)buf + wsz;
- sz -= wsz;
- }
-
-@@ -156,7 +156,7 @@ io_write_buf(struct sess *sess, int fd, const void *buf, size_t sz)
- }
- sess->total_write += wsz;
- sz -= wsz;
-- buf += wsz;
-+ buf = (char *)buf + wsz;
- }
-
- return 1;
-@@ -250,7 +250,7 @@ io_read_blocking(int fd, void *buf, size_t sz)
- ERRX("io_read_nonblocking: short read");
- return 0;
- }
-- buf += rsz;
-+ buf = (char *)buf + rsz;
- sz -= rsz;
- }
-
-@@ -367,7 +367,7 @@ io_read_buf(struct sess *sess, int fd, void *buf, size_t sz)
- }
- sz -= rsz;
- sess->mplex_read_remain -= rsz;
-- buf += rsz;
-+ buf = (char *)buf + rsz;
- sess->total_read += rsz;
- continue;
- }
-@@ -463,7 +463,7 @@ io_buffer_buf(void *buf, size_t *bufpos, size_t buflen, const void *val,
- {
-
- assert(*bufpos + valsz <= buflen);
-- memcpy(buf + *bufpos, val, valsz);
-+ memcpy((char *)buf + *bufpos, val, valsz);
- *bufpos += valsz;
- }
-
-@@ -662,7 +662,7 @@ io_unbuffer_buf(const void *buf, size_t *bufpos, size_t bufsz, void *val,
- {
-
- assert(*bufpos + valsz <= bufsz);
-- memcpy(val, buf + *bufpos, valsz);
-+ memcpy(val, (char *)buf + *bufpos, valsz);
- *bufpos += valsz;
- }
-
-diff --git a/usr.bin/rsync/sender.c b/usr.bin/rsync/sender.c
-index e2999aa2589..9dd008def01 100644
---- a/usr.bin/rsync/sender.c
-+++ b/usr.bin/rsync/sender.c
-@@ -128,7 +128,7 @@ send_up_fsm(struct sess *sess, size_t *phase,
- return 0;
- }
- io_lowbuffer_buf(sess, *wb, &pos, *wbsz,
-- up->stat.map + up->stat.curpos, sz);
-+ (char *)up->stat.map + up->stat.curpos, sz);
-
- up->stat.curpos += sz;
- if (up->stat.curpos == up->stat.curlen)
-@@ -557,7 +557,8 @@ rsync_sender(struct sess *sess, int fdin,
- if ((pfd[1].revents & POLLOUT) && wbufsz > 0) {
- assert(pfd[2].fd == -1);
- assert(wbufsz - wbufpos);
-- ssz = write(fdout, wbuf + wbufpos, wbufsz - wbufpos);
-+ ssz = write(fdout,
-+ (char *)wbuf + wbufpos, wbufsz - wbufpos);
- if (ssz == -1) {
- ERR("write");
- goto out;
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0026-Include-sys-sysmacros.h-if-necessary.patch b/pkg/openbsd/patch/0026-Include-sys-sysmacros.h-if-necessary.patch
@@ -1,73 +0,0 @@
-From 0d3a091280d0874fb561c83431803eb2489876cb Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Mon, 5 Aug 2019 21:42:54 -0700
-Subject: [PATCH] Include sys/sysmacros.h if necessary
-
----
- bin/pax/cpio.c | 4 ++++
- bin/pax/gen_subs.c | 3 +++
- bin/pax/tar.c | 3 +++
- usr.bin/rsync/flist.c | 4 ++++
- 4 files changed, 14 insertions(+)
-
-diff --git a/bin/pax/cpio.c b/bin/pax/cpio.c
-index 92fe965163a..3832b1e87aa 100644
---- a/bin/pax/cpio.c
-+++ b/bin/pax/cpio.c
-@@ -41,6 +41,10 @@
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
-+#ifndef major
-+#include <sys/sysmacros.h>
-+#endif
-+
- #include "pax.h"
- #include "cpio.h"
- #include "extern.h"
-diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c
-index 42c70804fb7..405dd2c24ed 100644
---- a/bin/pax/gen_subs.c
-+++ b/bin/pax/gen_subs.c
-@@ -45,6 +45,9 @@
- #include <unistd.h>
- #include <utmp.h>
- #include <vis.h>
-+#ifndef major
-+#include <sys/sysmacros.h>
-+#endif
-
- #include "pax.h"
- #include "extern.h"
-diff --git a/bin/pax/tar.c b/bin/pax/tar.c
-index 9d8a92d9d13..e84a9c69a09 100644
---- a/bin/pax/tar.c
-+++ b/bin/pax/tar.c
-@@ -45,6 +45,9 @@
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-+#ifndef major
-+#include <sys/sysmacros.h>
-+#endif
-
- #include "pax.h"
- #include "extern.h"
-diff --git a/usr.bin/rsync/flist.c b/usr.bin/rsync/flist.c
-index 392ba494423..5f15487623a 100644
---- a/usr.bin/rsync/flist.c
-+++ b/usr.bin/rsync/flist.c
-@@ -16,6 +16,10 @@
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #include <sys/stat.h>
-+#include <sys/types.h>
-+#ifndef major
-+#include <sys/sysmacros.h>
-+#endif
-
- #include <assert.h>
- #include <errno.h>
---
-2.34.1
-
diff --git a/pkg/openbsd/patch/0026-nc-Portability-fixes-from-libressl-portable.patch b/pkg/openbsd/patch/0026-nc-Portability-fixes-from-libressl-portable.patch
@@ -0,0 +1,194 @@
+From 05fd24cc7b3f1b73a58d41d70ef725925007165c Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Mon, 2 Dec 2019 21:11:04 -0800
+Subject: [PATCH] nc: Portability fixes from libressl-portable
+
+---
+ usr.bin/nc/netcat.c | 55 +++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 48 insertions(+), 7 deletions(-)
+
+diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
+index 8c60fd18826..b5129c2204d 100644
+--- a/usr.bin/nc/netcat.c
++++ b/usr.bin/nc/netcat.c
+@@ -93,9 +93,13 @@ int zflag; /* Port Scan Flag */
+ int Dflag; /* sodebug */
+ int Iflag; /* TCP receive buffer size */
+ int Oflag; /* TCP send buffer size */
++#ifdef TCP_MD5SIG
+ int Sflag; /* TCP MD5 signature option */
++#endif
+ int Tflag = -1; /* IP Type of Service */
++#ifdef SO_RTABLE
+ int rtableid = -1;
++#endif
+
+ int usetls; /* use TLS */
+ const char *Cflag; /* Public cert file */
+@@ -268,12 +272,14 @@ main(int argc, char *argv[])
+ case 'u':
+ uflag = 1;
+ break;
++#ifdef SO_RTABLE
+ case 'V':
+ rtableid = (int)strtonum(optarg, 0,
+ RT_TABLEID_MAX, &errstr);
+ if (errstr)
+ errx(1, "rtable %s: %s", errstr, optarg);
+ break;
++#endif
+ case 'v':
+ vflag = 1;
+ break;
+@@ -320,9 +326,11 @@ main(int argc, char *argv[])
+ case 'o':
+ oflag = optarg;
+ break;
++#ifdef TCP_MD5SIG
+ case 'S':
+ Sflag = 1;
+ break;
++#endif
+ case 'T':
+ errstr = NULL;
+ errno = 0;
+@@ -346,9 +354,11 @@ main(int argc, char *argv[])
+ argc -= optind;
+ argv += optind;
+
++#ifdef SO_RTABLE
+ if (rtableid >= 0)
+ if (setrtable(rtableid) == -1)
+ err(1, "setrtable");
++#endif
+
+ /* Cruft to make sure options are clean, and used properly. */
+ if (argc == 1 && family == AF_UNIX) {
+@@ -923,7 +933,10 @@ remote_connect(const char *host, const char *port, struct addrinfo hints,
+ char *ipaddr)
+ {
+ struct addrinfo *res, *res0;
+- int s = -1, error, herr, on = 1, save_errno;
++ int s = -1, error, herr, save_errno;
++#ifdef SO_BINDANY
++ int on = 1;
++#endif
+
+ if ((error = getaddrinfo(host, port, &hints, &res0)))
+ errx(1, "getaddrinfo for host \"%s\" port %s: %s", host,
+@@ -938,8 +951,10 @@ remote_connect(const char *host, const char *port, struct addrinfo hints,
+ if (sflag || pflag) {
+ struct addrinfo ahints, *ares;
+
++#ifdef SO_BINDANY
+ /* try SO_BINDANY, but don't insist */
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
++#endif
+ memset(&ahints, 0, sizeof(struct addrinfo));
+ ahints.ai_family = res->ai_family;
+ ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+@@ -1031,8 +1046,11 @@ int
+ local_listen(const char *host, const char *port, struct addrinfo hints)
+ {
+ struct addrinfo *res, *res0;
+- int s = -1, ret, x = 1, save_errno;
++ int s = -1, save_errno;
+ int error;
++#ifdef SO_REUSEPORT
++ int ret, x = 1;
++#endif
+
+ /* Allow nodename to be null. */
+ hints.ai_flags |= AI_PASSIVE;
+@@ -1052,9 +1070,11 @@ local_listen(const char *host, const char *port, struct addrinfo hints)
+ res->ai_protocol)) == -1)
+ continue;
+
++#ifdef SO_REUSEPORT
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
+ if (ret == -1)
+ err(1, NULL);
++#endif
+
+ set_common_sockopts(s, res->ai_family);
+
+@@ -1559,11 +1579,13 @@ set_common_sockopts(int s, int af)
+ {
+ int x = 1;
+
++#ifdef TCP_MD5SIG
+ if (Sflag) {
+ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
+ &x, sizeof(x)) == -1)
+ err(1, NULL);
+ }
++#endif
+ if (Dflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ &x, sizeof(x)) == -1)
+@@ -1574,9 +1596,16 @@ set_common_sockopts(int s, int af)
+ IP_TOS, &Tflag, sizeof(Tflag)) == -1)
+ err(1, "set IP ToS");
+
++#ifdef IPV6_TCLASS
+ else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
+ IPV6_TCLASS, &Tflag, sizeof(Tflag)) == -1)
+ err(1, "set IPv6 traffic class");
++#else
++ else if (af == AF_INET6) {
++ errno = ENOPROTOOPT;
++ err(1, "set IPv6 traffic class not supported");
++ }
++#endif
+ }
+ if (Iflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+@@ -1600,13 +1629,17 @@ set_common_sockopts(int s, int af)
+ }
+
+ if (minttl != -1) {
++#ifdef IP_MINTTL
+ if (af == AF_INET && setsockopt(s, IPPROTO_IP,
+ IP_MINTTL, &minttl, sizeof(minttl)))
+ err(1, "set IP min TTL");
++#endif
+
+- else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
++#ifdef IPV6_MINHOPCOUNT
++ if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
+ IPV6_MINHOPCOUNT, &minttl, sizeof(minttl)))
+ err(1, "set IPv6 min hop count");
++#endif
+ }
+ }
+
+@@ -1831,14 +1864,22 @@ help(void)
+ \t-P proxyuser\tUsername for proxy authentication\n\
+ \t-p port\t Specify local port for remote connects\n\
+ \t-R CAfile CA bundle\n\
+- \t-r Randomize remote ports\n\
+- \t-S Enable the TCP MD5 signature option\n\
++ \t-r Randomize remote ports\n"
++#ifdef TCP_MD5SIG
++ "\
++ \t-S Enable the TCP MD5 signature option\n"
++#endif
++ "\
+ \t-s sourceaddr Local source address\n\
+ \t-T keyword TOS value or TLS options\n\
+ \t-t Answer TELNET negotiation\n\
+ \t-U Use UNIX domain socket\n\
+- \t-u UDP mode\n\
+- \t-V rtable Specify alternate routing table\n\
++ \t-u UDP mode\n"
++#ifdef SO_RTABLE
++ "\
++ \t-V rtable Specify alternate routing table\n"
++#endif
++ "\
+ \t-v Verbose\n\
+ \t-W recvlimit Terminate after receiving a number of packets\n\
+ \t-w timeout Timeout for connects and final net reads\n\
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0027-nc-Portability-fixes-from-libressl-portable.patch b/pkg/openbsd/patch/0027-nc-Portability-fixes-from-libressl-portable.patch
@@ -1,194 +0,0 @@
-From 6c278af8cc6a9fcb94b9bbe572b0bd3f7dd492c1 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Mon, 2 Dec 2019 21:11:04 -0800
-Subject: [PATCH] nc: Portability fixes from libressl-portable
-
----
- usr.bin/nc/netcat.c | 55 +++++++++++++++++++++++++++++++++++++++------
- 1 file changed, 48 insertions(+), 7 deletions(-)
-
-diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
-index c8f1cdd9f75..7369ed85619 100644
---- a/usr.bin/nc/netcat.c
-+++ b/usr.bin/nc/netcat.c
-@@ -93,9 +93,13 @@ int zflag; /* Port Scan Flag */
- int Dflag; /* sodebug */
- int Iflag; /* TCP receive buffer size */
- int Oflag; /* TCP send buffer size */
-+#ifdef TCP_MD5SIG
- int Sflag; /* TCP MD5 signature option */
-+#endif
- int Tflag = -1; /* IP Type of Service */
-+#ifdef SO_RTABLE
- int rtableid = -1;
-+#endif
-
- int usetls; /* use TLS */
- const char *Cflag; /* Public cert file */
-@@ -268,12 +272,14 @@ main(int argc, char *argv[])
- case 'u':
- uflag = 1;
- break;
-+#ifdef SO_RTABLE
- case 'V':
- rtableid = (int)strtonum(optarg, 0,
- RT_TABLEID_MAX, &errstr);
- if (errstr)
- errx(1, "rtable %s: %s", errstr, optarg);
- break;
-+#endif
- case 'v':
- vflag = 1;
- break;
-@@ -320,9 +326,11 @@ main(int argc, char *argv[])
- case 'o':
- oflag = optarg;
- break;
-+#ifdef TCP_MD5SIG
- case 'S':
- Sflag = 1;
- break;
-+#endif
- case 'T':
- errstr = NULL;
- errno = 0;
-@@ -346,9 +354,11 @@ main(int argc, char *argv[])
- argc -= optind;
- argv += optind;
-
-+#ifdef SO_RTABLE
- if (rtableid >= 0)
- if (setrtable(rtableid) == -1)
- err(1, "setrtable");
-+#endif
-
- /* Cruft to make sure options are clean, and used properly. */
- if (argc == 1 && family == AF_UNIX) {
-@@ -927,7 +937,10 @@ remote_connect(const char *host, const char *port, struct addrinfo hints,
- char *ipaddr)
- {
- struct addrinfo *res, *res0;
-- int s = -1, error, herr, on = 1, save_errno;
-+ int s = -1, error, herr, save_errno;
-+#ifdef SO_BINDANY
-+ int on = 1;
-+#endif
-
- if ((error = getaddrinfo(host, port, &hints, &res0)))
- errx(1, "getaddrinfo for host \"%s\" port %s: %s", host,
-@@ -942,8 +955,10 @@ remote_connect(const char *host, const char *port, struct addrinfo hints,
- if (sflag || pflag) {
- struct addrinfo ahints, *ares;
-
-+#ifdef SO_BINDANY
- /* try SO_BINDANY, but don't insist */
- setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
-+#endif
- memset(&ahints, 0, sizeof(struct addrinfo));
- ahints.ai_family = res->ai_family;
- ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
-@@ -1035,8 +1050,11 @@ int
- local_listen(const char *host, const char *port, struct addrinfo hints)
- {
- struct addrinfo *res, *res0;
-- int s = -1, ret, x = 1, save_errno;
-+ int s = -1, save_errno;
- int error;
-+#ifdef SO_REUSEPORT
-+ int ret, x = 1;
-+#endif
-
- /* Allow nodename to be null. */
- hints.ai_flags |= AI_PASSIVE;
-@@ -1056,9 +1074,11 @@ local_listen(const char *host, const char *port, struct addrinfo hints)
- res->ai_protocol)) == -1)
- continue;
-
-+#ifdef SO_REUSEPORT
- ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
- if (ret == -1)
- err(1, NULL);
-+#endif
-
- set_common_sockopts(s, res->ai_family);
-
-@@ -1557,11 +1577,13 @@ set_common_sockopts(int s, int af)
- {
- int x = 1;
-
-+#ifdef TCP_MD5SIG
- if (Sflag) {
- if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
- &x, sizeof(x)) == -1)
- err(1, NULL);
- }
-+#endif
- if (Dflag) {
- if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
- &x, sizeof(x)) == -1)
-@@ -1572,9 +1594,16 @@ set_common_sockopts(int s, int af)
- IP_TOS, &Tflag, sizeof(Tflag)) == -1)
- err(1, "set IP ToS");
-
-+#ifdef IPV6_TCLASS
- else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
- IPV6_TCLASS, &Tflag, sizeof(Tflag)) == -1)
- err(1, "set IPv6 traffic class");
-+#else
-+ else if (af == AF_INET6) {
-+ errno = ENOPROTOOPT;
-+ err(1, "set IPv6 traffic class not supported");
-+ }
-+#endif
- }
- if (Iflag) {
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
-@@ -1598,13 +1627,17 @@ set_common_sockopts(int s, int af)
- }
-
- if (minttl != -1) {
-+#ifdef IP_MINTTL
- if (af == AF_INET && setsockopt(s, IPPROTO_IP,
- IP_MINTTL, &minttl, sizeof(minttl)))
- err(1, "set IP min TTL");
-+#endif
-
-- else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
-+#ifdef IPV6_MINHOPCOUNT
-+ if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
- IPV6_MINHOPCOUNT, &minttl, sizeof(minttl)))
- err(1, "set IPv6 min hop count");
-+#endif
- }
- }
-
-@@ -1829,14 +1862,22 @@ help(void)
- \t-P proxyuser\tUsername for proxy authentication\n\
- \t-p port\t Specify local port for remote connects\n\
- \t-R CAfile CA bundle\n\
-- \t-r Randomize remote ports\n\
-- \t-S Enable the TCP MD5 signature option\n\
-+ \t-r Randomize remote ports\n"
-+#ifdef TCP_MD5SIG
-+ "\
-+ \t-S Enable the TCP MD5 signature option\n"
-+#endif
-+ "\
- \t-s sourceaddr Local source address\n\
- \t-T keyword TOS value or TLS options\n\
- \t-t Answer TELNET negotiation\n\
- \t-U Use UNIX domain socket\n\
-- \t-u UDP mode\n\
-- \t-V rtable Specify alternate routing table\n\
-+ \t-u UDP mode\n"
-+#ifdef SO_RTABLE
-+ "\
-+ \t-V rtable Specify alternate routing table\n"
-+#endif
-+ "\
- \t-v Verbose\n\
- \t-W recvlimit Terminate after receiving a number of packets\n\
- \t-w timeout Timeout for connects and final net reads\n\
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0027-pax-Ignore-EOPNOTSUPP-from-fchmodat.patch b/pkg/openbsd/patch/0027-pax-Ignore-EOPNOTSUPP-from-fchmodat.patch
@@ -0,0 +1,26 @@
+From 38b0c680777d5eb9cc69cd8fbc38fe3dc5a0927a Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Fri, 10 Jan 2020 21:40:03 -0800
+Subject: [PATCH] pax: Ignore EOPNOTSUPP from fchmodat
+
+Linux does not support changing the mode of symlinks.
+---
+ bin/pax/file_subs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
+index ae0caf29f6c..429705976dc 100644
+--- a/bin/pax/file_subs.c
++++ b/bin/pax/file_subs.c
+@@ -800,7 +800,7 @@ void
+ set_pmode(char *fnm, mode_t mode)
+ {
+ mode &= ABITS;
+- if (fchmodat(AT_FDCWD, fnm, mode, AT_SYMLINK_NOFOLLOW) == -1)
++ if (fchmodat(AT_FDCWD, fnm, mode, AT_SYMLINK_NOFOLLOW) == -1 && errno != EOPNOTSUPP)
+ syswarn(1, errno, "Could not set permissions on %s", fnm);
+ }
+
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0029-acme-client-Fix-build-with-old-bison-versions.patch b/pkg/openbsd/patch/0028-acme-client-Fix-build-with-old-bison-versions.patch
diff --git a/pkg/openbsd/patch/0028-pax-Ignore-EOPNOTSUPP-from-fchmodat.patch b/pkg/openbsd/patch/0028-pax-Ignore-EOPNOTSUPP-from-fchmodat.patch
@@ -1,26 +0,0 @@
-From 0f49ae38698a163f7954d28bbaba473b6bf28239 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Fri, 10 Jan 2020 21:40:03 -0800
-Subject: [PATCH] pax: Ignore EOPNOTSUPP from fchmodat
-
-Linux does not support changing the mode of symlinks.
----
- bin/pax/file_subs.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/bin/pax/file_subs.c b/bin/pax/file_subs.c
-index 8aa3d249923..2c0994feca6 100644
---- a/bin/pax/file_subs.c
-+++ b/bin/pax/file_subs.c
-@@ -795,7 +795,7 @@ void
- set_pmode(char *fnm, mode_t mode)
- {
- mode &= ABITS;
-- if (fchmodat(AT_FDCWD, fnm, mode, AT_SYMLINK_NOFOLLOW) == -1)
-+ if (fchmodat(AT_FDCWD, fnm, mode, AT_SYMLINK_NOFOLLOW) == -1 && errno != EOPNOTSUPP)
- syswarn(1, errno, "Could not set permissions on %s", fnm);
- }
-
---
-2.26.2
-
diff --git a/pkg/openbsd/patch/0029-rsync-Add-implementation-of-MD4.patch b/pkg/openbsd/patch/0029-rsync-Add-implementation-of-MD4.patch
@@ -0,0 +1,425 @@
+From f6b4408dd3b8ddfa1dca692e1c52643d857d8102 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Wed, 15 Apr 2020 22:10:06 -0700
+Subject: [PATCH] rsync: Add implementation of MD4
+
+---
+ usr.bin/rsync/Makefile | 2 +-
+ usr.bin/rsync/blocks.c | 2 +-
+ usr.bin/rsync/downloader.c | 2 +-
+ usr.bin/rsync/extern.h | 3 +-
+ usr.bin/rsync/hash.c | 2 +-
+ usr.bin/rsync/md4.c | 266 +++++++++++++++++++++++++++++++++++++
+ usr.bin/rsync/md4.h | 47 +++++++
+ usr.bin/rsync/sender.c | 2 +-
+ 8 files changed, 320 insertions(+), 6 deletions(-)
+ create mode 100644 usr.bin/rsync/md4.c
+ create mode 100644 usr.bin/rsync/md4.h
+
+diff --git a/usr.bin/rsync/Makefile b/usr.bin/rsync/Makefile
+index 3c60f18e07f..172045ce7ac 100644
+--- a/usr.bin/rsync/Makefile
++++ b/usr.bin/rsync/Makefile
+@@ -2,7 +2,7 @@
+
+ PROG= openrsync
+ SRCS= blocks.c client.c copy.c downloader.c fargs.c flist.c hash.c ids.c \
+- io.c log.c main.c misc.c mkpath.c mktemp.c receiver.c rmatch.c \
++ io.c log.c main.c md4.c misc.c mkpath.c mktemp.c receiver.c rmatch.c \
+ rules.c sender.c server.c session.c socket.c symlinks.c uploader.c
+ LDADD+= -lcrypto -lm -lutil
+ DPADD+= ${LIBCRYPTO} ${LIBM} ${LIBUTIL}
+diff --git a/usr.bin/rsync/blocks.c b/usr.bin/rsync/blocks.c
+index 8f4bcb532e1..f21c9178487 100644
+--- a/usr.bin/rsync/blocks.c
++++ b/usr.bin/rsync/blocks.c
+@@ -26,7 +26,7 @@
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <openssl/md4.h>
++#include "md4.h"
+
+ #include "extern.h"
+
+diff --git a/usr.bin/rsync/downloader.c b/usr.bin/rsync/downloader.c
+index 07ec334f6b4..6543851fd2c 100644
+--- a/usr.bin/rsync/downloader.c
++++ b/usr.bin/rsync/downloader.c
+@@ -28,7 +28,7 @@
+ #include <time.h>
+ #include <unistd.h>
+
+-#include <openssl/md4.h>
++#include "md4.h"
+
+ #include "extern.h"
+
+diff --git a/usr.bin/rsync/extern.h b/usr.bin/rsync/extern.h
+index 55d7bc26ae2..d6b02fd4ad4 100644
+--- a/usr.bin/rsync/extern.h
++++ b/usr.bin/rsync/extern.h
+@@ -19,7 +19,8 @@
+
+ #include <stdint.h>
+ #include <sys/types.h>
+-#include <openssl/md4.h>
++
++#include "md4.h"
+
+ /*
+ * This is the rsync protocol version that we support.
+diff --git a/usr.bin/rsync/hash.c b/usr.bin/rsync/hash.c
+index 37529e951b4..e3f52047404 100644
+--- a/usr.bin/rsync/hash.c
++++ b/usr.bin/rsync/hash.c
+@@ -21,7 +21,7 @@
+ #include <stdint.h>
+ #include <stdlib.h>
+
+-#include <openssl/md4.h>
++#include "md4.h"
+
+ #include "extern.h"
+
+diff --git a/usr.bin/rsync/md4.c b/usr.bin/rsync/md4.c
+new file mode 100644
+index 00000000000..528f985563f
+--- /dev/null
++++ b/usr.bin/rsync/md4.c
+@@ -0,0 +1,266 @@
++/*
++ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
++ * MD4 Message-Digest Algorithm (RFC 1320).
++ *
++ * Homepage:
++ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
++ *
++ * Author:
++ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
++ *
++ * This software was written by Alexander Peslyak in 2001. No copyright is
++ * claimed, and the software is hereby placed in the public domain.
++ * In case this attempt to disclaim copyright and place the software in the
++ * public domain is deemed null and void, then the software is
++ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
++ * general public under the following terms:
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted.
++ *
++ * There's ABSOLUTELY NO WARRANTY, express or implied.
++ *
++ * (This is a heavily cut-down "BSD license".)
++ *
++ * This differs from Colin Plumb's older public domain implementation in that
++ * no exactly 32-bit integer data type is required (any 32-bit or wider
++ * unsigned integer data type will do), there's no compile-time endianness
++ * configuration, and the function prototypes match OpenSSL's. No code from
++ * Colin Plumb's implementation has been reused; this comment merely compares
++ * the properties of the two independent implementations.
++ *
++ * The primary goals of this implementation are portability and ease of use.
++ * It is meant to be fast, but not as fast as possible. Some known
++ * optimizations are not included to reduce source code size and avoid
++ * compile-time configuration.
++ */
++
++#include <string.h>
++
++#include "md4.h"
++
++/*
++ * The basic MD4 functions.
++ *
++ * F and G are optimized compared to their RFC 1320 definitions, with the
++ * optimization for F borrowed from Colin Plumb's MD5 implementation.
++ */
++#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
++#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
++#define H(x, y, z) ((x) ^ (y) ^ (z))
++
++/*
++ * The MD4 transformation for all three rounds.
++ */
++#define STEP(f, a, b, c, d, x, s) \
++ (a) += f((b), (c), (d)) + (x); \
++ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
++
++/*
++ * SET reads 4 input bytes in little-endian byte order and stores them in a
++ * properly aligned word in host byte order.
++ *
++ * The check for little-endian architectures that tolerate unaligned memory
++ * accesses is just an optimization. Nothing will break if it fails to detect
++ * a suitable architecture.
++ *
++ * Unfortunately, this optimization may be a C strict aliasing rules violation
++ * if the caller's data buffer has effective type that cannot be aliased by
++ * MD4_u32plus. In practice, this problem may occur if these MD4 routines are
++ * inlined into a calling function, or with future and dangerously advanced
++ * link-time optimizations. For the time being, keeping these MD4 routines in
++ * their own translation unit avoids the problem.
++ */
++#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
++#define SET(n) \
++ (*(MD4_u32plus *)&ptr[(n) * 4])
++#define GET(n) \
++ SET(n)
++#else
++#define SET(n) \
++ (ctx->block[(n)] = \
++ (MD4_u32plus)ptr[(n) * 4] | \
++ ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
++ ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
++ ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
++#define GET(n) \
++ (ctx->block[(n)])
++#endif
++
++/*
++ * This processes one or more 64-byte data blocks, but does NOT update the bit
++ * counters. There are no alignment requirements.
++ */
++static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
++{
++ const unsigned char *ptr;
++ MD4_u32plus a, b, c, d;
++ MD4_u32plus saved_a, saved_b, saved_c, saved_d;
++ const MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
++
++ ptr = (const unsigned char *)data;
++
++ a = ctx->a;
++ b = ctx->b;
++ c = ctx->c;
++ d = ctx->d;
++
++ do {
++ saved_a = a;
++ saved_b = b;
++ saved_c = c;
++ saved_d = d;
++
++/* Round 1 */
++ STEP(F, a, b, c, d, SET(0), 3)
++ STEP(F, d, a, b, c, SET(1), 7)
++ STEP(F, c, d, a, b, SET(2), 11)
++ STEP(F, b, c, d, a, SET(3), 19)
++ STEP(F, a, b, c, d, SET(4), 3)
++ STEP(F, d, a, b, c, SET(5), 7)
++ STEP(F, c, d, a, b, SET(6), 11)
++ STEP(F, b, c, d, a, SET(7), 19)
++ STEP(F, a, b, c, d, SET(8), 3)
++ STEP(F, d, a, b, c, SET(9), 7)
++ STEP(F, c, d, a, b, SET(10), 11)
++ STEP(F, b, c, d, a, SET(11), 19)
++ STEP(F, a, b, c, d, SET(12), 3)
++ STEP(F, d, a, b, c, SET(13), 7)
++ STEP(F, c, d, a, b, SET(14), 11)
++ STEP(F, b, c, d, a, SET(15), 19)
++
++/* Round 2 */
++ STEP(G, a, b, c, d, GET(0) + ac1, 3)
++ STEP(G, d, a, b, c, GET(4) + ac1, 5)
++ STEP(G, c, d, a, b, GET(8) + ac1, 9)
++ STEP(G, b, c, d, a, GET(12) + ac1, 13)
++ STEP(G, a, b, c, d, GET(1) + ac1, 3)
++ STEP(G, d, a, b, c, GET(5) + ac1, 5)
++ STEP(G, c, d, a, b, GET(9) + ac1, 9)
++ STEP(G, b, c, d, a, GET(13) + ac1, 13)
++ STEP(G, a, b, c, d, GET(2) + ac1, 3)
++ STEP(G, d, a, b, c, GET(6) + ac1, 5)
++ STEP(G, c, d, a, b, GET(10) + ac1, 9)
++ STEP(G, b, c, d, a, GET(14) + ac1, 13)
++ STEP(G, a, b, c, d, GET(3) + ac1, 3)
++ STEP(G, d, a, b, c, GET(7) + ac1, 5)
++ STEP(G, c, d, a, b, GET(11) + ac1, 9)
++ STEP(G, b, c, d, a, GET(15) + ac1, 13)
++
++/* Round 3 */
++ STEP(H, a, b, c, d, GET(0) + ac2, 3)
++ STEP(H, d, a, b, c, GET(8) + ac2, 9)
++ STEP(H, c, d, a, b, GET(4) + ac2, 11)
++ STEP(H, b, c, d, a, GET(12) + ac2, 15)
++ STEP(H, a, b, c, d, GET(2) + ac2, 3)
++ STEP(H, d, a, b, c, GET(10) + ac2, 9)
++ STEP(H, c, d, a, b, GET(6) + ac2, 11)
++ STEP(H, b, c, d, a, GET(14) + ac2, 15)
++ STEP(H, a, b, c, d, GET(1) + ac2, 3)
++ STEP(H, d, a, b, c, GET(9) + ac2, 9)
++ STEP(H, c, d, a, b, GET(5) + ac2, 11)
++ STEP(H, b, c, d, a, GET(13) + ac2, 15)
++ STEP(H, a, b, c, d, GET(3) + ac2, 3)
++ STEP(H, d, a, b, c, GET(11) + ac2, 9)
++ STEP(H, c, d, a, b, GET(7) + ac2, 11)
++ STEP(H, b, c, d, a, GET(15) + ac2, 15)
++
++ a += saved_a;
++ b += saved_b;
++ c += saved_c;
++ d += saved_d;
++
++ ptr += 64;
++ } while (size -= 64);
++
++ ctx->a = a;
++ ctx->b = b;
++ ctx->c = c;
++ ctx->d = d;
++
++ return ptr;
++}
++
++void MD4_Init(MD4_CTX *ctx)
++{
++ ctx->a = 0x67452301;
++ ctx->b = 0xefcdab89;
++ ctx->c = 0x98badcfe;
++ ctx->d = 0x10325476;
++
++ ctx->lo = 0;
++ ctx->hi = 0;
++}
++
++void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
++{
++ MD4_u32plus saved_lo;
++ unsigned long used, available;
++
++ saved_lo = ctx->lo;
++ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
++ ctx->hi++;
++ ctx->hi += size >> 29;
++
++ used = saved_lo & 0x3f;
++
++ if (used) {
++ available = 64 - used;
++
++ if (size < available) {
++ memcpy(&ctx->buffer[used], data, size);
++ return;
++ }
++
++ memcpy(&ctx->buffer[used], data, available);
++ data = (const unsigned char *)data + available;
++ size -= available;
++ body(ctx, ctx->buffer, 64);
++ }
++
++ if (size >= 64) {
++ data = body(ctx, data, size & ~(unsigned long)0x3f);
++ size &= 0x3f;
++ }
++
++ memcpy(ctx->buffer, data, size);
++}
++
++#define OUT(dst, src) \
++ (dst)[0] = (unsigned char)(src); \
++ (dst)[1] = (unsigned char)((src) >> 8); \
++ (dst)[2] = (unsigned char)((src) >> 16); \
++ (dst)[3] = (unsigned char)((src) >> 24);
++
++void MD4_Final(unsigned char *result, MD4_CTX *ctx)
++{
++ unsigned long used, available;
++
++ used = ctx->lo & 0x3f;
++
++ ctx->buffer[used++] = 0x80;
++
++ available = 64 - used;
++
++ if (available < 8) {
++ memset(&ctx->buffer[used], 0, available);
++ body(ctx, ctx->buffer, 64);
++ used = 0;
++ available = 64;
++ }
++
++ memset(&ctx->buffer[used], 0, available - 8);
++
++ ctx->lo <<= 3;
++ OUT(&ctx->buffer[56], ctx->lo)
++ OUT(&ctx->buffer[60], ctx->hi)
++
++ body(ctx, ctx->buffer, 64);
++
++ OUT(&result[0], ctx->a)
++ OUT(&result[4], ctx->b)
++ OUT(&result[8], ctx->c)
++ OUT(&result[12], ctx->d)
++
++ memset(ctx, 0, sizeof(*ctx));
++}
+diff --git a/usr.bin/rsync/md4.h b/usr.bin/rsync/md4.h
+new file mode 100644
+index 00000000000..ebf5bb555a0
+--- /dev/null
++++ b/usr.bin/rsync/md4.h
+@@ -0,0 +1,47 @@
++/*
++ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
++ * MD4 Message-Digest Algorithm (RFC 1320).
++ *
++ * Homepage:
++ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
++ *
++ * Author:
++ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
++ *
++ * This software was written by Alexander Peslyak in 2001. No copyright is
++ * claimed, and the software is hereby placed in the public domain.
++ * In case this attempt to disclaim copyright and place the software in the
++ * public domain is deemed null and void, then the software is
++ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
++ * general public under the following terms:
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted.
++ *
++ * There's ABSOLUTELY NO WARRANTY, express or implied.
++ *
++ * See md4.c for more information.
++ */
++
++#ifndef _MD4_H
++#define _MD4_H
++
++#include <stdint.h>
++
++#define MD4_DIGEST_LENGTH 16
++
++/* Any 32-bit or wider unsigned integer data type will do */
++typedef uint_fast32_t MD4_u32plus;
++
++typedef struct {
++ MD4_u32plus lo, hi;
++ MD4_u32plus a, b, c, d;
++ unsigned char buffer[64];
++ MD4_u32plus block[16];
++} MD4_CTX;
++
++extern void MD4_Init(MD4_CTX *ctx);
++extern void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
++extern void MD4_Final(unsigned char *result, MD4_CTX *ctx);
++
++#endif
+diff --git a/usr.bin/rsync/sender.c b/usr.bin/rsync/sender.c
+index 6469e7f27e5..81b25b9ee78 100644
+--- a/usr.bin/rsync/sender.c
++++ b/usr.bin/rsync/sender.c
+@@ -26,7 +26,7 @@
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <openssl/md4.h>
++#include "md4.h"
+
+ #include "extern.h"
+
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0030-pax-Fix-some-incorrect-format-specifiers.patch b/pkg/openbsd/patch/0030-pax-Fix-some-incorrect-format-specifiers.patch
@@ -0,0 +1,48 @@
+From e62d415fb66744cac915dc1873e09774a705d536 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Thu, 4 Jun 2020 21:36:11 -0700
+Subject: [PATCH] pax: Fix some incorrect format specifiers
+
+---
+ bin/pax/cpio.c | 2 +-
+ bin/pax/gen_subs.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/bin/pax/cpio.c b/bin/pax/cpio.c
+index fbcf032e091..1242ad0d8a7 100644
+--- a/bin/pax/cpio.c
++++ b/bin/pax/cpio.c
+@@ -214,7 +214,7 @@ rd_ln_nm(ARCHD *arcn)
+ */
+ if ((arcn->sb.st_size <= 0) ||
+ (arcn->sb.st_size >= (off_t)sizeof(arcn->ln_name))) {
+- paxwarn(1, "Cpio link name length is invalid: %lld",
++ paxwarn(1, "Cpio link name length is invalid: %zu",
+ arcn->sb.st_size);
+ return(-1);
+ }
+diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c
+index 928cfcd3657..897a688327e 100644
+--- a/bin/pax/gen_subs.c
++++ b/bin/pax/gen_subs.c
+@@ -112,7 +112,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
+ else if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now),
+ tm) == 0)
+ f_date[0] = '\0';
+- (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
++ (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, (unsigned)sbp->st_nlink,
+ NAME_WIDTH, UT_NAMESIZE, user_from_uid(sbp->st_uid, 0),
+ NAME_WIDTH, UT_NAMESIZE, group_from_gid(sbp->st_gid, 0));
+
+@@ -124,7 +124,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
+ (unsigned long)MAJOR(sbp->st_rdev),
+ (unsigned long)MINOR(sbp->st_rdev));
+ else {
+- (void)fprintf(fp, "%9llu ", sbp->st_size);
++ (void)fprintf(fp, "%9zu ", sbp->st_size);
+ }
+
+ /*
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0030-rsync-Add-implementation-of-MD4.patch b/pkg/openbsd/patch/0030-rsync-Add-implementation-of-MD4.patch
@@ -1,410 +0,0 @@
-From 01657f2c1445cf4874337a0966a76f24ba9c9536 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Wed, 15 Apr 2020 22:10:06 -0700
-Subject: [PATCH] rsync: Add implementation of MD4
-
----
- usr.bin/rsync/Makefile | 2 +-
- usr.bin/rsync/blocks.c | 2 +-
- usr.bin/rsync/downloader.c | 2 +-
- usr.bin/rsync/hash.c | 2 +-
- usr.bin/rsync/md4.c | 266 +++++++++++++++++++++++++++++++++++++
- usr.bin/rsync/md4.h | 47 +++++++
- usr.bin/rsync/sender.c | 2 +-
- 7 files changed, 318 insertions(+), 5 deletions(-)
- create mode 100644 usr.bin/rsync/md4.c
- create mode 100644 usr.bin/rsync/md4.h
-
-diff --git a/usr.bin/rsync/Makefile b/usr.bin/rsync/Makefile
-index 3c60f18e07f..172045ce7ac 100644
---- a/usr.bin/rsync/Makefile
-+++ b/usr.bin/rsync/Makefile
-@@ -2,7 +2,7 @@
-
- PROG= openrsync
- SRCS= blocks.c client.c copy.c downloader.c fargs.c flist.c hash.c ids.c \
-- io.c log.c main.c misc.c mkpath.c mktemp.c receiver.c rmatch.c \
-+ io.c log.c main.c md4.c misc.c mkpath.c mktemp.c receiver.c rmatch.c \
- rules.c sender.c server.c session.c socket.c symlinks.c uploader.c
- LDADD+= -lcrypto -lm -lutil
- DPADD+= ${LIBCRYPTO} ${LIBM} ${LIBUTIL}
-diff --git a/usr.bin/rsync/blocks.c b/usr.bin/rsync/blocks.c
-index 906733c968e..0a8c3f485d1 100644
---- a/usr.bin/rsync/blocks.c
-+++ b/usr.bin/rsync/blocks.c
-@@ -26,7 +26,7 @@
- #include <string.h>
- #include <unistd.h>
-
--#include <openssl/md4.h>
-+#include "md4.h"
-
- #include "extern.h"
-
-diff --git a/usr.bin/rsync/downloader.c b/usr.bin/rsync/downloader.c
-index 07ec334f6b4..6543851fd2c 100644
---- a/usr.bin/rsync/downloader.c
-+++ b/usr.bin/rsync/downloader.c
-@@ -28,7 +28,7 @@
- #include <time.h>
- #include <unistd.h>
-
--#include <openssl/md4.h>
-+#include "md4.h"
-
- #include "extern.h"
-
-diff --git a/usr.bin/rsync/hash.c b/usr.bin/rsync/hash.c
-index b87c56f527c..44ae0d26282 100644
---- a/usr.bin/rsync/hash.c
-+++ b/usr.bin/rsync/hash.c
-@@ -21,7 +21,7 @@
- #include <stdint.h>
- #include <stdlib.h>
-
--#include <openssl/md4.h>
-+#include "md4.h"
-
- #include "extern.h"
-
-diff --git a/usr.bin/rsync/md4.c b/usr.bin/rsync/md4.c
-new file mode 100644
-index 00000000000..528f985563f
---- /dev/null
-+++ b/usr.bin/rsync/md4.c
-@@ -0,0 +1,266 @@
-+/*
-+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
-+ * MD4 Message-Digest Algorithm (RFC 1320).
-+ *
-+ * Homepage:
-+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
-+ *
-+ * Author:
-+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
-+ *
-+ * This software was written by Alexander Peslyak in 2001. No copyright is
-+ * claimed, and the software is hereby placed in the public domain.
-+ * In case this attempt to disclaim copyright and place the software in the
-+ * public domain is deemed null and void, then the software is
-+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
-+ * general public under the following terms:
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted.
-+ *
-+ * There's ABSOLUTELY NO WARRANTY, express or implied.
-+ *
-+ * (This is a heavily cut-down "BSD license".)
-+ *
-+ * This differs from Colin Plumb's older public domain implementation in that
-+ * no exactly 32-bit integer data type is required (any 32-bit or wider
-+ * unsigned integer data type will do), there's no compile-time endianness
-+ * configuration, and the function prototypes match OpenSSL's. No code from
-+ * Colin Plumb's implementation has been reused; this comment merely compares
-+ * the properties of the two independent implementations.
-+ *
-+ * The primary goals of this implementation are portability and ease of use.
-+ * It is meant to be fast, but not as fast as possible. Some known
-+ * optimizations are not included to reduce source code size and avoid
-+ * compile-time configuration.
-+ */
-+
-+#include <string.h>
-+
-+#include "md4.h"
-+
-+/*
-+ * The basic MD4 functions.
-+ *
-+ * F and G are optimized compared to their RFC 1320 definitions, with the
-+ * optimization for F borrowed from Colin Plumb's MD5 implementation.
-+ */
-+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-+#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
-+#define H(x, y, z) ((x) ^ (y) ^ (z))
-+
-+/*
-+ * The MD4 transformation for all three rounds.
-+ */
-+#define STEP(f, a, b, c, d, x, s) \
-+ (a) += f((b), (c), (d)) + (x); \
-+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
-+
-+/*
-+ * SET reads 4 input bytes in little-endian byte order and stores them in a
-+ * properly aligned word in host byte order.
-+ *
-+ * The check for little-endian architectures that tolerate unaligned memory
-+ * accesses is just an optimization. Nothing will break if it fails to detect
-+ * a suitable architecture.
-+ *
-+ * Unfortunately, this optimization may be a C strict aliasing rules violation
-+ * if the caller's data buffer has effective type that cannot be aliased by
-+ * MD4_u32plus. In practice, this problem may occur if these MD4 routines are
-+ * inlined into a calling function, or with future and dangerously advanced
-+ * link-time optimizations. For the time being, keeping these MD4 routines in
-+ * their own translation unit avoids the problem.
-+ */
-+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
-+#define SET(n) \
-+ (*(MD4_u32plus *)&ptr[(n) * 4])
-+#define GET(n) \
-+ SET(n)
-+#else
-+#define SET(n) \
-+ (ctx->block[(n)] = \
-+ (MD4_u32plus)ptr[(n) * 4] | \
-+ ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
-+ ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
-+ ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
-+#define GET(n) \
-+ (ctx->block[(n)])
-+#endif
-+
-+/*
-+ * This processes one or more 64-byte data blocks, but does NOT update the bit
-+ * counters. There are no alignment requirements.
-+ */
-+static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
-+{
-+ const unsigned char *ptr;
-+ MD4_u32plus a, b, c, d;
-+ MD4_u32plus saved_a, saved_b, saved_c, saved_d;
-+ const MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
-+
-+ ptr = (const unsigned char *)data;
-+
-+ a = ctx->a;
-+ b = ctx->b;
-+ c = ctx->c;
-+ d = ctx->d;
-+
-+ do {
-+ saved_a = a;
-+ saved_b = b;
-+ saved_c = c;
-+ saved_d = d;
-+
-+/* Round 1 */
-+ STEP(F, a, b, c, d, SET(0), 3)
-+ STEP(F, d, a, b, c, SET(1), 7)
-+ STEP(F, c, d, a, b, SET(2), 11)
-+ STEP(F, b, c, d, a, SET(3), 19)
-+ STEP(F, a, b, c, d, SET(4), 3)
-+ STEP(F, d, a, b, c, SET(5), 7)
-+ STEP(F, c, d, a, b, SET(6), 11)
-+ STEP(F, b, c, d, a, SET(7), 19)
-+ STEP(F, a, b, c, d, SET(8), 3)
-+ STEP(F, d, a, b, c, SET(9), 7)
-+ STEP(F, c, d, a, b, SET(10), 11)
-+ STEP(F, b, c, d, a, SET(11), 19)
-+ STEP(F, a, b, c, d, SET(12), 3)
-+ STEP(F, d, a, b, c, SET(13), 7)
-+ STEP(F, c, d, a, b, SET(14), 11)
-+ STEP(F, b, c, d, a, SET(15), 19)
-+
-+/* Round 2 */
-+ STEP(G, a, b, c, d, GET(0) + ac1, 3)
-+ STEP(G, d, a, b, c, GET(4) + ac1, 5)
-+ STEP(G, c, d, a, b, GET(8) + ac1, 9)
-+ STEP(G, b, c, d, a, GET(12) + ac1, 13)
-+ STEP(G, a, b, c, d, GET(1) + ac1, 3)
-+ STEP(G, d, a, b, c, GET(5) + ac1, 5)
-+ STEP(G, c, d, a, b, GET(9) + ac1, 9)
-+ STEP(G, b, c, d, a, GET(13) + ac1, 13)
-+ STEP(G, a, b, c, d, GET(2) + ac1, 3)
-+ STEP(G, d, a, b, c, GET(6) + ac1, 5)
-+ STEP(G, c, d, a, b, GET(10) + ac1, 9)
-+ STEP(G, b, c, d, a, GET(14) + ac1, 13)
-+ STEP(G, a, b, c, d, GET(3) + ac1, 3)
-+ STEP(G, d, a, b, c, GET(7) + ac1, 5)
-+ STEP(G, c, d, a, b, GET(11) + ac1, 9)
-+ STEP(G, b, c, d, a, GET(15) + ac1, 13)
-+
-+/* Round 3 */
-+ STEP(H, a, b, c, d, GET(0) + ac2, 3)
-+ STEP(H, d, a, b, c, GET(8) + ac2, 9)
-+ STEP(H, c, d, a, b, GET(4) + ac2, 11)
-+ STEP(H, b, c, d, a, GET(12) + ac2, 15)
-+ STEP(H, a, b, c, d, GET(2) + ac2, 3)
-+ STEP(H, d, a, b, c, GET(10) + ac2, 9)
-+ STEP(H, c, d, a, b, GET(6) + ac2, 11)
-+ STEP(H, b, c, d, a, GET(14) + ac2, 15)
-+ STEP(H, a, b, c, d, GET(1) + ac2, 3)
-+ STEP(H, d, a, b, c, GET(9) + ac2, 9)
-+ STEP(H, c, d, a, b, GET(5) + ac2, 11)
-+ STEP(H, b, c, d, a, GET(13) + ac2, 15)
-+ STEP(H, a, b, c, d, GET(3) + ac2, 3)
-+ STEP(H, d, a, b, c, GET(11) + ac2, 9)
-+ STEP(H, c, d, a, b, GET(7) + ac2, 11)
-+ STEP(H, b, c, d, a, GET(15) + ac2, 15)
-+
-+ a += saved_a;
-+ b += saved_b;
-+ c += saved_c;
-+ d += saved_d;
-+
-+ ptr += 64;
-+ } while (size -= 64);
-+
-+ ctx->a = a;
-+ ctx->b = b;
-+ ctx->c = c;
-+ ctx->d = d;
-+
-+ return ptr;
-+}
-+
-+void MD4_Init(MD4_CTX *ctx)
-+{
-+ ctx->a = 0x67452301;
-+ ctx->b = 0xefcdab89;
-+ ctx->c = 0x98badcfe;
-+ ctx->d = 0x10325476;
-+
-+ ctx->lo = 0;
-+ ctx->hi = 0;
-+}
-+
-+void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
-+{
-+ MD4_u32plus saved_lo;
-+ unsigned long used, available;
-+
-+ saved_lo = ctx->lo;
-+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
-+ ctx->hi++;
-+ ctx->hi += size >> 29;
-+
-+ used = saved_lo & 0x3f;
-+
-+ if (used) {
-+ available = 64 - used;
-+
-+ if (size < available) {
-+ memcpy(&ctx->buffer[used], data, size);
-+ return;
-+ }
-+
-+ memcpy(&ctx->buffer[used], data, available);
-+ data = (const unsigned char *)data + available;
-+ size -= available;
-+ body(ctx, ctx->buffer, 64);
-+ }
-+
-+ if (size >= 64) {
-+ data = body(ctx, data, size & ~(unsigned long)0x3f);
-+ size &= 0x3f;
-+ }
-+
-+ memcpy(ctx->buffer, data, size);
-+}
-+
-+#define OUT(dst, src) \
-+ (dst)[0] = (unsigned char)(src); \
-+ (dst)[1] = (unsigned char)((src) >> 8); \
-+ (dst)[2] = (unsigned char)((src) >> 16); \
-+ (dst)[3] = (unsigned char)((src) >> 24);
-+
-+void MD4_Final(unsigned char *result, MD4_CTX *ctx)
-+{
-+ unsigned long used, available;
-+
-+ used = ctx->lo & 0x3f;
-+
-+ ctx->buffer[used++] = 0x80;
-+
-+ available = 64 - used;
-+
-+ if (available < 8) {
-+ memset(&ctx->buffer[used], 0, available);
-+ body(ctx, ctx->buffer, 64);
-+ used = 0;
-+ available = 64;
-+ }
-+
-+ memset(&ctx->buffer[used], 0, available - 8);
-+
-+ ctx->lo <<= 3;
-+ OUT(&ctx->buffer[56], ctx->lo)
-+ OUT(&ctx->buffer[60], ctx->hi)
-+
-+ body(ctx, ctx->buffer, 64);
-+
-+ OUT(&result[0], ctx->a)
-+ OUT(&result[4], ctx->b)
-+ OUT(&result[8], ctx->c)
-+ OUT(&result[12], ctx->d)
-+
-+ memset(ctx, 0, sizeof(*ctx));
-+}
-diff --git a/usr.bin/rsync/md4.h b/usr.bin/rsync/md4.h
-new file mode 100644
-index 00000000000..ebf5bb555a0
---- /dev/null
-+++ b/usr.bin/rsync/md4.h
-@@ -0,0 +1,47 @@
-+/*
-+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
-+ * MD4 Message-Digest Algorithm (RFC 1320).
-+ *
-+ * Homepage:
-+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
-+ *
-+ * Author:
-+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
-+ *
-+ * This software was written by Alexander Peslyak in 2001. No copyright is
-+ * claimed, and the software is hereby placed in the public domain.
-+ * In case this attempt to disclaim copyright and place the software in the
-+ * public domain is deemed null and void, then the software is
-+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
-+ * general public under the following terms:
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted.
-+ *
-+ * There's ABSOLUTELY NO WARRANTY, express or implied.
-+ *
-+ * See md4.c for more information.
-+ */
-+
-+#ifndef _MD4_H
-+#define _MD4_H
-+
-+#include <stdint.h>
-+
-+#define MD4_DIGEST_LENGTH 16
-+
-+/* Any 32-bit or wider unsigned integer data type will do */
-+typedef uint_fast32_t MD4_u32plus;
-+
-+typedef struct {
-+ MD4_u32plus lo, hi;
-+ MD4_u32plus a, b, c, d;
-+ unsigned char buffer[64];
-+ MD4_u32plus block[16];
-+} MD4_CTX;
-+
-+extern void MD4_Init(MD4_CTX *ctx);
-+extern void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
-+extern void MD4_Final(unsigned char *result, MD4_CTX *ctx);
-+
-+#endif
-diff --git a/usr.bin/rsync/sender.c b/usr.bin/rsync/sender.c
-index 9dd008def01..2aeb99b64a0 100644
---- a/usr.bin/rsync/sender.c
-+++ b/usr.bin/rsync/sender.c
-@@ -26,7 +26,7 @@
- #include <string.h>
- #include <unistd.h>
-
--#include <openssl/md4.h>
-+#include "md4.h"
-
- #include "extern.h"
-
---
-2.35.1
-
diff --git a/pkg/openbsd/patch/0031-pax-Fix-some-incorrect-format-specifiers.patch b/pkg/openbsd/patch/0031-pax-Fix-some-incorrect-format-specifiers.patch
@@ -1,48 +0,0 @@
-From f855b534ca2c34c3691a0c89d1be482a33a3610c Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Thu, 4 Jun 2020 21:36:11 -0700
-Subject: [PATCH] pax: Fix some incorrect format specifiers
-
----
- bin/pax/cpio.c | 2 +-
- bin/pax/gen_subs.c | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/bin/pax/cpio.c b/bin/pax/cpio.c
-index 3832b1e87aa..769a9dfb990 100644
---- a/bin/pax/cpio.c
-+++ b/bin/pax/cpio.c
-@@ -214,7 +214,7 @@ rd_ln_nm(ARCHD *arcn)
- */
- if ((arcn->sb.st_size <= 0) ||
- (arcn->sb.st_size >= (off_t)sizeof(arcn->ln_name))) {
-- paxwarn(1, "Cpio link name length is invalid: %lld",
-+ paxwarn(1, "Cpio link name length is invalid: %zu",
- arcn->sb.st_size);
- return(-1);
- }
-diff --git a/bin/pax/gen_subs.c b/bin/pax/gen_subs.c
-index 405dd2c24ed..7eb82007e3b 100644
---- a/bin/pax/gen_subs.c
-+++ b/bin/pax/gen_subs.c
-@@ -109,7 +109,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
- if (strftime(f_date, sizeof(f_date), TIMEFMT(sbp->st_mtime, now),
- localtime(&(sbp->st_mtime))) == 0)
- f_date[0] = '\0';
-- (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
-+ (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, (unsigned)sbp->st_nlink,
- NAME_WIDTH, UT_NAMESIZE, user_from_uid(sbp->st_uid, 0),
- NAME_WIDTH, UT_NAMESIZE, group_from_gid(sbp->st_gid, 0));
-
-@@ -121,7 +121,7 @@ ls_list(ARCHD *arcn, time_t now, FILE *fp)
- (unsigned long)MAJOR(sbp->st_rdev),
- (unsigned long)MINOR(sbp->st_rdev));
- else {
-- (void)fprintf(fp, "%9llu ", sbp->st_size);
-+ (void)fprintf(fp, "%9zu ", sbp->st_size);
- }
-
- /*
---
-2.27.0
-
diff --git a/pkg/openbsd/patch/0031-pax-Use-memcpy-to-set-TMAGIC-and-TVERSION-to-avoid-w.patch b/pkg/openbsd/patch/0031-pax-Use-memcpy-to-set-TMAGIC-and-TVERSION-to-avoid-w.patch
@@ -0,0 +1,38 @@
+From dc49fca08adc0fd8cd9565f2aeca6dc2c8d1fbd2 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Thu, 4 Jun 2020 21:44:26 -0700
+Subject: [PATCH] pax: Use memcpy to set TMAGIC and TVERSION to avoid warning
+
+---
+ bin/pax/tar.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/bin/pax/tar.c b/bin/pax/tar.c
+index a0cbb31b547..095eef85af0 100644
+--- a/bin/pax/tar.c
++++ b/bin/pax/tar.c
+@@ -1055,8 +1055,8 @@ wr_xheader(ARCHD *arcn, struct xheader *xhdr)
+ memset(hdblk, 0, sizeof(hdblk));
+ hd = (HD_USTAR *)hdblk;
+ hd->typeflag = XHDRTYPE;
+- strncpy(hd->magic, TMAGIC, TMAGLEN);
+- strncpy(hd->version, TVERSION, TVERSLEN);
++ memcpy(hd->magic, TMAGIC, TMAGLEN);
++ memcpy(hd->version, TVERSION, TVERSLEN);
+ if (ul_oct(size, hd->size, sizeof(hd->size), 3))
+ return -1;
+
+@@ -1263,8 +1263,8 @@ wr_ustar_or_pax(ARCHD *arcn, int ustar)
+ break;
+ }
+
+- strncpy(hd->magic, TMAGIC, TMAGLEN);
+- strncpy(hd->version, TVERSION, TVERSLEN);
++ memcpy(hd->magic, TMAGIC, TMAGLEN);
++ memcpy(hd->version, TVERSION, TVERSLEN);
+
+ /*
+ * set the remaining fields. Some versions want all 16 bits of mode
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0032-pax-Use-memcpy-to-set-TMAGIC-and-TVERSION-to-avoid-w.patch b/pkg/openbsd/patch/0032-pax-Use-memcpy-to-set-TMAGIC-and-TVERSION-to-avoid-w.patch
@@ -1,27 +0,0 @@
-From e5c8e801a42459bf0c416f6751b687d61f46fcf1 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Thu, 4 Jun 2020 21:44:26 -0700
-Subject: [PATCH] pax: Use memcpy to set TMAGIC and TVERSION to avoid warning
-
----
- bin/pax/tar.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/bin/pax/tar.c b/bin/pax/tar.c
-index 8d6b3f37012..1f4012123c3 100644
---- a/bin/pax/tar.c
-+++ b/bin/pax/tar.c
-@@ -1040,8 +1040,8 @@ ustar_wr(ARCHD *arcn)
- break;
- }
-
-- strncpy(hd->magic, TMAGIC, TMAGLEN);
-- strncpy(hd->version, TVERSION, TVERSLEN);
-+ memcpy(hd->magic, TMAGIC, TMAGLEN);
-+ memcpy(hd->version, TVERSION, TVERSLEN);
-
- /*
- * set the remaining fields. Some versions want all 16 bits of mode
---
-2.35.1
-
diff --git a/pkg/openbsd/patch/0032-rsync-Fix-some-incorrect-format-specifiers.patch b/pkg/openbsd/patch/0032-rsync-Fix-some-incorrect-format-specifiers.patch
@@ -0,0 +1,42 @@
+From e2bc701601abc23299d9a694cb3173bdb44fff83 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Thu, 4 Jun 2020 21:36:24 -0700
+Subject: [PATCH] rsync: Fix some incorrect format specifiers
+
+---
+ usr.bin/rsync/fargs.c | 4 ++--
+ usr.bin/rsync/uploader.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/usr.bin/rsync/fargs.c b/usr.bin/rsync/fargs.c
+index cbc8537f38c..0b1c255550d 100644
+--- a/usr.bin/rsync/fargs.c
++++ b/usr.bin/rsync/fargs.c
+@@ -134,9 +134,9 @@ fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip)
+ /* --devices is sent as -D --no-specials */
+ addargs(&args, "--no-specials");
+ if (sess->opts->max_size >= 0)
+- addargs(&args, "--max-size=%lld", sess->opts->max_size);
++ addargs(&args, "--max-size=%jd", (intmax_t)sess->opts->max_size);
+ if (sess->opts->min_size >= 0)
+- addargs(&args, "--min-size=%lld", sess->opts->min_size);
++ addargs(&args, "--min-size=%jd", (intmax_t)sess->opts->min_size);
+
+ /* extra options for the receiver (local is sender) */
+ if (f->mode == FARGS_SENDER) {
+diff --git a/usr.bin/rsync/uploader.c b/usr.bin/rsync/uploader.c
+index 6cb6d054da7..09fedfaadbc 100644
+--- a/usr.bin/rsync/uploader.c
++++ b/usr.bin/rsync/uploader.c
+@@ -1020,7 +1020,7 @@ rsync_uploader(struct upload *u, int *fileinfd,
+ init_blk(&blk.blks[i], &blk, offs, i, mbuf, sess);
+ offs += blk.len;
+ LOG3(
+- "i=%ld, offs=%lld, msz=%ld, blk.len=%lu, blk.rem=%lu",
++ "i=%zu, offs=%td, msz=%zd, blk.len=%zu, blk.rem=%zu",
+ i, offs, msz, blk.len, blk.rem);
+ i++;
+ } while (i < blk.blksz);
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0034-m4-Declare-dopaste-only-when-it-s-used.patch b/pkg/openbsd/patch/0033-m4-Declare-dopaste-only-when-it-s-used.patch
diff --git a/pkg/openbsd/patch/0033-rsync-Fix-some-incorrect-format-specifiers.patch b/pkg/openbsd/patch/0033-rsync-Fix-some-incorrect-format-specifiers.patch
@@ -1,42 +0,0 @@
-From 0a32d4f555441c1928547f8f08a6373a6c9d8bf1 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Thu, 4 Jun 2020 21:36:24 -0700
-Subject: [PATCH] rsync: Fix some incorrect format specifiers
-
----
- usr.bin/rsync/fargs.c | 4 ++--
- usr.bin/rsync/uploader.c | 2 +-
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/usr.bin/rsync/fargs.c b/usr.bin/rsync/fargs.c
-index 7ccb5bff7d2..ef1aaf37c87 100644
---- a/usr.bin/rsync/fargs.c
-+++ b/usr.bin/rsync/fargs.c
-@@ -132,9 +132,9 @@ fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip)
- /* --devices is sent as -D --no-specials */
- addargs(&args, "--no-specials");
- if (sess->opts->max_size >= 0)
-- addargs(&args, "--max-size=%lld", sess->opts->max_size);
-+ addargs(&args, "--max-size=%jd", (intmax_t)sess->opts->max_size);
- if (sess->opts->min_size >= 0)
-- addargs(&args, "--min-size=%lld", sess->opts->min_size);
-+ addargs(&args, "--min-size=%jd", (intmax_t)sess->opts->min_size);
-
- /* only add --compare-dest, etc if this is the sender */
- if (sess->opts->alt_base_mode != 0 &&
-diff --git a/usr.bin/rsync/uploader.c b/usr.bin/rsync/uploader.c
-index 678b6c96218..951a5ee4133 100644
---- a/usr.bin/rsync/uploader.c
-+++ b/usr.bin/rsync/uploader.c
-@@ -1010,7 +1010,7 @@ rsync_uploader(struct upload *u, int *fileinfd,
- init_blk(&blk.blks[i], &blk, offs, i, mbuf, sess);
- offs += blk.len;
- LOG3(
-- "i=%ld, offs=%lld, msz=%ld, blk.len=%lu, blk.rem=%lu",
-+ "i=%zu, offs=%td, msz=%zd, blk.len=%zu, blk.rem=%zu",
- i, offs, msz, blk.len, blk.rem);
- i++;
- } while (i < blk.blksz);
---
-2.35.1
-
diff --git a/pkg/openbsd/patch/0034-acme-client-Fix-signed-ness-of-base64buf_url-input.patch b/pkg/openbsd/patch/0034-acme-client-Fix-signed-ness-of-base64buf_url-input.patch
@@ -0,0 +1,160 @@
+From 67ffb8812ee7ac5fe23a5149ff643d1f392fb1f5 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Fri, 23 Apr 2021 20:10:05 -0700
+Subject: [PATCH] acme-client: Fix signed-ness of base64buf_url input
+
+This make most of the pointer casts unnecessary.
+---
+ usr.sbin/acme-client/acctproc.c | 17 +++++++++--------
+ usr.sbin/acme-client/base64.c | 2 +-
+ usr.sbin/acme-client/extern.h | 2 +-
+ usr.sbin/acme-client/keyproc.c | 5 +++--
+ usr.sbin/acme-client/revokeproc.c | 6 ++++--
+ 5 files changed, 18 insertions(+), 14 deletions(-)
+
+diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
+index da3d49107ae..9e97a8bb760 100644
+--- a/usr.sbin/acme-client/acctproc.c
++++ b/usr.sbin/acme-client/acctproc.c
+@@ -42,8 +42,9 @@
+ static char *
+ bn2string(const BIGNUM *bn)
+ {
+- int len;
+- char *buf, *bbuf;
++ int len;
++ unsigned char *buf;
++ char *bbuf;
+
+ /* Extract big-endian representation of BIGNUM. */
+
+@@ -51,7 +52,7 @@ bn2string(const BIGNUM *bn)
+ if ((buf = malloc(len)) == NULL) {
+ warn("malloc");
+ return NULL;
+- } else if (len != BN_bn2bin(bn, (unsigned char *)buf)) {
++ } else if (len != BN_bn2bin(bn, buf)) {
+ warnx("BN_bn2bin");
+ free(buf);
+ return NULL;
+@@ -167,7 +168,7 @@ op_thumbprint(int fd, EVP_PKEY *pkey)
+ warnx("EVP_Digest");
+ goto out;
+ }
+- if ((dig64 = base64buf_url((char *)dig, digsz)) == NULL) {
++ if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+@@ -281,7 +282,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ /* Base64-encode the payload. */
+
+- if ((pay64 = base64buf_url(pay, strlen(pay))) == NULL) {
++ if ((pay64 = base64buf_url((unsigned char *)pay, strlen(pay))) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+@@ -324,7 +325,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ /* The header combined with the nonce, base64. */
+
+- if ((prot64 = base64buf_url(prot, strlen(prot))) == NULL) {
++ if ((prot64 = base64buf_url((unsigned char *)prot, strlen(prot))) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+@@ -363,7 +364,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ switch (EVP_PKEY_base_id(pkey)) {
+ case EVP_PKEY_RSA:
+- if ((dig64 = base64buf_url((char *)dig, digsz)) == NULL) {
++ if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+@@ -402,7 +403,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+ goto out;
+ }
+
+- if ((dig64 = base64buf_url((char *)buf, 2 * bn_len)) == NULL) {
++ if ((dig64 = base64buf_url(buf, 2 * bn_len)) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+diff --git a/usr.sbin/acme-client/base64.c b/usr.sbin/acme-client/base64.c
+index 2b6377f0d81..0d84ad4b458 100644
+--- a/usr.sbin/acme-client/base64.c
++++ b/usr.sbin/acme-client/base64.c
+@@ -39,7 +39,7 @@ base64len(size_t len)
+ * Returns NULL on allocation failure (not logged).
+ */
+ char *
+-base64buf_url(const char *data, size_t len)
++base64buf_url(const unsigned char *data, size_t len)
+ {
+ size_t i, sz;
+ char *buf;
+diff --git a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h
+index 915f80e3992..5b0950b0693 100644
+--- a/usr.sbin/acme-client/extern.h
++++ b/usr.sbin/acme-client/extern.h
+@@ -244,7 +244,7 @@ int checkexit_ext(int *, pid_t, enum comp);
+ * Returns a buffer or NULL on allocation error.
+ */
+ size_t base64len(size_t);
+-char *base64buf_url(const char *, size_t);
++char *base64buf_url(const unsigned char *, size_t);
+
+ /*
+ * JSON parsing routines.
+diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
+index a3b6666c279..f0df9f292d4 100644
+--- a/usr.sbin/acme-client/keyproc.c
++++ b/usr.sbin/acme-client/keyproc.c
+@@ -77,7 +77,8 @@ int
+ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+ enum keytype keytype)
+ {
+- char *der64 = NULL, *der = NULL, *dercp;
++ char *der64 = NULL;
++ unsigned char *der = NULL, *dercp;
+ char *sans = NULL, *san = NULL;
+ FILE *f;
+ size_t i, sansz;
+@@ -238,7 +239,7 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+ } else if ((der = dercp = malloc(len)) == NULL) {
+ warn("malloc");
+ goto out;
+- } else if (len != i2d_X509_REQ(x, (u_char **)&dercp)) {
++ } else if (len != i2d_X509_REQ(x, &dercp)) {
+ warnx("i2d_X509_REQ");
+ goto out;
+ } else if ((der64 = base64buf_url(der, len)) == NULL) {
+diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
+index 0f1bf32678b..58e81233f1a 100644
+--- a/usr.sbin/acme-client/revokeproc.c
++++ b/usr.sbin/acme-client/revokeproc.c
+@@ -63,7 +63,9 @@ revokeproc(int fd, const char *certfile, int force,
+ int revocate, const char *const *alts, size_t altsz)
+ {
+ GENERAL_NAMES *sans = NULL;
+- char *der = NULL, *dercp, *der64 = NULL;
++ unsigned char *der = NULL, *dercp;
++ char *der64 = NULL;
++ char *san = NULL, *str, *tok;
+ int rc = 0, cc, i, len;
+ size_t *found = NULL;
+ FILE *f = NULL;
+@@ -240,7 +242,7 @@ revokeproc(int fd, const char *certfile, int force,
+ } else if ((der = dercp = malloc(len)) == NULL) {
+ warn("malloc");
+ goto out;
+- } else if (len != i2d_X509(x, (u_char **)&dercp)) {
++ } else if (len != i2d_X509(x, &dercp)) {
+ warnx("i2d_X509");
+ goto out;
+ } else if ((der64 = base64buf_url(der, len)) == NULL) {
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0035-acme-client-Fix-signed-ness-of-base64buf_url-input.patch b/pkg/openbsd/patch/0035-acme-client-Fix-signed-ness-of-base64buf_url-input.patch
@@ -1,160 +0,0 @@
-From cc94758cade79724cc820e654ae12bee639c2692 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Fri, 23 Apr 2021 20:10:05 -0700
-Subject: [PATCH] acme-client: Fix signed-ness of base64buf_url input
-
-This make most of the pointer casts unnecessary.
----
- usr.sbin/acme-client/acctproc.c | 17 +++++++++--------
- usr.sbin/acme-client/base64.c | 2 +-
- usr.sbin/acme-client/extern.h | 2 +-
- usr.sbin/acme-client/keyproc.c | 5 +++--
- usr.sbin/acme-client/revokeproc.c | 6 ++++--
- 5 files changed, 18 insertions(+), 14 deletions(-)
-
-diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
-index e3a0eb64dec..23d8a1c3a33 100644
---- a/usr.sbin/acme-client/acctproc.c
-+++ b/usr.sbin/acme-client/acctproc.c
-@@ -43,8 +43,9 @@
- static char *
- bn2string(const BIGNUM *bn)
- {
-- int len;
-- char *buf, *bbuf;
-+ int len;
-+ unsigned char *buf;
-+ char *bbuf;
-
- /* Extract big-endian representation of BIGNUM. */
-
-@@ -52,7 +53,7 @@ bn2string(const BIGNUM *bn)
- if ((buf = malloc(len)) == NULL) {
- warn("malloc");
- return NULL;
-- } else if (len != BN_bn2bin(bn, (unsigned char *)buf)) {
-+ } else if (len != BN_bn2bin(bn, buf)) {
- warnx("BN_bn2bin");
- free(buf);
- return NULL;
-@@ -168,7 +169,7 @@ op_thumbprint(int fd, EVP_PKEY *pkey)
- warnx("EVP_Digest");
- goto out;
- }
-- if ((dig64 = base64buf_url((char *)dig, digsz)) == NULL) {
-+ if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-@@ -282,7 +283,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- /* Base64-encode the payload. */
-
-- if ((pay64 = base64buf_url(pay, strlen(pay))) == NULL) {
-+ if ((pay64 = base64buf_url((unsigned char *)pay, strlen(pay))) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-@@ -325,7 +326,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- /* The header combined with the nonce, base64. */
-
-- if ((prot64 = base64buf_url(prot, strlen(prot))) == NULL) {
-+ if ((prot64 = base64buf_url((unsigned char *)prot, strlen(prot))) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-@@ -364,7 +365,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- switch (EVP_PKEY_base_id(pkey)) {
- case EVP_PKEY_RSA:
-- if ((dig64 = base64buf_url((char *)dig, digsz)) == NULL) {
-+ if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-@@ -403,7 +404,7 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
- goto out;
- }
-
-- if ((dig64 = base64buf_url((char *)buf, 2 * bn_len)) == NULL) {
-+ if ((dig64 = base64buf_url(buf, 2 * bn_len)) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-diff --git a/usr.sbin/acme-client/base64.c b/usr.sbin/acme-client/base64.c
-index 2b6377f0d81..0d84ad4b458 100644
---- a/usr.sbin/acme-client/base64.c
-+++ b/usr.sbin/acme-client/base64.c
-@@ -39,7 +39,7 @@ base64len(size_t len)
- * Returns NULL on allocation failure (not logged).
- */
- char *
--base64buf_url(const char *data, size_t len)
-+base64buf_url(const unsigned char *data, size_t len)
- {
- size_t i, sz;
- char *buf;
-diff --git a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h
-index 32d4b4b3d85..701733df786 100644
---- a/usr.sbin/acme-client/extern.h
-+++ b/usr.sbin/acme-client/extern.h
-@@ -245,7 +245,7 @@ int checkexit_ext(int *, pid_t, enum comp);
- */
- size_t base64buf(char *, const char *, size_t);
- size_t base64len(size_t);
--char *base64buf_url(const char *, size_t);
-+char *base64buf_url(const unsigned char *, size_t);
-
- /*
- * JSON parsing routines.
-diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
-index a3b6666c279..f0df9f292d4 100644
---- a/usr.sbin/acme-client/keyproc.c
-+++ b/usr.sbin/acme-client/keyproc.c
-@@ -77,7 +77,8 @@ int
- keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
- enum keytype keytype)
- {
-- char *der64 = NULL, *der = NULL, *dercp;
-+ char *der64 = NULL;
-+ unsigned char *der = NULL, *dercp;
- char *sans = NULL, *san = NULL;
- FILE *f;
- size_t i, sansz;
-@@ -238,7 +239,7 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
- } else if ((der = dercp = malloc(len)) == NULL) {
- warn("malloc");
- goto out;
-- } else if (len != i2d_X509_REQ(x, (u_char **)&dercp)) {
-+ } else if (len != i2d_X509_REQ(x, &dercp)) {
- warnx("i2d_X509_REQ");
- goto out;
- } else if ((der64 = base64buf_url(der, len)) == NULL) {
-diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
-index 0f1bf32678b..58e81233f1a 100644
---- a/usr.sbin/acme-client/revokeproc.c
-+++ b/usr.sbin/acme-client/revokeproc.c
-@@ -63,7 +63,9 @@ revokeproc(int fd, const char *certfile, int force,
- int revocate, const char *const *alts, size_t altsz)
- {
- GENERAL_NAMES *sans = NULL;
-- char *der = NULL, *dercp, *der64 = NULL;
-+ unsigned char *der = NULL, *dercp;
-+ char *der64 = NULL;
-+ char *san = NULL, *str, *tok;
- int rc = 0, cc, i, len;
- size_t *found = NULL;
- FILE *f = NULL;
-@@ -240,7 +242,7 @@ revokeproc(int fd, const char *certfile, int force,
- } else if ((der = dercp = malloc(len)) == NULL) {
- warn("malloc");
- goto out;
-- } else if (len != i2d_X509(x, (u_char **)&dercp)) {
-+ } else if (len != i2d_X509(x, &dercp)) {
- warnx("i2d_X509");
- goto out;
- } else if ((der64 = base64buf_url(der, len)) == NULL) {
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0035-acme-client-Port-to-BearSSL.patch b/pkg/openbsd/patch/0035-acme-client-Port-to-BearSSL.patch
@@ -0,0 +1,1543 @@
+From 1ab0f94943e02c49d88a358351914f9032a5bca3 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Fri, 23 Apr 2021 23:14:16 -0700
+Subject: [PATCH] acme-client: Port to BearSSL
+
+---
+ usr.sbin/acme-client/acctproc.c | 298 +++++++++------------------
+ usr.sbin/acme-client/certproc.c | 5 -
+ usr.sbin/acme-client/key.c | 329 ++++++++++++++++++++++++------
+ usr.sbin/acme-client/key.h | 22 +-
+ usr.sbin/acme-client/keyproc.c | 198 ++++++------------
+ usr.sbin/acme-client/revokeproc.c | 237 ++++++++++-----------
+ 6 files changed, 564 insertions(+), 525 deletions(-)
+
+diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
+index 9e97a8bb760..8d66dac49d9 100644
+--- a/usr.sbin/acme-client/acctproc.c
++++ b/usr.sbin/acme-client/acctproc.c
+@@ -19,73 +19,29 @@
+
+ #include <err.h>
+ #include <errno.h>
+-#include <limits.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <openssl/bn.h>
+-#include <openssl/ec.h>
+-#include <openssl/evp.h>
+-#include <openssl/rsa.h>
+-#include <openssl/err.h>
++#include <bearssl.h>
+
+ #include "extern.h"
+ #include "key.h"
+
+-/*
+- * Converts a BIGNUM to the form used in JWK.
+- * This is essentially a base64-encoded big-endian binary string
+- * representation of the number.
+- */
+-static char *
+-bn2string(const BIGNUM *bn)
+-{
+- int len;
+- unsigned char *buf;
+- char *bbuf;
+-
+- /* Extract big-endian representation of BIGNUM. */
+-
+- len = BN_num_bytes(bn);
+- if ((buf = malloc(len)) == NULL) {
+- warn("malloc");
+- return NULL;
+- } else if (len != BN_bn2bin(bn, buf)) {
+- warnx("BN_bn2bin");
+- free(buf);
+- return NULL;
+- }
+-
+- /* Convert to base64url. */
+-
+- if ((bbuf = base64buf_url(buf, len)) == NULL) {
+- warnx("base64buf_url");
+- free(buf);
+- return NULL;
+- }
+-
+- free(buf);
+- return bbuf;
+-}
+-
+ /*
+ * Extract the relevant RSA components from the key and create the JSON
+ * thumbprint from them.
+ */
+ static char *
+-op_thumb_rsa(EVP_PKEY *pkey)
++op_thumb_rsa(struct key *key)
+ {
+ char *exp = NULL, *mod = NULL, *json = NULL;
+- RSA *r;
+-
+- if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
+- warnx("EVP_PKEY_get0_RSA");
+- else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
+- warnx("bn2string");
+- else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
+- warnx("bn2string");
++
++ if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
++ warnx("base64buf_url");
++ else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
++ warnx("base64buf_url");
+ else if ((json = json_fmt_thumb_rsa(exp, mod)) == NULL)
+ warnx("json_fmt_thumb_rsa");
+
+@@ -99,31 +55,23 @@ op_thumb_rsa(EVP_PKEY *pkey)
+ * thumbprint from them.
+ */
+ static char *
+-op_thumb_ec(EVP_PKEY *pkey)
++op_thumb_ec(struct key *key)
+ {
+- BIGNUM *X = NULL, *Y = NULL;
+- EC_KEY *ec = NULL;
++ size_t len;
+ char *x = NULL, *y = NULL;
+ char *json = NULL;
+
+- if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
+- warnx("EVP_PKEY_get0_EC_KEY");
+- else if ((X = BN_new()) == NULL)
+- warnx("BN_new");
+- else if ((Y = BN_new()) == NULL)
+- warnx("BN_new");
+- else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
+- EC_KEY_get0_public_key(ec), X, Y, NULL))
+- warnx("EC_POINT_get_affine_coordinates");
+- else if ((x = bn2string(X)) == NULL)
+- warnx("bn2string");
+- else if ((y = bn2string(Y)) == NULL)
+- warnx("bn2string");
++ /* Points are stored in uncompressed format. */
++ len = key->ec.pk.qlen / 2;
++ if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
++ warnx("invalid EC public key");
++ else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
++ warnx("base64buf_url");
++ else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
++ warnx("base64buf_url");
+ else if ((json = json_fmt_thumb_ec(x, y)) == NULL)
+ warnx("json_fmt_thumb_ec");
+
+- BN_free(X);
+- BN_free(Y);
+ free(x);
+ free(y);
+ return json;
+@@ -133,26 +81,26 @@ op_thumb_ec(EVP_PKEY *pkey)
+ * The thumbprint operation is used for the challenge sequence.
+ */
+ static int
+-op_thumbprint(int fd, EVP_PKEY *pkey)
++op_thumbprint(int fd, struct key *pkey)
+ {
+- char *thumb = NULL, *dig64 = NULL;
+- unsigned char dig[EVP_MAX_MD_SIZE];
+- unsigned int digsz;
+- int rc = 0;
++ char *thumb = NULL, *dig64 = NULL;
++ br_sha256_context ctx;
++ unsigned char dig[br_sha256_SIZE];
++ int rc = 0;
+
+ /* Construct the thumbprint input itself. */
+
+- switch (EVP_PKEY_base_id(pkey)) {
+- case EVP_PKEY_RSA:
++ switch (pkey->type) {
++ case BR_KEYTYPE_RSA:
+ if ((thumb = op_thumb_rsa(pkey)) != NULL)
+ break;
+ goto out;
+- case EVP_PKEY_EC:
++ case BR_KEYTYPE_EC:
+ if ((thumb = op_thumb_ec(pkey)) != NULL)
+ break;
+ goto out;
+ default:
+- warnx("EVP_PKEY_base_id: unknown key type");
++ warnx("unknown key type");
+ goto out;
+ }
+
+@@ -163,12 +111,10 @@ op_thumbprint(int fd, EVP_PKEY *pkey)
+ * it up in the read loop).
+ */
+
+- if (!EVP_Digest(thumb, strlen(thumb), dig, &digsz, EVP_sha256(),
+- NULL)) {
+- warnx("EVP_Digest");
+- goto out;
+- }
+- if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
++ br_sha256_init(&ctx);
++ br_sha256_update(&ctx, thumb, strlen(thumb));
++ br_sha256_out(&ctx, dig);
++ if ((dig64 = base64buf_url(dig, sizeof(dig))) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+@@ -183,11 +129,10 @@ out:
+ }
+
+ static int
+-op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
++op_sign_rsa(char **prot, struct key *key, const char *nonce, const char *url)
+ {
+ char *exp = NULL, *mod = NULL;
+ int rc = 0;
+- RSA *r;
+
+ *prot = NULL;
+
+@@ -196,12 +141,10 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
+ * Finally, format the header combined with the nonce.
+ */
+
+- if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
+- warnx("EVP_PKEY_get0_RSA");
+- else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
+- warnx("bn2string");
+- else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
+- warnx("bn2string");
++ if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
++ warnx("base64buf_url");
++ else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
++ warnx("base64buf_url");
+ else if ((*prot = json_fmt_protected_rsa(exp, mod, nonce, url)) == NULL)
+ warnx("json_fmt_protected_rsa");
+ else
+@@ -213,35 +156,27 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
+ }
+
+ static int
+-op_sign_ec(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
++op_sign_ec(char **prot, struct key *key, const char *nonce, const char *url)
+ {
+- BIGNUM *X = NULL, *Y = NULL;
+- EC_KEY *ec = NULL;
++ size_t len;
+ char *x = NULL, *y = NULL;
+ int rc = 0;
+
+ *prot = NULL;
+
+- if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
+- warnx("EVP_PKEY_get0_EC_KEY");
+- else if ((X = BN_new()) == NULL)
+- warnx("BN_new");
+- else if ((Y = BN_new()) == NULL)
+- warnx("BN_new");
+- else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
+- EC_KEY_get0_public_key(ec), X, Y, NULL))
+- warnx("EC_POINT_get_affine_coordinates");
+- else if ((x = bn2string(X)) == NULL)
+- warnx("bn2string");
+- else if ((y = bn2string(Y)) == NULL)
+- warnx("bn2string");
++ /* Points are stored in uncompressed format. */
++ len = key->ec.pk.qlen / 2;
++ if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
++ warnx("invalid EC public key");
++ else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
++ warnx("base64buf_url");
++ else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
++ warnx("base64buf_url");
+ else if ((*prot = json_fmt_protected_ec(x, y, nonce, url)) == NULL)
+ warnx("json_fmt_protected_ec");
+ else
+ rc = 1;
+
+- BN_free(X);
+- BN_free(Y);
+ free(x);
+ free(y);
+ return rc;
+@@ -252,20 +187,18 @@ op_sign_ec(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
+ * This requires the sender ("fd") to provide the payload and a nonce.
+ */
+ static int
+-op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
++op_sign(int fd, struct key *key, enum acctop op)
+ {
+- EVP_MD_CTX *ctx = NULL;
+- const EVP_MD *evp_md = NULL;
+- ECDSA_SIG *ec_sig = NULL;
+- const BIGNUM *ec_sig_r = NULL, *ec_sig_s = NULL;
+- int bn_len, sign_len, rc = 0;
++ br_hash_compat_context ctx;
++ int sign_len, rc = 0;
++ unsigned int digsz, sigsz;
+ char *nonce = NULL, *pay = NULL, *pay64 = NULL;
+ char *prot = NULL, *prot64 = NULL;
+- char *sign = NULL, *dig64 = NULL, *fin = NULL;
++ char *sign = NULL, *sig64 = NULL, *fin = NULL;
+ char *url = NULL, *kid = NULL, *alg = NULL;
+- const unsigned char *digp;
+- unsigned char *dig = NULL, *buf = NULL;
+- size_t digsz;
++ unsigned char dig[64];
++ unsigned char *sig = NULL;
++ const unsigned char *oid = NULL;
+
+ /* Read our payload and nonce from the requestor. */
+
+@@ -282,19 +215,22 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ /* Base64-encode the payload. */
+
+- if ((pay64 = base64buf_url((unsigned char *)pay, strlen(pay))) == NULL) {
++ if ((pay64 = base64buf_url(pay, strlen(pay))) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ }
+
+- switch (EVP_PKEY_base_id(pkey)) {
+- case EVP_PKEY_RSA:
++ switch (key->type) {
++ case BR_KEYTYPE_RSA:
+ alg = "RS256";
+- evp_md = EVP_sha256();
++ ctx.vtable = &br_sha256_vtable;
++ oid = BR_HASH_OID_SHA256;
++ sigsz = (key->rsa.sk.n_bitlen + 7) / 8;
+ break;
+- case EVP_PKEY_EC:
++ case BR_KEYTYPE_EC:
+ alg = "ES384";
+- evp_md = EVP_sha384();
++ ctx.vtable = &br_sha384_vtable;
++ sigsz = 96;
+ break;
+ default:
+ warnx("unknown account key type");
+@@ -308,17 +244,17 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+ goto out;
+ }
+ } else {
+- switch (EVP_PKEY_base_id(pkey)) {
+- case EVP_PKEY_RSA:
+- if (!op_sign_rsa(&prot, pkey, nonce, url))
++ switch (key->type) {
++ case BR_KEYTYPE_RSA:
++ if (!op_sign_rsa(&prot, key, nonce, url))
+ goto out;
+ break;
+- case EVP_PKEY_EC:
+- if (!op_sign_ec(&prot, pkey, nonce, url))
++ case BR_KEYTYPE_EC:
++ if (!op_sign_ec(&prot, key, nonce, url))
+ goto out;
+ break;
+ default:
+- warnx("EVP_PKEY_base_id");
++ warnx("unknown key type");
+ goto out;
+ }
+ }
+@@ -341,76 +277,34 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ /* Sign the message. */
+
+- if ((ctx = EVP_MD_CTX_new()) == NULL) {
+- warnx("EVP_MD_CTX_new");
+- goto out;
+- }
+- if (!EVP_DigestSignInit(ctx, NULL, evp_md, NULL, pkey)) {
+- warnx("EVP_DigestSignInit");
+- goto out;
+- }
+- if (!EVP_DigestSign(ctx, NULL, &digsz, sign, sign_len)) {
+- warnx("EVP_DigestSign");
+- goto out;
+- }
+- if ((dig = malloc(digsz)) == NULL) {
++ ctx.vtable->init(&ctx.vtable);
++ ctx.vtable->update(&ctx.vtable, sign, sign_len);
++ ctx.vtable->out(&ctx.vtable, dig);
++ digsz = ctx.vtable->desc >> BR_HASHDESC_OUT_OFF & BR_HASHDESC_OUT_MASK;
++
++ if ((sig = malloc(sigsz)) == NULL) {
+ warn("malloc");
+ goto out;
+ }
+- if (!EVP_DigestSign(ctx, dig, &digsz, sign, sign_len)) {
+- warnx("EVP_DigestSign");
+- goto out;
+- }
+
+- switch (EVP_PKEY_base_id(pkey)) {
+- case EVP_PKEY_RSA:
+- if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
+- warnx("base64buf_url");
++ switch (key->type) {
++ case BR_KEYTYPE_RSA:
++ if (!br_rsa_pkcs1_sign_get_default()(oid, dig, digsz,
++ &key->rsa.sk, sig)) {
++ warnx("br_rsa_pkcs1_sign");
+ goto out;
+ }
+ break;
+- case EVP_PKEY_EC:
+- if (digsz > LONG_MAX) {
+- warnx("EC signature too long");
+- goto out;
+- }
+-
+- digp = dig;
+- if ((ec_sig = d2i_ECDSA_SIG(NULL, &digp, digsz)) == NULL) {
+- warnx("d2i_ECDSA_SIG");
++ case BR_KEYTYPE_EC:
++ sigsz = br_ecdsa_sign_raw_get_default()(br_ec_get_default(),
++ ctx.vtable, dig, &key->ec.sk, sig);
++ if (sigsz == 0 || sigsz % 2 != 0) {
++ warnx("br_ecdsa_sign_raw");
+ goto out;
+ }
+-
+- if ((ec_sig_r = ECDSA_SIG_get0_r(ec_sig)) == NULL ||
+- (ec_sig_s = ECDSA_SIG_get0_s(ec_sig)) == NULL) {
+- warnx("ECDSA_SIG_get0");
+- goto out;
+- }
+-
+- if ((bn_len = (EVP_PKEY_bits(pkey) + 7) / 8) <= 0) {
+- warnx("EVP_PKEY_bits");
+- goto out;
+- }
+-
+- if ((buf = calloc(2, bn_len)) == NULL) {
+- warnx("calloc");
+- goto out;
+- }
+-
+- if (BN_bn2binpad(ec_sig_r, buf, bn_len) != bn_len ||
+- BN_bn2binpad(ec_sig_s, buf + bn_len, bn_len) != bn_len) {
+- warnx("BN_bn2binpad");
+- goto out;
+- }
+-
+- if ((dig64 = base64buf_url(buf, 2 * bn_len)) == NULL) {
+- warnx("base64buf_url");
+- goto out;
+- }
+-
+ break;
+ default:
+- warnx("EVP_PKEY_base_id");
++ warnx("unknown key type");
+ goto out;
+ }
+
+@@ -420,7 +314,11 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+ * when we next enter the read loop).
+ */
+
+- if ((fin = json_fmt_signed(prot64, pay64, dig64)) == NULL) {
++ if ((sig64 = base64buf_url(sig, sigsz)) == NULL) {
++ warnx("base64buf_url");
++ goto out;
++ }
++ if ((fin = json_fmt_signed(prot64, pay64, sig64)) == NULL) {
+ warnx("json_fmt_signed");
+ goto out;
+ } else if (writestr(fd, COMM_REQ, fin) < 0)
+@@ -428,8 +326,6 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
+
+ rc = 1;
+ out:
+- ECDSA_SIG_free(ec_sig);
+- EVP_MD_CTX_free(ctx);
+ free(pay);
+ free(sign);
+ free(pay64);
+@@ -438,10 +334,9 @@ out:
+ free(kid);
+ free(prot);
+ free(prot64);
+- free(dig);
+- free(dig64);
++ free(sig);
++ free(sig64);
+ free(fin);
+- free(buf);
+ return rc;
+ }
+
+@@ -449,7 +344,7 @@ int
+ acctproc(int netsock, const char *acctkey, enum keytype keytype)
+ {
+ FILE *f = NULL;
+- EVP_PKEY *pkey = NULL;
++ struct key *pkey = NULL;
+ long lval;
+ enum acctop op;
+ int rc = 0, cc, newacct = 0;
+@@ -475,8 +370,6 @@ acctproc(int netsock, const char *acctkey, enum keytype keytype)
+
+ /* File-system, user, and sandbox jailing. */
+
+- ERR_load_crypto_strings();
+-
+ if (pledge("stdio", NULL) == -1) {
+ warn("pledge");
+ goto out;
+@@ -554,8 +447,7 @@ out:
+ close(netsock);
+ if (f != NULL)
+ fclose(f);
+- EVP_PKEY_free(pkey);
+- ERR_print_errors_fp(stderr);
+- ERR_free_strings();
++ if (pkey != NULL)
++ freezero(pkey, sizeof(*pkey) + pkey->datasz);
+ return rc;
+ }
+diff --git a/usr.sbin/acme-client/certproc.c b/usr.sbin/acme-client/certproc.c
+index f443d573675..85c3897a4b8 100644
+--- a/usr.sbin/acme-client/certproc.c
++++ b/usr.sbin/acme-client/certproc.c
+@@ -21,11 +21,6 @@
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <openssl/pem.h>
+-#include <openssl/x509.h>
+-#include <openssl/x509v3.h>
+-#include <openssl/err.h>
+-
+ #include "extern.h"
+
+ #define BEGIN_MARKER "-----BEGIN CERTIFICATE-----"
+diff --git a/usr.sbin/acme-client/key.c b/usr.sbin/acme-client/key.c
+index 9ece3059d4e..9599a7fdbd5 100644
+--- a/usr.sbin/acme-client/key.c
++++ b/usr.sbin/acme-client/key.c
+@@ -17,14 +17,11 @@
+ */
+
+ #include <err.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+
+-#include <openssl/evp.h>
+-#include <openssl/pem.h>
+-#include <openssl/rsa.h>
+-#include <openssl/ec.h>
+-#include <openssl/obj_mac.h>
++#include <bearssl.h>
+
+ #include "key.h"
+
+@@ -33,102 +30,320 @@
+ */
+ #define KBITS 4096
+
++static void
++prng_init(const br_prng_class **ctx, const void *params, const void *seed, size_t len)
++{
++}
++
++static void
++prng_generate(const br_prng_class **ctx, void *out, size_t len)
++{
++ arc4random_buf(out, len);
++}
++
++static void
++prng_update(const br_prng_class **ctx, const void *seed, size_t len)
++{
++}
++
++static const br_prng_class prng_class = {
++ 0, prng_init, prng_generate, prng_update
++}, *prng = &prng_class;
++
+ /*
+ * Create an RSA key with the default KBITS number of bits.
+ */
+-EVP_PKEY *
++struct key *
+ rsa_key_create(FILE *f, const char *fname)
+ {
+- EVP_PKEY_CTX *ctx = NULL;
+- EVP_PKEY *pkey = NULL;
++ struct key *key = NULL;
++ size_t slen, plen;
++ unsigned char *sbuf, *pbuf;
++ unsigned char d[KBITS / 8];
++ unsigned char *der = NULL, *pem = NULL;
++ size_t derlen, pemlen;
+
+- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
+- warnx("EVP_PKEY_CTX_new_id");
+- goto err;
+- }
+- if (EVP_PKEY_keygen_init(ctx) <= 0) {
+- warnx("EVP_PKEY_keygen_init");
++ slen = BR_RSA_KBUF_PRIV_SIZE(KBITS);
++ plen = BR_RSA_KBUF_PUB_SIZE(KBITS);
++ if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
++ warnx("malloc");
+ goto err;
+ }
+- if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) {
+- warnx("EVP_PKEY_set_rsa_keygen_bits");
++ key->type = BR_KEYTYPE_RSA;
++ key->datasz = slen + plen;
++ sbuf = key->data;
++ pbuf = key->data + slen;
++ if (!br_rsa_keygen_get_default()(&prng, &key->rsa.sk, sbuf,
++ &key->rsa.pk, pbuf, KBITS, 0x10001)) {
++ warnx("br_rsa_keygen");
+ goto err;
+ }
+- if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
+- warnx("EVP_PKEY_keygen");
++
++ /* Compute the private exponent. */
++
++ if (!br_rsa_compute_privexp_get_default()(d, &key->rsa.sk, 0x10001)) {
++ warnx("br_rsa_compute_modulus");
+ goto err;
+ }
+
+- /* Serialise the key to the disc. */
++ /* Serialise the key to the disk. */
+
+- if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
+- warnx("%s: PEM_write_PrivateKey", fname);
++ derlen = br_encode_rsa_raw_der(NULL, &key->rsa.sk, &key->rsa.pk,
++ d, sizeof(d));
++ if ((der = malloc(derlen)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ br_encode_rsa_raw_der(der, &key->rsa.sk, &key->rsa.pk, d, sizeof(d));
++ pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
++ if ((pem = malloc(pemlen + 1)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
++ if (fwrite(pem, 1, pemlen, f) != pemlen) {
++ warn("write private key");
+ goto err;
+ }
+
+- EVP_PKEY_CTX_free(ctx);
+- return pkey;
++ free(der);
++ free(pem);
++ return key;
+
+ err:
+- EVP_PKEY_free(pkey);
+- EVP_PKEY_CTX_free(ctx);
++ free(der);
++ free(pem);
++ free(key);
+ return NULL;
+ }
+
+-EVP_PKEY *
++struct key *
+ ec_key_create(FILE *f, const char *fname)
+ {
+- EVP_PKEY_CTX *ctx = NULL;
+- EVP_PKEY *pkey = NULL;
++ struct key *key = NULL;
++ const br_ec_impl *ec;
++ size_t slen, plen;
++ unsigned char *sbuf, *pbuf;
++ unsigned char *der = NULL, *pem = NULL;
++ size_t derlen, pemlen;
+
+- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) {
+- warnx("EVP_PKEY_CTX_new_id");
+- goto err;
+- }
+- if (EVP_PKEY_keygen_init(ctx) <= 0) {
+- warnx("EVP_PKEY_keygen_init");
++ slen = BR_EC_KBUF_PRIV_MAX_SIZE;
++ plen = BR_EC_KBUF_PUB_MAX_SIZE;
++ if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
++ warn("malloc");
+ goto err;
+ }
+- if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp384r1) <= 0) {
+- warnx("EVP_PKEY_CTX_set_ec_paramgen_curve_nid");
++ key->type = BR_KEYTYPE_EC;
++ key->datasz = slen + plen;
++ sbuf = key->data;
++ pbuf = key->data + slen;
++
++ ec = br_ec_get_default();
++ if (br_ec_keygen(&prng, ec, &key->ec.sk, sbuf, BR_EC_secp384r1) == 0) {
++ warnx("br_ec_keygen");
+ goto err;
+ }
+- if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
+- warnx("EVP_PKEY_keygen");
++ if (br_ec_compute_pub(ec, &key->ec.pk, pbuf, &key->ec.sk) == 0) {
++ warnx("br_ec_compute_pub");
+ goto err;
+ }
+
+- /* Serialise the key to the disc. */
++ /* Serialise the key to the disk in EC format */
+
+- if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
+- warnx("%s: PEM_write_PrivateKey", fname);
++ if ((derlen = br_encode_ec_raw_der(NULL, &key->ec.sk,
++ &key->ec.pk)) == 0) {
++ warnx("br_encode_ec_raw_der");
++ goto err;
++ }
++ if ((der = malloc(derlen)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ br_encode_ec_raw_der(der, &key->ec.sk, &key->ec.pk);
++ pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
++ if ((pem = malloc(pemlen + 1)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
++ if (fwrite(pem, 1, pemlen, f) != pemlen) {
++ warn("write private key");
+ goto err;
+ }
+
+- EVP_PKEY_CTX_free(ctx);
+- return pkey;
++ free(der);
++ free(pem);
++ return key;
+
+ err:
+- EVP_PKEY_free(pkey);
+- EVP_PKEY_CTX_free(ctx);
++ free(der);
++ free(pem);
++ free(key);
+ return NULL;
+ }
+
+-EVP_PKEY *
++static void
++append_skey(void *ctx, const void *src, size_t len)
++{
++ br_skey_decoder_push(ctx, src, len);
++}
++
++struct key *
+ key_load(FILE *f, const char *fname)
+ {
+- EVP_PKEY *pkey;
++ struct key *key = NULL;
++ size_t datasz, len = 0, n;
++ int type = 0, err;
++ unsigned char buf[8192], *pos;
++ br_pem_decoder_context pemctx;
++ br_skey_decoder_context keyctx;
++ br_rsa_compute_modulus compute_modulus;
++ br_rsa_compute_pubexp compute_pubexp;
++ const br_ec_impl *ecimpl;
++ const br_rsa_private_key *rsa;
++ const br_ec_private_key *ec;
++ const char *name = NULL;
++ uint32_t pubexp;
+
+- pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
+- if (pkey == NULL) {
+- warnx("%s: PEM_read_PrivateKey", fname);
+- return NULL;
++ br_pem_decoder_init(&pemctx);
++ br_skey_decoder_init(&keyctx);
++ while (type == 0) {
++ if (len == 0) {
++ if (feof(f)) {
++ warnx("%s: missing private key", fname);
++ break;
++ }
++ len = fread(buf, 1, sizeof(buf), f);
++ if (ferror(f)) {
++ warn("%s: read", fname);
++ goto err;
++ }
++ pos = buf;
++ }
++ n = br_pem_decoder_push(&pemctx, pos, len);
++ pos += n;
++ len -= n;
++ switch (br_pem_decoder_event(&pemctx)) {
++ case BR_PEM_BEGIN_OBJ:
++ name = br_pem_decoder_name(&pemctx);
++ if (strcmp(name, BR_ENCODE_PEM_PKCS8) != 0 &&
++ strcmp(name, BR_ENCODE_PEM_RSA_RAW) != 0 &&
++ strcmp(name, BR_ENCODE_PEM_EC_RAW) != 0) {
++ name = NULL;
++ break;
++ }
++ br_pem_decoder_setdest(&pemctx, append_skey, &keyctx);
++ break;
++ case BR_PEM_END_OBJ:
++ if (name == NULL)
++ break;
++ if ((err = br_skey_decoder_last_error(&keyctx)) != 0) {
++ warnx("%s: br_skey_decoder: %d", fname, err);
++ goto err;
++ }
++ type = br_skey_decoder_key_type(&keyctx);
++ break;
++ case 0:
++ break;
++ default:
++ warnx("%s: PEM decoding failed", fname);
++ goto err;
++ }
+ }
+- if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA ||
+- EVP_PKEY_base_id(pkey) == EVP_PKEY_EC)
+- return pkey;
+
+- warnx("%s: unsupported key type", fname);
+- EVP_PKEY_free(pkey);
+- return NULL;
++ switch (type) {
++ case BR_KEYTYPE_RSA:
++ rsa = br_skey_decoder_get_rsa(&keyctx);
++ compute_modulus = br_rsa_compute_modulus_get_default();
++ compute_pubexp = br_rsa_compute_pubexp_get_default();
++
++ /* Compute public modulus size. This will fail if
++ * p or q is not 3 mod 4. */
++ if ((datasz = compute_modulus(NULL, rsa)) == 0) {
++ warnx("%s: br_rsa_compute_modulus", fname);
++ goto err;
++ }
++ datasz += 4 + rsa->plen + rsa->qlen + rsa->dplen + rsa->dqlen +
++ rsa->iqlen;
++
++ if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ key->type = BR_KEYTYPE_RSA;
++ key->datasz = datasz;
++
++ if ((pubexp = compute_pubexp(rsa)) == 0) {
++ warnx("%s: br_rsa_compute_pubexp", fname);
++ goto err;
++ }
++
++ /* Copy private key. */
++ key->rsa.sk.n_bitlen = rsa->n_bitlen;
++ key->rsa.sk.p = key->data;
++ key->rsa.sk.plen = rsa->plen;
++ key->rsa.sk.q = key->rsa.sk.p + rsa->plen;
++ key->rsa.sk.qlen = rsa->qlen;
++ key->rsa.sk.dp = key->rsa.sk.q + rsa->qlen;
++ key->rsa.sk.dplen = rsa->dplen;
++ key->rsa.sk.dq = key->rsa.sk.dp + rsa->dplen;
++ key->rsa.sk.dqlen = rsa->dqlen;
++ key->rsa.sk.iq = key->rsa.sk.dq + rsa->dqlen;
++ key->rsa.sk.iqlen = rsa->iqlen;
++ memcpy(key->rsa.sk.p, rsa->p, rsa->plen);
++ memcpy(key->rsa.sk.q, rsa->q, rsa->qlen);
++ memcpy(key->rsa.sk.dp, rsa->dp, rsa->dplen);
++ memcpy(key->rsa.sk.dq, rsa->dq, rsa->dqlen);
++ memcpy(key->rsa.sk.iq, rsa->iq, rsa->iqlen);
++
++ /* Compute public modulus and encode public exponent. */
++ key->rsa.pk.n = key->rsa.sk.iq + rsa->iqlen;
++ key->rsa.pk.nlen = compute_modulus(key->rsa.pk.n, rsa);
++ key->rsa.pk.elen = 4;
++ key->rsa.pk.e = key->rsa.pk.n + key->rsa.pk.nlen;
++ key->rsa.pk.e[0] = pubexp >> 24;
++ key->rsa.pk.e[1] = pubexp >> 16;
++ key->rsa.pk.e[2] = pubexp >> 8;
++ key->rsa.pk.e[3] = pubexp;
++
++ /* Trim leading zeros. */
++ while (key->rsa.pk.elen > 0 && key->rsa.pk.e[0] == 0) {
++ --key->rsa.pk.elen;
++ ++key->rsa.pk.e;
++ }
++ goto out;
++ case BR_KEYTYPE_EC:
++ ec = br_skey_decoder_get_ec(&keyctx);
++ ecimpl = br_ec_get_default();
++ if ((datasz = br_ec_compute_pub(ecimpl, NULL, NULL, ec)) == 0) {
++ warnx("%s: br_ec_compute_pub", fname);
++ goto err;
++ }
++ datasz += ec->xlen;
++
++ if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
++ warn("malloc");
++ goto err;
++ }
++ key->type = BR_KEYTYPE_EC;
++ key->datasz = datasz;
++
++ key->ec.sk.curve = ec->curve;
++ key->ec.sk.x = key->data;
++ key->ec.sk.xlen = ec->xlen;
++ memcpy(key->ec.sk.x, ec->x, ec->xlen);
++ br_ec_compute_pub(ecimpl, &key->ec.pk,
++ key->ec.sk.x + key->ec.sk.xlen, &key->ec.sk);
++ goto out;
++ }
++
++ warnx("%s: missing private key", fname);
++
++err:
++ free(key);
++ key = NULL;
++out:
++ explicit_bzero(&pemctx, sizeof(pemctx));
++ explicit_bzero(&keyctx, sizeof(keyctx));
++ return key;
+ }
+diff --git a/usr.sbin/acme-client/key.h b/usr.sbin/acme-client/key.h
+index 272d36eb09a..12abdec813c 100644
+--- a/usr.sbin/acme-client/key.h
++++ b/usr.sbin/acme-client/key.h
+@@ -18,8 +18,24 @@
+ #ifndef KEY_H
+ #define KEY_H
+
+-EVP_PKEY *rsa_key_create(FILE *, const char *);
+-EVP_PKEY *ec_key_create(FILE *, const char *);
+-EVP_PKEY *key_load(FILE *, const char *);
++struct key {
++ int type;
++ union {
++ struct {
++ br_rsa_public_key pk;
++ br_rsa_private_key sk;
++ } rsa;
++ struct {
++ br_ec_public_key pk;
++ br_ec_private_key sk;
++ } ec;
++ };
++ size_t datasz;
++ unsigned char data[];
++};
++
++struct key *rsa_key_create(FILE *, const char *);
++struct key *ec_key_create(FILE *, const char *);
++struct key *key_load(FILE *, const char *);
+
+ #endif /* ! KEY_H */
+diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
+index f0df9f292d4..fc7de74b616 100644
+--- a/usr.sbin/acme-client/keyproc.c
++++ b/usr.sbin/acme-client/keyproc.c
+@@ -18,55 +18,18 @@
+ #include <sys/stat.h>
+
+ #include <err.h>
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+
+-#include <openssl/pem.h>
+-#include <openssl/err.h>
+-#include <openssl/rand.h>
+-#include <openssl/x509.h>
+-#include <openssl/x509v3.h>
++#include <bearssl.h>
++#include <x509cert.h>
+
+ #include "extern.h"
+ #include "key.h"
+
+-/*
+- * This was lifted more or less directly from demos/x509/mkreq.c of the
+- * OpenSSL source code.
+- */
+-static int
+-add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
+-{
+- X509_EXTENSION *ex;
+- char *cp;
+-
+- /*
+- * XXX: I don't like this at all.
+- * There's no documentation for X509V3_EXT_conf_nid, so I'm not
+- * sure if the "value" parameter is ever written to, touched,
+- * etc.
+- * The 'official' examples suggest not (they use a string
+- * literal as the input), but to be safe, I'm doing an
+- * allocation here and just letting it go.
+- * This leaks memory, but bounded to the number of SANs.
+- */
+-
+- if ((cp = strdup(value)) == NULL) {
+- warn("strdup");
+- return (0);
+- }
+- ex = X509V3_EXT_conf_nid(NULL, NULL, nid, cp);
+- if (ex == NULL) {
+- warnx("X509V3_EXT_conf_nid");
+- free(cp);
+- return (0);
+- }
+- sk_X509_EXTENSION_push(sk, ex);
+- return (1);
+-}
+-
+ /*
+ * Create an X509 certificate from the private key we have on file.
+ * To do this, we first open the key file, then jail ourselves.
+@@ -77,18 +40,20 @@ int
+ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+ enum keytype keytype)
+ {
+- char *der64 = NULL;
+- unsigned char *der = NULL, *dercp;
+- char *sans = NULL, *san = NULL;
+- FILE *f;
+- size_t i, sansz;
+- void *pp;
+- EVP_PKEY *pkey = NULL;
+- X509_REQ *x = NULL;
+- X509_NAME *name = NULL;
+- int len, rc = 0, cc, nid, newkey = 0;
+- mode_t prev;
+- STACK_OF(X509_EXTENSION) *exts = NULL;
++ char *der64 = NULL;
++ unsigned char *der = NULL;
++ FILE *f;
++ size_t i;
++ struct key *pkey = NULL;
++ struct x509cert_req req;
++ struct x509cert_skey skey;
++ struct x509cert_dn dn;
++ struct x509cert_rdn rdn;
++ struct x509cert_item item;
++ int len, rc = 0, newkey = 0;
++ mode_t prev;
++
++ req.alts = NULL;
+
+ /*
+ * First, open our private key file read-only or write-only if
+@@ -110,8 +75,6 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+
+ /* File-system, user, and sandbox jail. */
+
+- ERR_load_crypto_strings();
+-
+ if (pledge("stdio", NULL) == -1) {
+ warn("pledge");
+ goto out;
+@@ -145,102 +108,61 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+ * Then set it as the X509 requester's key.
+ */
+
+- if ((x = X509_REQ_new()) == NULL) {
+- warnx("X509_REQ_new");
+- goto out;
+- } else if (!X509_REQ_set_version(x, 0)) {
+- warnx("X509_REQ_set_version");
+- goto out;
+- } else if (!X509_REQ_set_pubkey(x, pkey)) {
+- warnx("X509_REQ_set_pubkey");
+- goto out;
++ req.pkey.key_type = pkey->type;
++ skey.type = pkey->type;
++ switch (pkey->type) {
++ case BR_KEYTYPE_RSA:
++ req.pkey.key.rsa = pkey->rsa.pk;
++ skey.u.rsa = &pkey->rsa.sk;
++ break;
++ case BR_KEYTYPE_EC:
++ req.pkey.key.ec = pkey->ec.pk;
++ skey.u.ec = &pkey->ec.sk;
++ break;
+ }
+
+ /* Now specify the common name that we'll request. */
+
+- if ((name = X509_NAME_new()) == NULL) {
+- warnx("X509_NAME_new");
+- goto out;
+- } else if (!X509_NAME_add_entry_by_txt(name, "CN",
+- MBSTRING_ASC, (u_char *)alts[0], -1, -1, 0)) {
+- warnx("X509_NAME_add_entry_by_txt: CN=%s", alts[0]);
+- goto out;
+- } else if (!X509_REQ_set_subject_name(x, name)) {
+- warnx("X509_req_set_issuer_name");
+- goto out;
+- }
++ rdn.oid = x509cert_oid_CN;
++ rdn.val.tag = X509CERT_ASN1_UTF8STRING;
++ rdn.val.val = alts[0];
++ rdn.val.len = strlen(alts[0]);
++ rdn.val.enc = NULL;
++ dn.rdn = &rdn;
++ dn.rdn_len = 1;
++ req.subject.enc = x509cert_dn_encoder;
++ req.subject.val = &dn;
+
+- /*
+- * Now add the SAN extensions.
+- * This was lifted more or less directly from demos/x509/mkreq.c
+- * of the OpenSSL source code.
+- * (The zeroth altname is the domain name.)
+- * TODO: is this the best way of doing this?
+- */
++ /* Now add the SAN extension. */
+
+- nid = NID_subject_alt_name;
+- if ((exts = sk_X509_EXTENSION_new_null()) == NULL) {
+- warnx("sk_X509_EXTENSION_new_null");
++ req.alts_len = altsz;
++ req.alts = calloc(altsz, sizeof(req.alts[0]));
++ if (req.alts == NULL) {
++ warn("calloc");
+ goto out;
+ }
+- /* Initialise to empty string. */
+- if ((sans = strdup("")) == NULL) {
+- warn("strdup");
+- goto out;
+- }
+- sansz = strlen(sans) + 1;
+
+- /*
+- * For each SAN entry, append it to the string.
+- * We need a single SAN entry for all of the SAN
+- * domains: NOT an entry per domain!
+- */
++ /* Add a dNSName SAN entry for each alternate name. */
+
+ for (i = 0; i < altsz; i++) {
+- cc = asprintf(&san, "%sDNS:%s",
+- i ? "," : "", alts[i]);
+- if (cc == -1) {
+- warn("asprintf");
+- goto out;
+- }
+- pp = recallocarray(sans, sansz, sansz + strlen(san), 1);
+- if (pp == NULL) {
+- warn("recallocarray");
+- goto out;
+- }
+- sans = pp;
+- sansz += strlen(san);
+- strlcat(sans, san, sansz);
+- free(san);
+- san = NULL;
+- }
+-
+- if (!add_ext(exts, nid, sans)) {
+- warnx("add_ext");
+- goto out;
+- } else if (!X509_REQ_add_extensions(x, exts)) {
+- warnx("X509_REQ_add_extensions");
+- goto out;
+- }
+- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+-
+- /* Sign the X509 request using SHA256. */
+-
+- if (!X509_REQ_sign(x, pkey, EVP_sha256())) {
+- warnx("X509_sign");
+- goto out;
++ req.alts[i].tag = X509CERT_SAN_DNSNAME;
++ req.alts[i].val = alts[i];
++ req.alts[i].len = strlen(alts[i]);
+ }
+
+- /* Now, serialise to DER, then base64. */
++ /* Sign the X.509 request using SHA256, and serialise to
++ * DER then base64. */
+
+- if ((len = i2d_X509_REQ(x, NULL)) < 0) {
+- warnx("i2d_X509_REQ");
++ item.enc = x509cert_req_encoder;
++ item.val = &req;
++ if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, NULL)) == 0) {
++ warnx("x509cert_sign");
+ goto out;
+- } else if ((der = dercp = malloc(len)) == NULL) {
++ } else if ((der = malloc(len)) == NULL) {
+ warn("malloc");
+ goto out;
+- } else if (len != i2d_X509_REQ(x, &dercp)) {
+- warnx("i2d_X509_REQ");
++ } else if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, der)) == 0) {
++ warnx("x509cert_sign");
+ goto out;
+ } else if ((der64 = base64buf_url(der, len)) == NULL) {
+ warnx("base64buf_url");
+@@ -265,12 +187,8 @@ out:
+ fclose(f);
+ free(der);
+ free(der64);
+- free(sans);
+- free(san);
+- X509_REQ_free(x);
+- X509_NAME_free(name);
+- EVP_PKEY_free(pkey);
+- ERR_print_errors_fp(stderr);
+- ERR_free_strings();
++ free(req.alts);
++ if (pkey != NULL)
++ freezero(pkey, pkey->datasz);
+ return rc;
+ }
+diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
+index 58e81233f1a..378de35f662 100644
+--- a/usr.sbin/acme-client/revokeproc.c
++++ b/usr.sbin/acme-client/revokeproc.c
+@@ -22,58 +22,54 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <time.h>
+ #include <unistd.h>
+ #include <vis.h>
+
+-#include <openssl/pem.h>
+-#include <openssl/x509.h>
+-#include <openssl/x509v3.h>
+-#include <openssl/err.h>
++#include <bearssl.h>
+
+ #include "extern.h"
+
+ #define RENEW_ALLOW (30 * 24 * 60 * 60)
+
+-/*
+- * Convert the X509's expiration time into a time_t value.
+- */
+-static time_t
+-X509expires(X509 *x)
++static void
++append_cert(void *ctx, const void *buf, size_t len)
+ {
+- ASN1_TIME *atim;
+- struct tm t;
+-
+- if ((atim = X509_getm_notAfter(x)) == NULL) {
+- warnx("missing notAfter");
+- return -1;
+- }
+-
+- memset(&t, 0, sizeof(t));
+-
+- if (!ASN1_TIME_to_tm(atim, &t)) {
+- warnx("invalid ASN1_TIME");
+- return -1;
++ br_x509_certificate *cert = ctx;
++ size_t newlen;
++ unsigned char *newdata;
++
++ if (cert->data_len == -1)
++ return;
++ newlen = cert->data_len + len;
++ if ((newdata = realloc(cert->data, newlen)) != NULL) {
++ memcpy(newdata + cert->data_len, buf, len);
++ cert->data = newdata;
++ cert->data_len = newlen;
++ } else {
++ warn("realloc");
++ cert->data_len = -1;
+ }
+-
+- return timegm(&t);
+ }
+
+ int
+ revokeproc(int fd, const char *certfile, int force,
+ int revocate, const char *const *alts, size_t altsz)
+ {
+- GENERAL_NAMES *sans = NULL;
+- unsigned char *der = NULL, *dercp;
+- char *der64 = NULL;
+- char *san = NULL, *str, *tok;
+- int rc = 0, cc, i, len;
+- size_t *found = NULL;
++ static const unsigned char dnsname[] = {0, 2};
++ char buf[8192], *pos, *sans = NULL, *der64 = NULL;
++ int rc = 0, cc, state, err;
++ size_t i, j, n, len = 0, altlen, altmax, eltsz;
+ FILE *f = NULL;
+- X509 *x = NULL;
++ br_pem_decoder_context pc;
++ br_x509_decoder_context xd;
++ br_x509_minimal_context xc;
++ br_x509_certificate cert = {0};
++ br_name_element *elts = NULL;
++ uint32_t days, secs;
+ long lval;
+ enum revokeop op, rop;
+ time_t t;
+- size_t j;
+
+ /*
+ * First try to open the certificate before we drop privileges
+@@ -88,8 +84,6 @@ revokeproc(int fd, const char *certfile, int force,
+
+ /* File-system and sandbox jailing. */
+
+- ERR_load_crypto_strings();
+-
+ if (pledge("stdio", NULL) == -1) {
+ warn("pledge");
+ goto out;
+@@ -113,39 +107,86 @@ revokeproc(int fd, const char *certfile, int force,
+ goto out;
+ }
+
+- if ((x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
+- warnx("PEM_read_X509");
+- goto out;
++ br_pem_decoder_init(&pc);
++ for (state = 0; state != 2;) {
++ if (len == 0) {
++ if (feof(f)) {
++ warnx("%s: truncated certificate", certfile);
++ goto out;
++ }
++ len = fread(buf, 1, sizeof(buf), f);
++ if (ferror(f)) {
++ warn("fread");
++ goto out;
++ }
++ pos = buf;
++ }
++ n = br_pem_decoder_push(&pc, pos, len);
++ pos += n;
++ len -= n;
++ switch (br_pem_decoder_event(&pc)) {
++ case BR_PEM_BEGIN_OBJ:
++ if (strcmp(br_pem_decoder_name(&pc), "CERTIFICATE") == 0) {
++ br_pem_decoder_setdest(&pc, append_cert, &cert);
++ state = 1;
++ }
++ break;
++ case BR_PEM_END_OBJ:
++ if (state == 1)
++ state = 2;
++ break;
++ case 0:
++ break;
++ default:
++ warnx("%s: PEM decoding error", certfile);
++ goto out;
++ }
+ }
+-
+- /* Cache and sanity check X509v3 extensions. */
+-
+- if (X509_check_purpose(x, -1, -1) <= 0) {
+- warnx("%s: invalid X509v3 extensions", certfile);
++ if (cert.data_len == -1)
+ goto out;
+- }
+
+ /* Read out the expiration date. */
+
+- if ((t = X509expires(x)) == -1) {
+- warnx("X509expires");
++ br_x509_decoder_init(&xd, NULL, NULL);
++ br_x509_decoder_push(&xd, cert.data, cert.data_len);
++ if ((err = br_x509_decoder_last_error(&xd)) != 0) {
++ warnx("%s: X.509 decoding error %d", certfile, err);
+ goto out;
+ }
++ br_x509_decoder_get_notafter(&xd, &days, &secs);
++ t = 86400ll * (days - 719528) + 86400;
+
+- /* Extract list of SAN entries from the certificate. */
+-
+- sans = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+- if (sans == NULL) {
+- warnx("%s: does not have a SAN entry", certfile);
+- if (revocate)
+- goto out;
+- force = 2;
++ for (i = 0, altmax = 0; i < altsz; ++i) {
++ altlen = strlen(alts[i]) + 1;
++ if (altlen > altmax)
++ altmax = altlen;
++ }
++ eltsz = altsz + 1;
++ if ((elts = calloc(eltsz, sizeof(elts[0]))) == NULL ||
++ (sans = calloc(eltsz, altmax)) == NULL) {
++ warn("calloc");
++ goto out;
++ }
++ for (i = 0; i < eltsz; ++i) {
++ elts[i].oid = dnsname;
++ elts[i].buf = sans + i * altmax;
++ elts[i].len = altmax;
+ }
+
+- /* An array of buckets: the number of entries found. */
++ /* Extract list of SAN entries from the certificate. */
+
+- if ((found = calloc(altsz, sizeof(size_t))) == NULL) {
+- warn("calloc");
++ br_x509_minimal_init(&xc, &br_sha256_vtable, NULL, 0);
++ br_x509_minimal_set_hash(&xc, br_sha256_ID, &br_sha256_vtable);
++ br_x509_minimal_set_hash(&xc, br_sha384_ID, &br_sha384_vtable);
++ br_x509_minimal_set_hash(&xc, br_sha512_ID, &br_sha512_vtable);
++ br_x509_minimal_set_name_elements(&xc, elts, eltsz);
++ xc.vtable->start_chain(&xc.vtable, NULL);
++ xc.vtable->start_cert(&xc.vtable, cert.data_len);
++ xc.vtable->append(&xc.vtable, cert.data, cert.data_len);
++ xc.vtable->end_cert(&xc.vtable);
++ err = xc.vtable->end_chain(&xc.vtable);
++ if (err != BR_ERR_X509_NOT_TRUSTED && err != BR_ERR_X509_EXPIRED) {
++ warnx("%s: X.509 engine error %d", certfile, err);
+ goto out;
+ }
+
+@@ -154,63 +195,37 @@ revokeproc(int fd, const char *certfile, int force,
+ * configuration file and that all domains are represented only once.
+ */
+
+- for (i = 0; i < sk_GENERAL_NAME_num(sans); i++) {
+- GENERAL_NAME *gen_name;
+- const ASN1_IA5STRING *name;
+- const unsigned char *name_buf;
+- int name_len;
+- int name_type;
+-
+- gen_name = sk_GENERAL_NAME_value(sans, i);
+- assert(gen_name != NULL);
+-
+- name = GENERAL_NAME_get0_value(gen_name, &name_type);
+- if (name_type != GEN_DNS)
+- continue;
+-
+- /* name_buf isn't a C string and could contain embedded NULs. */
+- name_buf = ASN1_STRING_get0_data(name);
+- name_len = ASN1_STRING_length(name);
+-
+- for (j = 0; j < altsz; j++) {
+- if ((size_t)name_len != strlen(alts[j]))
+- continue;
+- if (memcmp(name_buf, alts[j], name_len) == 0)
++ for (i = 0; i < altsz; i++) {
++ for (j = 0; j < eltsz; j++) {
++ if (elts[j].status == 1 &&
++ strcmp(alts[i], elts[j].buf) == 0) {
++ elts[j].status = 0;
+ break;
+- }
+- if (j == altsz) {
+- if (revocate) {
+- char *visbuf;
+-
+- visbuf = calloc(4, name_len + 1);
+- if (visbuf == NULL) {
+- warn("%s: unexpected SAN", certfile);
+- goto out;
+- }
+- strvisx(visbuf, name_buf, name_len, VIS_SAFE);
+- warnx("%s: unexpected SAN entry: %s",
+- certfile, visbuf);
+- free(visbuf);
+- goto out;
+ }
+- force = 2;
+- continue;
+ }
+- if (found[j]++) {
++ if (j == eltsz) {
+ if (revocate) {
+- warnx("%s: duplicate SAN entry: %.*s",
+- certfile, name_len, name_buf);
++ warnx("%s: domain not listed: %s", certfile, alts[i]);
+ goto out;
+ }
+ force = 2;
+ }
+ }
+
+- for (j = 0; j < altsz; j++) {
+- if (found[j])
++ for (i = 0; i < eltsz; i++) {
++ if (elts[i].status == 0)
+ continue;
+ if (revocate) {
+- warnx("%s: domain not listed: %s", certfile, alts[j]);
++ char *visbuf;
++
++ if (elts[i].status != 1 ||
++ stravis(&visbuf, elts[i].buf, VIS_SAFE) < 0) {
++ warnx("%s: unexpected SAN", certfile);
++ goto out;
++ }
++ warnx("%s: unexpected SAN entry: %s",
++ certfile, visbuf);
++ free(visbuf);
+ goto out;
+ }
+ force = 2;
+@@ -236,16 +251,7 @@ revokeproc(int fd, const char *certfile, int force,
+ if (cc <= 0)
+ goto out;
+
+- if ((len = i2d_X509(x, NULL)) < 0) {
+- warnx("i2d_X509");
+- goto out;
+- } else if ((der = dercp = malloc(len)) == NULL) {
+- warn("malloc");
+- goto out;
+- } else if (len != i2d_X509(x, &dercp)) {
+- warnx("i2d_X509");
+- goto out;
+- } else if ((der64 = base64buf_url(der, len)) == NULL) {
++ if ((der64 = base64buf_url(cert.data, cert.data_len)) == NULL) {
+ warnx("base64buf_url");
+ goto out;
+ } else if (writestr(fd, COMM_CSR, der64) >= 0)
+@@ -298,12 +304,9 @@ out:
+ close(fd);
+ if (f != NULL)
+ fclose(f);
+- X509_free(x);
+- GENERAL_NAMES_free(sans);
+- free(der);
+- free(found);
++ free(cert.data);
++ free(sans);
++ free(elts);
+ free(der64);
+- ERR_print_errors_fp(stderr);
+- ERR_free_strings();
+ return rc;
+ }
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0036-acme-client-Port-to-BearSSL.patch b/pkg/openbsd/patch/0036-acme-client-Port-to-BearSSL.patch
@@ -1,1550 +0,0 @@
-From f34464dc0940837a48e071392a84455df2138c0b Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Fri, 23 Apr 2021 23:14:16 -0700
-Subject: [PATCH] acme-client: Port to BearSSL
-
----
- usr.sbin/acme-client/acctproc.c | 299 +++++++++------------------
- usr.sbin/acme-client/certproc.c | 5 -
- usr.sbin/acme-client/key.c | 333 ++++++++++++++++++++++++------
- usr.sbin/acme-client/key.h | 22 +-
- usr.sbin/acme-client/keyproc.c | 198 ++++++------------
- usr.sbin/acme-client/revokeproc.c | 237 ++++++++++-----------
- 6 files changed, 560 insertions(+), 534 deletions(-)
-
-diff --git a/usr.sbin/acme-client/acctproc.c b/usr.sbin/acme-client/acctproc.c
-index 23d8a1c3a33..3d3e32c1a57 100644
---- a/usr.sbin/acme-client/acctproc.c
-+++ b/usr.sbin/acme-client/acctproc.c
-@@ -19,74 +19,29 @@
-
- #include <err.h>
- #include <errno.h>
--#include <limits.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-
--#include <openssl/bn.h>
--#include <openssl/ec.h>
--#include <openssl/ecdsa.h>
--#include <openssl/evp.h>
--#include <openssl/rsa.h>
--#include <openssl/err.h>
-+#include <bearssl.h>
-
- #include "extern.h"
- #include "key.h"
-
--/*
-- * Converts a BIGNUM to the form used in JWK.
-- * This is essentially a base64-encoded big-endian binary string
-- * representation of the number.
-- */
--static char *
--bn2string(const BIGNUM *bn)
--{
-- int len;
-- unsigned char *buf;
-- char *bbuf;
--
-- /* Extract big-endian representation of BIGNUM. */
--
-- len = BN_num_bytes(bn);
-- if ((buf = malloc(len)) == NULL) {
-- warn("malloc");
-- return NULL;
-- } else if (len != BN_bn2bin(bn, buf)) {
-- warnx("BN_bn2bin");
-- free(buf);
-- return NULL;
-- }
--
-- /* Convert to base64url. */
--
-- if ((bbuf = base64buf_url(buf, len)) == NULL) {
-- warnx("base64buf_url");
-- free(buf);
-- return NULL;
-- }
--
-- free(buf);
-- return bbuf;
--}
--
- /*
- * Extract the relevant RSA components from the key and create the JSON
- * thumbprint from them.
- */
- static char *
--op_thumb_rsa(EVP_PKEY *pkey)
-+op_thumb_rsa(struct key *key)
- {
- char *exp = NULL, *mod = NULL, *json = NULL;
-- RSA *r;
--
-- if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
-- warnx("EVP_PKEY_get0_RSA");
-- else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
-- warnx("bn2string");
-- else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
-- warnx("bn2string");
-+
-+ if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
-+ warnx("base64buf_url");
-+ else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
-+ warnx("base64buf_url");
- else if ((json = json_fmt_thumb_rsa(exp, mod)) == NULL)
- warnx("json_fmt_thumb_rsa");
-
-@@ -100,31 +55,23 @@ op_thumb_rsa(EVP_PKEY *pkey)
- * thumbprint from them.
- */
- static char *
--op_thumb_ec(EVP_PKEY *pkey)
-+op_thumb_ec(struct key *key)
- {
-- BIGNUM *X = NULL, *Y = NULL;
-- EC_KEY *ec = NULL;
-+ size_t len;
- char *x = NULL, *y = NULL;
- char *json = NULL;
-
-- if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
-- warnx("EVP_PKEY_get0_EC_KEY");
-- else if ((X = BN_new()) == NULL)
-- warnx("BN_new");
-- else if ((Y = BN_new()) == NULL)
-- warnx("BN_new");
-- else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
-- EC_KEY_get0_public_key(ec), X, Y, NULL))
-- warnx("EC_POINT_get_affine_coordinates");
-- else if ((x = bn2string(X)) == NULL)
-- warnx("bn2string");
-- else if ((y = bn2string(Y)) == NULL)
-- warnx("bn2string");
-+ /* Points are stored in uncompressed format. */
-+ len = key->ec.pk.qlen / 2;
-+ if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
-+ warnx("invalid EC public key");
-+ else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
-+ warnx("base64buf_url");
-+ else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
-+ warnx("base64buf_url");
- else if ((json = json_fmt_thumb_ec(x, y)) == NULL)
- warnx("json_fmt_thumb_ec");
-
-- BN_free(X);
-- BN_free(Y);
- free(x);
- free(y);
- return json;
-@@ -134,26 +81,26 @@ op_thumb_ec(EVP_PKEY *pkey)
- * The thumbprint operation is used for the challenge sequence.
- */
- static int
--op_thumbprint(int fd, EVP_PKEY *pkey)
-+op_thumbprint(int fd, struct key *pkey)
- {
-- char *thumb = NULL, *dig64 = NULL;
-- unsigned char dig[EVP_MAX_MD_SIZE];
-- unsigned int digsz;
-- int rc = 0;
-+ char *thumb = NULL, *dig64 = NULL;
-+ br_sha256_context ctx;
-+ unsigned char dig[br_sha256_SIZE];
-+ int rc = 0;
-
- /* Construct the thumbprint input itself. */
-
-- switch (EVP_PKEY_base_id(pkey)) {
-- case EVP_PKEY_RSA:
-+ switch (pkey->type) {
-+ case BR_KEYTYPE_RSA:
- if ((thumb = op_thumb_rsa(pkey)) != NULL)
- break;
- goto out;
-- case EVP_PKEY_EC:
-+ case BR_KEYTYPE_EC:
- if ((thumb = op_thumb_ec(pkey)) != NULL)
- break;
- goto out;
- default:
-- warnx("EVP_PKEY_base_id: unknown key type");
-+ warnx("unknown key type");
- goto out;
- }
-
-@@ -164,12 +111,10 @@ op_thumbprint(int fd, EVP_PKEY *pkey)
- * it up in the read loop).
- */
-
-- if (!EVP_Digest(thumb, strlen(thumb), dig, &digsz, EVP_sha256(),
-- NULL)) {
-- warnx("EVP_Digest");
-- goto out;
-- }
-- if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
-+ br_sha256_init(&ctx);
-+ br_sha256_update(&ctx, thumb, strlen(thumb));
-+ br_sha256_out(&ctx, dig);
-+ if ((dig64 = base64buf_url(dig, sizeof(dig))) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-@@ -184,11 +129,10 @@ out:
- }
-
- static int
--op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
-+op_sign_rsa(char **prot, struct key *key, const char *nonce, const char *url)
- {
- char *exp = NULL, *mod = NULL;
- int rc = 0;
-- RSA *r;
-
- *prot = NULL;
-
-@@ -197,12 +141,10 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
- * Finally, format the header combined with the nonce.
- */
-
-- if ((r = EVP_PKEY_get0_RSA(pkey)) == NULL)
-- warnx("EVP_PKEY_get0_RSA");
-- else if ((mod = bn2string(RSA_get0_n(r))) == NULL)
-- warnx("bn2string");
-- else if ((exp = bn2string(RSA_get0_e(r))) == NULL)
-- warnx("bn2string");
-+ if ((mod = base64buf_url(key->rsa.pk.n, key->rsa.pk.nlen)) == NULL)
-+ warnx("base64buf_url");
-+ else if ((exp = base64buf_url(key->rsa.pk.e, key->rsa.pk.elen)) == NULL)
-+ warnx("base64buf_url");
- else if ((*prot = json_fmt_protected_rsa(exp, mod, nonce, url)) == NULL)
- warnx("json_fmt_protected_rsa");
- else
-@@ -214,35 +156,27 @@ op_sign_rsa(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
- }
-
- static int
--op_sign_ec(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
-+op_sign_ec(char **prot, struct key *key, const char *nonce, const char *url)
- {
-- BIGNUM *X = NULL, *Y = NULL;
-- EC_KEY *ec = NULL;
-+ size_t len;
- char *x = NULL, *y = NULL;
- int rc = 0;
-
- *prot = NULL;
-
-- if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
-- warnx("EVP_PKEY_get0_EC_KEY");
-- else if ((X = BN_new()) == NULL)
-- warnx("BN_new");
-- else if ((Y = BN_new()) == NULL)
-- warnx("BN_new");
-- else if (!EC_POINT_get_affine_coordinates(EC_KEY_get0_group(ec),
-- EC_KEY_get0_public_key(ec), X, Y, NULL))
-- warnx("EC_POINT_get_affine_coordinates");
-- else if ((x = bn2string(X)) == NULL)
-- warnx("bn2string");
-- else if ((y = bn2string(Y)) == NULL)
-- warnx("bn2string");
-+ /* Points are stored in uncompressed format. */
-+ len = key->ec.pk.qlen / 2;
-+ if (key->ec.pk.qlen % 2 != 1 || key->ec.pk.q[0] != 0x04)
-+ warnx("invalid EC public key");
-+ else if ((x = base64buf_url(key->ec.pk.q + 1, len)) == NULL)
-+ warnx("base64buf_url");
-+ else if ((y = base64buf_url(key->ec.pk.q + 1 + len, len)) == NULL)
-+ warnx("base64buf_url");
- else if ((*prot = json_fmt_protected_ec(x, y, nonce, url)) == NULL)
- warnx("json_fmt_protected_ec");
- else
- rc = 1;
-
-- BN_free(X);
-- BN_free(Y);
- free(x);
- free(y);
- return rc;
-@@ -253,20 +187,18 @@ op_sign_ec(char **prot, EVP_PKEY *pkey, const char *nonce, const char *url)
- * This requires the sender ("fd") to provide the payload and a nonce.
- */
- static int
--op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-+op_sign(int fd, struct key *key, enum acctop op)
- {
-- EVP_MD_CTX *ctx = NULL;
-- const EVP_MD *evp_md = NULL;
-- ECDSA_SIG *ec_sig = NULL;
-- const BIGNUM *ec_sig_r = NULL, *ec_sig_s = NULL;
-- int bn_len, sign_len, rc = 0;
-+ br_hash_compat_context ctx;
-+ int sign_len, rc = 0;
-+ unsigned int digsz, sigsz;
- char *nonce = NULL, *pay = NULL, *pay64 = NULL;
- char *prot = NULL, *prot64 = NULL;
-- char *sign = NULL, *dig64 = NULL, *fin = NULL;
-+ char *sign = NULL, *sig64 = NULL, *fin = NULL;
- char *url = NULL, *kid = NULL, *alg = NULL;
-- const unsigned char *digp;
-- unsigned char *dig = NULL, *buf = NULL;
-- size_t digsz;
-+ unsigned char dig[64];
-+ unsigned char *sig = NULL;
-+ const unsigned char *oid = NULL;
-
- /* Read our payload and nonce from the requestor. */
-
-@@ -283,19 +215,22 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- /* Base64-encode the payload. */
-
-- if ((pay64 = base64buf_url((unsigned char *)pay, strlen(pay))) == NULL) {
-+ if ((pay64 = base64buf_url(pay, strlen(pay))) == NULL) {
- warnx("base64buf_url");
- goto out;
- }
-
-- switch (EVP_PKEY_base_id(pkey)) {
-- case EVP_PKEY_RSA:
-+ switch (key->type) {
-+ case BR_KEYTYPE_RSA:
- alg = "RS256";
-- evp_md = EVP_sha256();
-+ ctx.vtable = &br_sha256_vtable;
-+ oid = BR_HASH_OID_SHA256;
-+ sigsz = (key->rsa.sk.n_bitlen + 7) / 8;
- break;
-- case EVP_PKEY_EC:
-+ case BR_KEYTYPE_EC:
- alg = "ES384";
-- evp_md = EVP_sha384();
-+ ctx.vtable = &br_sha384_vtable;
-+ sigsz = 96;
- break;
- default:
- warnx("unknown account key type");
-@@ -309,17 +244,17 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
- goto out;
- }
- } else {
-- switch (EVP_PKEY_base_id(pkey)) {
-- case EVP_PKEY_RSA:
-- if (!op_sign_rsa(&prot, pkey, nonce, url))
-+ switch (key->type) {
-+ case BR_KEYTYPE_RSA:
-+ if (!op_sign_rsa(&prot, key, nonce, url))
- goto out;
- break;
-- case EVP_PKEY_EC:
-- if (!op_sign_ec(&prot, pkey, nonce, url))
-+ case BR_KEYTYPE_EC:
-+ if (!op_sign_ec(&prot, key, nonce, url))
- goto out;
- break;
- default:
-- warnx("EVP_PKEY_base_id");
-+ warnx("unknown key type");
- goto out;
- }
- }
-@@ -342,76 +277,34 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- /* Sign the message. */
-
-- if ((ctx = EVP_MD_CTX_new()) == NULL) {
-- warnx("EVP_MD_CTX_new");
-- goto out;
-- }
-- if (!EVP_DigestSignInit(ctx, NULL, evp_md, NULL, pkey)) {
-- warnx("EVP_DigestSignInit");
-- goto out;
-- }
-- if (!EVP_DigestSign(ctx, NULL, &digsz, sign, sign_len)) {
-- warnx("EVP_DigestSign");
-- goto out;
-- }
-- if ((dig = malloc(digsz)) == NULL) {
-+ ctx.vtable->init(&ctx.vtable);
-+ ctx.vtable->update(&ctx.vtable, sign, sign_len);
-+ ctx.vtable->out(&ctx.vtable, dig);
-+ digsz = ctx.vtable->desc >> BR_HASHDESC_OUT_OFF & BR_HASHDESC_OUT_MASK;
-+
-+ if ((sig = malloc(sigsz)) == NULL) {
- warn("malloc");
- goto out;
- }
-- if (!EVP_DigestSign(ctx, dig, &digsz, sign, sign_len)) {
-- warnx("EVP_DigestSign");
-- goto out;
-- }
-
-- switch (EVP_PKEY_base_id(pkey)) {
-- case EVP_PKEY_RSA:
-- if ((dig64 = base64buf_url(dig, digsz)) == NULL) {
-- warnx("base64buf_url");
-+ switch (key->type) {
-+ case BR_KEYTYPE_RSA:
-+ if (!br_rsa_pkcs1_sign_get_default()(oid, dig, digsz,
-+ &key->rsa.sk, sig)) {
-+ warnx("br_rsa_pkcs1_sign");
- goto out;
- }
- break;
-- case EVP_PKEY_EC:
-- if (digsz > LONG_MAX) {
-- warnx("EC signature too long");
-- goto out;
-- }
--
-- digp = dig;
-- if ((ec_sig = d2i_ECDSA_SIG(NULL, &digp, digsz)) == NULL) {
-- warnx("d2i_ECDSA_SIG");
-+ case BR_KEYTYPE_EC:
-+ sigsz = br_ecdsa_sign_raw_get_default()(br_ec_get_default(),
-+ ctx.vtable, dig, &key->ec.sk, sig);
-+ if (sigsz == 0 || sigsz % 2 != 0) {
-+ warnx("br_ecdsa_sign_raw");
- goto out;
- }
--
-- if ((ec_sig_r = ECDSA_SIG_get0_r(ec_sig)) == NULL ||
-- (ec_sig_s = ECDSA_SIG_get0_s(ec_sig)) == NULL) {
-- warnx("ECDSA_SIG_get0");
-- goto out;
-- }
--
-- if ((bn_len = (EVP_PKEY_bits(pkey) + 7) / 8) <= 0) {
-- warnx("EVP_PKEY_bits");
-- goto out;
-- }
--
-- if ((buf = calloc(2, bn_len)) == NULL) {
-- warnx("calloc");
-- goto out;
-- }
--
-- if (BN_bn2binpad(ec_sig_r, buf, bn_len) != bn_len ||
-- BN_bn2binpad(ec_sig_s, buf + bn_len, bn_len) != bn_len) {
-- warnx("BN_bn2binpad");
-- goto out;
-- }
--
-- if ((dig64 = base64buf_url(buf, 2 * bn_len)) == NULL) {
-- warnx("base64buf_url");
-- goto out;
-- }
--
- break;
- default:
-- warnx("EVP_PKEY_base_id");
-+ warnx("unknown key type");
- goto out;
- }
-
-@@ -421,7 +314,11 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
- * when we next enter the read loop).
- */
-
-- if ((fin = json_fmt_signed(prot64, pay64, dig64)) == NULL) {
-+ if ((sig64 = base64buf_url(sig, sigsz)) == NULL) {
-+ warnx("base64buf_url");
-+ goto out;
-+ }
-+ if ((fin = json_fmt_signed(prot64, pay64, sig64)) == NULL) {
- warnx("json_fmt_signed");
- goto out;
- } else if (writestr(fd, COMM_REQ, fin) < 0)
-@@ -429,8 +326,6 @@ op_sign(int fd, EVP_PKEY *pkey, enum acctop op)
-
- rc = 1;
- out:
-- ECDSA_SIG_free(ec_sig);
-- EVP_MD_CTX_free(ctx);
- free(pay);
- free(sign);
- free(pay64);
-@@ -439,10 +334,9 @@ out:
- free(kid);
- free(prot);
- free(prot64);
-- free(dig);
-- free(dig64);
-+ free(sig);
-+ free(sig64);
- free(fin);
-- free(buf);
- return rc;
- }
-
-@@ -450,7 +344,7 @@ int
- acctproc(int netsock, const char *acctkey, enum keytype keytype)
- {
- FILE *f = NULL;
-- EVP_PKEY *pkey = NULL;
-+ struct key *pkey = NULL;
- long lval;
- enum acctop op;
- int rc = 0, cc, newacct = 0;
-@@ -476,8 +370,6 @@ acctproc(int netsock, const char *acctkey, enum keytype keytype)
-
- /* File-system, user, and sandbox jailing. */
-
-- ERR_load_crypto_strings();
--
- if (pledge("stdio", NULL) == -1) {
- warn("pledge");
- goto out;
-@@ -555,8 +447,7 @@ out:
- close(netsock);
- if (f != NULL)
- fclose(f);
-- EVP_PKEY_free(pkey);
-- ERR_print_errors_fp(stderr);
-- ERR_free_strings();
-+ if (pkey != NULL)
-+ freezero(pkey, sizeof(*pkey) + pkey->datasz);
- return rc;
- }
-diff --git a/usr.sbin/acme-client/certproc.c b/usr.sbin/acme-client/certproc.c
-index f443d573675..85c3897a4b8 100644
---- a/usr.sbin/acme-client/certproc.c
-+++ b/usr.sbin/acme-client/certproc.c
-@@ -21,11 +21,6 @@
- #include <string.h>
- #include <unistd.h>
-
--#include <openssl/pem.h>
--#include <openssl/x509.h>
--#include <openssl/x509v3.h>
--#include <openssl/err.h>
--
- #include "extern.h"
-
- #define BEGIN_MARKER "-----BEGIN CERTIFICATE-----"
-diff --git a/usr.sbin/acme-client/key.c b/usr.sbin/acme-client/key.c
-index a6fc437f863..c0e54b15742 100644
---- a/usr.sbin/acme-client/key.c
-+++ b/usr.sbin/acme-client/key.c
-@@ -17,15 +17,11 @@
- */
-
- #include <err.h>
-+#include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
-
--#include <openssl/evp.h>
--#include <openssl/pem.h>
--#include <openssl/rsa.h>
--#include <openssl/ecdsa.h>
--#include <openssl/ec.h>
--#include <openssl/obj_mac.h>
-+#include <bearssl.h>
-
- #include "key.h"
-
-@@ -34,111 +30,318 @@
- */
- #define KBITS 4096
-
-+static void
-+prng_init(const br_prng_class **ctx, const void *params, const void *seed, size_t len)
-+{
-+}
-+
-+static void
-+prng_generate(const br_prng_class **ctx, void *out, size_t len)
-+{
-+ arc4random_buf(out, len);
-+}
-+
-+static void
-+prng_update(const br_prng_class **ctx, const void *seed, size_t len)
-+{
-+}
-+
-+static const br_prng_class prng_class = {
-+ 0, prng_init, prng_generate, prng_update
-+}, *prng = &prng_class;
-+
- /*
- * Create an RSA key with the default KBITS number of bits.
- */
--EVP_PKEY *
-+struct key *
- rsa_key_create(FILE *f, const char *fname)
- {
-- EVP_PKEY_CTX *ctx = NULL;
-- EVP_PKEY *pkey = NULL;
-+ struct key *key = NULL;
-+ size_t slen, plen;
-+ unsigned char *sbuf, *pbuf;
-+ unsigned char d[KBITS / 8];
-+ unsigned char *der = NULL, *pem = NULL;
-+ size_t derlen, pemlen;
-
-- /* First, create the context and the key. */
-+ /* First, allocate and generate the key. */
-
-- if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
-- warnx("EVP_PKEY_CTX_new_id");
-- goto err;
-- } else if (EVP_PKEY_keygen_init(ctx) <= 0) {
-- warnx("EVP_PKEY_keygen_init");
-+ slen = BR_RSA_KBUF_PRIV_SIZE(KBITS);
-+ plen = BR_RSA_KBUF_PUB_SIZE(KBITS);
-+ if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
-+ warnx("malloc");
- goto err;
-- } else if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) {
-- warnx("EVP_PKEY_set_rsa_keygen_bits");
-+ }
-+ key->type = BR_KEYTYPE_RSA;
-+ key->datasz = slen + plen;
-+ sbuf = key->data;
-+ pbuf = key->data + slen;
-+ if (!br_rsa_keygen_get_default()(&prng, &key->rsa.sk, sbuf,
-+ &key->rsa.pk, pbuf, KBITS, 0x10001)) {
-+ warnx("br_rsa_keygen");
- goto err;
-- } else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
-- warnx("EVP_PKEY_keygen");
-+ }
-+
-+ /* Compute the private exponent. */
-+
-+ if (!br_rsa_compute_privexp_get_default()(d, &key->rsa.sk, 0x10001)) {
-+ warnx("br_rsa_compute_modulus");
- goto err;
- }
-
-- /* Serialise the key to the disc. */
-+ /* Serialise the key to the disk. */
-
-- if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL))
-+ derlen = br_encode_rsa_raw_der(NULL, &key->rsa.sk, &key->rsa.pk,
-+ d, sizeof(d));
-+ if ((der = malloc(derlen)) == NULL) {
-+ warn("malloc");
-+ goto err;
-+ }
-+ br_encode_rsa_raw_der(der, &key->rsa.sk, &key->rsa.pk, d, sizeof(d));
-+ pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
-+ if ((pem = malloc(pemlen + 1)) == NULL) {
-+ warn("malloc");
-+ goto err;
-+ }
-+ br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_RSA_RAW, 0);
-+ if (fwrite(pem, 1, pemlen, f) == pemlen)
- goto out;
-
-- warnx("%s: PEM_write_PrivateKey", fname);
-+ warn("write private key");
-
- err:
-- EVP_PKEY_free(pkey);
-- pkey = NULL;
-+ free(key);
-+ key = NULL;
- out:
-- EVP_PKEY_CTX_free(ctx);
-- return pkey;
-+ free(der);
-+ free(pem);
-+ return key;
- }
-
--EVP_PKEY *
-+struct key *
- ec_key_create(FILE *f, const char *fname)
- {
-- EC_KEY *eckey = NULL;
-- EVP_PKEY *pkey = NULL;
-+ struct key *key = NULL;
-+ const br_ec_impl *ec;
-+ size_t slen, plen;
-+ unsigned char *sbuf, *pbuf;
-+ unsigned char *der = NULL, *pem = NULL;
-+ size_t derlen, pemlen;
-
-- if ((eckey = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL ) {
-- warnx("EC_KEY_new_by_curve_name");
-+ slen = BR_EC_KBUF_PRIV_MAX_SIZE;
-+ plen = BR_EC_KBUF_PUB_MAX_SIZE;
-+ if ((key = malloc(sizeof(*key) + slen + plen)) == NULL) {
-+ warn("malloc");
- goto err;
- }
-+ key->type = BR_KEYTYPE_EC;
-+ key->datasz = slen + plen;
-+ sbuf = key->data;
-+ pbuf = key->data + slen;
-
-- if (!EC_KEY_generate_key(eckey)) {
-- warnx("EC_KEY_generate_key");
-+ ec = br_ec_get_default();
-+ if (br_ec_keygen(&prng, ec, &key->ec.sk, sbuf, BR_EC_secp384r1) == 0) {
-+ warnx("br_ec_keygen");
- goto err;
- }
--
-- /* set OPENSSL_EC_NAMED_CURVE to be able to load the key */
--
-- EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
--
-- /* Serialise the key to the disc in EC format */
--
-- if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) {
-- warnx("%s: PEM_write_ECPrivateKey", fname);
-+ if (br_ec_compute_pub(ec, &key->ec.pk, pbuf, &key->ec.sk) == 0) {
-+ warnx("br_ec_compute_pub");
- goto err;
- }
-
-- /* Convert the EC key into a PKEY structure */
-+ /* Serialise the key to the disk in EC format */
-
-- if ((pkey = EVP_PKEY_new()) == NULL) {
-- warnx("EVP_PKEY_new");
-+ if ((derlen = br_encode_ec_raw_der(NULL, &key->ec.sk,
-+ &key->ec.pk)) == 0) {
-+ warnx("br_encode_ec_raw_der");
-+ goto err;
-+ }
-+ if ((der = malloc(derlen)) == NULL) {
-+ warn("malloc");
- goto err;
- }
-- if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
-- warnx("EVP_PKEY_assign_EC_KEY");
-+ br_encode_ec_raw_der(der, &key->ec.sk, &key->ec.pk);
-+ pemlen = br_pem_encode(NULL, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
-+ if ((pem = malloc(pemlen + 1)) == NULL) {
-+ warn("malloc");
- goto err;
- }
-+ br_pem_encode(pem, der, derlen, BR_ENCODE_PEM_EC_RAW, 0);
-+ if (fwrite(pem, 1, pemlen, f) == pemlen)
-+ goto out;
-
-- goto out;
-+ warn("write private key");
-
- err:
-- EVP_PKEY_free(pkey);
-- pkey = NULL;
-+ free(key);
-+ key = NULL;
- out:
-- EC_KEY_free(eckey);
-- return pkey;
-+ free(der);
-+ free(pem);
-+ return key;
- }
-
-+static void
-+append_skey(void *ctx, const void *src, size_t len)
-+{
-+ br_skey_decoder_push(ctx, src, len);
-+}
-
--
--EVP_PKEY *
-+struct key *
- key_load(FILE *f, const char *fname)
- {
-- EVP_PKEY *pkey;
-+ struct key *key = NULL;
-+ size_t datasz, len = 0, n;
-+ int type = 0, err;
-+ unsigned char buf[8192], *pos;
-+ br_pem_decoder_context pemctx;
-+ br_skey_decoder_context keyctx;
-+ br_rsa_compute_modulus compute_modulus;
-+ br_rsa_compute_pubexp compute_pubexp;
-+ const br_ec_impl *ecimpl;
-+ const br_rsa_private_key *rsa;
-+ const br_ec_private_key *ec;
-+ const char *name = NULL;
-+ uint32_t pubexp;
-+
-+ br_pem_decoder_init(&pemctx);
-+ br_skey_decoder_init(&keyctx);
-+ while (type == 0) {
-+ if (len == 0) {
-+ if (feof(f)) {
-+ warnx("%s: missing private key", fname);
-+ break;
-+ }
-+ len = fread(buf, 1, sizeof(buf), f);
-+ if (ferror(f)) {
-+ warn("%s: read", fname);
-+ goto err;
-+ }
-+ pos = buf;
-+ }
-+ n = br_pem_decoder_push(&pemctx, pos, len);
-+ pos += n;
-+ len -= n;
-+ switch (br_pem_decoder_event(&pemctx)) {
-+ case BR_PEM_BEGIN_OBJ:
-+ name = br_pem_decoder_name(&pemctx);
-+ if (strcmp(name, BR_ENCODE_PEM_PKCS8) != 0 &&
-+ strcmp(name, BR_ENCODE_PEM_RSA_RAW) != 0 &&
-+ strcmp(name, BR_ENCODE_PEM_EC_RAW) != 0) {
-+ name = NULL;
-+ break;
-+ }
-+ br_pem_decoder_setdest(&pemctx, append_skey, &keyctx);
-+ break;
-+ case BR_PEM_END_OBJ:
-+ if (name == NULL)
-+ break;
-+ if ((err = br_skey_decoder_last_error(&keyctx)) != 0) {
-+ warnx("%s: br_skey_decoder: %d", fname, err);
-+ goto err;
-+ }
-+ type = br_skey_decoder_key_type(&keyctx);
-+ break;
-+ case 0:
-+ break;
-+ default:
-+ warnx("%s: PEM decoding failed", fname);
-+ goto err;
-+ }
-+ }
-+
-+ switch (type) {
-+ case BR_KEYTYPE_RSA:
-+ rsa = br_skey_decoder_get_rsa(&keyctx);
-+ compute_modulus = br_rsa_compute_modulus_get_default();
-+ compute_pubexp = br_rsa_compute_pubexp_get_default();
-+
-+ /* Compute public modulus size. This will fail if
-+ * p or q is not 3 mod 4. */
-+ if ((datasz = compute_modulus(NULL, rsa)) == 0) {
-+ warnx("%s: br_rsa_compute_modulus", fname);
-+ goto err;
-+ }
-+ datasz += 4 + rsa->plen + rsa->qlen + rsa->dplen + rsa->dqlen +
-+ rsa->iqlen;
-
-- pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
-- if (pkey == NULL) {
-- warnx("%s: PEM_read_PrivateKey", fname);
-- return NULL;
-+ if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
-+ warn("malloc");
-+ goto err;
-+ }
-+ key->type = BR_KEYTYPE_RSA;
-+ key->datasz = datasz;
-+
-+ if ((pubexp = compute_pubexp(rsa)) == 0) {
-+ warnx("%s: br_rsa_compute_pubexp", fname);
-+ goto err;
-+ }
-+
-+ /* Copy private key. */
-+ key->rsa.sk.n_bitlen = rsa->n_bitlen;
-+ key->rsa.sk.p = key->data;
-+ key->rsa.sk.plen = rsa->plen;
-+ key->rsa.sk.q = key->rsa.sk.p + rsa->plen;
-+ key->rsa.sk.qlen = rsa->qlen;
-+ key->rsa.sk.dp = key->rsa.sk.q + rsa->qlen;
-+ key->rsa.sk.dplen = rsa->dplen;
-+ key->rsa.sk.dq = key->rsa.sk.dp + rsa->dplen;
-+ key->rsa.sk.dqlen = rsa->dqlen;
-+ key->rsa.sk.iq = key->rsa.sk.dq + rsa->dqlen;
-+ key->rsa.sk.iqlen = rsa->iqlen;
-+ memcpy(key->rsa.sk.p, rsa->p, rsa->plen);
-+ memcpy(key->rsa.sk.q, rsa->q, rsa->qlen);
-+ memcpy(key->rsa.sk.dp, rsa->dp, rsa->dplen);
-+ memcpy(key->rsa.sk.dq, rsa->dq, rsa->dqlen);
-+ memcpy(key->rsa.sk.iq, rsa->iq, rsa->iqlen);
-+
-+ /* Compute public modulus and encode public exponent. */
-+ key->rsa.pk.n = key->rsa.sk.iq + rsa->iqlen;
-+ key->rsa.pk.nlen = compute_modulus(key->rsa.pk.n, rsa);
-+ key->rsa.pk.elen = 4;
-+ key->rsa.pk.e = key->rsa.pk.n + key->rsa.pk.nlen;
-+ key->rsa.pk.e[0] = pubexp >> 24;
-+ key->rsa.pk.e[1] = pubexp >> 16;
-+ key->rsa.pk.e[2] = pubexp >> 8;
-+ key->rsa.pk.e[3] = pubexp;
-+
-+ /* Trim leading zeros. */
-+ while (key->rsa.pk.elen > 0 && key->rsa.pk.e[0] == 0) {
-+ --key->rsa.pk.elen;
-+ ++key->rsa.pk.e;
-+ }
-+ goto out;
-+ case BR_KEYTYPE_EC:
-+ ec = br_skey_decoder_get_ec(&keyctx);
-+ ecimpl = br_ec_get_default();
-+ if ((datasz = br_ec_compute_pub(ecimpl, NULL, NULL, ec)) == 0) {
-+ warnx("%s: br_ec_compute_pub", fname);
-+ goto err;
-+ }
-+ datasz += ec->xlen;
-+
-+ if ((key = malloc(sizeof(*key) + datasz)) == NULL) {
-+ warn("malloc");
-+ goto err;
-+ }
-+ key->type = BR_KEYTYPE_EC;
-+ key->datasz = datasz;
-+
-+ key->ec.sk.curve = ec->curve;
-+ key->ec.sk.x = key->data;
-+ key->ec.sk.xlen = ec->xlen;
-+ memcpy(key->ec.sk.x, ec->x, ec->xlen);
-+ br_ec_compute_pub(ecimpl, &key->ec.pk,
-+ key->ec.sk.x + key->ec.sk.xlen, &key->ec.sk);
-+ goto out;
- }
-- if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA ||
-- EVP_PKEY_base_id(pkey) == EVP_PKEY_EC)
-- return pkey;
-
-- warnx("%s: unsupported key type", fname);
-- EVP_PKEY_free(pkey);
-- return NULL;
-+ warnx("%s: missing private key", fname);
-+
-+err:
-+ free(key);
-+ key = NULL;
-+out:
-+ explicit_bzero(&pemctx, sizeof(pemctx));
-+ explicit_bzero(&keyctx, sizeof(keyctx));
-+ return key;
- }
-diff --git a/usr.sbin/acme-client/key.h b/usr.sbin/acme-client/key.h
-index 272d36eb09a..12abdec813c 100644
---- a/usr.sbin/acme-client/key.h
-+++ b/usr.sbin/acme-client/key.h
-@@ -18,8 +18,24 @@
- #ifndef KEY_H
- #define KEY_H
-
--EVP_PKEY *rsa_key_create(FILE *, const char *);
--EVP_PKEY *ec_key_create(FILE *, const char *);
--EVP_PKEY *key_load(FILE *, const char *);
-+struct key {
-+ int type;
-+ union {
-+ struct {
-+ br_rsa_public_key pk;
-+ br_rsa_private_key sk;
-+ } rsa;
-+ struct {
-+ br_ec_public_key pk;
-+ br_ec_private_key sk;
-+ } ec;
-+ };
-+ size_t datasz;
-+ unsigned char data[];
-+};
-+
-+struct key *rsa_key_create(FILE *, const char *);
-+struct key *ec_key_create(FILE *, const char *);
-+struct key *key_load(FILE *, const char *);
-
- #endif /* ! KEY_H */
-diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
-index f0df9f292d4..fc7de74b616 100644
---- a/usr.sbin/acme-client/keyproc.c
-+++ b/usr.sbin/acme-client/keyproc.c
-@@ -18,55 +18,18 @@
- #include <sys/stat.h>
-
- #include <err.h>
-+#include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
-
--#include <openssl/pem.h>
--#include <openssl/err.h>
--#include <openssl/rand.h>
--#include <openssl/x509.h>
--#include <openssl/x509v3.h>
-+#include <bearssl.h>
-+#include <x509cert.h>
-
- #include "extern.h"
- #include "key.h"
-
--/*
-- * This was lifted more or less directly from demos/x509/mkreq.c of the
-- * OpenSSL source code.
-- */
--static int
--add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
--{
-- X509_EXTENSION *ex;
-- char *cp;
--
-- /*
-- * XXX: I don't like this at all.
-- * There's no documentation for X509V3_EXT_conf_nid, so I'm not
-- * sure if the "value" parameter is ever written to, touched,
-- * etc.
-- * The 'official' examples suggest not (they use a string
-- * literal as the input), but to be safe, I'm doing an
-- * allocation here and just letting it go.
-- * This leaks memory, but bounded to the number of SANs.
-- */
--
-- if ((cp = strdup(value)) == NULL) {
-- warn("strdup");
-- return (0);
-- }
-- ex = X509V3_EXT_conf_nid(NULL, NULL, nid, cp);
-- if (ex == NULL) {
-- warnx("X509V3_EXT_conf_nid");
-- free(cp);
-- return (0);
-- }
-- sk_X509_EXTENSION_push(sk, ex);
-- return (1);
--}
--
- /*
- * Create an X509 certificate from the private key we have on file.
- * To do this, we first open the key file, then jail ourselves.
-@@ -77,18 +40,20 @@ int
- keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
- enum keytype keytype)
- {
-- char *der64 = NULL;
-- unsigned char *der = NULL, *dercp;
-- char *sans = NULL, *san = NULL;
-- FILE *f;
-- size_t i, sansz;
-- void *pp;
-- EVP_PKEY *pkey = NULL;
-- X509_REQ *x = NULL;
-- X509_NAME *name = NULL;
-- int len, rc = 0, cc, nid, newkey = 0;
-- mode_t prev;
-- STACK_OF(X509_EXTENSION) *exts = NULL;
-+ char *der64 = NULL;
-+ unsigned char *der = NULL;
-+ FILE *f;
-+ size_t i;
-+ struct key *pkey = NULL;
-+ struct x509cert_req req;
-+ struct x509cert_skey skey;
-+ struct x509cert_dn dn;
-+ struct x509cert_rdn rdn;
-+ struct x509cert_item item;
-+ int len, rc = 0, newkey = 0;
-+ mode_t prev;
-+
-+ req.alts = NULL;
-
- /*
- * First, open our private key file read-only or write-only if
-@@ -110,8 +75,6 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
-
- /* File-system, user, and sandbox jail. */
-
-- ERR_load_crypto_strings();
--
- if (pledge("stdio", NULL) == -1) {
- warn("pledge");
- goto out;
-@@ -145,102 +108,61 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
- * Then set it as the X509 requester's key.
- */
-
-- if ((x = X509_REQ_new()) == NULL) {
-- warnx("X509_REQ_new");
-- goto out;
-- } else if (!X509_REQ_set_version(x, 0)) {
-- warnx("X509_REQ_set_version");
-- goto out;
-- } else if (!X509_REQ_set_pubkey(x, pkey)) {
-- warnx("X509_REQ_set_pubkey");
-- goto out;
-+ req.pkey.key_type = pkey->type;
-+ skey.type = pkey->type;
-+ switch (pkey->type) {
-+ case BR_KEYTYPE_RSA:
-+ req.pkey.key.rsa = pkey->rsa.pk;
-+ skey.u.rsa = &pkey->rsa.sk;
-+ break;
-+ case BR_KEYTYPE_EC:
-+ req.pkey.key.ec = pkey->ec.pk;
-+ skey.u.ec = &pkey->ec.sk;
-+ break;
- }
-
- /* Now specify the common name that we'll request. */
-
-- if ((name = X509_NAME_new()) == NULL) {
-- warnx("X509_NAME_new");
-- goto out;
-- } else if (!X509_NAME_add_entry_by_txt(name, "CN",
-- MBSTRING_ASC, (u_char *)alts[0], -1, -1, 0)) {
-- warnx("X509_NAME_add_entry_by_txt: CN=%s", alts[0]);
-- goto out;
-- } else if (!X509_REQ_set_subject_name(x, name)) {
-- warnx("X509_req_set_issuer_name");
-- goto out;
-- }
-+ rdn.oid = x509cert_oid_CN;
-+ rdn.val.tag = X509CERT_ASN1_UTF8STRING;
-+ rdn.val.val = alts[0];
-+ rdn.val.len = strlen(alts[0]);
-+ rdn.val.enc = NULL;
-+ dn.rdn = &rdn;
-+ dn.rdn_len = 1;
-+ req.subject.enc = x509cert_dn_encoder;
-+ req.subject.val = &dn;
-
-- /*
-- * Now add the SAN extensions.
-- * This was lifted more or less directly from demos/x509/mkreq.c
-- * of the OpenSSL source code.
-- * (The zeroth altname is the domain name.)
-- * TODO: is this the best way of doing this?
-- */
-+ /* Now add the SAN extension. */
-
-- nid = NID_subject_alt_name;
-- if ((exts = sk_X509_EXTENSION_new_null()) == NULL) {
-- warnx("sk_X509_EXTENSION_new_null");
-+ req.alts_len = altsz;
-+ req.alts = calloc(altsz, sizeof(req.alts[0]));
-+ if (req.alts == NULL) {
-+ warn("calloc");
- goto out;
- }
-- /* Initialise to empty string. */
-- if ((sans = strdup("")) == NULL) {
-- warn("strdup");
-- goto out;
-- }
-- sansz = strlen(sans) + 1;
-
-- /*
-- * For each SAN entry, append it to the string.
-- * We need a single SAN entry for all of the SAN
-- * domains: NOT an entry per domain!
-- */
-+ /* Add a dNSName SAN entry for each alternate name. */
-
- for (i = 0; i < altsz; i++) {
-- cc = asprintf(&san, "%sDNS:%s",
-- i ? "," : "", alts[i]);
-- if (cc == -1) {
-- warn("asprintf");
-- goto out;
-- }
-- pp = recallocarray(sans, sansz, sansz + strlen(san), 1);
-- if (pp == NULL) {
-- warn("recallocarray");
-- goto out;
-- }
-- sans = pp;
-- sansz += strlen(san);
-- strlcat(sans, san, sansz);
-- free(san);
-- san = NULL;
-- }
--
-- if (!add_ext(exts, nid, sans)) {
-- warnx("add_ext");
-- goto out;
-- } else if (!X509_REQ_add_extensions(x, exts)) {
-- warnx("X509_REQ_add_extensions");
-- goto out;
-- }
-- sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
--
-- /* Sign the X509 request using SHA256. */
--
-- if (!X509_REQ_sign(x, pkey, EVP_sha256())) {
-- warnx("X509_sign");
-- goto out;
-+ req.alts[i].tag = X509CERT_SAN_DNSNAME;
-+ req.alts[i].val = alts[i];
-+ req.alts[i].len = strlen(alts[i]);
- }
-
-- /* Now, serialise to DER, then base64. */
-+ /* Sign the X.509 request using SHA256, and serialise to
-+ * DER then base64. */
-
-- if ((len = i2d_X509_REQ(x, NULL)) < 0) {
-- warnx("i2d_X509_REQ");
-+ item.enc = x509cert_req_encoder;
-+ item.val = &req;
-+ if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, NULL)) == 0) {
-+ warnx("x509cert_sign");
- goto out;
-- } else if ((der = dercp = malloc(len)) == NULL) {
-+ } else if ((der = malloc(len)) == NULL) {
- warn("malloc");
- goto out;
-- } else if (len != i2d_X509_REQ(x, &dercp)) {
-- warnx("i2d_X509_REQ");
-+ } else if ((len = x509cert_sign(&item, &skey, &br_sha256_vtable, der)) == 0) {
-+ warnx("x509cert_sign");
- goto out;
- } else if ((der64 = base64buf_url(der, len)) == NULL) {
- warnx("base64buf_url");
-@@ -265,12 +187,8 @@ out:
- fclose(f);
- free(der);
- free(der64);
-- free(sans);
-- free(san);
-- X509_REQ_free(x);
-- X509_NAME_free(name);
-- EVP_PKEY_free(pkey);
-- ERR_print_errors_fp(stderr);
-- ERR_free_strings();
-+ free(req.alts);
-+ if (pkey != NULL)
-+ freezero(pkey, pkey->datasz);
- return rc;
- }
-diff --git a/usr.sbin/acme-client/revokeproc.c b/usr.sbin/acme-client/revokeproc.c
-index 58e81233f1a..378de35f662 100644
---- a/usr.sbin/acme-client/revokeproc.c
-+++ b/usr.sbin/acme-client/revokeproc.c
-@@ -22,58 +22,54 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-+#include <time.h>
- #include <unistd.h>
- #include <vis.h>
-
--#include <openssl/pem.h>
--#include <openssl/x509.h>
--#include <openssl/x509v3.h>
--#include <openssl/err.h>
-+#include <bearssl.h>
-
- #include "extern.h"
-
- #define RENEW_ALLOW (30 * 24 * 60 * 60)
-
--/*
-- * Convert the X509's expiration time into a time_t value.
-- */
--static time_t
--X509expires(X509 *x)
-+static void
-+append_cert(void *ctx, const void *buf, size_t len)
- {
-- ASN1_TIME *atim;
-- struct tm t;
--
-- if ((atim = X509_getm_notAfter(x)) == NULL) {
-- warnx("missing notAfter");
-- return -1;
-- }
--
-- memset(&t, 0, sizeof(t));
--
-- if (!ASN1_TIME_to_tm(atim, &t)) {
-- warnx("invalid ASN1_TIME");
-- return -1;
-+ br_x509_certificate *cert = ctx;
-+ size_t newlen;
-+ unsigned char *newdata;
-+
-+ if (cert->data_len == -1)
-+ return;
-+ newlen = cert->data_len + len;
-+ if ((newdata = realloc(cert->data, newlen)) != NULL) {
-+ memcpy(newdata + cert->data_len, buf, len);
-+ cert->data = newdata;
-+ cert->data_len = newlen;
-+ } else {
-+ warn("realloc");
-+ cert->data_len = -1;
- }
--
-- return timegm(&t);
- }
-
- int
- revokeproc(int fd, const char *certfile, int force,
- int revocate, const char *const *alts, size_t altsz)
- {
-- GENERAL_NAMES *sans = NULL;
-- unsigned char *der = NULL, *dercp;
-- char *der64 = NULL;
-- char *san = NULL, *str, *tok;
-- int rc = 0, cc, i, len;
-- size_t *found = NULL;
-+ static const unsigned char dnsname[] = {0, 2};
-+ char buf[8192], *pos, *sans = NULL, *der64 = NULL;
-+ int rc = 0, cc, state, err;
-+ size_t i, j, n, len = 0, altlen, altmax, eltsz;
- FILE *f = NULL;
-- X509 *x = NULL;
-+ br_pem_decoder_context pc;
-+ br_x509_decoder_context xd;
-+ br_x509_minimal_context xc;
-+ br_x509_certificate cert = {0};
-+ br_name_element *elts = NULL;
-+ uint32_t days, secs;
- long lval;
- enum revokeop op, rop;
- time_t t;
-- size_t j;
-
- /*
- * First try to open the certificate before we drop privileges
-@@ -88,8 +84,6 @@ revokeproc(int fd, const char *certfile, int force,
-
- /* File-system and sandbox jailing. */
-
-- ERR_load_crypto_strings();
--
- if (pledge("stdio", NULL) == -1) {
- warn("pledge");
- goto out;
-@@ -113,39 +107,86 @@ revokeproc(int fd, const char *certfile, int force,
- goto out;
- }
-
-- if ((x = PEM_read_X509(f, NULL, NULL, NULL)) == NULL) {
-- warnx("PEM_read_X509");
-- goto out;
-+ br_pem_decoder_init(&pc);
-+ for (state = 0; state != 2;) {
-+ if (len == 0) {
-+ if (feof(f)) {
-+ warnx("%s: truncated certificate", certfile);
-+ goto out;
-+ }
-+ len = fread(buf, 1, sizeof(buf), f);
-+ if (ferror(f)) {
-+ warn("fread");
-+ goto out;
-+ }
-+ pos = buf;
-+ }
-+ n = br_pem_decoder_push(&pc, pos, len);
-+ pos += n;
-+ len -= n;
-+ switch (br_pem_decoder_event(&pc)) {
-+ case BR_PEM_BEGIN_OBJ:
-+ if (strcmp(br_pem_decoder_name(&pc), "CERTIFICATE") == 0) {
-+ br_pem_decoder_setdest(&pc, append_cert, &cert);
-+ state = 1;
-+ }
-+ break;
-+ case BR_PEM_END_OBJ:
-+ if (state == 1)
-+ state = 2;
-+ break;
-+ case 0:
-+ break;
-+ default:
-+ warnx("%s: PEM decoding error", certfile);
-+ goto out;
-+ }
- }
--
-- /* Cache and sanity check X509v3 extensions. */
--
-- if (X509_check_purpose(x, -1, -1) <= 0) {
-- warnx("%s: invalid X509v3 extensions", certfile);
-+ if (cert.data_len == -1)
- goto out;
-- }
-
- /* Read out the expiration date. */
-
-- if ((t = X509expires(x)) == -1) {
-- warnx("X509expires");
-+ br_x509_decoder_init(&xd, NULL, NULL);
-+ br_x509_decoder_push(&xd, cert.data, cert.data_len);
-+ if ((err = br_x509_decoder_last_error(&xd)) != 0) {
-+ warnx("%s: X.509 decoding error %d", certfile, err);
- goto out;
- }
-+ br_x509_decoder_get_notafter(&xd, &days, &secs);
-+ t = 86400ll * (days - 719528) + 86400;
-
-- /* Extract list of SAN entries from the certificate. */
--
-- sans = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
-- if (sans == NULL) {
-- warnx("%s: does not have a SAN entry", certfile);
-- if (revocate)
-- goto out;
-- force = 2;
-+ for (i = 0, altmax = 0; i < altsz; ++i) {
-+ altlen = strlen(alts[i]) + 1;
-+ if (altlen > altmax)
-+ altmax = altlen;
-+ }
-+ eltsz = altsz + 1;
-+ if ((elts = calloc(eltsz, sizeof(elts[0]))) == NULL ||
-+ (sans = calloc(eltsz, altmax)) == NULL) {
-+ warn("calloc");
-+ goto out;
-+ }
-+ for (i = 0; i < eltsz; ++i) {
-+ elts[i].oid = dnsname;
-+ elts[i].buf = sans + i * altmax;
-+ elts[i].len = altmax;
- }
-
-- /* An array of buckets: the number of entries found. */
-+ /* Extract list of SAN entries from the certificate. */
-
-- if ((found = calloc(altsz, sizeof(size_t))) == NULL) {
-- warn("calloc");
-+ br_x509_minimal_init(&xc, &br_sha256_vtable, NULL, 0);
-+ br_x509_minimal_set_hash(&xc, br_sha256_ID, &br_sha256_vtable);
-+ br_x509_minimal_set_hash(&xc, br_sha384_ID, &br_sha384_vtable);
-+ br_x509_minimal_set_hash(&xc, br_sha512_ID, &br_sha512_vtable);
-+ br_x509_minimal_set_name_elements(&xc, elts, eltsz);
-+ xc.vtable->start_chain(&xc.vtable, NULL);
-+ xc.vtable->start_cert(&xc.vtable, cert.data_len);
-+ xc.vtable->append(&xc.vtable, cert.data, cert.data_len);
-+ xc.vtable->end_cert(&xc.vtable);
-+ err = xc.vtable->end_chain(&xc.vtable);
-+ if (err != BR_ERR_X509_NOT_TRUSTED && err != BR_ERR_X509_EXPIRED) {
-+ warnx("%s: X.509 engine error %d", certfile, err);
- goto out;
- }
-
-@@ -154,63 +195,37 @@ revokeproc(int fd, const char *certfile, int force,
- * configuration file and that all domains are represented only once.
- */
-
-- for (i = 0; i < sk_GENERAL_NAME_num(sans); i++) {
-- GENERAL_NAME *gen_name;
-- const ASN1_IA5STRING *name;
-- const unsigned char *name_buf;
-- int name_len;
-- int name_type;
--
-- gen_name = sk_GENERAL_NAME_value(sans, i);
-- assert(gen_name != NULL);
--
-- name = GENERAL_NAME_get0_value(gen_name, &name_type);
-- if (name_type != GEN_DNS)
-- continue;
--
-- /* name_buf isn't a C string and could contain embedded NULs. */
-- name_buf = ASN1_STRING_get0_data(name);
-- name_len = ASN1_STRING_length(name);
--
-- for (j = 0; j < altsz; j++) {
-- if ((size_t)name_len != strlen(alts[j]))
-- continue;
-- if (memcmp(name_buf, alts[j], name_len) == 0)
-+ for (i = 0; i < altsz; i++) {
-+ for (j = 0; j < eltsz; j++) {
-+ if (elts[j].status == 1 &&
-+ strcmp(alts[i], elts[j].buf) == 0) {
-+ elts[j].status = 0;
- break;
-- }
-- if (j == altsz) {
-- if (revocate) {
-- char *visbuf;
--
-- visbuf = calloc(4, name_len + 1);
-- if (visbuf == NULL) {
-- warn("%s: unexpected SAN", certfile);
-- goto out;
-- }
-- strvisx(visbuf, name_buf, name_len, VIS_SAFE);
-- warnx("%s: unexpected SAN entry: %s",
-- certfile, visbuf);
-- free(visbuf);
-- goto out;
- }
-- force = 2;
-- continue;
- }
-- if (found[j]++) {
-+ if (j == eltsz) {
- if (revocate) {
-- warnx("%s: duplicate SAN entry: %.*s",
-- certfile, name_len, name_buf);
-+ warnx("%s: domain not listed: %s", certfile, alts[i]);
- goto out;
- }
- force = 2;
- }
- }
-
-- for (j = 0; j < altsz; j++) {
-- if (found[j])
-+ for (i = 0; i < eltsz; i++) {
-+ if (elts[i].status == 0)
- continue;
- if (revocate) {
-- warnx("%s: domain not listed: %s", certfile, alts[j]);
-+ char *visbuf;
-+
-+ if (elts[i].status != 1 ||
-+ stravis(&visbuf, elts[i].buf, VIS_SAFE) < 0) {
-+ warnx("%s: unexpected SAN", certfile);
-+ goto out;
-+ }
-+ warnx("%s: unexpected SAN entry: %s",
-+ certfile, visbuf);
-+ free(visbuf);
- goto out;
- }
- force = 2;
-@@ -236,16 +251,7 @@ revokeproc(int fd, const char *certfile, int force,
- if (cc <= 0)
- goto out;
-
-- if ((len = i2d_X509(x, NULL)) < 0) {
-- warnx("i2d_X509");
-- goto out;
-- } else if ((der = dercp = malloc(len)) == NULL) {
-- warn("malloc");
-- goto out;
-- } else if (len != i2d_X509(x, &dercp)) {
-- warnx("i2d_X509");
-- goto out;
-- } else if ((der64 = base64buf_url(der, len)) == NULL) {
-+ if ((der64 = base64buf_url(cert.data, cert.data_len)) == NULL) {
- warnx("base64buf_url");
- goto out;
- } else if (writestr(fd, COMM_CSR, der64) >= 0)
-@@ -298,12 +304,9 @@ out:
- close(fd);
- if (f != NULL)
- fclose(f);
-- X509_free(x);
-- GENERAL_NAMES_free(sans);
-- free(der);
-- free(found);
-+ free(cert.data);
-+ free(sans);
-+ free(elts);
- free(der64);
-- ERR_print_errors_fp(stderr);
-- ERR_free_strings();
- return rc;
- }
---
-2.44.0
-
diff --git a/pkg/openbsd/patch/0036-rsync-Pass-long-long-to-scan_scaled.patch b/pkg/openbsd/patch/0036-rsync-Pass-long-long-to-scan_scaled.patch
@@ -0,0 +1,42 @@
+From 0b46c097e66f06fc7e5b4817e6cfdbb145bf4825 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Wed, 27 Apr 2022 20:03:45 -0700
+Subject: [PATCH] rsync: Pass long long * to scan_scaled
+
+off_t might not be long long.
+---
+ usr.bin/rsync/main.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/usr.bin/rsync/main.c b/usr.bin/rsync/main.c
+index d59848f0214..477adbbba50 100644
+--- a/usr.bin/rsync/main.c
++++ b/usr.bin/rsync/main.c
+@@ -361,6 +361,7 @@ main(int argc, char *argv[])
+ struct fargs *fargs;
+ char **args;
+ const char *errstr;
++ long long size;
+
+ /* Global pledge. */
+
+@@ -509,12 +510,14 @@ basedir:
+ opts.basedir[basedir_cnt++] = optarg;
+ break;
+ case OP_MAX_SIZE:
+- if (scan_scaled(optarg, &opts.max_size) == -1)
++ if (scan_scaled(optarg, &size) == -1)
+ err(1, "bad max-size");
++ opts.max_size = size;
+ break;
+ case OP_MIN_SIZE:
+- if (scan_scaled(optarg, &opts.min_size) == -1)
++ if (scan_scaled(optarg, &size) == -1)
+ err(1, "bad min-size");
++ opts.max_size = size;
+ break;
+ case 'h':
+ default:
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0039-libutil-Include-util.h-instead-of-util.h.patch b/pkg/openbsd/patch/0037-libutil-Include-util.h-instead-of-util.h.patch
diff --git a/pkg/openbsd/patch/0037-pax-Use-POSIX-struct-stat-fields-for-high-resolution.patch b/pkg/openbsd/patch/0037-pax-Use-POSIX-struct-stat-fields-for-high-resolution.patch
@@ -1,46 +0,0 @@
-From 82646d38665109ec5f0753ba384da94d529bbbe9 Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Wed, 27 Apr 2022 19:57:54 -0700
-Subject: [PATCH] pax: Use POSIX struct stat fields for high resolution
- timestamps
-
----
- bin/pax/tar.c | 15 +++++----------
- 1 file changed, 5 insertions(+), 10 deletions(-)
-
-diff --git a/bin/pax/tar.c b/bin/pax/tar.c
-index 1f4012123c3..7ede7938c3d 100644
---- a/bin/pax/tar.c
-+++ b/bin/pax/tar.c
-@@ -417,8 +417,7 @@ tar_rd(ARCHD *arcn, char *buf)
- arcn->sb.st_mtime = INT_MAX; /* XXX 2038 */
- else
- arcn->sb.st_mtime = val;
-- arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
-- arcn->sb.st_ctimensec = arcn->sb.st_atimensec = arcn->sb.st_mtimensec;
-+ arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim;
-
- /*
- * have to look at the last character, it may be a '/' and that is used
-@@ -795,14 +794,10 @@ reset:
- else
- arcn->sb.st_mtime = val;
- }
-- if (arcn->sb.st_ctime == 0) {
-- arcn->sb.st_ctime = arcn->sb.st_mtime;
-- arcn->sb.st_ctimensec = arcn->sb.st_mtimensec;
-- }
-- if (arcn->sb.st_atime == 0) {
-- arcn->sb.st_atime = arcn->sb.st_mtime;
-- arcn->sb.st_atimensec = arcn->sb.st_mtimensec;
-- }
-+ if (arcn->sb.st_ctime == 0)
-+ arcn->sb.st_ctim = arcn->sb.st_mtim;
-+ if (arcn->sb.st_atime == 0)
-+ arcn->sb.st_atim = arcn->sb.st_mtim;
-
- /*
- * If we can find the ascii names for gname and uname in the password
---
-2.35.1
-
diff --git a/pkg/openbsd/patch/0038-nc-Add-option-to-disable-certificate-time-checking.patch b/pkg/openbsd/patch/0038-nc-Add-option-to-disable-certificate-time-checking.patch
@@ -0,0 +1,59 @@
+From 5e993fe93c590d60b05948e22b51dfc34c3eac4b Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Thu, 20 May 2021 13:44:35 -0700
+Subject: [PATCH] nc: Add option to disable certificate time checking
+
+---
+ usr.bin/nc/nc.1 | 2 ++
+ usr.bin/nc/netcat.c | 8 ++++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1
+index 76b6dc018ea..9e13b84acf7 100644
+--- a/usr.bin/nc/nc.1
++++ b/usr.bin/nc/nc.1
+@@ -249,6 +249,8 @@ may be one of:
+ which disables certificate verification;
+ .Cm noname ,
+ which disables certificate name checking;
++.Cm notime ,
++which disables certificate validity time checking;
+ .Cm clientcert ,
+ which requires a client certificate on incoming connections; or
+ .Cm muststaple ,
+diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
+index b5129c2204d..d1ed530eb2c 100644
+--- a/usr.bin/nc/netcat.c
++++ b/usr.bin/nc/netcat.c
+@@ -70,8 +70,9 @@
+
+ #define TLS_NOVERIFY (1 << 1)
+ #define TLS_NONAME (1 << 2)
+-#define TLS_CCERT (1 << 3)
+-#define TLS_MUSTSTAPLE (1 << 4)
++#define TLS_NOTIME (1 << 3)
++#define TLS_CCERT (1 << 4)
++#define TLS_MUSTSTAPLE (1 << 5)
+
+ /* Command Line Options */
+ int dflag; /* detached, no stdin */
+@@ -546,6 +547,8 @@ main(int argc, char *argv[])
+ errx(1, "clientcert is only valid with -l");
+ if (TLSopt & TLS_NONAME)
+ tls_config_insecure_noverifyname(tls_cfg);
++ if (TLSopt & TLS_NOTIME)
++ tls_config_insecure_noverifytime(tls_cfg);
+ if (TLSopt & TLS_NOVERIFY) {
+ if (tls_expecthash != NULL)
+ errx(1, "-H and -T noverify may not be used "
+@@ -1707,6 +1710,7 @@ process_tls_opt(char *s, int *flags)
+ { "muststaple", TLS_MUSTSTAPLE, NULL },
+ { "noverify", TLS_NOVERIFY, NULL },
+ { "noname", TLS_NONAME, NULL },
++ { "notime", TLS_NOTIME, NULL },
+ { "protocols", -1, &tls_protocols },
+ { NULL, -1, NULL },
+ };
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0038-rsync-Pass-long-long-to-scan_scaled.patch b/pkg/openbsd/patch/0038-rsync-Pass-long-long-to-scan_scaled.patch
@@ -1,42 +0,0 @@
-From 0e9ff28bc2e5bd4828b98b50333d12a6d24486fe Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Wed, 27 Apr 2022 20:03:45 -0700
-Subject: [PATCH] rsync: Pass long long * to scan_scaled
-
-off_t might not be long long.
----
- usr.bin/rsync/main.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/usr.bin/rsync/main.c b/usr.bin/rsync/main.c
-index dd175597914..5d7f055a9ae 100644
---- a/usr.bin/rsync/main.c
-+++ b/usr.bin/rsync/main.c
-@@ -353,6 +353,7 @@ main(int argc, char *argv[])
- struct fargs *fargs;
- char **args;
- const char *errstr;
-+ long long size;
-
- /* Global pledge. */
-
-@@ -488,12 +489,14 @@ basedir:
- opts.basedir[basedir_cnt++] = optarg;
- break;
- case OP_MAX_SIZE:
-- if (scan_scaled(optarg, &opts.max_size) == -1)
-+ if (scan_scaled(optarg, &size) == -1)
- err(1, "bad max-size");
-+ opts.max_size = size;
- break;
- case OP_MIN_SIZE:
-- if (scan_scaled(optarg, &opts.min_size) == -1)
-+ if (scan_scaled(optarg, &size) == -1)
- err(1, "bad min-size");
-+ opts.max_size = size;
- break;
- case OP_VERSION:
- fprintf(stderr, "openrsync: protocol version %u\n",
---
-2.37.3
-
diff --git a/pkg/openbsd/patch/0039-pax-Only-use-_PC_TIMESTAMP_RESOLUTION-if-it-is-defin.patch b/pkg/openbsd/patch/0039-pax-Only-use-_PC_TIMESTAMP_RESOLUTION-if-it-is-defin.patch
@@ -0,0 +1,41 @@
+From 7977b9211356095517951e86fa53f64c6b27e16b Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 29 Apr 2025 16:50:16 -0700
+Subject: [PATCH] pax: Only use _PC_TIMESTAMP_RESOLUTION if it is defined
+
+---
+ bin/pax/ar_subs.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/bin/pax/ar_subs.c b/bin/pax/ar_subs.c
+index 4c49efa1362..a0e4fdfdea5 100644
+--- a/bin/pax/ar_subs.c
++++ b/bin/pax/ar_subs.c
+@@ -167,12 +167,13 @@ cmp_file_times(int mtime_flag, int ctime_flag, ARCHD *arcn, const char *path)
+ else if (timespeccmp(&arcn->sb.st_mtim, &sb.st_mtim, <=))
+ return 1;
+
++#ifdef _PC_TIMESTAMP_RESOLUTION
+ /*
+ * If we got here then the target arcn > sb for mtime *and* that's
+ * the deciding factor. Check whether they're equal after rounding
+ * down the arcn mtime to the precision of the target path.
+ */
+- res = pathconfat(AT_FDCWD, path, _PC_TIMESTAMP_RESOLUTION,
++ res = pathconf(path, _PC_TIMESTAMP_RESOLUTION,
+ AT_SYMLINK_NOFOLLOW);
+ if (res == -1)
+ return 0;
+@@ -195,6 +196,9 @@ cmp_file_times(int mtime_flag, int ctime_flag, ARCHD *arcn, const char *path)
+ return ((arcn->sb.st_mtime / res) * res) <= sb.st_mtime;
+ return arcn->sb.st_mtime <= ((sb.st_mtime / res) * res);
+ }
++#else
++ return 0;
++#endif
+ }
+
+ /*
+--
+2.49.0
+
diff --git a/pkg/openbsd/patch/0040-nc-Add-option-to-disable-certificate-time-checking.patch b/pkg/openbsd/patch/0040-nc-Add-option-to-disable-certificate-time-checking.patch
@@ -1,59 +0,0 @@
-From 506272f64ba252c562e3036d14713de780817d1a Mon Sep 17 00:00:00 2001
-From: Michael Forney <mforney@mforney.org>
-Date: Thu, 20 May 2021 13:44:35 -0700
-Subject: [PATCH] nc: Add option to disable certificate time checking
-
----
- usr.bin/nc/nc.1 | 2 ++
- usr.bin/nc/netcat.c | 8 ++++++--
- 2 files changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1
-index 0ef318e0e6f..5858ef763dc 100644
---- a/usr.bin/nc/nc.1
-+++ b/usr.bin/nc/nc.1
-@@ -249,6 +249,8 @@ may be one of:
- which disables certificate verification;
- .Cm noname ,
- which disables certificate name checking;
-+.Cm notime ,
-+which disables certificate validity time checking;
- .Cm clientcert ,
- which requires a client certificate on incoming connections; or
- .Cm muststaple ,
-diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
-index 7369ed85619..29d2cb3bf29 100644
---- a/usr.bin/nc/netcat.c
-+++ b/usr.bin/nc/netcat.c
-@@ -70,8 +70,9 @@
-
- #define TLS_NOVERIFY (1 << 1)
- #define TLS_NONAME (1 << 2)
--#define TLS_CCERT (1 << 3)
--#define TLS_MUSTSTAPLE (1 << 4)
-+#define TLS_NOTIME (1 << 3)
-+#define TLS_CCERT (1 << 4)
-+#define TLS_MUSTSTAPLE (1 << 5)
-
- /* Command Line Options */
- int dflag; /* detached, no stdin */
-@@ -546,6 +547,8 @@ main(int argc, char *argv[])
- errx(1, "clientcert is only valid with -l");
- if (TLSopt & TLS_NONAME)
- tls_config_insecure_noverifyname(tls_cfg);
-+ if (TLSopt & TLS_NOTIME)
-+ tls_config_insecure_noverifytime(tls_cfg);
- if (TLSopt & TLS_NOVERIFY) {
- if (tls_expecthash != NULL)
- errx(1, "-H and -T noverify may not be used "
-@@ -1705,6 +1708,7 @@ process_tls_opt(char *s, int *flags)
- { "muststaple", TLS_MUSTSTAPLE, NULL },
- { "noverify", TLS_NOVERIFY, NULL },
- { "noname", TLS_NONAME, NULL },
-+ { "notime", TLS_NOTIME, NULL },
- { "protocols", -1, &tls_protocols },
- { NULL, -1, NULL },
- };
---
-2.37.3
-
diff --git a/pkg/openbsd/sha256 b/pkg/openbsd/sha256
@@ -1,2 +1,2 @@
-4d545e75c144848b06cb1ee661ab13b654683ae47fcd5f264a4520ab2bfe4c0f src.tar.gz
-bb0dfa11584d68464b3f788e43655f6454bb3ecba8ad5500377630bcf23570ec sys.tar.gz
+6239a7a906bec7c386a06e6fda5893d854a4a00b6702eb47cbed0353a6a0c4fb src.tar.gz
+65b58e8432c8f678840fa58402daee8acf196770b748068e165664bd2d6cd85c sys.tar.gz
diff --git a/pkg/openbsd/url b/pkg/openbsd/url
@@ -1,5 +1,5 @@
remote-name
-url = "https://cdn.openbsd.org/pub/OpenBSD/7.3/src.tar.gz"
+url = "https://cdn.openbsd.org/pub/OpenBSD/7.7/src.tar.gz"
remote-name
-url = "https://cdn.openbsd.org/pub/OpenBSD/7.3/sys.tar.gz"
+url = "https://cdn.openbsd.org/pub/OpenBSD/7.7/sys.tar.gz"
diff --git a/pkg/openbsd/ver b/pkg/openbsd/ver
@@ -1 +1 @@
-7.3 r1
+7.7 r0