Regarding small footprint dropbear

Matt Johnston matt@ucc.asn.au
Mon Aug 30 10:09:50 2004


---------------------- multipart/mixed attachment
(CCed to the list in case it is useful for others too)

On Sun, Aug 29, 2004 at 01:58:56PM -0700, Ritesh Banerjee wrote:
> Hi Matt
>   I saw on dropbear home page the following line :
> 
> "A small memory footprint suitable for
> memory-constrained environments - Dropbear can compile
> to a 110kB statically linked binary with uClibc (and
> only minimal options selected)."
> 
>   Could you please provide some hints / config options
> for dropbear to compile such a small statically linked
> dropbear ? My dynamically linked (with uclibc)
> dropbear is 200000 approx!

OK, I've gotten around to setting up a sensible compile environment again.

I did "apt-get source uclibc-toolchain", changed the config file in there
to the one attached, compiled it, and installed it. (This came from Debian
unstable, so was uclibc 0.9.26). 

I then set up a minimal options.h (attached), and did:

export CC=i386-uclibc-linux-gcc
export CFLAGS="-Os -ffunction-sections -fdata-sections"
export LDFLAGS="-Wl,--gc-sections"
./configure --disable-zlib 

then "make static", "strip staticdropbear". The end result:

evil:~/src/rel/dropbear-0.43> ls -l staticdropbear
-rwx------    1 matt     matt       133822 Aug 30 17:58 staticdropbear*
evil:~/src/rel/dropbear-0.43> strip staticdropbear
evil:~/src/rel/dropbear-0.43> ls -l staticdropbear
-rwx------    1 matt     matt       109500 Aug 30 17:59 staticdropbear*
evil:~/src/rel/dropbear-0.43> file staticdropbear
staticdropbear: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
evil:~/src/rel/dropbear-0.43> ./staticdropbear -h
Dropbear sshd v0.43
...


So that's a 110kB binary. I'm actually surprised it hasn't bloated more :)
The "-ffunction-sections", "-fdata-sections", and "-Wl,--gc-sections" are
important for removing parts from files which aren't used - they only work for
static compilation.  The GCC version is "gcc version 3.3.3 (Debian 20040401)".

Note that some architectures will have significantly larger binary-sizes than
i386.

Matt

---------------------- multipart/mixed attachment
#
# Automatically generated make config: don't edit
#
# TARGET_alpha is not set
# TARGET_arm is not set
# TARGET_cris is not set
# TARGET_e1 is not set
# TARGET_h8300 is not set
TARGET_i386=y
# TARGET_i960 is not set
# TARGET_m68k is not set
# TARGET_microblaze is not set
# TARGET_mips is not set
# TARGET_powerpc is not set
# TARGET_sh is not set
# TARGET_sparc is not set
# TARGET_v850 is not set

#
# Target Architecture Features and Options
#
HAVE_ELF=y
TARGET_ARCH="i386"
# CONFIG_GENERIC_386 is not set
CONFIG_386=y
# CONFIG_486 is not set
# CONFIG_586 is not set
# CONFIG_586MMX is not set
# CONFIG_686 is not set
# CONFIG_PENTIUMIII is not set
# CONFIG_PENTIUM4 is not set
# CONFIG_K6 is not set
# CONFIG_K7 is not set
# CONFIG_CRUSOE is not set
# CONFIG_WINCHIPC6 is not set
# CONFIG_WINCHIP2 is not set
# CONFIG_CYRIXIII is not set
ARCH_LITTLE_ENDIAN=y
# ARCH_BIG_ENDIAN is not set
# ARCH_HAS_NO_MMU is not set
UCLIBC_HAS_MMU=y
UCLIBC_HAS_FLOATS=y
HAS_FPU=y
# DO_C99_MATH is not set
WARNINGS="-Wall"
KERNEL_SOURCE="/home/matt/uclibc/tc/uclibc-0.9.26/kernel-source-2.4.26"
C_SYMBOL_PREFIX=""
HAVE_DOT_CONFIG=y

#
# General Library Settings
#
# HAVE_NO_PIC is not set
DOPIC=y
# HAVE_NO_SHARED is not set
HAVE_SHARED=y
# ARCH_HAS_NO_LDSO is not set
BUILD_UCLIBC_LDSO=y
# UCLIBC_PIE_SUPPORT is not set
LDSO_LDD_SUPPORT=y
UCLIBC_CTOR_DTOR=y
# UCLIBC_PROPOLICE is not set
# UCLIBC_PROFILING is not set
# HAS_NO_THREADS is not set
# UCLIBC_HAS_THREADS is not set
UCLIBC_HAS_LFS=y
# MALLOC is not set
# MALLOC_SIMPLE is not set
MALLOC_STANDARD=y
# MALLOC_GLIBC_COMPAT is not set
UCLIBC_DYNAMIC_ATEXIT=y
HAS_SHADOW=y
UNIX98PTY_ONLY=y
ASSUME_DEVPTS=y
UCLIBC_HAS_TM_EXTENSIONS=y
UCLIBC_HAS_TZ_CACHING=y
UCLIBC_HAS_TZ_FILE=y
UCLIBC_HAS_TZ_FILE_READ_MANY=y
UCLIBC_TZ_FILE_PATH="/etc/TZ"

