From 1acb6c70b31ebf30be656d8e906c4be06193f0c2 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 14 Jul 2014 00:49:37 +0200 Subject: [PATCH] openssh: switch to libressl support, add patch to support libressl Signed-off-by: Stephan Raue --- packages/network/openssh/package.mk | 2 +- .../openssh-libressl-compat_arc4random.patch | 371 ++++++++++++++++++ 2 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 packages/network/openssh/patches/openssh-libressl-compat_arc4random.patch diff --git a/packages/network/openssh/package.mk b/packages/network/openssh/package.mk index 1c8181383e..731d082ef2 100644 --- a/packages/network/openssh/package.mk +++ b/packages/network/openssh/package.mk @@ -23,7 +23,7 @@ PKG_ARCH="any" PKG_LICENSE="OSS" PKG_SITE="http://www.openssh.com/" PKG_URL="ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/$PKG_NAME-$PKG_VERSION.tar.gz" -PKG_DEPENDS_TARGET="toolchain zlib openssl" +PKG_DEPENDS_TARGET="toolchain zlib libressl" PKG_PRIORITY="optional" PKG_SECTION="network" PKG_SHORTDESC="openssh: An open re-implementation of the SSH package" diff --git a/packages/network/openssh/patches/openssh-libressl-compat_arc4random.patch b/packages/network/openssh/patches/openssh-libressl-compat_arc4random.patch new file mode 100644 index 0000000000..6f4244e579 --- /dev/null +++ b/packages/network/openssh/patches/openssh-libressl-compat_arc4random.patch @@ -0,0 +1,371 @@ +diff -Naur openssh-6.6p1-van/openbsd-compat/arc4random.c openssh-6.6p1/openbsd-compat/arc4random.c +--- openssh-6.6p1-van/openbsd-compat/arc4random.c 2013-10-09 01:44:49.000000000 +0200 ++++ openssh-6.6p1/openbsd-compat/arc4random.c 2014-07-12 02:18:41.091969421 +0200 +@@ -1,6 +1,4 @@ +-/* OPENBSD ORIGINAL: lib/libc/crypto/arc4random.c */ +- +-/* $OpenBSD: arc4random.c,v 1.25 2013/10/01 18:34:57 markus Exp $ */ ++/* $OpenBSD: arc4random.c,v 1.38 2014/06/26 19:23:15 deraadt Exp $ */ + + /* + * Copyright (c) 1996, David Mazieres +@@ -24,43 +22,46 @@ + * ChaCha based random number generator for OpenBSD. + */ + +-#include "includes.h" +- ++#include ++#include ++#include ++#include + #include + #include + #include + #include ++#include ++#include ++#include + +-#ifndef HAVE_ARC4RANDOM +- +-#include +-#include +- +-#include "log.h" ++#include "thread_private.h" + + #define KEYSTREAM_ONLY + #include "chacha_private.h" + ++#define min(a, b) ((a) < (b) ? (a) : (b)) + #ifdef __GNUC__ + #define inline __inline + #else /* !__GNUC__ */ + #define inline + #endif /* !__GNUC__ */ + +-/* OpenSSH isn't multithreaded */ +-#define _ARC4_LOCK() +-#define _ARC4_UNLOCK() +- + #define KEYSZ 32 + #define IVSZ 8 + #define BLOCKSZ 64 + #define RSBUFSZ (16*BLOCKSZ) +-static int rs_initialized; +-static pid_t rs_stir_pid; +-static chacha_ctx rs; /* chacha context for random keystream */ +-static u_char rs_buf[RSBUFSZ]; /* keystream blocks */ +-static size_t rs_have; /* valid bytes at end of rs_buf */ +-static size_t rs_count; /* bytes till reseed */ ++ ++/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ ++static struct { ++ size_t rs_have; /* valid bytes at end of rs_buf */ ++ size_t rs_count; /* bytes till reseed */ ++} *rs; ++ ++/* Preserved in fork children. */ ++static struct { ++ chacha_ctx rs_chacha; /* chacha context for random keystream */ ++ u_char rs_buf[RSBUFSZ]; /* keystream blocks */ ++} *rsx; + + static inline void _rs_rekey(u_char *dat, size_t datlen); + +@@ -69,8 +70,24 @@ + { + if (n < KEYSZ + IVSZ) + return; +- chacha_keysetup(&rs, buf, KEYSZ * 8, 0); +- chacha_ivsetup(&rs, buf + KEYSZ); ++ ++ if (rs == NULL) { ++ if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE, ++ MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) ++ abort(); ++#ifdef MAP_INHERIT_ZERO ++ if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1) ++ abort(); ++#endif ++ } ++ if (rsx == NULL) { ++ if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE, ++ MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) ++ abort(); ++ } ++ ++ chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); ++ chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); + } + + static void +@@ -78,120 +95,108 @@ + { + u_char rnd[KEYSZ + IVSZ]; + +- if (RAND_bytes(rnd, sizeof(rnd)) <= 0) +- fatal("Couldn't obtain random bytes (error %ld)", +- ERR_get_error()); ++ if (getentropy(rnd, sizeof rnd) == -1) ++ raise(SIGKILL); + +- if (!rs_initialized) { +- rs_initialized = 1; ++ if (!rs) + _rs_init(rnd, sizeof(rnd)); +- } else ++ else + _rs_rekey(rnd, sizeof(rnd)); +- memset(rnd, 0, sizeof(rnd)); ++ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ + + /* invalidate rs_buf */ +- rs_have = 0; +- memset(rs_buf, 0, RSBUFSZ); ++ rs->rs_have = 0; ++ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); + +- rs_count = 1600000; ++ rs->rs_count = 1600000; + } + + static inline void + _rs_stir_if_needed(size_t len) + { ++#ifndef MAP_INHERIT_ZERO ++ static pid_t _rs_pid = 0; + pid_t pid = getpid(); + +- if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) { +- rs_stir_pid = pid; ++ /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */ ++ if (_rs_pid == 0 || _rs_pid != pid) { ++ _rs_pid = pid; ++ if (rs) ++ rs->rs_count = 0; ++ } ++#endif ++ if (!rs || rs->rs_count <= len) + _rs_stir(); +- } else +- rs_count -= len; ++ if (rs->rs_count <= len) ++ rs->rs_count = 0; ++ else ++ rs->rs_count -= len; + } + + static inline void + _rs_rekey(u_char *dat, size_t datlen) + { + #ifndef KEYSTREAM_ONLY +- memset(rs_buf, 0,RSBUFSZ); ++ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); + #endif + /* fill rs_buf with the keystream */ +- chacha_encrypt_bytes(&rs, rs_buf, rs_buf, RSBUFSZ); ++ chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf, ++ rsx->rs_buf, sizeof(rsx->rs_buf)); + /* mix in optional user provided data */ + if (dat) { + size_t i, m; + +- m = MIN(datlen, KEYSZ + IVSZ); ++ m = min(datlen, KEYSZ + IVSZ); + for (i = 0; i < m; i++) +- rs_buf[i] ^= dat[i]; ++ rsx->rs_buf[i] ^= dat[i]; + } + /* immediately reinit for backtracking resistance */ +- _rs_init(rs_buf, KEYSZ + IVSZ); +- memset(rs_buf, 0, KEYSZ + IVSZ); +- rs_have = RSBUFSZ - KEYSZ - IVSZ; ++ _rs_init(rsx->rs_buf, KEYSZ + IVSZ); ++ memset(rsx->rs_buf, 0, KEYSZ + IVSZ); ++ rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; + } + + static inline void + _rs_random_buf(void *_buf, size_t n) + { + u_char *buf = (u_char *)_buf; ++ u_char *keystream; + size_t m; + + _rs_stir_if_needed(n); + while (n > 0) { +- if (rs_have > 0) { +- m = MIN(n, rs_have); +- memcpy(buf, rs_buf + RSBUFSZ - rs_have, m); +- memset(rs_buf + RSBUFSZ - rs_have, 0, m); ++ if (rs->rs_have > 0) { ++ m = min(n, rs->rs_have); ++ keystream = rsx->rs_buf + sizeof(rsx->rs_buf) ++ - rs->rs_have; ++ memcpy(buf, keystream, m); ++ memset(keystream, 0, m); + buf += m; + n -= m; +- rs_have -= m; ++ rs->rs_have -= m; + } +- if (rs_have == 0) ++ if (rs->rs_have == 0) + _rs_rekey(NULL, 0); + } + } + + static inline void +-_rs_random_u32(u_int32_t *val) ++_rs_random_u32(uint32_t *val) + { ++ u_char *keystream; + _rs_stir_if_needed(sizeof(*val)); +- if (rs_have < sizeof(*val)) ++ if (rs->rs_have < sizeof(*val)) + _rs_rekey(NULL, 0); +- memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val)); +- memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val)); +- rs_have -= sizeof(*val); +- return; +-} +- +-void +-arc4random_stir(void) +-{ +- _ARC4_LOCK(); +- _rs_stir(); +- _ARC4_UNLOCK(); +-} +- +-void +-arc4random_addrandom(u_char *dat, int datlen) +-{ +- int m; +- +- _ARC4_LOCK(); +- if (!rs_initialized) +- _rs_stir(); +- while (datlen > 0) { +- m = MIN(datlen, KEYSZ + IVSZ); +- _rs_rekey(dat, m); +- dat += m; +- datlen -= m; +- } +- _ARC4_UNLOCK(); ++ keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; ++ memcpy(val, keystream, sizeof(*val)); ++ memset(keystream, 0, sizeof(*val)); ++ rs->rs_have -= sizeof(*val); + } + +-u_int32_t ++uint32_t + arc4random(void) + { +- u_int32_t val; ++ uint32_t val; + + _ARC4_LOCK(); + _rs_random_u32(&val); +@@ -199,11 +204,6 @@ + return val; + } + +-/* +- * If we are providing arc4random, then we can provide a more efficient +- * arc4random_buf(). +- */ +-# ifndef HAVE_ARC4RANDOM_BUF + void + arc4random_buf(void *buf, size_t n) + { +@@ -211,29 +211,7 @@ + _rs_random_buf(buf, n); + _ARC4_UNLOCK(); + } +-# endif /* !HAVE_ARC4RANDOM_BUF */ +-#endif /* !HAVE_ARC4RANDOM */ + +-/* arc4random_buf() that uses platform arc4random() */ +-#if !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) +-void +-arc4random_buf(void *_buf, size_t n) +-{ +- size_t i; +- u_int32_t r = 0; +- char *buf = (char *)_buf; +- +- for (i = 0; i < n; i++) { +- if (i % 4 == 0) +- r = arc4random(); +- buf[i] = r & 0xff; +- r >>= 8; +- } +- i = r = 0; +-} +-#endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ +- +-#ifndef HAVE_ARC4RANDOM_UNIFORM + /* + * Calculate a uniformly distributed random number less than upper_bound + * avoiding "modulo bias". +@@ -244,10 +222,10 @@ + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + */ +-u_int32_t +-arc4random_uniform(u_int32_t upper_bound) ++uint32_t ++arc4random_uniform(uint32_t upper_bound) + { +- u_int32_t r, min; ++ uint32_t r, min; + + if (upper_bound < 2) + return 0; +@@ -269,26 +247,11 @@ + + return r % upper_bound; + } +-#endif /* !HAVE_ARC4RANDOM_UNIFORM */ +- +-#if 0 +-/*-------- Test code for i386 --------*/ +-#include +-#include +-int +-main(int argc, char **argv) ++void ++arc4random_stir(void) + { +- const int iter = 1000000; +- int i; +- pctrval v; +- +- v = rdtsc(); +- for (i = 0; i < iter; i++) +- arc4random(); +- v = rdtsc() - v; +- v /= iter; +- +- printf("%qd cycles\n", v); +- exit(0); ++ _ARC4_LOCK(); ++ _rs_stir(); ++ _ARC4_UNLOCK(); + } +-#endif ++ +diff -Naur openssh-6.6p1-van/openbsd-compat/thread_private.h openssh-6.6p1/openbsd-compat/thread_private.h +--- openssh-6.6p1-van/openbsd-compat/thread_private.h 1970-01-01 01:00:00.000000000 +0100 ++++ openssh-6.6p1/openbsd-compat/thread_private.h 2014-07-12 02:12:30.085607639 +0200 +@@ -0,0 +1,6 @@ ++#include ++ ++static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; ++ ++#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) ++#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)