#
# Networking Support
#
# UCLIBC_HAS_IPV6 is not set
# UCLIBC_HAS_RPC is not set

#
# String and Stdio Support
#
UCLIBC_HAS_CTYPE_TABLES=y
UCLIBC_HAS_CTYPE_SIGNED=y
UCLIBC_HAS_CTYPE_UNSAFE=y
# UCLIBC_HAS_CTYPE_CHECKED is not set
# UCLIBC_HAS_CTYPE_ENFORCED is not set
# UCLIBC_HAS_WCHAR is not set
# UCLIBC_HAS_LOCALE is not set
UCLIBC_HAS_HEXADECIMAL_FLOATS=y
UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
# USE_OLD_VFPRINTF is not set
UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
UCLIBC_HAS_SCANF_GLIBC_A_FLAG=y
# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
UCLIBC_HAS_STDIO_BUFSIZ_256=y
# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
# UCLIBC_HAS_STDIO_BUFSIZ_4096 is not set
# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
UCLIBC_HAS_STDIO_GETC_MACRO=y
UCLIBC_HAS_STDIO_PUTC_MACRO=y
UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
UCLIBC_HAS_FOPEN_LARGEFILE_MODE=y
UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
UCLIBC_HAS_PRINTF_M_SPEC=y
UCLIBC_HAS_ERRNO_MESSAGES=y
# UCLIBC_HAS_SYS_ERRLIST is not set
UCLIBC_HAS_SIGNUM_MESSAGES=y
# UCLIBC_HAS_SYS_SIGLIST is not set
# UCLIBC_HAS_GNU_GETOPT is not set

#
# Big and Tall
#
# UCLIBC_HAS_REGEX is not set
# UCLIBC_HAS_WORDEXP is not set
# UCLIBC_HAS_FTW is not set
# UCLIBC_HAS_GLOB is not set

#
# Library Installation Options
#
SHARED_LIB_LOADER_PREFIX="$(DEVEL_PREFIX)/lib"
RUNTIME_PREFIX="/usr/$(TARGET_ARCH)-uclibc-linux/"
DEVEL_PREFIX="/usr/$(TARGET_ARCH)-uclibc-linux"

#
# uClibc development/debugging options
#
# DODEBUG is not set
# DOASSERTS is not set
# SUPPORT_LD_DEBUG is not set
# SUPPORT_LD_DEBUG_EARLY is not set
# UCLIBC_MJN3_ONLY is not set

---------------------- multipart/mixed attachment
/*
 * Dropbear - a SSH2 server
 * 
 * Copyright (c) 2002,2003 Matt Johnston
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. */

#ifndef _OPTIONS_H_
#define _OPTIONS_H_

/******************************************************************
 * Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
 * parts are to allow for commandline -DDROPBEAR_XXX options etc.
 ******************************************************************/

#ifndef DROPBEAR_PORT
#define DROPBEAR_PORT 22
#endif

/* Default hostkey paths - these can be specified on the command line */
#ifndef DSS_PRIV_FILENAME
#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
#endif
#ifndef RSA_PRIV_FILENAME
#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
#endif

/* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens
 * on chosen ports and keeps accepting connections. This is the default.
 *
 * Set INETD_MODE if you want to be able to run Dropbear with inetd (or
 * similar), where it will use stdin/stdout for connections, and each process
 * lasts for a single connection. Dropbear should be invoked with the -i flag
 * for inetd, and can only accept IPv4 connections.
 *
 * Both of these flags can be defined at once, don't compile without at least
 * one of them. */
#define NON_INETD_MODE
#define INETD_MODE

/* Setting this disables the faster version of the modular exponentiation
 * bignum code. It saves ~5kB, but is perhaps 20% slower for public-key and key
 * exchange operations.  It is probably worth experimenting to decide if it's
 * worthwhile on your platform. */
#define NO_FAST_EXPTMOD

/* Set this if you want to use the DROPBEAR_SMALL_CODE option. This can save
 * several kB in binary size, however will make the symmetrical ciphers (AES,
 * DES etc) slower (perhaps by 50%). Recommended for most small systems. */
#define DROPBEAR_SMALL_CODE

/* Enable X11 Forwarding */
/*#define ENABLE_X11FWD*/

/* Enable TCP Fowarding */
/* OpenSSH's "-L" style forwarding (client port forwarded via server) */
/*#define ENABLE_LOCALTCPFWD*/
/* OpenSSH's "-R" style forwarding (server port forwarded via client) */
/*#define ENABLE_REMOTETCPFWD*/

/* Enable Authentication Agent Forwarding */
/*#define ENABLE_AGENTFWD*/

/* Encryption - at least one required.
 * RFC Draft requires 3DES, and recommends Blowfish, AES128 & Twofish128 */
/*#define DROPBEAR_AES128_CBC
#define DROPBEAR_BLOWFISH_CBC
#define DROPBEAR_TWOFISH128_CBC*/
#define DROPBEAR_3DES_CBC

/* Integrity - at least one required.
 * RFC Draft requires sha1-hmac, and recommends md5-hmac.
 *
 * Note: there's no point disabling sha1 to save space, since it's used in the
 * for the random number generator and public-key cryptography anyway.
 * Disabling it here will just stop it from being used as the integrity portion
 * of the ssh protocol.
 *
 * These are also used for key fingerprints in logs (when pubkey auth is used),
 * MD5 fingerprints are printed by default, however SHA1 fingerprints will be
 * generated otherwise. This isn't exactly optimal, although sha1 fingerprints
 * are not too hard to create from pubkeys if required. */
#define DROPBEAR_SHA1_HMAC
/*#define DROPBEAR_MD5_HMAC*/

/* Hostkey/public key algorithms - at least one required, these are used
 * for hostkey as well as for verifying signatures with pubkey auth.
 * Removing either of these won't save very much space.
 * SSH2 RFC Draft requires dss, recommends rsa */
#define DROPBEAR_RSA
/*#define DROPBEAR_DSS*/

/* Define DSS_PROTOK to use PuTTY's method of generating the value k for dss,
 * rather than just from the random byte source. Undefining this will save you
 * ~4k in binary size with static uclibc, but your DSS hostkey could be exposed
 * if the random number source isn't good. In general this isn't required */
/* #define DSS_PROTOK */

/* Whether to do reverse DNS lookups. This is advisable, though will add
 * code size with gethostbyname() etc, so for very small environments where
 * you are statically linking, you might want to undefine this */
/*#define DO_HOST_LOOKUP*/

/* Whether to print the message of the day (MOTD). This doesn't add much code
 * size */
/*#define DO_MOTD*/

/* The MOTD file path */
#ifndef MOTD_FILENAME
#define MOTD_FILENAME "/etc/motd"
#endif

/* Authentication types to enable, at least one required.
   RFC Draft requires pubkey auth, and recommends password */
#define DROPBEAR_PASSWORD_AUTH
/*#define DROPBEAR_PUBKEY_AUTH*/

/* Random device to use - you must specify _one only_.
 * DEV_RANDOM is recommended on hosts with a good /dev/urandom, otherwise use
 * PRNGD and run prngd, specifying the socket. This device must be able to
 * produce a large amount of random data, so using /dev/random or Entropy
 * Gathering Daemon (egd) may result in halting, as it waits for more random
 * data */
#define DROPBEAR_DEV_URANDOM /* use /dev/urandom */

/*#undef DROPBEAR_PRNGD */ /* use prngd socket - you must manually set up prngd
							  to produce output */
#ifndef DROPBEAR_PRNGD_SOCKET
#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"
#endif

/* Specify the number of clients we will allow to be connected but
 * not yet authenticated. After this limit, connections are rejected */
#ifndef MAX_UNAUTH_CLIENTS
#define MAX_UNAUTH_CLIENTS 30
#endif

/* Maximum number of failed authentication tries */
#ifndef MAX_AUTH_TRIES
#define MAX_AUTH_TRIES 10
#endif

/* The file to store the daemon's process ID, for shutdown scripts etc */
#ifndef DROPBEAR_PIDFILE
#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
#endif

/* The command to invoke for xauth when using X11 forwarding.
 * "-q" for quiet */
#ifndef XAUTH_COMMAND
#define XAUTH_COMMAND "/usr/X11R6/bin/xauth -q"
#endif

/* if you want to enable running an sftp server (such as the one included with
 * OpenSSH), set the path below. If the path isn't defined, sftp will not
 * be enabled */
/*
#ifndef SFTPSERVER_PATH
#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
#endif
*/

/* This is used by the scp binary when used as a client binary */
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"

/* Multi-purpose binary  configuration - if you want to make the combined
 * binary, first define DROPBEAR_MULTI, and then define which of the three
 * components you want. You should then compile Dropbear with 
 * "make clean; make dropbearmulti". You'll need to install the binary
 * manually, see MULTI for details */

/* #define DROPBEAR_MULTI */

/* The three multi binaries: dropbear, dropbearkey, dropbearconvert
 * Comment out these if you don't want some of them */
#define DBMULTI_DROPBEAR
#define DBMULTI_KEY
#define DBMULTI_CONVERT


/*******************************************************************
 * You shouldn't edit below here unless you know you need to.
 *******************************************************************/

#ifndef DROPBEAR_VERSION
#define DROPBEAR_VERSION "0.43"
#endif

#define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION
#define PROGNAME "dropbear"

/* Spec recommends after one hour or 1 gigabyte of data. One hour
 * is a bit too verbose, so we try 8 hours */
#ifndef KEX_REKEY_TIMEOUT
#define KEX_REKEY_TIMEOUT (3600 * 8)
#endif
#ifndef KEX_REKEY_DATA
#define KEX_REKEY_DATA (1<<30) /* 2^30 == 1GB, this value must be < INT_MAX */
#endif
/* Close connections to clients which haven't authorised after AUTH_TIMEOUT */
#ifndef AUTH_TIMEOUT
#define AUTH_TIMEOUT 300 /* we choose 5 minutes */
#endif

/* Minimum key sizes for DSS and RSA */
#ifndef MIN_DSS_KEYLEN
#define MIN_DSS_KEYLEN 512
#endif
#ifndef MIN_RSA_KEYLEN
#define MIN_RSA_KEYLEN 512
#endif

#define MAX_BANNER_SIZE 2000 /* this is 25*80 chars, any more is foolish */

#define DEV_URANDOM "/dev/urandom"

/* the number of NAME=VALUE pairs to malloc for environ, if we don't have
 * the clearenv() function */
#define ENV_SIZE 100

#define MAX_CMD_LEN 1024 /* max length of a command */
#define MAX_TERM_LEN 200 /* max length of TERM name */

#define MAX_HOST_LEN 254 /* max hostname len for tcp fwding */
#define MAX_IP_LEN 15 /* strlen("255.255.255.255") == 15 */

#define DROPBEAR_MAX_PORTS 10 /* max number of ports which can be specified,
								 ipv4 and ipv6 don't count twice */

#define _PATH_TTY "/dev/tty"

/* Timeouts in seconds */
#define SELECT_TIMEOUT 20

/* success/failure defines */
#define DROPBEAR_SUCCESS 0
#define DROPBEAR_FAILURE -1

/* various algorithm identifiers */
#define DROPBEAR_KEX_DH_GROUP1 0

#define DROPBEAR_SIGNKEY_ANY 0
#define DROPBEAR_SIGNKEY_RSA 1
#define DROPBEAR_SIGNKEY_DSS 2

#define DROPBEAR_COMP_NONE 0
#define DROPBEAR_COMP_ZLIB 1

/* Required for pubkey auth */
#ifdef DROPBEAR_PUBKEY_AUTH
#define DROPBEAR_SIGNKEY_VERIFY
#endif

/* SHA1 is 20 bytes == 160 bits */
#define SHA1_HASH_SIZE 20
/* SHA512 is 64 bytes == 512 bits */
#define SHA512_HASH_SIZE 64
/* MD5 is 16 bytes = 128 bits */
#define MD5_HASH_SIZE 16

/* largest of MD5 and SHA1 */
#define MAX_MAC_LEN SHA1_HASH_SIZE


#define MAX_KEY_LEN 24 /* 3DES requires a 24 byte key */
#define MAX_IV_LEN 20 /* must be same as max blocksize, 
						 and >= SHA1_HASH_SIZE */
#define MAX_MAC_KEY 20

#define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
						   explicitly specified for all protocols (just
						   for algos) but seems valid */

#define MAX_PROPOSED_ALGO 20

/* size/count limits */
#define MAX_LISTEN_ADDR 10

#define MAX_PACKET_LEN 35000
#define MIN_PACKET_LEN 16
#define MAX_PAYLOAD_LEN 32768

#define MAX_TRANS_PAYLOAD_LEN 32768
#define MAX_TRANS_PACKET_LEN (MAX_TRANS_PAYLOAD_LEN+50)

#define MAX_TRANS_WINDOW 500000000 /* 500MB is sufficient, stopping overflow */
#define MAX_TRANS_WIN_INCR 500000000 /* overflow prevention */

#define MAX_STRING_LEN 1400 /* ~= MAX_PROPOSED_ALGO * MAX_NAME_LEN, also
							   is the max length for a password etc */

#ifndef ENABLE_X11FWD
#define DISABLE_X11FWD
#endif

#ifndef ENABLE_AGENTFWD
#define DISABLE_AGENTFWD
#endif

#ifndef ENABLE_LOCALTCPFWD
#define DISABLE_LOCALTCPFWD
#endif

#ifndef ENABLE_REMOTETCPFWD
#define DISABLE_REMOTETCPFWD
#endif

#endif /* _OPTIONS_H_ */

---------------------- multipart/mixed attachment--