aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-11-28 10:28:18 +0000
committerRon Yorston <rmy@pobox.com>2018-11-28 10:28:18 +0000
commit2a69a2200a141c1504b662eca64b802cdab71b12 (patch)
treeeab0cc01852db237a26052a83c8f582ed92b7cd9
parent97ca1f4b955f486cd26461cb09185335483d2921 (diff)
parent572dfb8e78323b9837f7c5e3369ee233a440b8f2 (diff)
downloadbusybox-w32-2a69a2200a141c1504b662eca64b802cdab71b12.tar.gz
busybox-w32-2a69a2200a141c1504b662eca64b802cdab71b12.tar.bz2
busybox-w32-2a69a2200a141c1504b662eca64b802cdab71b12.zip
Merge branch 'busybox' into merge
-rw-r--r--.gitignore5
-rw-r--r--Config.in5
-rw-r--r--Makefile8
-rw-r--r--applets/applet_tables.c10
-rwxr-xr-xapplets/busybox.mkscripts16
-rw-r--r--applets_sh/README5
-rwxr-xr-xapplets_sh/dos2unix5
-rwxr-xr-xapplets_sh/nologin3
-rwxr-xr-xapplets_sh/tac7
-rwxr-xr-xapplets_sh/unix2dos5
-rw-r--r--archival/libarchive/Kbuild.src1
-rw-r--r--archival/libarchive/decompress_bunzip2.c40
-rw-r--r--archival/libarchive/decompress_unlzma.c20
-rw-r--r--archival/libarchive/get_header_tar.c3
-rw-r--r--archival/libarchive/open_transformer.c3
-rw-r--r--archival/tar.c8
-rw-r--r--configs/mingw32_defconfig8
-rw-r--r--configs/mingw64_defconfig8
-rw-r--r--coreutils/dd.c65
-rw-r--r--coreutils/printf.c13
-rw-r--r--docs/embedded-scripts.txt111
-rw-r--r--docs/posix_conformance.txt1
-rwxr-xr-xexamples/udhcp/simple.script18
-rw-r--r--findutils/xargs.c7
-rw-r--r--include/.gitignore1
-rw-r--r--include/applets.src.h15
-rw-r--r--include/bb_archive.h7
-rw-r--r--include/libbb.h33
-rw-r--r--include/platform.h5
-rw-r--r--include/usage.src.h3
-rw-r--r--libbb/appletlib.c125
-rw-r--r--libbb/hash_md5_sha.c5
-rw-r--r--libbb/progress.c5
-rw-r--r--libbb/u_signal_names.c82
-rw-r--r--miscutils/bbconfig.c27
-rw-r--r--modutils/modprobe.c5
-rw-r--r--networking/brctl.c13
-rw-r--r--networking/nbd-client.c230
-rw-r--r--networking/ntpd.c268
-rw-r--r--networking/tls.c1116
-rw-r--r--networking/tls.h13
-rw-r--r--networking/tls_aes.c41
-rw-r--r--networking/tls_aes.h8
-rw-r--r--networking/tls_aesgcm.c151
-rw-r--r--networking/tls_aesgcm.h11
-rw-r--r--networking/tls_fe.c611
-rw-r--r--networking/tls_fe.h7
-rw-r--r--networking/tls_rsa.c2
-rw-r--r--networking/tls_rsa.h14
-rw-r--r--networking/udhcp/d6_dhcpc.c9
-rw-r--r--networking/udhcp/dhcpc.c9
-rw-r--r--networking/wget.c25
-rw-r--r--procps/free.c63
-rw-r--r--runit/svlogd.c8
-rwxr-xr-xscripts/embedded_scripts125
-rwxr-xr-xscripts/gen_build_files.sh21
-rwxr-xr-xscripts/trylink21
-rw-r--r--shell/Config.src14
-rw-r--r--shell/ash.c29
-rw-r--r--shell/hush.c18
-rw-r--r--testsuite/echo/echo-prints-dash1
-rw-r--r--testsuite/echo/echo-prints-non-opts1
-rw-r--r--testsuite/echo/echo-prints-slash-zero2
-rw-r--r--testsuite/echo/echo-prints-slash_000412
-rw-r--r--testsuite/echo/echo-prints-slash_00412
-rw-r--r--testsuite/echo/echo-prints-slash_0412
-rw-r--r--testsuite/echo/echo-prints-slash_412
-rwxr-xr-xtestsuite/printf.tests33
-rw-r--r--util-linux/nologin.c27
69 files changed, 2946 insertions, 641 deletions
diff --git a/.gitignore b/.gitignore
index 517e750c1..cc485189e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,3 +58,8 @@ cscope.po.out
58# 58#
59tags 59tags
60TAGS 60TAGS
61
62#
63# user-supplied scripts
64#
65/embed
diff --git a/Config.in b/Config.in
index 43061e9ac..a92360240 100644
--- a/Config.in
+++ b/Config.in
@@ -192,6 +192,11 @@ config BUSYBOX
192 192
193 Running "busybox APPLET [ARGS...]" will still work, of course. 193 Running "busybox APPLET [ARGS...]" will still work, of course.
194 194
195config FEATURE_SHOW_SCRIPT
196 bool "Support --show SCRIPT"
197 default y
198 depends on BUSYBOX
199
195config FEATURE_INSTALLER 200config FEATURE_INSTALLER
196 bool "Support --install [-s] to install applet links at runtime" 201 bool "Support --install [-s] to install applet links at runtime"
197 default y 202 default y
diff --git a/Makefile b/Makefile
index b6aa3f158..d6e84984e 100644
--- a/Makefile
+++ b/Makefile
@@ -363,7 +363,7 @@ scripts/basic/%: scripts_basic ;
363 363
364# This target generates Kbuild's and Config.in's from *.c files 364# This target generates Kbuild's and Config.in's from *.c files
365PHONY += gen_build_files 365PHONY += gen_build_files
366gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) 366gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) $(wildcard $(srctree)/embed/*)
367 $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) 367 $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree)
368 368
369# bbox: we have helpers in applets/ 369# bbox: we have helpers in applets/
@@ -854,11 +854,14 @@ quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h
854 cmd_gen_common_bufsiz = $(srctree)/scripts/generate_BUFSIZ.sh include/common_bufsiz.h 854 cmd_gen_common_bufsiz = $(srctree)/scripts/generate_BUFSIZ.sh include/common_bufsiz.h
855quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* 855quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/*
856 cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config 856 cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config
857quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h
858 cmd_gen_embedded_scripts = $(srctree)/scripts/embedded_scripts include/embedded_scripts.h $(srctree)/embed $(srctree)/applets_sh
857#bbox# piggybacked generation of few .h files 859#bbox# piggybacked generation of few .h files
858include/config/MARKER: scripts/basic/split-include include/autoconf.h 860include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard $(srctree)/embed/*) $(wildcard $(srctree)/applets_sh/*) $(srctree)/scripts/embedded_scripts
859 $(call cmd,split_autoconf) 861 $(call cmd,split_autoconf)
860 $(call cmd,gen_bbconfigopts) 862 $(call cmd,gen_bbconfigopts)
861 $(call cmd,gen_common_bufsiz) 863 $(call cmd,gen_common_bufsiz)
864 $(call cmd,gen_embedded_scripts)
862 @touch $@ 865 @touch $@
863 866
864# Generate some files 867# Generate some files
@@ -978,6 +981,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
978 include/autoconf.h \ 981 include/autoconf.h \
979 include/bbconfigopts.h \ 982 include/bbconfigopts.h \
980 include/bbconfigopts_bz2.h \ 983 include/bbconfigopts_bz2.h \
984 include/embedded_scripts.h \
981 include/usage_compressed.h \ 985 include/usage_compressed.h \
982 include/applet_tables.h \ 986 include/applet_tables.h \
983 include/applets.h \ 987 include/applets.h \
diff --git a/applets/applet_tables.c b/applets/applet_tables.c
index b997194ad..6a20c8b38 100644
--- a/applets/applet_tables.c
+++ b/applets/applet_tables.c
@@ -85,7 +85,15 @@ int main(int argc, char **argv)
85 85
86 qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); 86 qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name);
87 87
88 if (!argv[1]) 88 for (i = j = 0; i < NUM_APPLETS-1; ++i) {
89 if (cmp_name(applets+i, applets+i+1) == 0) {
90 fprintf(stderr, "%s: duplicate applet name '%s'\n", argv[0],
91 applets[i].name);
92 j = 1;
93 }
94 }
95
96 if (j != 0 || !argv[1])
89 return 1; 97 return 1;
90 snprintf(tmp1, PATH_MAX, "%s.%u.new", argv[1], (int) getpid()); 98 snprintf(tmp1, PATH_MAX, "%s.%u.new", argv[1], (int) getpid());
91 i = open(tmp1, O_WRONLY | O_TRUNC | O_CREAT, 0666); 99 i = open(tmp1, O_WRONLY | O_TRUNC | O_CREAT, 0666);
diff --git a/applets/busybox.mkscripts b/applets/busybox.mkscripts
new file mode 100755
index 000000000..935685cba
--- /dev/null
+++ b/applets/busybox.mkscripts
@@ -0,0 +1,16 @@
1#!/bin/sh
2# Make busybox scripted applet list file.
3
4# input $1: full path to Config.h
5# input $2: full path to applets.h
6# output (stdout): list of pathnames that should be linked to busybox
7
8export LC_ALL=POSIX
9export LC_CTYPE=POSIX
10
11CONFIG_H=${1:-include/autoconf.h}
12APPLETS_H=${2:-include/applets.h}
13$HOSTCC -E -DMAKE_SCRIPTS -include $CONFIG_H $APPLETS_H |
14 awk '/^[ \t]*SCRIPT/{
15 print $2
16 }'
diff --git a/applets_sh/README b/applets_sh/README
deleted file mode 100644
index 9dcd38ae3..000000000
--- a/applets_sh/README
+++ /dev/null
@@ -1,5 +0,0 @@
1This directory contains examples of applets implemented as shell scripts.
2
3So far these scripts are not hooked to the build system and are not
4installed by "make install". If you want to use them,
5you need to install them by hand.
diff --git a/applets_sh/dos2unix b/applets_sh/dos2unix
deleted file mode 100755
index 0fd5206f6..000000000
--- a/applets_sh/dos2unix
+++ /dev/null
@@ -1,5 +0,0 @@
1#!/bin/sh
2# TODO: use getopt to avoid parsing options as filenames,
3# and to support -- and --help
4[ $# -ne 0 ] && DASH_I=-i
5sed $DASH_I -e 's/\r$//' "$@"
diff --git a/applets_sh/nologin b/applets_sh/nologin
index 3768eaaa7..4ed5f6ca3 100755
--- a/applets_sh/nologin
+++ b/applets_sh/nologin
@@ -1,4 +1,3 @@
1#!/bin/sh 1cat /etc/nologin.txt 2>/dev/null || echo This account is not available
2cat /etc/nologin.txt 2>/dev/null || echo "This account is not available"
3sleep 5 2sleep 5
4exit 1 3exit 1
diff --git a/applets_sh/tac b/applets_sh/tac
deleted file mode 100755
index c5a8e39c1..000000000
--- a/applets_sh/tac
+++ /dev/null
@@ -1,7 +0,0 @@
1#!/bin/sh
2# TODO: use getopt to avoid parsing options as filenames,
3# and to support -- and --help
4for i in "$@"
5do
6sed -e '1!G;h;$!d' "$i"
7done
diff --git a/applets_sh/unix2dos b/applets_sh/unix2dos
deleted file mode 100755
index 70e042906..000000000
--- a/applets_sh/unix2dos
+++ /dev/null
@@ -1,5 +0,0 @@
1#!/bin/sh
2# TODO: use getopt to avoid parsing options as filenames,
3# and to support -- and --help
4[ $# -ne 0 ] && DASH_I=-i
5sed $DASH_I -e 's/$/\r/' "$@"
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index e1a8a7529..d2f284b08 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -91,6 +91,7 @@ lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.
91lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o 91lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
92lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o 92lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o
93lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o 93lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o
94lib-$(CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o
94 95
95ifneq ($(lib-y),) 96ifneq ($(lib-y),)
96lib-y += $(COMMON_FILES) 97lib-y += $(COMMON_FILES)
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index 7ef4e035f..78366f26a 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -107,7 +107,7 @@ struct bunzip_data {
107 uint8_t selectors[32768]; /* nSelectors=15 bits */ 107 uint8_t selectors[32768]; /* nSelectors=15 bits */
108 struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ 108 struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
109}; 109};
110/* typedef struct bunzip_data bunzip_data; -- done in .h file */ 110typedef struct bunzip_data bunzip_data;
111 111
112 112
113/* Return the next nnn bits of input. All reads from the compressed input 113/* Return the next nnn bits of input. All reads from the compressed input
@@ -575,7 +575,7 @@ static int get_next_block(bunzip_data *bd)
575 in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. 575 in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0.
576 (Why? This allows to get rid of one local variable) 576 (Why? This allows to get rid of one local variable)
577*/ 577*/
578int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) 578static int read_bunzip(bunzip_data *bd, char *outbuf, int len)
579{ 579{
580 const uint32_t *dbuf; 580 const uint32_t *dbuf;
581 int pos, current, previous; 581 int pos, current, previous;
@@ -699,7 +699,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
699/* Because bunzip2 is used for help text unpacking, and because bb_show_usage() 699/* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
700 should work for NOFORK applets too, we must be extremely careful to not leak 700 should work for NOFORK applets too, we must be extremely careful to not leak
701 any allocations! */ 701 any allocations! */
702int FAST_FUNC start_bunzip( 702static int FAST_FUNC start_bunzip(
703 void *jmpbuf, 703 void *jmpbuf,
704 bunzip_data **bdp, 704 bunzip_data **bdp,
705 int in_fd, 705 int in_fd,
@@ -759,7 +759,7 @@ int FAST_FUNC start_bunzip(
759 return RETVAL_OK; 759 return RETVAL_OK;
760} 760}
761 761
762void FAST_FUNC dealloc_bunzip(bunzip_data *bd) 762static void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
763{ 763{
764 free(bd->dbuf); 764 free(bd->dbuf);
765 free(bd); 765 free(bd);
@@ -809,7 +809,7 @@ unpack_bz2_stream(transformer_state_t *xstate)
809 /* Observed case when i == RETVAL_OK: 809 /* Observed case when i == RETVAL_OK:
810 * "bzcat z.bz2", where "z.bz2" is a bzipped zero-length file 810 * "bzcat z.bz2", where "z.bz2" is a bzipped zero-length file
811 * (to be exact, z.bz2 is exactly these 14 bytes: 811 * (to be exact, z.bz2 is exactly these 14 bytes:
812 * 42 5a 68 39 17 72 45 38 50 90 00 00 00 00). 812 * 42 5a 68 39 17 72 45 38 50 90 00 00 00 00).
813 */ 813 */
814 && i != RETVAL_OK 814 && i != RETVAL_OK
815 ) { 815 ) {
@@ -847,6 +847,36 @@ unpack_bz2_stream(transformer_state_t *xstate)
847 return i ? i : IF_DESKTOP(total_written) + 0; 847 return i ? i : IF_DESKTOP(total_written) + 0;
848} 848}
849 849
850char* FAST_FUNC
851unpack_bz2_data(const char *packed, int packed_len, int unpacked_len)
852{
853 char *outbuf = NULL;
854 bunzip_data *bd;
855 int i;
856 jmp_buf jmpbuf;
857
858 /* Setup for I/O error handling via longjmp */
859 i = setjmp(jmpbuf);
860 if (i == 0) {
861 i = start_bunzip(&jmpbuf,
862 &bd,
863 /* src_fd: */ -1,
864 /* inbuf: */ packed,
865 /* len: */ packed_len
866 );
867 }
868 /* read_bunzip can longjmp and end up here with i != 0
869 * on read data errors! Not trivial */
870 if (i == 0) {
871 /* Cannot use xmalloc: will leak bd in NOFORK case! */
872 outbuf = malloc_or_warn(unpacked_len);
873 if (outbuf)
874 read_bunzip(bd, outbuf, unpacked_len);
875 }
876 dealloc_bunzip(bd);
877 return outbuf;
878}
879
850#ifdef TESTING 880#ifdef TESTING
851 881
852static char *const bunzip_errors[] = { 882static char *const bunzip_errors[] = {
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index 6886239d0..668b01618 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -353,8 +353,10 @@ unpack_lzma_stream(transformer_state_t *xstate)
353 if ((int32_t)pos < 0) { 353 if ((int32_t)pos < 0) {
354 pos += header.dict_size; 354 pos += header.dict_size;
355 /* see unzip_bad_lzma_2.zip: */ 355 /* see unzip_bad_lzma_2.zip: */
356 if (pos >= buffer_size) 356 if (pos >= buffer_size) {
357 dbg("%d pos:%d buffer_size:%d", __LINE__, pos, buffer_size);
357 goto bad; 358 goto bad;
359 }
358 } 360 }
359 previous_byte = buffer[pos]; 361 previous_byte = buffer[pos];
360 goto one_byte1; 362 goto one_byte1;
@@ -430,10 +432,9 @@ unpack_lzma_stream(transformer_state_t *xstate)
430 for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--) 432 for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
431 rep0 = (rep0 << 1) | rc_direct_bit(rc); 433 rep0 = (rep0 << 1) | rc_direct_bit(rc);
432 rep0 <<= LZMA_NUM_ALIGN_BITS; 434 rep0 <<= LZMA_NUM_ALIGN_BITS;
433 if ((int32_t)rep0 < 0) { 435 // Note: (int32_t)rep0 may be < 0 here
434 dbg("%d rep0:%d", __LINE__, rep0); 436 // (I have linux-3.3.4.tar.lzma which has it).
435 goto bad; 437 // I moved the check after "++rep0 == 0" check below.
436 }
437 prob3 = p + LZMA_ALIGN; 438 prob3 = p + LZMA_ALIGN;
438 } 439 }
439 i2 = 1; 440 i2 = 1;
@@ -444,8 +445,13 @@ unpack_lzma_stream(transformer_state_t *xstate)
444 i2 <<= 1; 445 i2 <<= 1;
445 } 446 }
446 } 447 }
447 if (++rep0 == 0) 448 rep0++;
448 break; 449 if ((int32_t)rep0 <= 0) {
450 if (rep0 == 0)
451 break;
452 dbg("%d rep0:%d", __LINE__, rep0);
453 goto bad;
454 }
449 } 455 }
450 456
451 len += LZMA_MATCH_MIN_LEN; 457 len += LZMA_MATCH_MIN_LEN;
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index 5c495e14e..52fa4554a 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -414,7 +414,8 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
414// case 'D': /* GNU dump dir */ 414// case 'D': /* GNU dump dir */
415// case 'M': /* Continuation of multi volume archive */ 415// case 'M': /* Continuation of multi volume archive */
416// case 'N': /* Old GNU for names > 100 characters */ 416// case 'N': /* Old GNU for names > 100 characters */
417// case 'V': /* Volume header */ 417 case 'V': /* Volume header */
418 ; /* Fall through to skip it */
418#endif 419#endif
419 } 420 }
420 skip_ext_hdr: 421 skip_ext_hdr:
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index 0160a64fe..399ee03a7 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -304,8 +304,7 @@ static transformer_state_t *open_transformer(const char *fname, int fail_if_not_
304 304
305 if (ENABLE_FEATURE_SEAMLESS_LZMA) { 305 if (ENABLE_FEATURE_SEAMLESS_LZMA) {
306 /* .lzma has no header/signature, can only detect it by extension */ 306 /* .lzma has no header/signature, can only detect it by extension */
307 char *sfx = strrchr(fname, '.'); 307 if (is_suffixed_with(fname, ".lzma")) {
308 if (sfx && strcmp(sfx+1, "lzma") == 0) {
309 xstate = xzalloc(sizeof(*xstate)); 308 xstate = xzalloc(sizeof(*xstate));
310 xstate->src_fd = fd; 309 xstate->src_fd = fd;
311 xstate->xformer = unpack_lzma_stream; 310 xstate->xformer = unpack_lzma_stream;
diff --git a/archival/tar.c b/archival/tar.c
index 9a171ceea..22ad0e0f2 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -1197,8 +1197,16 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1197 tar_handle->seek = seek_by_read; 1197 tar_handle->seek = seek_by_read;
1198 } else 1198 } else
1199 if (ENABLE_FEATURE_TAR_AUTODETECT 1199 if (ENABLE_FEATURE_TAR_AUTODETECT
1200 && ENABLE_FEATURE_SEAMLESS_LZMA
1200 && flags == O_RDONLY 1201 && flags == O_RDONLY
1201 && !(opt & OPT_ANY_COMPRESS) 1202 && !(opt & OPT_ANY_COMPRESS)
1203 && is_suffixed_with(tar_filename, ".lzma")
1204 /* We do this only for .lzma files, they have no signature.
1205 * All other compression formats are recognized in
1206 * get_header_tar() when first tar block has invalid format.
1207 * Doing it here for all filenames would falsely trigger
1208 * on e.g. tarball with 1st file named "BZh5".
1209 */
1202 ) { 1210 ) {
1203 tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0); 1211 tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0);
1204 if (tar_handle->src_fd < 0) 1212 if (tar_handle->src_fd < 0)
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
index 18005618e..5a49bc4a8 100644
--- a/configs/mingw32_defconfig
+++ b/configs/mingw32_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Busybox version: 1.30.0.git 3# Busybox version: 1.30.0.git
4# Mon Sep 10 15:03:06 2018 4# Wed Nov 28 10:24:41 2018
5# 5#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set 7# CONFIG_PLATFORM_POSIX is not set
@@ -26,6 +26,7 @@ CONFIG_LFS=y
26# CONFIG_FEATURE_PIDFILE is not set 26# CONFIG_FEATURE_PIDFILE is not set
27CONFIG_PID_FILE_PATH="" 27CONFIG_PID_FILE_PATH=""
28CONFIG_BUSYBOX=y 28CONFIG_BUSYBOX=y
29CONFIG_FEATURE_SHOW_SCRIPT=y
29CONFIG_FEATURE_INSTALLER=y 30CONFIG_FEATURE_INSTALLER=y
30# CONFIG_INSTALL_NO_USR is not set 31# CONFIG_INSTALL_NO_USR is not set
31# CONFIG_FEATURE_SUID is not set 32# CONFIG_FEATURE_SUID is not set
@@ -96,6 +97,7 @@ CONFIG_NO_DEBUG_LIB=y
96# CONFIG_FEATURE_USE_BSS_TAIL is not set 97# CONFIG_FEATURE_USE_BSS_TAIL is not set
97CONFIG_FLOAT_DURATION=y 98CONFIG_FLOAT_DURATION=y
98CONFIG_FEATURE_RTMINMAX=y 99CONFIG_FEATURE_RTMINMAX=y
100CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y
99CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 101CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
100# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 102# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
101# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 103# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
@@ -668,6 +670,8 @@ CONFIG_XXD=y
668# CONFIG_FEATURE_MOUNT_FSTAB is not set 670# CONFIG_FEATURE_MOUNT_FSTAB is not set
669# CONFIG_FEATURE_MOUNT_OTHERTAB is not set 671# CONFIG_FEATURE_MOUNT_OTHERTAB is not set
670# CONFIG_MOUNTPOINT is not set 672# CONFIG_MOUNTPOINT is not set
673# CONFIG_NOLOGIN is not set
674# CONFIG_NOLOGIN_DEPENDENCIES is not set
671# CONFIG_NSENTER is not set 675# CONFIG_NSENTER is not set
672# CONFIG_PIVOT_ROOT is not set 676# CONFIG_PIVOT_ROOT is not set
673# CONFIG_RDATE is not set 677# CONFIG_RDATE is not set
@@ -916,6 +920,7 @@ CONFIG_NC_SERVER=y
916# CONFIG_NTPD is not set 920# CONFIG_NTPD is not set
917# CONFIG_FEATURE_NTPD_SERVER is not set 921# CONFIG_FEATURE_NTPD_SERVER is not set
918# CONFIG_FEATURE_NTPD_CONF is not set 922# CONFIG_FEATURE_NTPD_CONF is not set
923# CONFIG_FEATURE_NTP_AUTH is not set
919# CONFIG_PING is not set 924# CONFIG_PING is not set
920# CONFIG_PING6 is not set 925# CONFIG_PING6 is not set
921# CONFIG_FEATURE_FANCY_PING is not set 926# CONFIG_FEATURE_FANCY_PING is not set
@@ -1147,6 +1152,7 @@ CONFIG_FEATURE_SH_STANDALONE=y
1147CONFIG_FEATURE_SH_NOFORK=y 1152CONFIG_FEATURE_SH_NOFORK=y
1148# CONFIG_FEATURE_SH_READ_FRAC is not set 1153# CONFIG_FEATURE_SH_READ_FRAC is not set
1149CONFIG_FEATURE_SH_HISTFILESIZE=y 1154CONFIG_FEATURE_SH_HISTFILESIZE=y
1155CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS=y
1150 1156
1151# 1157#
1152# System Logging Utilities 1158# System Logging Utilities
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig
index 6389867f2..9d6e32104 100644
--- a/configs/mingw64_defconfig
+++ b/configs/mingw64_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Busybox version: 1.30.0.git 3# Busybox version: 1.30.0.git
4# Mon Sep 10 15:03:06 2018 4# Wed Nov 28 10:26:29 2018
5# 5#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set 7# CONFIG_PLATFORM_POSIX is not set
@@ -26,6 +26,7 @@ CONFIG_LFS=y
26# CONFIG_FEATURE_PIDFILE is not set 26# CONFIG_FEATURE_PIDFILE is not set
27CONFIG_PID_FILE_PATH="" 27CONFIG_PID_FILE_PATH=""
28CONFIG_BUSYBOX=y 28CONFIG_BUSYBOX=y
29CONFIG_FEATURE_SHOW_SCRIPT=y
29CONFIG_FEATURE_INSTALLER=y 30CONFIG_FEATURE_INSTALLER=y
30# CONFIG_INSTALL_NO_USR is not set 31# CONFIG_INSTALL_NO_USR is not set
31# CONFIG_FEATURE_SUID is not set 32# CONFIG_FEATURE_SUID is not set
@@ -96,6 +97,7 @@ CONFIG_NO_DEBUG_LIB=y
96# CONFIG_FEATURE_USE_BSS_TAIL is not set 97# CONFIG_FEATURE_USE_BSS_TAIL is not set
97CONFIG_FLOAT_DURATION=y 98CONFIG_FLOAT_DURATION=y
98CONFIG_FEATURE_RTMINMAX=y 99CONFIG_FEATURE_RTMINMAX=y
100CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y
99CONFIG_FEATURE_BUFFERS_USE_MALLOC=y 101CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
100# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set 102# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
101# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set 103# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
@@ -668,6 +670,8 @@ CONFIG_XXD=y
668# CONFIG_FEATURE_MOUNT_FSTAB is not set 670# CONFIG_FEATURE_MOUNT_FSTAB is not set
669# CONFIG_FEATURE_MOUNT_OTHERTAB is not set 671# CONFIG_FEATURE_MOUNT_OTHERTAB is not set
670# CONFIG_MOUNTPOINT is not set 672# CONFIG_MOUNTPOINT is not set
673# CONFIG_NOLOGIN is not set
674# CONFIG_NOLOGIN_DEPENDENCIES is not set
671# CONFIG_NSENTER is not set 675# CONFIG_NSENTER is not set
672# CONFIG_PIVOT_ROOT is not set 676# CONFIG_PIVOT_ROOT is not set
673# CONFIG_RDATE is not set 677# CONFIG_RDATE is not set
@@ -916,6 +920,7 @@ CONFIG_NC_SERVER=y
916# CONFIG_NTPD is not set 920# CONFIG_NTPD is not set
917# CONFIG_FEATURE_NTPD_SERVER is not set 921# CONFIG_FEATURE_NTPD_SERVER is not set
918# CONFIG_FEATURE_NTPD_CONF is not set 922# CONFIG_FEATURE_NTPD_CONF is not set
923# CONFIG_FEATURE_NTP_AUTH is not set
919# CONFIG_PING is not set 924# CONFIG_PING is not set
920# CONFIG_PING6 is not set 925# CONFIG_PING6 is not set
921# CONFIG_FEATURE_FANCY_PING is not set 926# CONFIG_FEATURE_FANCY_PING is not set
@@ -1147,6 +1152,7 @@ CONFIG_FEATURE_SH_STANDALONE=y
1147CONFIG_FEATURE_SH_NOFORK=y 1152CONFIG_FEATURE_SH_NOFORK=y
1148# CONFIG_FEATURE_SH_READ_FRAC is not set 1153# CONFIG_FEATURE_SH_READ_FRAC is not set
1149CONFIG_FEATURE_SH_HISTFILESIZE=y 1154CONFIG_FEATURE_SH_HISTFILESIZE=y
1155CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS=y
1150 1156
1151# 1157#
1152# System Logging Utilities 1158# System Logging Utilities
diff --git a/coreutils/dd.c b/coreutils/dd.c
index d29357dae..d73f6224b 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -37,7 +37,7 @@
37//config: elapsed time and speed. 37//config: elapsed time and speed.
38//config: 38//config:
39//config:config FEATURE_DD_IBS_OBS 39//config:config FEATURE_DD_IBS_OBS
40//config: bool "Enable ibs, obs, iflag and conv options" 40//config: bool "Enable ibs, obs, iflag, oflag and conv options"
41//config: default y 41//config: default y
42//config: depends on DD 42//config: depends on DD
43//config: help 43//config: help
@@ -56,8 +56,11 @@
56//kbuild:lib-$(CONFIG_DD) += dd.o 56//kbuild:lib-$(CONFIG_DD) += dd.o
57 57
58//usage:#define dd_trivial_usage 58//usage:#define dd_trivial_usage
59//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" 59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n"
60//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock]") 60//usage: IF_FEATURE_DD_IBS_OBS(
61//usage: " [conv=notrunc|noerror|sync|fsync]\n"
62//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes]"
63//usage: )
61//usage:#define dd_full_usage "\n\n" 64//usage:#define dd_full_usage "\n\n"
62//usage: "Copy a file with converting and formatting\n" 65//usage: "Copy a file with converting and formatting\n"
63//usage: "\n if=FILE Read from FILE instead of stdin" 66//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -80,6 +83,7 @@
80//usage: "\n conv=swab Swap every pair of bytes" 83//usage: "\n conv=swab Swap every pair of bytes"
81//usage: "\n iflag=skip_bytes skip=N is in bytes" 84//usage: "\n iflag=skip_bytes skip=N is in bytes"
82//usage: "\n iflag=fullblock Read full blocks" 85//usage: "\n iflag=fullblock Read full blocks"
86//usage: "\n oflag=seek_bytes seek=N is in bytes"
83//usage: ) 87//usage: )
84//usage: IF_FEATURE_DD_STATUS( 88//usage: IF_FEATURE_DD_STATUS(
85//usage: "\n status=noxfer Suppress rate output" 89//usage: "\n status=noxfer Suppress rate output"
@@ -136,10 +140,14 @@ enum {
136 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 140 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
137 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 141 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
138 /* end of input flags */ 142 /* end of input flags */
139 FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, 143 /* start of output flags */
140 FLAG_COUNT = 1 << 8, 144 FLAG_OFLAG_SHIFT = 7,
141 FLAG_STATUS_NONE = 1 << 9, 145 FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
142 FLAG_STATUS_NOXFER = 1 << 10, 146 /* end of output flags */
147 FLAG_TWOBUFS = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
148 FLAG_COUNT = 1 << 9,
149 FLAG_STATUS_NONE = 1 << 10,
150 FLAG_STATUS_NOXFER = 1 << 11,
143}; 151};
144 152
145static void dd_output_status(int UNUSED_PARAM cur_signal) 153static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -253,7 +261,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
253 static const char keywords[] ALIGN1 = 261 static const char keywords[] ALIGN1 =
254 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") 262 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0")
255#if ENABLE_FEATURE_DD_IBS_OBS 263#if ENABLE_FEATURE_DD_IBS_OBS
256 "ibs\0""obs\0""conv\0""iflag\0" 264 "ibs\0""obs\0""conv\0""iflag\0""oflag\0"
257#endif 265#endif
258 ; 266 ;
259#if ENABLE_FEATURE_DD_IBS_OBS 267#if ENABLE_FEATURE_DD_IBS_OBS
@@ -261,6 +269,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
261 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 269 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
262 static const char iflag_words[] ALIGN1 = 270 static const char iflag_words[] ALIGN1 =
263 "skip_bytes\0""fullblock\0"; 271 "skip_bytes\0""fullblock\0";
272 static const char oflag_words[] ALIGN1 =
273 "seek_bytes\0";
264#endif 274#endif
265#if ENABLE_FEATURE_DD_STATUS 275#if ENABLE_FEATURE_DD_STATUS
266 static const char status_words[] ALIGN1 = 276 static const char status_words[] ALIGN1 =
@@ -279,6 +289,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
279 OP_obs, 289 OP_obs,
280 OP_conv, 290 OP_conv,
281 OP_iflag, 291 OP_iflag,
292 OP_oflag,
282 /* Must be in the same order as FLAG_XXX! */ 293 /* Must be in the same order as FLAG_XXX! */
283 OP_conv_notrunc = 0, 294 OP_conv_notrunc = 0,
284 OP_conv_sync, 295 OP_conv_sync,
@@ -300,6 +311,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
300 //swab swap every pair of input bytes: will abort on non-even reads 311 //swab swap every pair of input bytes: will abort on non-even reads
301 OP_iflag_skip_bytes, 312 OP_iflag_skip_bytes,
302 OP_iflag_fullblock, 313 OP_iflag_fullblock,
314 OP_oflag_seek_bytes,
303#endif 315#endif
304 }; 316 };
305 smallint exitcode = EXIT_FAILURE; 317 smallint exitcode = EXIT_FAILURE;
@@ -315,13 +327,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
315#endif 327#endif
316 /* These are all zeroed at once! */ 328 /* These are all zeroed at once! */
317 struct { 329 struct {
318 size_t oc; 330 IF_FEATURE_DD_IBS_OBS(size_t ocount;)
319 ssize_t prev_read_size; /* for detecting swab failure */ 331 ssize_t prev_read_size; /* for detecting swab failure */
320 off_t count; 332 off_t count;
321 off_t seek, skip; 333 off_t seek, skip;
322 const char *infile, *outfile; 334 const char *infile, *outfile;
323 } Z; 335 } Z;
324#define oc (Z.oc ) 336#define ocount (Z.ocount )
325#define prev_read_size (Z.prev_read_size) 337#define prev_read_size (Z.prev_read_size)
326#define count (Z.count ) 338#define count (Z.count )
327#define seek (Z.seek ) 339#define seek (Z.seek )
@@ -371,6 +383,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
371 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT; 383 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
372 /*continue;*/ 384 /*continue;*/
373 } 385 }
386 if (what == OP_oflag) {
387 G.flags |= parse_comma_flags(val, oflag_words, "oflag") << FLAG_OFLAG_SHIFT;
388 /*continue;*/
389 }
374#endif 390#endif
375 if (what == OP_bs) { 391 if (what == OP_bs) {
376 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes); 392 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
@@ -447,7 +463,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
447 xmove_fd(xopen(outfile, oflag), ofd); 463 xmove_fd(xopen(outfile, oflag), ofd);
448 464
449 if (seek && !(G.flags & FLAG_NOTRUNC)) { 465 if (seek && !(G.flags & FLAG_NOTRUNC)) {
450 if (ftruncate(ofd, seek * obs) < 0) { 466 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
467 if (ftruncate(ofd, seek * blocksz) < 0) {
451 struct stat st; 468 struct stat st;
452 469
453 if (fstat(ofd, &st) < 0 470 if (fstat(ofd, &st) < 0
@@ -480,7 +497,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
480 } 497 }
481 } 498 }
482 if (seek) { 499 if (seek) {
483 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) 500 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
501 if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0)
484 goto die_outfile; 502 goto die_outfile;
485 } 503 }
486 504
@@ -536,24 +554,26 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
536 n = ibs; 554 n = ibs;
537 } 555 }
538 } 556 }
557#if ENABLE_FEATURE_DD_IBS_OBS
539 if (G.flags & FLAG_TWOBUFS) { 558 if (G.flags & FLAG_TWOBUFS) {
540 char *tmp = ibuf; 559 char *tmp = ibuf;
541 while (n) { 560 while (n) {
542 size_t d = obs - oc; 561 size_t d = obs - ocount;
543
544 if (d > (size_t)n) 562 if (d > (size_t)n)
545 d = n; 563 d = n;
546 memcpy(obuf + oc, tmp, d); 564 memcpy(obuf + ocount, tmp, d);
547 n -= d; 565 n -= d;
548 tmp += d; 566 tmp += d;
549 oc += d; 567 ocount += d;
550 if (oc == obs) { 568 if (ocount == obs) {
551 if (write_and_stats(obuf, obs, obs, outfile)) 569 if (write_and_stats(obuf, obs, obs, outfile))
552 goto out_status; 570 goto out_status;
553 oc = 0; 571 ocount = 0;
554 } 572 }
555 } 573 }
556 } else { 574 } else
575#endif
576 {
557 if (write_and_stats(ibuf, n, obs, outfile)) 577 if (write_and_stats(ibuf, n, obs, outfile))
558 goto out_status; 578 goto out_status;
559 } 579 }
@@ -564,11 +584,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
564 goto die_outfile; 584 goto die_outfile;
565 } 585 }
566 586
567 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 587#if ENABLE_FEATURE_DD_IBS_OBS
568 if (write_and_stats(obuf, oc, obs, outfile)) 588 if (ocount != 0) {
589 if (write_and_stats(obuf, ocount, obs, outfile))
569 goto out_status; 590 goto out_status;
570 } 591 }
571 592#endif
572 if (close(ifd) < 0) { 593 if (close(ifd) < 0) {
573 die_infile: 594 die_infile:
574 bb_simple_perror_msg_and_die(infile); 595 bb_simple_perror_msg_and_die(infile);
diff --git a/coreutils/printf.c b/coreutils/printf.c
index a666ff7ac..67d3b2eda 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -95,6 +95,12 @@ static int multiconvert(const char *arg, void *result, converter convert)
95 95
96static void FAST_FUNC conv_strtoull(const char *arg, void *result) 96static void FAST_FUNC conv_strtoull(const char *arg, void *result)
97{ 97{
98 /* Allow leading '+' - bb_strtoull() by itself does not allow it,
99 * and probably shouldn't (other callers might require purely numeric
100 * inputs to be allowed.
101 */
102 if (arg[0] == '+')
103 arg++;
98 *(unsigned long long*)result = bb_strtoull(arg, NULL, 0); 104 *(unsigned long long*)result = bb_strtoull(arg, NULL, 0);
99 /* both coreutils 6.10 and bash 3.2: 105 /* both coreutils 6.10 and bash 3.2:
100 * $ printf '%x\n' -2 106 * $ printf '%x\n' -2
@@ -107,6 +113,8 @@ static void FAST_FUNC conv_strtoull(const char *arg, void *result)
107} 113}
108static void FAST_FUNC conv_strtoll(const char *arg, void *result) 114static void FAST_FUNC conv_strtoll(const char *arg, void *result)
109{ 115{
116 if (arg[0] == '+')
117 arg++;
110 *(long long*)result = bb_strtoll(arg, NULL, 0); 118 *(long long*)result = bb_strtoll(arg, NULL, 0);
111} 119}
112static void FAST_FUNC conv_strtod(const char *arg, void *result) 120static void FAST_FUNC conv_strtod(const char *arg, void *result)
@@ -191,6 +199,7 @@ static void print_direc(char *format, unsigned fmt_length,
191 if (have_width - 1 == have_prec) 199 if (have_width - 1 == have_prec)
192 have_width = NULL; 200 have_width = NULL;
193 201
202 /* multiconvert sets errno = 0, but %s needs it cleared */
194 errno = 0; 203 errno = 0;
195 204
196 switch (format[fmt_length - 1]) { 205 switch (format[fmt_length - 1]) {
@@ -199,7 +208,7 @@ static void print_direc(char *format, unsigned fmt_length,
199 break; 208 break;
200 case 'd': 209 case 'd':
201 case 'i': 210 case 'i':
202 llv = my_xstrtoll(argument); 211 llv = my_xstrtoll(skip_whitespace(argument));
203 print_long: 212 print_long:
204 if (!have_width) { 213 if (!have_width) {
205 if (!have_prec) 214 if (!have_prec)
@@ -217,7 +226,7 @@ static void print_direc(char *format, unsigned fmt_length,
217 case 'u': 226 case 'u':
218 case 'x': 227 case 'x':
219 case 'X': 228 case 'X':
220 llv = my_xstrtoull(argument); 229 llv = my_xstrtoull(skip_whitespace(argument));
221 /* cheat: unsigned long and long have same width, so... */ 230 /* cheat: unsigned long and long have same width, so... */
222 goto print_long; 231 goto print_long;
223 case 's': 232 case 's':
diff --git a/docs/embedded-scripts.txt b/docs/embedded-scripts.txt
new file mode 100644
index 000000000..7a273d698
--- /dev/null
+++ b/docs/embedded-scripts.txt
@@ -0,0 +1,111 @@
1Embedded Shell Scripts in BusyBox
2=================================
3
4BusyBox allows applets to be implemented as shell scripts. Since
5this obviously requires a shell to interpret the scripts the feature
6depends on having a shell built into the binary. Either ash or hush
7will do. If both are present ash will be used. Support for embedded
8scripts also has to be enabled.
9
10It's unlikely that your applet will be implemented as a pure shell
11script: it will probably need some external commands. If these are
12to be provided by BusyBox you'll need to ensure they're enabled too.
13
14There are two ways to include scripts in BusyBox: the quick-and-dirty
15custom script and the full-featured scripted applet.
16
17Custom Scripts
18--------------
19
20When embedded script support is enabled the BusyBox build process
21assumes that any files in the directory 'embed' at the top level of
22the source tree are scripts to be embedded.
23
24The embed directory isn't present in the BusyBox source tree and
25BusyBox itself will never put anything there: it's entirely for the
26use of third parties.
27
28Adding a custom script is as simple as running the following sequence
29of commands in the BusyBox source directory:
30
31 mkdir embed
32 echo 'echo foo' >embed/foo
33 make defconfig
34 make
35
36The resulting binary includes the new applet foo!
37
38Custom scripts have limited opportunities for configuration: the only
39control developers have is to put them in the embed directory, or not.
40Everything else takes default values. For more control you need the
41additional features provided by scripted applets.
42
43Scripted Applets
44----------------
45
46Suppose we want to make a shell script version of the sample applet
47from the New Applet HOWTO. First we'd have to write a script (vaguely)
48equivalent to the C code:
49
50 return $(($RANDOM%256))
51
52This should be placed in the file applets_sh/mu in the source tree.
53
54Next we need the configuration data. This is very similar to the example
55code for the native applet:
56
57//config:config MU
58//config: bool "MU"
59//config: default y
60//config: help
61//config: Returns an indeterminate value.
62
63//applet:IF_MU(APPLET_SCRIPTED(mu, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, mu))
64
65//usage:#define mu_trivial_usage
66//usage: "[-abcde] FILE..."
67//usage:#define mu_full_usage
68//usage: "Returns an indeterminate value\n"
69//usage: "\n -a First function"
70//usage: "\n -b Second function"
71
72The only difference is that the applet is specified as being of type
73APPLET_SCRIPTED. It would also be useful to include details of any
74dependencies the script has. No external commands are used by our mu
75script, but it does depend on optional shell features. We can ensure
76these are selected by adding this to the configuration:
77
78//config:config MU_DEPENDENCIES
79//config: bool "Enable dependencies for mu"
80//config: default y
81//config: depends on MU
82//config: select ASH_RANDOM_SUPPORT
83//config: select FEATURE_SH_MATH
84//config: help
85//config: mu is implemented as a shell script. It requires support
86//config: for $RANDOM and arithmetic.
87
88The configuration data should be placed in a C file in an appropriate
89subdirectory. There isn't any C code, though! In this case the file
90could be miscutils/mu.c.
91
92Scripted applets are just as configurable as applets written in C.
93They can be enabled or disabled using the configuration menu; their
94install directory can be specified and their usage messages are stored
95along with those of all other applets.
96
97Additional Notes
98----------------
99
100The source for embedded scripts can be displayed by running:
101
102 busybox --show SCRIPT
103
104This can be disabled by turning off FEATURE_SHOW_SCRIPT in the
105configuration, though it won't prevent a determined user from
106extracting the source code.
107
108It can be argued that embedded scripts are linked into the BusyBox
109binary and are therefore not subject to the 'mere aggregation'
110exception in the GPL. If this is the case embedded scripts should
111have a licence compatible with BusyBox's GPL v2-only licence.
diff --git a/docs/posix_conformance.txt b/docs/posix_conformance.txt
index cdf89b744..0e6f4a317 100644
--- a/docs/posix_conformance.txt
+++ b/docs/posix_conformance.txt
@@ -182,6 +182,7 @@ dd compatibility options:
182 conv=fsync | yes | | 182 conv=fsync | yes | |
183 iflag=skip_bytes| yes | | 183 iflag=skip_bytes| yes | |
184 iflag=fullblock | yes | | 184 iflag=fullblock | yes | |
185 oflag=seek_bytes| yes | |
185 186
186df POSIX options 187df POSIX options
187 option | exists | compliant | remarks 188 option | exists | compliant | remarks
diff --git a/examples/udhcp/simple.script b/examples/udhcp/simple.script
index e4c1f2d76..44aa46ece 100755
--- a/examples/udhcp/simple.script
+++ b/examples/udhcp/simple.script
@@ -6,19 +6,31 @@ RESOLV_CONF="/etc/resolv.conf"
6[ -n "$1" ] || { echo "Error: should be called from udhcpc"; exit 1; } 6[ -n "$1" ] || { echo "Error: should be called from udhcpc"; exit 1; }
7 7
8NETMASK="" 8NETMASK=""
9[ -n "$subnet" ] && NETMASK="netmask $subnet" 9if command -v ip >/dev/null; then
10 [ -n "$subnet" ] && NETMASK="/$subnet"
11else
12 [ -n "$subnet" ] && NETMASK="netmask $subnet"
13fi
10BROADCAST="broadcast +" 14BROADCAST="broadcast +"
11[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" 15[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
12 16
13case "$1" in 17case "$1" in
14 deconfig) 18 deconfig)
15 echo "Setting IP address 0.0.0.0 on $interface" 19 echo "Setting IP address 0.0.0.0 on $interface"
16 ifconfig $interface 0.0.0.0 20 if command -v ip >/dev/null; then
21 ip addr flush dev $interface
22 else
23 ifconfig $interface 0.0.0.0
24 fi
17 ;; 25 ;;
18 26
19 renew|bound) 27 renew|bound)
20 echo "Setting IP address $ip on $interface" 28 echo "Setting IP address $ip on $interface"
21 ifconfig $interface $ip $NETMASK $BROADCAST 29 if command -v ip >/dev/null; then
30 ip addr add $ip$NETMASK $BROADCAST dev $interface
31 else
32 ifconfig $interface $ip $NETMASK $BROADCAST
33 fi
22 34
23 if [ -n "$router" ] ; then 35 if [ -n "$router" ] ; then
24 echo "Deleting routers" 36 echo "Deleting routers"
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 4399783ea..2ce5634ca 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -277,14 +277,15 @@ static int xargs_exec(void)
277 status = (errno == ENOENT) ? 127 : 126; 277 status = (errno == ENOENT) ? 127 : 126;
278 } 278 }
279 else if (status >= 0x180) { 279 else if (status >= 0x180) {
280 bb_error_msg("'%s' terminated by signal %d", 280 bb_error_msg("'%s' terminated by signal %u",
281 G.args[0], status - 0x180); 281 G.args[0], status - 0x180);
282 status = 125; 282 status = 125;
283 } 283 }
284 else if (status != 0) { 284 else if (status != 0) {
285 if (status == 255) { 285 if (status == 255) {
286 bb_error_msg("%s: exited with status 255; aborting", G.args[0]); 286 bb_error_msg("%s: exited with status 255; aborting", G.args[0]);
287 return 124; 287 status = 124;
288 goto ret;
288 } 289 }
289 /* "123 if any invocation of the command exited with status 1-125" 290 /* "123 if any invocation of the command exited with status 1-125"
290 * This implies that nonzero exit code is remembered, 291 * This implies that nonzero exit code is remembered,
@@ -293,7 +294,7 @@ static int xargs_exec(void)
293 G.xargs_exitcode = 123; 294 G.xargs_exitcode = 123;
294 status = 0; 295 status = 0;
295 } 296 }
296 297 ret:
297 if (status != 0) 298 if (status != 0)
298 G.xargs_exitcode = status; 299 G.xargs_exitcode = status;
299 return status; 300 return status;
diff --git a/include/.gitignore b/include/.gitignore
index 75afff9ca..13a96e018 100644
--- a/include/.gitignore
+++ b/include/.gitignore
@@ -5,6 +5,7 @@
5/autoconf.h 5/autoconf.h
6/bbconfigopts_bz2.h 6/bbconfigopts_bz2.h
7/bbconfigopts.h 7/bbconfigopts.h
8/embedded_scripts.h
8/NUM_APPLETS.h 9/NUM_APPLETS.h
9/usage_compressed.h 10/usage_compressed.h
10/usage.h 11/usage.h
diff --git a/include/applets.src.h b/include/applets.src.h
index 2ddf120ad..60968cec7 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -27,36 +27,49 @@ s - suid type:
27# define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 27# define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
28# define APPLET_NOEXEC(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 28# define APPLET_NOEXEC(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
29# define APPLET_NOFORK(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 29# define APPLET_NOFORK(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
30# define APPLET_SCRIPTED(name,main,l,s,help)
30 31
31#elif defined(NAME_MAIN) 32#elif defined(NAME_MAIN)
32# define APPLET(name,l,s) name name##_main 33# define APPLET(name,l,s) name name##_main
33# define APPLET_ODDNAME(name,main,l,s,help) name main##_main 34# define APPLET_ODDNAME(name,main,l,s,help) name main##_main
34# define APPLET_NOEXEC(name,main,l,s,help) name main##_main 35# define APPLET_NOEXEC(name,main,l,s,help) name main##_main
35# define APPLET_NOFORK(name,main,l,s,help) name main##_main 36# define APPLET_NOFORK(name,main,l,s,help) name main##_main
37# define APPLET_SCRIPTED(name,main,l,s,help) name scripted_main
36 38
37#elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE 39#elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE
38# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage name##_full_usage) 40# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage name##_full_usage)
39# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) 41# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
40# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) 42# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
41# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) 43# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
44# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage)
42 45
43#elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE 46#elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE
44# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage) 47# define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage)
45# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) 48# define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
46# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) 49# define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
47# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) 50# define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
51# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage)
48 52
49#elif defined(MAKE_LINKS) 53#elif defined(MAKE_LINKS)
50# define APPLET(name,l,c) LINK l name 54# define APPLET(name,l,c) LINK l name
51# define APPLET_ODDNAME(name,main,l,s,help) LINK l name 55# define APPLET_ODDNAME(name,main,l,s,help) LINK l name
52# define APPLET_NOEXEC(name,main,l,s,help) LINK l name 56# define APPLET_NOEXEC(name,main,l,s,help) LINK l name
53# define APPLET_NOFORK(name,main,l,s,help) LINK l name 57# define APPLET_NOFORK(name,main,l,s,help) LINK l name
58# define APPLET_SCRIPTED(name,main,l,s,help) LINK l name
54 59
55#elif defined(MAKE_SUID) 60#elif defined(MAKE_SUID)
56# define APPLET(name,l,s) SUID s l name 61# define APPLET(name,l,s) SUID s l name
57# define APPLET_ODDNAME(name,main,l,s,help) SUID s l name 62# define APPLET_ODDNAME(name,main,l,s,help) SUID s l name
58# define APPLET_NOEXEC(name,main,l,s,help) SUID s l name 63# define APPLET_NOEXEC(name,main,l,s,help) SUID s l name
59# define APPLET_NOFORK(name,main,l,s,help) SUID s l name 64# define APPLET_NOFORK(name,main,l,s,help) SUID s l name
65# define APPLET_SCRIPTED(name,main,l,s,help) SUID s l name
66
67#elif defined(MAKE_SCRIPTS)
68# define APPLET(name,l,s)
69# define APPLET_ODDNAME(name,main,l,s,help)
70# define APPLET_NOEXEC(name,main,l,s,help)
71# define APPLET_NOFORK(name,main,l,s,help)
72# define APPLET_SCRIPTED(name,main,l,s,help) SCRIPT name
60 73
61#else 74#else
62 static struct bb_applet applets[] = { /* name, main, location, need_suid */ 75 static struct bb_applet applets[] = { /* name, main, location, need_suid */
@@ -64,6 +77,7 @@ s - suid type:
64# define APPLET_ODDNAME(name,main,l,s,help) { #name, #main, l, s }, 77# define APPLET_ODDNAME(name,main,l,s,help) { #name, #main, l, s },
65# define APPLET_NOEXEC(name,main,l,s,help) { #name, #main, l, s, 1 }, 78# define APPLET_NOEXEC(name,main,l,s,help) { #name, #main, l, s, 1 },
66# define APPLET_NOFORK(name,main,l,s,help) { #name, #main, l, s, 1, 1 }, 79# define APPLET_NOFORK(name,main,l,s,help) { #name, #main, l, s, 1, 1 },
80# define APPLET_SCRIPTED(name,main,l,s,help) { #name, #main, l, s },
67#endif 81#endif
68 82
69#if ENABLE_INSTALL_NO_USR 83#if ENABLE_INSTALL_NO_USR
@@ -84,3 +98,4 @@ INSERT
84#undef APPLET_ODDNAME 98#undef APPLET_ODDNAME
85#undef APPLET_NOEXEC 99#undef APPLET_NOEXEC
86#undef APPLET_NOFORK 100#undef APPLET_NOFORK
101#undef APPLET_SCRIPTED
diff --git a/include/bb_archive.h b/include/bb_archive.h
index ace9c8e23..5abcdcb44 100644
--- a/include/bb_archive.h
+++ b/include/bb_archive.h
@@ -228,12 +228,7 @@ const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_F
228const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; 228const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC;
229 229
230/* A bit of bunzip2 internals are exposed for compressed help support: */ 230/* A bit of bunzip2 internals are exposed for compressed help support: */
231typedef struct bunzip_data bunzip_data; 231char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC;
232int start_bunzip(void *, bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC;
233/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
234 * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */
235int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
236void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
237 232
238/* Meaning and direction (input/output) of the fields are transformer-specific */ 233/* Meaning and direction (input/output) of the fields are transformer-specific */
239typedef struct transformer_state_t { 234typedef struct transformer_state_t {
diff --git a/include/libbb.h b/include/libbb.h
index 90fdd1178..405c929a2 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -777,18 +777,25 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC;
777// + inet_common.c has additional IPv4-only stuff 777// + inet_common.c has additional IPv4-only stuff
778 778
779 779
780struct tls_aes {
781 uint32_t key[60];
782 unsigned rounds;
783};
780#define TLS_MAX_MAC_SIZE 32 784#define TLS_MAX_MAC_SIZE 32
781#define TLS_MAX_KEY_SIZE 32 785#define TLS_MAX_KEY_SIZE 32
786#define TLS_MAX_IV_SIZE 4
782struct tls_handshake_data; /* opaque */ 787struct tls_handshake_data; /* opaque */
783typedef struct tls_state { 788typedef struct tls_state {
789 unsigned flags;
790
784 int ofd; 791 int ofd;
785 int ifd; 792 int ifd;
786 793
787 unsigned min_encrypted_len_on_read; 794 unsigned min_encrypted_len_on_read;
788 uint16_t cipher_id; 795 uint16_t cipher_id;
789 uint8_t encrypt_on_write;
790 unsigned MAC_size; 796 unsigned MAC_size;
791 unsigned key_size; 797 unsigned key_size;
798 unsigned IV_size;
792 799
793 uint8_t *outbuf; 800 uint8_t *outbuf;
794 int outbuf_size; 801 int outbuf_size;
@@ -810,12 +817,21 @@ typedef struct tls_state {
810 /*uint64_t read_seq64_be;*/ 817 /*uint64_t read_seq64_be;*/
811 uint64_t write_seq64_be; 818 uint64_t write_seq64_be;
812 819
820 /*uint8_t *server_write_MAC_key;*/
813 uint8_t *client_write_key; 821 uint8_t *client_write_key;
814 uint8_t *server_write_key; 822 uint8_t *server_write_key;
823 uint8_t *client_write_IV;
824 uint8_t *server_write_IV;
815 uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE]; 825 uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE];
816 uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE]; 826 uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE];
817 uint8_t client_write_k__[TLS_MAX_KEY_SIZE]; 827 uint8_t client_write_k__[TLS_MAX_KEY_SIZE];
818 uint8_t server_write_k__[TLS_MAX_KEY_SIZE]; 828 uint8_t server_write_k__[TLS_MAX_KEY_SIZE];
829 uint8_t client_write_I_[TLS_MAX_IV_SIZE];
830 uint8_t server_write_I_[TLS_MAX_IV_SIZE];
831
832 struct tls_aes aes_encrypt;
833 struct tls_aes aes_decrypt;
834 uint8_t H[16]; //used by AES_GCM
819} tls_state_t; 835} tls_state_t;
820 836
821static inline tls_state_t *new_tls_state(void) 837static inline tls_state_t *new_tls_state(void)
@@ -1366,9 +1382,22 @@ void bb_logenv_override(void) FAST_FUNC;
1366#define MAIN_EXTERNALLY_VISIBLE 1382#define MAIN_EXTERNALLY_VISIBLE
1367#endif 1383#endif
1368 1384
1385/* Embedded script support */
1386char *get_script_content(unsigned n) FAST_FUNC;
1387int scripted_main(int argc, char** argv);
1369 1388
1370/* Applets which are useful from another applets */ 1389/* Applets which are useful from another applets */
1371int bb_cat(char** argv) FAST_FUNC; 1390int bb_cat(char** argv) FAST_FUNC;
1391int ash_main(int argc, char** argv)
1392#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH
1393 MAIN_EXTERNALLY_VISIBLE
1394#endif
1395;
1396int hush_main(int argc, char** argv)
1397#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
1398 MAIN_EXTERNALLY_VISIBLE
1399#endif
1400;
1372/* If shell needs them, they exist even if not enabled as applets */ 1401/* If shell needs them, they exist even if not enabled as applets */
1373int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); 1402int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
1374int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); 1403int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
@@ -2041,7 +2070,7 @@ typedef struct bb_progress_t {
2041 (p)->curfile = NULL; \ 2070 (p)->curfile = NULL; \
2042} while (0) 2071} while (0)
2043void bb_progress_init(bb_progress_t *p, const char *curfile) FAST_FUNC; 2072void bb_progress_init(bb_progress_t *p, const char *curfile) FAST_FUNC;
2044void bb_progress_update(bb_progress_t *p, 2073int bb_progress_update(bb_progress_t *p,
2045 uoff_t beg_range, 2074 uoff_t beg_range,
2046 uoff_t transferred, 2075 uoff_t transferred,
2047 uoff_t totalsize) FAST_FUNC; 2076 uoff_t totalsize) FAST_FUNC;
diff --git a/include/platform.h b/include/platform.h
index 0d17062da..afd8cf292 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -252,6 +252,7 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING;
252# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) 252# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p))
253# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v)) 253# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v))
254# define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v)) 254# define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v))
255# define move_to_unaligned64(u64p, v) (*(bb__aliased_uint64_t*)(u64p) = (v))
255/* #elif ... - add your favorite arch today! */ 256/* #elif ... - add your favorite arch today! */
256#else 257#else
257# define BB_UNALIGNED_MEMACCESS_OK 0 258# define BB_UNALIGNED_MEMACCESS_OK 0
@@ -268,6 +269,10 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING;
268 uint32_t __t = (v); \ 269 uint32_t __t = (v); \
269 memcpy((u32p), &__t, 4); \ 270 memcpy((u32p), &__t, 4); \
270} while (0) 271} while (0)
272# define move_to_unaligned64(u64p, v) do { \
273 uint64_t __t = (v); \
274 memcpy((u64p), &__t, 8); \
275} while (0)
271#endif 276#endif
272 277
273/* Unaligned, fixed-endian accessors */ 278/* Unaligned, fixed-endian accessors */
diff --git a/include/usage.src.h b/include/usage.src.h
index 00369dfb3..d22efd3ba 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -14,6 +14,9 @@
14 14
15#define NOUSAGE_STR "\b" 15#define NOUSAGE_STR "\b"
16 16
17#define scripted_trivial_usage NOUSAGE_STR
18#define scripted_full_usage ""
19
17#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA 20#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
18# define CRYPT_METHODS_HELP_STR "des,md5,sha256/512" \ 21# define CRYPT_METHODS_HELP_STR "des,md5,sha256/512" \
19 " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" 22 " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")"
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index add609b78..3cbb5699c 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -59,6 +59,17 @@
59 59
60#include "usage_compressed.h" 60#include "usage_compressed.h"
61 61
62#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
63# define DEFINE_SCRIPT_DATA 1
64# include "embedded_scripts.h"
65#else
66# define NUM_SCRIPTS 0
67#endif
68#if NUM_SCRIPTS > 0
69# define BB_ARCHIVE_PUBLIC
70# include "bb_archive.h"
71static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS };
72#endif
62 73
63/* "Do not compress usage text if uncompressed text is small 74/* "Do not compress usage text if uncompressed text is small
64 * and we don't include bunzip2 code for other reasons" 75 * and we don't include bunzip2 code for other reasons"
@@ -105,36 +116,10 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
105#if ENABLE_FEATURE_COMPRESS_USAGE 116#if ENABLE_FEATURE_COMPRESS_USAGE
106 117
107static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; 118static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
108#define BB_ARCHIVE_PUBLIC 119# define BB_ARCHIVE_PUBLIC
109# include "bb_archive.h" 120# include "bb_archive.h"
110static const char *unpack_usage_messages(void) 121# define unpack_usage_messages() \
111{ 122 unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE))
112 char *outbuf = NULL;
113 bunzip_data *bd;
114 int i;
115 jmp_buf jmpbuf;
116
117 /* Setup for I/O error handling via longjmp */
118 i = setjmp(jmpbuf);
119 if (i == 0) {
120 i = start_bunzip(&jmpbuf,
121 &bd,
122 /* src_fd: */ -1,
123 /* inbuf: */ packed_usage,
124 /* len: */ sizeof(packed_usage)
125 );
126 }
127 /* read_bunzip can longjmp and end up here with i != 0
128 * on read data errors! Not trivial */
129 if (i == 0) {
130 /* Cannot use xmalloc: will leak bd in NOFORK case! */
131 outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE));
132 if (outbuf)
133 read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE));
134 }
135 dealloc_bunzip(bd);
136 return outbuf;
137}
138# define dealloc_usage_messages(s) free(s) 123# define dealloc_usage_messages(s) free(s)
139 124
140#else 125#else
@@ -152,21 +137,23 @@ void FAST_FUNC bb_show_usage(void)
152 /* Imagine that this applet is "true". Dont suck in printf! */ 137 /* Imagine that this applet is "true". Dont suck in printf! */
153 const char *usage_string = unpack_usage_messages(); 138 const char *usage_string = unpack_usage_messages();
154 139
155 if (*usage_string == '\b') { 140 if (usage_string) {
156 full_write2_str("No help available.\n\n"); 141 if (*usage_string == '\b') {
157 } else { 142 full_write2_str("No help available.\n\n");
158 full_write2_str("Usage: "SINGLE_APPLET_STR" "); 143 } else {
159 full_write2_str(usage_string); 144 full_write2_str("Usage: "SINGLE_APPLET_STR" ");
160 full_write2_str("\n\n"); 145 full_write2_str(usage_string);
146 full_write2_str("\n\n");
147 }
148 if (ENABLE_FEATURE_CLEAN_UP)
149 dealloc_usage_messages((char*)usage_string);
161 } 150 }
162 if (ENABLE_FEATURE_CLEAN_UP)
163 dealloc_usage_messages((char*)usage_string);
164#else 151#else
165 const char *p; 152 const char *p;
166 const char *usage_string = p = unpack_usage_messages(); 153 const char *usage_string = p = unpack_usage_messages();
167 int ap = find_applet_by_name(applet_name); 154 int ap = find_applet_by_name(applet_name);
168 155
169 if (ap < 0) /* never happens, paranoia */ 156 if (ap < 0 || usage_string == NULL)
170 xfunc_die(); 157 xfunc_die();
171 while (ap) { 158 while (ap) {
172 while (*p++) continue; 159 while (*p++) continue;
@@ -808,6 +795,50 @@ static void install_links(const char *busybox UNUSED_PARAM,
808 795
809static void run_applet_and_exit(const char *name, char **argv) NORETURN; 796static void run_applet_and_exit(const char *name, char **argv) NORETURN;
810 797
798# if NUM_SCRIPTS > 0
799static int find_script_by_name(const char *name)
800{
801 int i;
802 int applet = find_applet_by_name(name);
803
804 if (applet >= 0) {
805 for (i = 0; i < NUM_SCRIPTS; ++i)
806 if (applet_numbers[i] == applet)
807 return i;
808 }
809 return -1;
810}
811
812int scripted_main(int argc UNUSED_PARAM, char **argv)
813{
814 int script = find_script_by_name(applet_name);
815 if (script >= 0)
816#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH
817 exit(ash_main(-script - 1, argv));
818#elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
819 exit(hush_main(-script - 1, argv));
820#else
821 return 1;
822#endif
823 return 0;
824}
825
826char* FAST_FUNC
827get_script_content(unsigned n)
828{
829 char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts),
830 UNPACKED_SCRIPTS_LENGTH);
831 if (t) {
832 while (n != 0) {
833 while (*t++ != '\0')
834 continue;
835 n--;
836 }
837 }
838 return t;
839}
840# endif /* NUM_SCRIPTS > 0 */
841
811# if ENABLE_BUSYBOX 842# if ENABLE_BUSYBOX
812# if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION 843# if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION
813 /* 844 /*
@@ -850,6 +881,9 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
850 "\n" 881 "\n"
851 "Usage: busybox [function [arguments]...]\n" 882 "Usage: busybox [function [arguments]...]\n"
852 " or: busybox --list"IF_FULL_LIST_OPTION("[-full]")"\n" 883 " or: busybox --list"IF_FULL_LIST_OPTION("[-full]")"\n"
884# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0
885 " or: busybox --show SCRIPT\n"
886# endif
853 IF_FEATURE_INSTALLER( 887 IF_FEATURE_INSTALLER(
854 " or: busybox --install "IF_NOT_PLATFORM_MINGW32("[-s] ")"[DIR]\n" 888 " or: busybox --install "IF_NOT_PLATFORM_MINGW32("[-s] ")"[DIR]\n"
855 ) 889 )
@@ -877,9 +911,9 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
877 "Currently defined functions:\n" 911 "Currently defined functions:\n"
878 ); 912 );
879 col = 0; 913 col = 0;
880 a = applet_names;
881 /* prevent last comma to be in the very last pos */ 914 /* prevent last comma to be in the very last pos */
882 output_width--; 915 output_width--;
916 a = applet_names;
883 while (*a) { 917 while (*a) {
884 int len2 = strlen(a) + 2; 918 int len2 = strlen(a) + 2;
885 if (col >= (int)output_width - len2) { 919 if (col >= (int)output_width - len2) {
@@ -900,6 +934,19 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
900 return 0; 934 return 0;
901 } 935 }
902 936
937# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0
938 if (strcmp(argv[1], "--show") == 0) {
939 int n;
940 if (!argv[2])
941 bb_error_msg_and_die(bb_msg_requires_arg, "--show");
942 n = find_script_by_name(argv[2]);
943 if (n < 0)
944 bb_error_msg_and_die("script '%s' not found", argv[2]);
945 full_write1_str(get_script_content(n));
946 return 0;
947 }
948# endif
949
903 if (is_prefixed_with(argv[1], "--list")) { 950 if (is_prefixed_with(argv[1], "--list")) {
904 unsigned i = 0; 951 unsigned i = 0;
905 const char *a = applet_names; 952 const char *a = applet_names;
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index a53a382ce..9db79ea8b 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -794,6 +794,11 @@ static const uint32_t init512_lo[] = {
794}; 794};
795#endif /* NEED_SHA512 */ 795#endif /* NEED_SHA512 */
796 796
797// Note: SHA-384 is identical to SHA-512, except that initial hash values are
798// 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
799// 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
800// and the output is constructed by omitting last two 64-bit words of it.
801
797/* Initialize structure containing state of computation. 802/* Initialize structure containing state of computation.
798 (FIPS 180-2:5.3.2) */ 803 (FIPS 180-2:5.3.2) */
799void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) 804void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
diff --git a/libbb/progress.c b/libbb/progress.c
index 23e974ce7..d071ce705 100644
--- a/libbb/progress.c
+++ b/libbb/progress.c
@@ -69,7 +69,7 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile)
69 * will be "totalsize" bytes. 69 * will be "totalsize" bytes.
70 * If totalsize == 0, then it is unknown. 70 * If totalsize == 0, then it is unknown.
71 */ 71 */
72void FAST_FUNC bb_progress_update(bb_progress_t *p, 72int FAST_FUNC bb_progress_update(bb_progress_t *p,
73 uoff_t beg_size, 73 uoff_t beg_size,
74 uoff_t transferred, 74 uoff_t transferred,
75 uoff_t totalsize) 75 uoff_t totalsize)
@@ -94,7 +94,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
94 * Do not update on every call 94 * Do not update on every call
95 * (we can be called on every network read!) 95 * (we can be called on every network read!)
96 */ 96 */
97 return; 97 return -1;
98 } 98 }
99 99
100 /* Before we lose real, unscaled sizes, produce human-readable size string */ 100 /* Before we lose real, unscaled sizes, produce human-readable size string */
@@ -211,4 +211,5 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
211 } 211 }
212 if (notty) 212 if (notty)
213 fputc('\n', stderr); 213 fputc('\n', stderr);
214 return notty;
214} 215}
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c
index b3038e32d..f7d598c7a 100644
--- a/libbb/u_signal_names.c
+++ b/libbb/u_signal_names.c
@@ -12,6 +12,18 @@
12//config: help 12//config: help
13//config: Support RTMIN[+n] and RTMAX[-n] signal names 13//config: Support RTMIN[+n] and RTMAX[-n] signal names
14//config: in kill, killall etc. This costs ~250 bytes. 14//config: in kill, killall etc. This costs ~250 bytes.
15//config:
16//config:config FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
17//config: bool "Use the definitions of SIGRTMIN/SIGRTMAX provided by libc"
18//config: default y
19//config: depends on FEATURE_RTMINMAX
20//config: help
21//config: Some C libraries reserve a few real-time signals for internal
22//config: use, and adjust the values of SIGRTMIN/SIGRTMAX seen by
23//config: applications accordingly. Saying yes here means that a signal
24//config: name RTMIN+n will be interpreted according to the libc definition
25//config: of SIGRTMIN, and not the raw definition provided by the kernel.
26//config: This behavior matches "kill -l RTMIN+n" from bash.
15 27
16#include "libbb.h" 28#include "libbb.h"
17 29
@@ -123,7 +135,7 @@ static const char signals[][7] ALIGN1 = {
123#ifdef SIGSYS 135#ifdef SIGSYS
124 [SIGSYS ] = "SYS", 136 [SIGSYS ] = "SYS",
125#endif 137#endif
126#if ENABLE_FEATURE_RTMINMAX 138#if ENABLE_FEATURE_RTMINMAX && !ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
127# ifdef __SIGRTMIN 139# ifdef __SIGRTMIN
128 [__SIGRTMIN] = "RTMIN", 140 [__SIGRTMIN] = "RTMIN",
129# endif 141# endif
@@ -141,8 +153,12 @@ int FAST_FUNC get_signum(const char *name)
141{ 153{
142 unsigned i; 154 unsigned i;
143 155
156 /* bb_strtou returns UINT_MAX on error. NSIG is smaller
157 * than UINT_MAX on any sane Unix. Hence no need
158 * to check errno after bb_strtou().
159 */
144 i = bb_strtou(name, NULL, 10); 160 i = bb_strtou(name, NULL, 10);
145 if (!errno && i < NSIG) /* for shells, we allow 0 too */ 161 if (i < NSIG) /* for shells, we allow 0 too */
146 return i; 162 return i;
147 if (strncasecmp(name, "SIG", 3) == 0) 163 if (strncasecmp(name, "SIG", 3) == 0)
148 name += 3; 164 name += 3;
@@ -168,36 +184,46 @@ int FAST_FUNC get_signum(const char *name)
168# endif 184# endif
169#endif 185#endif
170 186
171#if ENABLE_FEATURE_RTMINMAX 187#if ENABLE_FEATURE_RTMINMAX && defined(SIGRTMIN) && defined(SIGRTMAX)
172# if defined(SIGRTMIN) && defined(SIGRTMAX) 188 {
173/* libc may use some rt sigs for pthreads and therefore "remap" SIGRTMIN/MAX, 189# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
174 * but we want to use "raw" SIGRTMIN/MAX. Underscored names, if exist, provide 190 /* Use the libc provided values. */
175 * them. If they don't exist, fall back to non-underscored ones: */ 191 unsigned sigrtmin = SIGRTMIN;
192 unsigned sigrtmax = SIGRTMAX;
193# else
194 /* Use the "raw" SIGRTMIN/MAX. Underscored names, if exist, provide
195 * them. If they don't exist, fall back to non-underscored ones: */
176# if !defined(__SIGRTMIN) 196# if !defined(__SIGRTMIN)
177# define __SIGRTMIN SIGRTMIN 197# define __SIGRTMIN SIGRTMIN
178# endif 198# endif
179# if !defined(__SIGRTMAX) 199# if !defined(__SIGRTMAX)
180# define __SIGRTMAX SIGRTMAX 200# define __SIGRTMAX SIGRTMAX
181# endif 201# endif
182 if (strncasecmp(name, "RTMIN", 5) == 0) { 202
183 if (!name[5]) 203# define sigrtmin __SIGRTMIN
184 return __SIGRTMIN; 204# define sigrtmax __SIGRTMAX
185 if (name[5] == '+') { 205# endif
186 i = bb_strtou(name + 6, NULL, 10); 206 if (strncasecmp(name, "RTMIN", 5) == 0) {
187 if (!errno && i <= __SIGRTMAX - __SIGRTMIN) 207 if (!name[5])
188 return __SIGRTMIN + i; 208 return sigrtmin;
209 if (name[5] == '+') {
210 i = bb_strtou(name + 6, NULL, 10);
211 if (i <= sigrtmax - sigrtmin)
212 return sigrtmin + i;
213 }
189 } 214 }
190 } 215 else if (strncasecmp(name, "RTMAX", 5) == 0) {
191 else if (strncasecmp(name, "RTMAX", 5) == 0) { 216 if (!name[5])
192 if (!name[5]) 217 return sigrtmax;
193 return __SIGRTMAX; 218 if (name[5] == '-') {
194 if (name[5] == '-') { 219 i = bb_strtou(name + 6, NULL, 10);
195 i = bb_strtou(name + 6, NULL, 10); 220 if (i <= sigrtmax - sigrtmin)
196 if (!errno && i <= __SIGRTMAX - __SIGRTMIN) 221 return sigrtmax - i;
197 return __SIGRTMAX - i; 222 }
198 } 223 }
224# undef sigrtmin
225# undef sigrtmax
199 } 226 }
200# endif
201#endif 227#endif
202 228
203 return -1; 229 return -1;
@@ -228,8 +254,16 @@ void FAST_FUNC print_signames(void)
228 printf("%2u) %s\n", signo, name); 254 printf("%2u) %s\n", signo, name);
229 } 255 }
230#if ENABLE_FEATURE_RTMINMAX 256#if ENABLE_FEATURE_RTMINMAX
231# ifdef __SIGRTMAX 257# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
258# if defined(SIGRTMIN) && defined(SIGRTMAX)
259 printf("%2u) %s\n", SIGRTMIN, "RTMIN");
260 printf("%2u) %s\n", SIGRTMAX, "RTMAX");
261# endif
262# else
263// __SIGRTMIN is included in signals[] array.
264# ifdef __SIGRTMAX
232 printf("%2u) %s\n", __SIGRTMAX, "RTMAX"); 265 printf("%2u) %s\n", __SIGRTMAX, "RTMAX");
266# endif
233# endif 267# endif
234#endif 268#endif
235} 269}
diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c
index aa42de648..077e03c5d 100644
--- a/miscutils/bbconfig.c
+++ b/miscutils/bbconfig.c
@@ -44,29 +44,10 @@ int bbconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
44int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 44int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
45{ 45{
46#if ENABLE_FEATURE_COMPRESS_BBCONFIG 46#if ENABLE_FEATURE_COMPRESS_BBCONFIG
47 bunzip_data *bd; 47 const char *outbuf = unpack_bz2_data(bbconfig_config_bz2,
48 int i; 48 sizeof(bbconfig_config_bz2), sizeof(bbconfig_config));
49 jmp_buf jmpbuf; 49 if (outbuf) {
50 50 full_write1_str(outbuf);
51 /* Setup for I/O error handling via longjmp */
52 i = setjmp(jmpbuf);
53 if (i == 0) {
54 i = start_bunzip(&jmpbuf,
55 &bd,
56 /* src_fd: */ -1,
57 /* inbuf: */ bbconfig_config_bz2,
58 /* len: */ sizeof(bbconfig_config_bz2)
59 );
60 }
61 /* read_bunzip can longjmp and end up here with i != 0
62 * on read data errors! Not trivial */
63 if (i == 0) {
64 /* Cannot use xmalloc: will leak bd in NOFORK case! */
65 char *outbuf = malloc_or_warn(sizeof(bbconfig_config));
66 if (outbuf) {
67 read_bunzip(bd, outbuf, sizeof(bbconfig_config));
68 full_write1_str(outbuf);
69 }
70 } 51 }
71#else 52#else
72 full_write1_str(bbconfig_config); 53 full_write1_str(bbconfig_config);
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 59f6d54f3..291e4cb90 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -245,7 +245,7 @@ static int FAST_FUNC config_file_action(const char *filename,
245 parser_t *p; 245 parser_t *p;
246 struct module_entry *m; 246 struct module_entry *m;
247 int rc = TRUE; 247 int rc = TRUE;
248 const char *base, *ext; 248 const char *base;
249 249
250 /* Skip files that begin with a "." */ 250 /* Skip files that begin with a "." */
251 base = bb_basename(filename); 251 base = bb_basename(filename);
@@ -266,8 +266,7 @@ static int FAST_FUNC config_file_action(const char *filename,
266 * "include FILE_NOT_ENDING_IN_CONF" must work too. 266 * "include FILE_NOT_ENDING_IN_CONF" must work too.
267 */ 267 */
268 if (depth != 0) { 268 if (depth != 0) {
269 ext = strrchr(base, '.'); 269 if (!is_suffixed_with(base, ".conf"))
270 if (ext == NULL || strcmp(ext + 1, "conf"))
271 goto error; 270 goto error;
272 } 271 }
273 272
diff --git a/networking/brctl.c b/networking/brctl.c
index 5d5f0af30..ba4a714f8 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -241,7 +241,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
241 241
242#if ENABLE_FEATURE_BRCTL_SHOW 242#if ENABLE_FEATURE_BRCTL_SHOW
243 if (key == ARG_show) { /* show */ 243 if (key == ARG_show) { /* show */
244 char brname[IFNAMSIZ]; 244 char buf[IFNAMSIZ];
245 int bridx[MAX_PORTS]; 245 int bridx[MAX_PORTS];
246 int i, num; 246 int i, num;
247 arm_ioctl(args, BRCTL_GET_BRIDGES, 247 arm_ioctl(args, BRCTL_GET_BRIDGES,
@@ -249,19 +249,18 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
249 num = xioctl(fd, SIOCGIFBR, args); 249 num = xioctl(fd, SIOCGIFBR, args);
250 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); 250 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
251 for (i = 0; i < num; i++) { 251 for (i = 0; i < num; i++) {
252 char ifname[IFNAMSIZ];
253 int j, tabs; 252 int j, tabs;
254 struct __bridge_info bi; 253 struct __bridge_info bi;
255 unsigned char *x; 254 unsigned char *x;
256 255
257 if (!if_indextoname(bridx[i], brname)) 256 if (!if_indextoname(bridx[i], buf))
258 bb_perror_msg_and_die("can't get bridge name for index %d", i); 257 bb_perror_msg_and_die("can't get bridge name for index %d", i);
259 strncpy_IFNAMSIZ(ifr.ifr_name, brname); 258 strncpy_IFNAMSIZ(ifr.ifr_name, buf);
260 259
261 arm_ioctl(args, BRCTL_GET_BRIDGE_INFO, 260 arm_ioctl(args, BRCTL_GET_BRIDGE_INFO,
262 (unsigned long) &bi, 0); 261 (unsigned long) &bi, 0);
263 xioctl(fd, SIOCDEVPRIVATE, &ifr); 262 xioctl(fd, SIOCDEVPRIVATE, &ifr);
264 printf("%s\t\t", brname); 263 printf("%s\t\t", buf);
265 264
266 /* print bridge id */ 265 /* print bridge id */
267 x = (unsigned char *) &bi.bridge_id; 266 x = (unsigned char *) &bi.bridge_id;
@@ -280,13 +279,13 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
280 for (j = 0; j < MAX_PORTS; j++) { 279 for (j = 0; j < MAX_PORTS; j++) {
281 if (!ifidx[j]) 280 if (!ifidx[j])
282 continue; 281 continue;
283 if (!if_indextoname(ifidx[j], ifname)) 282 if (!if_indextoname(ifidx[j], buf))
284 bb_perror_msg_and_die("can't get interface name for index %d", j); 283 bb_perror_msg_and_die("can't get interface name for index %d", j);
285 if (tabs) 284 if (tabs)
286 printf("\t\t\t\t\t"); 285 printf("\t\t\t\t\t");
287 else 286 else
288 tabs = 1; 287 tabs = 1;
289 printf("\t\t%s\n", ifname); 288 printf("\t\t%s\n", buf);
290 } 289 }
291 if (!tabs) /* bridge has no interfaces */ 290 if (!tabs) /* bridge has no interfaces */
292 bb_putchar('\n'); 291 bb_putchar('\n');
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index bedb01a1c..103756b59 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -16,6 +16,7 @@
16#include "libbb.h" 16#include "libbb.h"
17#include <netinet/tcp.h> 17#include <netinet/tcp.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <getopt.h>
19 20
20#define NBD_SET_SOCK _IO(0xab, 0) 21#define NBD_SET_SOCK _IO(0xab, 0)
21#define NBD_SET_BLKSIZE _IO(0xab, 1) 22#define NBD_SET_BLKSIZE _IO(0xab, 1)
@@ -27,57 +28,144 @@
27#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) 28#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
28#define NBD_DISCONNECT _IO(0xab, 8) 29#define NBD_DISCONNECT _IO(0xab, 8)
29#define NBD_SET_TIMEOUT _IO(0xab, 9) 30#define NBD_SET_TIMEOUT _IO(0xab, 9)
31#define NBD_SET_FLAGS _IO(0xab, 10)
30 32
31//usage:#define nbdclient_trivial_usage 33//usage:#define nbdclient_trivial_usage
32//usage: "HOST PORT BLOCKDEV" 34//usage: "{ [-b BLKSIZE] [-N NAME] [-t SEC] [-p] HOST [PORT] | -d } BLOCKDEV"
33//usage:#define nbdclient_full_usage "\n\n" 35//usage:#define nbdclient_full_usage "\n\n"
34//usage: "Connect to HOST and provide a network block device on BLOCKDEV" 36//usage: "Connect to HOST and provide network block device on BLOCKDEV"
35 37
36//TODO: more compat with nbd-client version 2.9.13 - 38//TODO: more compat with nbd-client version 3.17 -
37//Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-persist] [-nofork] 39//nbd-client host [ port ] nbd-device [ -connections num ] [ -sdp ] [ -swap ]
38//Or : nbd-client -d nbd_device 40// [ -persist ] [ -nofork ] [ -nonetlink ] [ -systemd-mark ]
39//Or : nbd-client -c nbd_device 41// [ -block-size block size ] [ -timeout seconds ] [ -name name ]
40//Default value for blocksize is 1024 (recommended for ethernet) 42// [ -certfile certfile ] [ -keyfile keyfile ] [ -cacertfile cacertfile ]
43// [ -tlshostname hostname ]
44//nbd-client -unix path nbd-device [ -connections num ] [ -sdp ] [ -swap ]
45// [ -persist ] [ -nofork ] [ -nonetlink ] [ -systemd-mark ]
46// [ -block-size block size ] [ -timeout seconds ] [ -name name ]
47//nbd-client nbd-device
48//nbd-client -d nbd-device
49//nbd-client -c nbd-device
50//nbd-client -l host [ port ]
51//nbd-client [ -netlink ] -l host
52//
53//Default value for blocksize is 4096
41//Allowed values for blocksize are 512,1024,2048,4096 54//Allowed values for blocksize are 512,1024,2048,4096
42//Note, that kernel 2.4.2 and older ones do not work correctly with
43//blocksizes other than 1024 without patches
44 55
45int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 56int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
46int nbdclient_main(int argc UNUSED_PARAM, char **argv) 57int nbdclient_main(int argc, char **argv)
47{ 58{
48 unsigned long timeout = 0;
49#if BB_MMU 59#if BB_MMU
50 int nofork = 0; 60 bool nofork;
51#endif 61#endif
52 char *host, *port, *device; 62 bool opt_d;
63 bool opt_p;
64 const char *host, *port, *device;
65 const char *name;
66 unsigned blksize, size_blocks;
67 unsigned timeout;
68 int ch;
53 struct nbd_header_t { 69 struct nbd_header_t {
54 uint64_t magic1; // "NBDMAGIC" 70 uint64_t magic1; // "NBDMAGIC"
55 uint64_t magic2; // 0x420281861253 big endian 71 uint64_t magic2; // old style: 0x420281861253 big endian
72 // // new style: 0x49484156454F5054 (IHAVEOPT)
73 } nbd_header;
74 struct old_nbd_header_t {
56 uint64_t devsize; 75 uint64_t devsize;
57 uint32_t flags; 76 uint32_t flags;
58 char data[124]; 77 char data[124];
59 } nbd_header; 78 } old_nbd_header;
79 struct new_nbd_header_t {
80 uint64_t devsize;
81 uint16_t transmission_flags;
82 char data[124];
83 } new_nbd_header;
84 struct nbd_opt_t {
85 uint64_t magic;
86 uint32_t opt;
87 uint32_t len;
88 } nbd_opts;
60 89
61 BUILD_BUG_ON(offsetof(struct nbd_header_t, data) != 8+8+8+4); 90 static const struct option long_options[] = {
91 { "block-size", required_argument, NULL, 'b' },
92 { "timeout" , required_argument, NULL, 't' },
93 { "name" , required_argument, NULL, 'n' },
94 { "persist" , no_argument , NULL, 'p' },
95 { NULL }
96 };
62 97
63 // Parse command line stuff (just a stub now) 98 BUILD_BUG_ON(offsetof(struct old_nbd_header_t, data) != 8 + 4);
64 if (!argv[1] || !argv[2] || !argv[3] || argv[4]) 99 BUILD_BUG_ON(offsetof(struct new_nbd_header_t, data) != 8 + 2);
65 bb_show_usage();
66 100
67#if !BB_MMU 101#if !BB_MMU
68 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); 102 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
69#endif 103#endif
70 104
71 host = argv[1]; 105 // Parse args. nbd-client uses stupid "one-dash long options" style :(
72 port = argv[2]; 106 // Even though short forms (-b,-t,-N,-p) exist for all long opts,
73 device = argv[3]; 107 // older manpages only contained long forms, which probably resulted
108 // in many scripts using them.
109 blksize = 4096;
110 timeout = 0;
111 name = ""; // use of "" instead of NULL simplifies strlen() later
112 opt_d = opt_p = 0;
113 while ((ch = getopt_long_only(argc, argv, "dN:", long_options, NULL)) != -1) {
114 switch (ch) {
115 case 'p': // -persist
116 opt_p = 1;
117 break;
118 case 'd': // -d
119 opt_d = 1;
120 break;
121 case 'b': // -block-size
122 blksize = xatou(optarg);
123 break;
124 case 't': // -timeout
125 timeout = xatou(optarg);
126 break;
127 case 'N': // -N
128 case 'n': // -name
129 name = optarg;
130 break;
131 default:
132 bb_show_usage();
133 }
134 }
135 argv += optind;
136
137 if (opt_d) { // -d
138 if (argv[0] && !argv[1]) {
139 int nbd = xopen(argv[0], O_RDWR);
140 ioctl(nbd, NBD_DISCONNECT);
141 ioctl(nbd, NBD_CLEAR_SOCK);
142 if (ENABLE_FEATURE_CLEAN_UP)
143 close(nbd);
144 return 0;
145 }
146 bb_show_usage();
147 }
148
149 // Allow only argv[] of: HOST [PORT] BLOCKDEV
150 if (!argv[0] || !argv[1] || (argv[2] && argv[3])) {
151 bb_show_usage();
152 }
74 153
75 // Repeat until spanked (-persist behavior) 154 host = argv[0];
76 for (;;) { 155 port = argv[2] ? argv[1] : "10809";
156 device = argv[2] ? argv[2] : argv[1];
157
158 // Repeat until spanked if -persist
159#if BB_MMU
160 nofork = 0;
161#endif
162 do {
77 int sock, nbd; 163 int sock, nbd;
78 int ro; 164 int ro;
165 int proto_new; // 0 for old, 1 for new
166 char *data;
79 167
80 // Make sure the /dev/nbd exists 168 // Make sure BLOCKDEV exists
81 nbd = xopen(device, O_RDWR); 169 nbd = xopen(device, O_RDWR);
82 170
83 // Find and connect to server 171 // Find and connect to server
@@ -85,40 +173,95 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv)
85 setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY); 173 setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY);
86 174
87 // Log on to the server 175 // Log on to the server
88 xread(sock, &nbd_header, 8+8+8+4 + 124); 176 xread(sock, &nbd_header, 8 + 8);
89 if (memcmp(&nbd_header.magic1, "NBDMAGIC""\x00\x00\x42\x02\x81\x86\x12\x53", 16) != 0) 177 if (memcmp(&nbd_header.magic1, "NBDMAGIC",
178 sizeof(nbd_header.magic1)) != 0
179 ) {
180 bb_error_msg_and_die("login failed");
181 }
182 if (memcmp(&nbd_header.magic2,
183 "\x00\x00\x42\x02\x81\x86\x12\x53",
184 sizeof(nbd_header.magic2)) == 0
185 ) {
186 proto_new = 0;
187 } else if (memcmp(&nbd_header.magic2, "IHAVEOPT", 8) == 0) {
188 proto_new = 1;
189 } else {
90 bb_error_msg_and_die("login failed"); 190 bb_error_msg_and_die("login failed");
191 }
192
193 if (!proto_new) {
194 xread(sock, &old_nbd_header,
195 sizeof(old_nbd_header.devsize) +
196 sizeof(old_nbd_header.flags) +
197 sizeof(old_nbd_header.data));
198 size_blocks = SWAP_BE64(old_nbd_header.devsize) / blksize;
199 ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long) blksize);
200 ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks);
201 ioctl(nbd, NBD_CLEAR_SOCK);
202 ro = !!(old_nbd_header.flags & htons(2));
203 data = old_nbd_header.data;
204 } else {
205 unsigned namelen;
206 uint16_t handshake_flags;
207
208 xread(sock, &handshake_flags, sizeof(handshake_flags));
209 xwrite(sock, &const_int_0, sizeof(const_int_0)); // client_flags
210
211 memcpy(&nbd_opts.magic, "IHAVEOPT",
212 sizeof(nbd_opts.magic));
213 nbd_opts.opt = htonl(1); // NBD_OPT_EXPORT_NAME
214 namelen = strlen(name);
215 nbd_opts.len = htonl(namelen);
216 xwrite(sock, &nbd_opts,
217 sizeof(nbd_opts.magic) +
218 sizeof(nbd_opts.opt) +
219 sizeof(nbd_opts.len));
220 xwrite(sock, name, namelen);
91 221
92 // Set 4k block size. Everything uses that these days 222 xread(sock, &new_nbd_header,
93 ioctl(nbd, NBD_SET_BLKSIZE, 4096); 223 sizeof(new_nbd_header.devsize) +
94 ioctl(nbd, NBD_SET_SIZE_BLOCKS, SWAP_BE64(nbd_header.devsize) / 4096); 224 sizeof(new_nbd_header.transmission_flags) +
95 ioctl(nbd, NBD_CLEAR_SOCK); 225 sizeof(new_nbd_header.data));
226 size_blocks = SWAP_BE64(new_nbd_header.devsize) / blksize;
227 ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long) blksize);
228 ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks);
229 ioctl(nbd, NBD_CLEAR_SOCK);
230 ioctl(nbd, NBD_SET_FLAGS,
231 ntohs(new_nbd_header.transmission_flags));
232 ro = !!(new_nbd_header.transmission_flags & htons(2));
233 data = new_nbd_header.data;
234 }
96 235
97 // If the sucker was exported read only, respect that locally 236 if (ioctl(nbd, BLKROSET, &ro) < 0) {
98 ro = (nbd_header.flags & SWAP_BE32(2)) / SWAP_BE32(2);
99 if (ioctl(nbd, BLKROSET, &ro) < 0)
100 bb_perror_msg_and_die("BLKROSET"); 237 bb_perror_msg_and_die("BLKROSET");
238 }
101 239
102 if (timeout) 240 if (timeout) {
103 if (ioctl(nbd, NBD_SET_TIMEOUT, timeout)) 241 if (ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long) timeout)) {
104 bb_perror_msg_and_die("NBD_SET_TIMEOUT"); 242 bb_perror_msg_and_die("NBD_SET_TIMEOUT");
105 if (ioctl(nbd, NBD_SET_SOCK, sock)) 243 }
106 bb_perror_msg_and_die("NBD_SET_SOCK"); 244 }
107 245
108 // if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); 246 if (ioctl(nbd, NBD_SET_SOCK, sock)) {
247 bb_perror_msg_and_die("NBD_SET_SOCK");
248 }
109 249
250 //if (swap) mlockall(MCL_CURRENT|MCL_FUTURE);
110#if BB_MMU 251#if BB_MMU
111 // Open the device to force reread of the partition table. 252 // Open the device to force reread of the partition table.
112 // Need to do it in a separate process, since open(device) 253 // Need to do it in a separate process, since open(device)
113 // needs some other process to sit in ioctl(nbd, NBD_DO_IT). 254 // needs some other process to sit in ioctl(nbd, NBD_DO_IT).
114 if (fork() == 0) { 255 if (fork() == 0) {
256 /* child */
115 char *s = strrchr(device, '/'); 257 char *s = strrchr(device, '/');
116 sprintf(nbd_header.data, "/sys/block/%.32s/pid", s ? s + 1 : device); 258 sprintf(data, "/sys/block/%.32s/pid", s ? s + 1 : device);
117 // Is it up yet? 259 // Is it up yet?
118 for (;;) { 260 for (;;) {
119 int fd = open(nbd_header.data, O_RDONLY); 261 int fd = open(data, O_RDONLY);
120 if (fd >= 0) { 262 if (fd >= 0) {
121 //close(fd); 263 if (ENABLE_FEATURE_CLEAN_UP)
264 close(fd);
122 break; 265 break;
123 } 266 }
124 sleep(1); 267 sleep(1);
@@ -133,7 +276,6 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv)
133 nofork = 1; 276 nofork = 1;
134 } 277 }
135#endif 278#endif
136
137 // This turns us (the process that calls this ioctl) 279 // This turns us (the process that calls this ioctl)
138 // into a dedicated NBD request handler. 280 // into a dedicated NBD request handler.
139 // We block here for a long time. 281 // We block here for a long time.
@@ -148,7 +290,7 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv)
148 290
149 close(sock); 291 close(sock);
150 close(nbd); 292 close(nbd);
151 } 293 } while (opt_p);
152 294
153 return 0; 295 return 0;
154} 296}
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 1ebdc34c3..041cac762 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -62,13 +62,20 @@
62//config: help 62//config: help
63//config: Make ntpd look in /etc/ntp.conf for peers. Only "server address" 63//config: Make ntpd look in /etc/ntp.conf for peers. Only "server address"
64//config: is supported. 64//config: is supported.
65//config:
66//config:config FEATURE_NTP_AUTH
67//config: bool "Support md5/sha1 message authentication codes"
68//config: default y
69//config: depends on NTPD
65 70
66//applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) 71//applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
67 72
68//kbuild:lib-$(CONFIG_NTPD) += ntpd.o 73//kbuild:lib-$(CONFIG_NTPD) += ntpd.o
69 74
70//usage:#define ntpd_trivial_usage 75//usage:#define ntpd_trivial_usage
71//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..." 76//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l] [-I IFACE")"] [-S PROG]"
77//usage: IF_NOT_FEATURE_NTP_AUTH(" [-p PEER]...")
78//usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...")
72//usage:#define ntpd_full_usage "\n\n" 79//usage:#define ntpd_full_usage "\n\n"
73//usage: "NTP client/server\n" 80//usage: "NTP client/server\n"
74//usage: "\n -d Verbose (may be repeated)" 81//usage: "\n -d Verbose (may be repeated)"
@@ -76,8 +83,16 @@
76//usage: "\n -q Quit after clock is set" 83//usage: "\n -q Quit after clock is set"
77//usage: "\n -N Run at high priority" 84//usage: "\n -N Run at high priority"
78//usage: "\n -w Do not set time (only query peers), implies -n" 85//usage: "\n -w Do not set time (only query peers), implies -n"
79//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" 86//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 min"
87//usage: IF_NOT_FEATURE_NTP_AUTH(
80//usage: "\n -p PEER Obtain time from PEER (may be repeated)" 88//usage: "\n -p PEER Obtain time from PEER (may be repeated)"
89//usage: )
90//usage: IF_FEATURE_NTP_AUTH(
91//usage: "\n -k FILE Key file (ntp.keys compatible)"
92//usage: "\n -p [keyno:NUM:]PEER"
93//usage: "\n Obtain time from PEER (may be repeated)"
94//usage: "\n Use key NUM for authentication"
95//usage: )
81//usage: IF_FEATURE_NTPD_CONF( 96//usage: IF_FEATURE_NTPD_CONF(
82//usage: "\n If -p is not given, 'server HOST' lines" 97//usage: "\n If -p is not given, 'server HOST' lines"
83//usage: "\n from /etc/ntp.conf are used" 98//usage: "\n from /etc/ntp.conf are used"
@@ -228,14 +243,18 @@
228/* Parameter averaging constant */ 243/* Parameter averaging constant */
229#define AVG 4 244#define AVG 4
230 245
246#define MAX_KEY_NUMBER 65535
247#define KEYID_SIZE sizeof(uint32_t)
231 248
232enum { 249enum {
233 NTP_VERSION = 4, 250 NTP_VERSION = 4,
234 NTP_MAXSTRATUM = 15, 251 NTP_MAXSTRATUM = 15,
235 252
236 NTP_DIGESTSIZE = 16, 253 NTP_MD5_DIGESTSIZE = 16,
237 NTP_MSGSIZE_NOAUTH = 48, 254 NTP_MSGSIZE_NOAUTH = 48,
238 NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE), 255 NTP_MSGSIZE_MD5_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_MD5_DIGESTSIZE,
256 NTP_SHA1_DIGESTSIZE = 20,
257 NTP_MSGSIZE_SHA1_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_SHA1_DIGESTSIZE,
239 258
240 /* Status Masks */ 259 /* Status Masks */
241 MODE_MASK = (7 << 0), 260 MODE_MASK = (7 << 0),
@@ -288,7 +307,7 @@ typedef struct {
288 l_fixedpt_t m_rectime; 307 l_fixedpt_t m_rectime;
289 l_fixedpt_t m_xmttime; 308 l_fixedpt_t m_xmttime;
290 uint32_t m_keyid; 309 uint32_t m_keyid;
291 uint8_t m_digest[NTP_DIGESTSIZE]; 310 uint8_t m_digest[ENABLE_FEATURE_NTP_AUTH ? NTP_SHA1_DIGESTSIZE : NTP_MD5_DIGESTSIZE];
292} msg_t; 311} msg_t;
293 312
294typedef struct { 313typedef struct {
@@ -297,9 +316,26 @@ typedef struct {
297 double d_dispersion; 316 double d_dispersion;
298} datapoint_t; 317} datapoint_t;
299 318
319#if ENABLE_FEATURE_NTP_AUTH
320enum {
321 HASH_MD5,
322 HASH_SHA1,
323};
324typedef struct {
325 unsigned id; //try uint16_t?
326 smalluint type;
327 smalluint msg_size;
328 smalluint key_length;
329 char key[0];
330} key_entry_t;
331#endif
332
300typedef struct { 333typedef struct {
301 len_and_sockaddr *p_lsa; 334 len_and_sockaddr *p_lsa;
302 char *p_dotted; 335 char *p_dotted;
336#if ENABLE_FEATURE_NTP_AUTH
337 key_entry_t *key_entry;
338#endif
303 int p_fd; 339 int p_fd;
304 int datapoint_idx; 340 int datapoint_idx;
305 uint32_t lastpkt_refid; 341 uint32_t lastpkt_refid;
@@ -337,13 +373,14 @@ enum {
337 OPT_q = (1 << 1), 373 OPT_q = (1 << 1),
338 OPT_N = (1 << 2), 374 OPT_N = (1 << 2),
339 OPT_x = (1 << 3), 375 OPT_x = (1 << 3),
376 OPT_k = (1 << 4) * ENABLE_FEATURE_NTP_AUTH,
340 /* Insert new options above this line. */ 377 /* Insert new options above this line. */
341 /* Non-compat options: */ 378 /* Non-compat options: */
342 OPT_w = (1 << 4), 379 OPT_w = (1 << (4+ENABLE_FEATURE_NTP_AUTH)),
343 OPT_p = (1 << 5), 380 OPT_p = (1 << (5+ENABLE_FEATURE_NTP_AUTH)),
344 OPT_S = (1 << 6), 381 OPT_S = (1 << (6+ENABLE_FEATURE_NTP_AUTH)),
345 OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, 382 OPT_l = (1 << (7+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER,
346 OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER, 383 OPT_I = (1 << (8+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER,
347 /* We hijack some bits for other purposes */ 384 /* We hijack some bits for other purposes */
348 OPT_qq = (1 << 31), 385 OPT_qq = (1 << 31),
349}; 386};
@@ -816,8 +853,12 @@ resolve_peer_hostname(peer_t *p)
816 return lsa; 853 return lsa;
817} 854}
818 855
856#if !ENABLE_FEATURE_NTP_AUTH
857#define add_peers(s, key_entry) \
858 add_peers(s)
859#endif
819static void 860static void
820add_peers(const char *s) 861add_peers(const char *s, key_entry_t *key_entry)
821{ 862{
822 llist_t *item; 863 llist_t *item;
823 peer_t *p; 864 peer_t *p;
@@ -846,6 +887,7 @@ add_peers(const char *s)
846 } 887 }
847 } 888 }
848 889
890 IF_FEATURE_NTP_AUTH(p->key_entry = key_entry;)
849 llist_add_to(&G.ntp_peers, p); 891 llist_add_to(&G.ntp_peers, p);
850 G.peer_cnt++; 892 G.peer_cnt++;
851} 893}
@@ -870,6 +912,48 @@ do_sendto(int fd,
870 return 0; 912 return 0;
871} 913}
872 914
915#if ENABLE_FEATURE_NTP_AUTH
916static void
917hash(key_entry_t *key_entry, const msg_t *msg, uint8_t *output)
918{
919 union {
920 md5_ctx_t m;
921 sha1_ctx_t s;
922 } ctx;
923 unsigned hash_size = sizeof(*msg) - sizeof(msg->m_keyid) - sizeof(msg->m_digest);
924
925 switch (key_entry->type) {
926 case HASH_MD5:
927 md5_begin(&ctx.m);
928 md5_hash(&ctx.m, key_entry->key, key_entry->key_length);
929 md5_hash(&ctx.m, msg, hash_size);
930 md5_end(&ctx.m, output);
931 break;
932 default: /* it's HASH_SHA1 */
933 sha1_begin(&ctx.s);
934 sha1_hash(&ctx.s, key_entry->key, key_entry->key_length);
935 sha1_hash(&ctx.s, msg, hash_size);
936 sha1_end(&ctx.s, output);
937 break;
938 }
939}
940
941static void
942hash_peer(peer_t *p)
943{
944 p->p_xmt_msg.m_keyid = htonl(p->key_entry->id);
945 hash(p->key_entry, &p->p_xmt_msg, p->p_xmt_msg.m_digest);
946}
947
948static int
949hashes_differ(peer_t *p, const msg_t *msg)
950{
951 uint8_t digest[NTP_SHA1_DIGESTSIZE];
952 hash(p->key_entry, msg, digest);
953 return memcmp(digest, msg->m_digest, p->key_entry->msg_size - NTP_MSGSIZE_NOAUTH - KEYID_SIZE);
954}
955#endif
956
873static void 957static void
874send_query_to_peer(peer_t *p) 958send_query_to_peer(peer_t *p)
875{ 959{
@@ -946,9 +1030,18 @@ send_query_to_peer(peer_t *p)
946 */ 1030 */
947 p->reachable_bits <<= 1; 1031 p->reachable_bits <<= 1;
948 1032
1033#if ENABLE_FEATURE_NTP_AUTH
1034 if (p->key_entry)
1035 hash_peer(p);
949 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, 1036 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
950 &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 1037 &p->p_xmt_msg, !p->key_entry ? NTP_MSGSIZE_NOAUTH : p->key_entry->msg_size) == -1
951 ) { 1038 )
1039#else
1040 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
1041 &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1
1042 )
1043#endif
1044 {
952 close(p->p_fd); 1045 close(p->p_fd);
953 p->p_fd = -1; 1046 p->p_fd = -1;
954 /* 1047 /*
@@ -1924,10 +2017,21 @@ recv_and_process_peer_pkt(peer_t *p)
1924 bb_perror_msg_and_die("recv(%s) error", p->p_dotted); 2017 bb_perror_msg_and_die("recv(%s) error", p->p_dotted);
1925 } 2018 }
1926 2019
1927 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 2020#if ENABLE_FEATURE_NTP_AUTH
2021 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH) {
2022 bb_error_msg("malformed packet received from %s", p->p_dotted);
2023 return;
2024 }
2025 if (p->key_entry && hashes_differ(p, &msg)) {
2026 bb_error_msg("invalid cryptographic hash received from %s", p->p_dotted);
2027 return;
2028 }
2029#else
2030 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH) {
1928 bb_error_msg("malformed packet received from %s", p->p_dotted); 2031 bb_error_msg("malformed packet received from %s", p->p_dotted);
1929 return; 2032 return;
1930 } 2033 }
2034#endif
1931 2035
1932 if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl 2036 if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl
1933 || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl 2037 || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl
@@ -2135,7 +2239,12 @@ recv_and_process_client_pkt(void /*int fd*/)
2135 from = xzalloc(to->len); 2239 from = xzalloc(to->len);
2136 2240
2137 size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len); 2241 size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
2138 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 2242#if ENABLE_FEATURE_NTP_AUTH
2243 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH)
2244#else
2245 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH)
2246#endif
2247 {
2139 char *addr; 2248 char *addr;
2140 if (size < 0) { 2249 if (size < 0) {
2141 if (errno == EAGAIN) 2250 if (errno == EAGAIN)
@@ -2278,6 +2387,19 @@ recv_and_process_client_pkt(void /*int fd*/)
2278 * with the -g and -q options. See the tinker command for other options. 2387 * with the -g and -q options. See the tinker command for other options.
2279 * Note: The kernel time discipline is disabled with this option. 2388 * Note: The kernel time discipline is disabled with this option.
2280 */ 2389 */
2390#if ENABLE_FEATURE_NTP_AUTH
2391static key_entry_t *
2392find_key_entry(llist_t *key_entries, unsigned id)
2393{
2394 while (key_entries) {
2395 key_entry_t *cur = (key_entry_t*) key_entries->data;
2396 if (cur->id == id)
2397 return cur;
2398 key_entries = key_entries->link;
2399 }
2400 bb_error_msg_and_die("key %u is not defined", id);
2401}
2402#endif
2281 2403
2282/* By doing init in a separate function we decrease stack usage 2404/* By doing init in a separate function we decrease stack usage
2283 * in main loop. 2405 * in main loop.
@@ -2286,6 +2408,10 @@ static NOINLINE void ntp_init(char **argv)
2286{ 2408{
2287 unsigned opts; 2409 unsigned opts;
2288 llist_t *peers; 2410 llist_t *peers;
2411#if ENABLE_FEATURE_NTP_AUTH
2412 llist_t *key_entries;
2413 char *key_file_path;
2414#endif
2289 2415
2290 srand(getpid()); 2416 srand(getpid());
2291 2417
@@ -2302,8 +2428,10 @@ static NOINLINE void ntp_init(char **argv)
2302 2428
2303 /* Parse options */ 2429 /* Parse options */
2304 peers = NULL; 2430 peers = NULL;
2431 IF_FEATURE_NTP_AUTH(key_entries = NULL;)
2305 opts = getopt32(argv, "^" 2432 opts = getopt32(argv, "^"
2306 "nqNx" /* compat */ 2433 "nqNx" /* compat */
2434 IF_FEATURE_NTP_AUTH("k:") /* compat */
2307 "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ 2435 "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
2308 IF_FEATURE_NTPD_SERVER("I:") /* compat */ 2436 IF_FEATURE_NTPD_SERVER("I:") /* compat */
2309 "d" /* compat */ 2437 "d" /* compat */
@@ -2311,11 +2439,11 @@ static NOINLINE void ntp_init(char **argv)
2311 "\0" 2439 "\0"
2312 "dd:wn" /* -d: counter; -p: list; -w implies -n */ 2440 "dd:wn" /* -d: counter; -p: list; -w implies -n */
2313 IF_FEATURE_NTPD_SERVER(":Il") /* -I implies -l */ 2441 IF_FEATURE_NTPD_SERVER(":Il") /* -I implies -l */
2314 , &peers, &G.script_name, 2442 IF_FEATURE_NTP_AUTH(, &key_file_path)
2315#if ENABLE_FEATURE_NTPD_SERVER 2443 , &peers, &G.script_name
2316 &G.if_name, 2444 IF_FEATURE_NTPD_SERVER(, &G.if_name)
2317#endif 2445 , &G.verbose
2318 &G.verbose); 2446 );
2319 2447
2320// if (opts & OPT_x) /* disable stepping, only slew is allowed */ 2448// if (opts & OPT_x) /* disable stepping, only slew is allowed */
2321// G.time_was_stepped = 1; 2449// G.time_was_stepped = 1;
@@ -2341,19 +2469,108 @@ static NOINLINE void ntp_init(char **argv)
2341 logmode = LOGMODE_NONE; 2469 logmode = LOGMODE_NONE;
2342 } 2470 }
2343 2471
2472#if ENABLE_FEATURE_NTP_AUTH
2473 if (opts & OPT_k) {
2474 char *tokens[4];
2475 parser_t *parser;
2476
2477 parser = config_open(key_file_path);
2478 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL | PARSE_MIN_DIE) == 3) {
2479 key_entry_t *key_entry;
2480 char buffer[40];
2481 smalluint hash_type;
2482 smalluint msg_size;
2483 smalluint key_length;
2484 char *key;
2485
2486 if ((tokens[1][0] | 0x20) == 'm')
2487 /* supports 'M' and 'md5' formats */
2488 hash_type = HASH_MD5;
2489 else
2490 if (strncasecmp(tokens[1], "sha", 3) == 0)
2491 /* supports 'sha' and 'sha1' formats */
2492 hash_type = HASH_SHA1;
2493 else
2494 bb_error_msg_and_die("only MD5 and SHA1 keys supported");
2495/* man ntp.keys:
2496 * MD5 The key is 1 to 16 printable characters terminated by an EOL,
2497 * whitespace, or a # (which is the "start of comment" character).
2498 * SHA
2499 * SHA1
2500 * RMD160 The key is a hex-encoded ASCII string of 40 characters, which
2501 * is truncated as necessary.
2502 */
2503 key_length = strnlen(tokens[2], sizeof(buffer)+1);
2504 if (key_length >= sizeof(buffer)+1) {
2505 err:
2506 bb_error_msg_and_die("malformed key at line %u", parser->lineno);
2507 }
2508 if (hash_type == HASH_MD5) {
2509 key = tokens[2];
2510 msg_size = NTP_MSGSIZE_MD5_AUTH;
2511 } else /* it's hash_type == HASH_SHA1 */
2512 if (!(key_length & 1)) {
2513 key_length >>= 1;
2514 if (!hex2bin(buffer, tokens[2], key_length))
2515 goto err;
2516 key = buffer;
2517 msg_size = NTP_MSGSIZE_SHA1_AUTH;
2518 } else {
2519 goto err;
2520 }
2521 key_entry = xzalloc(sizeof(*key_entry) + key_length);
2522 key_entry->type = hash_type;
2523 key_entry->msg_size = msg_size;
2524 key_entry->key_length = key_length;
2525 memcpy(key_entry->key, key, key_length);
2526 key_entry->id = xatou_range(tokens[0], 1, MAX_KEY_NUMBER);
2527 llist_add_to(&key_entries, key_entry);
2528 }
2529 config_close(parser);
2530 }
2531#endif
2344 if (peers) { 2532 if (peers) {
2533#if ENABLE_FEATURE_NTP_AUTH
2534 while (peers) {
2535 char *peer = llist_pop(&peers);
2536 key_entry_t *key_entry = NULL;
2537 if (strncmp(peer, "keyno:", 6) == 0) {
2538 char *end;
2539 int key_id;
2540 peer += 6;
2541 end = strchr(peer, ':');
2542 if (!end) bb_show_usage();
2543 *end = '\0';
2544 key_id = xatou_range(peer, 1, MAX_KEY_NUMBER);
2545 *end = ':';
2546 key_entry = find_key_entry(key_entries, key_id);
2547 peer = end + 1;
2548 }
2549 add_peers(peer, key_entry);
2550 }
2551#else
2345 while (peers) 2552 while (peers)
2346 add_peers(llist_pop(&peers)); 2553 add_peers(llist_pop(&peers), NULL);
2554#endif
2347 } 2555 }
2348#if ENABLE_FEATURE_NTPD_CONF 2556#if ENABLE_FEATURE_NTPD_CONF
2349 else { 2557 else {
2350 parser_t *parser; 2558 parser_t *parser;
2351 char *token[3]; 2559 char *token[3 + 2*ENABLE_FEATURE_NTP_AUTH];
2352 2560
2353 parser = config_open("/etc/ntp.conf"); 2561 parser = config_open("/etc/ntp.conf");
2354 while (config_read(parser, token, 3, 1, "# \t", PARSE_NORMAL)) { 2562 while (config_read(parser, token, 3 + 2*ENABLE_FEATURE_NTP_AUTH, 1, "# \t", PARSE_NORMAL)) {
2355 if (strcmp(token[0], "server") == 0 && token[1]) { 2563 if (strcmp(token[0], "server") == 0 && token[1]) {
2356 add_peers(token[1]); 2564# if ENABLE_FEATURE_NTP_AUTH
2565 key_entry_t *key_entry = NULL;
2566 if (token[2] && token[3] && strcmp(token[2], "key") == 0) {
2567 unsigned key_id = xatou_range(token[3], 1, MAX_KEY_NUMBER);
2568 key_entry = find_key_entry(key_entries, key_id);
2569 }
2570 add_peers(token[1], key_entry);
2571# else
2572 add_peers(token[1], NULL);
2573# endif
2357 continue; 2574 continue;
2358 } 2575 }
2359 bb_error_msg("skipping %s:%u: unimplemented command '%s'", 2576 bb_error_msg("skipping %s:%u: unimplemented command '%s'",
@@ -2394,6 +2611,7 @@ static NOINLINE void ntp_init(char **argv)
2394 | (1 << SIGCHLD) 2611 | (1 << SIGCHLD)
2395 , SIG_IGN 2612 , SIG_IGN
2396 ); 2613 );
2614//TODO: free unused elements of key_entries?
2397} 2615}
2398 2616
2399int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; 2617int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
diff --git a/networking/tls.c b/networking/tls.c
index fce1d0ea6..38eb79798 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -12,16 +12,18 @@
12//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o 12//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o
13//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o 13//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o
14//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o 14//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o
15//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o
16//kbuild:lib-$(CONFIG_TLS) += tls_aes.o 15//kbuild:lib-$(CONFIG_TLS) += tls_aes.o
17////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o 16//kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o
17//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o
18//kbuild:lib-$(CONFIG_TLS) += tls_fe.o
18 19
19#include "tls.h" 20#include "tls.h"
20 21
22// works against "openssl s_server -cipher NULL"
23// and against wolfssl-3.9.10-stable/examples/server/server.c:
24#define ALLOW_RSA_NULL_SHA256 0 // for testing (does everything except encrypting)
25
21//Tested against kernel.org: 26//Tested against kernel.org:
22//TLS 1.2
23#define TLS_MAJ 3
24#define TLS_MIN 3
25//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box 27//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box
26//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE 28//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE
27//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE 29//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE
@@ -35,26 +37,28 @@
35//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 37//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
36//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE 38//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
37//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE 39//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE
38//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? 40//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE
39
40// works against "openssl s_server -cipher NULL"
41// and against wolfssl-3.9.10-stable/examples/server/server.c:
42//#define CIPHER_ID1 TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting)
43 41
44// works against wolfssl-3.9.10-stable/examples/server/server.c 42// works against wolfssl-3.9.10-stable/examples/server/server.c
45// works for kernel.org 43// works for kernel.org
46// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) 44// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page)
47// getting alert 40 "handshake failure" at once 45// getting alert 40 "handshake failure" at once
48// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher 46// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher
49// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256 47// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-SHA256
50// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384 48// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-GCM-SHA384
51// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 49// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA256
52// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 50// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-GCM-SHA256
53// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA 51// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA
54// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) 52// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported)
55#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer 53//#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D
56// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" 54// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz"
57#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA 55//#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F
56
57// bug #11456:
58// ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305
59//#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F
60// host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009)
61//#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009
58 62
59 63
60#define TLS_DEBUG 0 64#define TLS_DEBUG 0
@@ -84,6 +88,11 @@
84# define dbg_der(...) ((void)0) 88# define dbg_der(...) ((void)0)
85#endif 89#endif
86 90
91
92//TLS 1.2
93#define TLS_MAJ 3
94#define TLS_MIN 3
95
87#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 /* 0x14 */ 96#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 /* 0x14 */
88#define RECORD_TYPE_ALERT 21 /* 0x15 */ 97#define RECORD_TYPE_ALERT 21 /* 0x15 */
89#define RECORD_TYPE_HANDSHAKE 22 /* 0x16 */ 98#define RECORD_TYPE_HANDSHAKE 22 /* 0x16 */
@@ -102,66 +111,98 @@
102#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 /* 0x10 */ 111#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 /* 0x10 */
103#define HANDSHAKE_FINISHED 20 /* 0x14 */ 112#define HANDSHAKE_FINISHED 20 /* 0x14 */
104 113
114#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF /* not a real cipher id... */
115
105#define SSL_NULL_WITH_NULL_NULL 0x0000 116#define SSL_NULL_WITH_NULL_NULL 0x0000
106#define SSL_RSA_WITH_NULL_MD5 0x0001 117#define SSL_RSA_WITH_NULL_MD5 0x0001
107#define SSL_RSA_WITH_NULL_SHA 0x0002 118#define SSL_RSA_WITH_NULL_SHA 0x0002
108#define SSL_RSA_WITH_RC4_128_MD5 0x0004 119#define SSL_RSA_WITH_RC4_128_MD5 0x0004
109#define SSL_RSA_WITH_RC4_128_SHA 0x0005 120#define SSL_RSA_WITH_RC4_128_SHA 0x0005
121#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */
110#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ 122#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */
111#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */
112#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */
113#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */
114
115#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
116 123
117#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */
118#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */ 124#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */
119#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */ 125#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */
120#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */ 126#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */
127#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /*SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 */
121#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */ 128#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */
122#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */
123#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */
124#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */
125#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */ 129#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */
130#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */
131#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */
126#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */ 132#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */
133#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */
127#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */ 134#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */
128#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */ 135#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */
129#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ 136#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */
137#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */
130#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */ 138#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */
131#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */
132#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */
133#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */ 139#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */
134#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */ 140#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */
135#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ 141#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */
142#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */
143#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD */
144#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD */
145#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD */
146#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD */
147#define TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 /* RFC 5288 */
148#define TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 /* RFC 5288 */
149#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */
150#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */
136#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ 151#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */
137#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */ 152#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */
138#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */ 153#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 */
139#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */ 154#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 */
140#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */
141#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */
142#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */
143#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ 155#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */
144#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ 156#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */
145#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */ 157#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */
146#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */ 158#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 */
159#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 */
160#define TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 /* RFC 4492 */
161#define TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 /* RFC 4492 */
162#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 */
163#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 */
147#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ 164#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */
148#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */ 165#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */
149#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */ 166#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 */
150#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */ 167#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 */
151#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ 168#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */
152#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ 169#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */
153
154/* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */ 170/* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */
155#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ 171#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD */
156#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ 172#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD */
157#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */
158#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */
159#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */ 173#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */
160#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */ 174#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */
161#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */ 175#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /*TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD */
162#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */ 176#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD */
163#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ 177#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */
164#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ 178#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */
179#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035
180#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036
181#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037
182#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038
183
184/* From http://wiki.mozilla.org/Security/Server_Side_TLS */
185/* and 'openssl ciphers -V -stdname' */
186#define TLS_RSA_WITH_AES_128_CCM 0xC09C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(128) Mac=AEAD */
187#define TLS_RSA_WITH_AES_256_CCM 0xC09D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(256) Mac=AEAD */
188#define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(128) Mac=AEAD */
189#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(256) Mac=AEAD */
190#define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(128) Mac=AEAD */
191#define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(256) Mac=AEAD */
192#define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(128) Mac=AEAD */
193#define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(256) Mac=AEAD */
194#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(128) Mac=AEAD */
195#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(256) Mac=AEAD */
196#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(128) Mac=AEAD */
197#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(256) Mac=AEAD */
198#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /*TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */
199#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */
200#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /*TLSv1.2 Kx=DH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */
201
202#define TLS_AES_128_GCM_SHA256 0x1301 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD */
203#define TLS_AES_256_GCM_SHA384 0x1302 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD */
204#define TLS_CHACHA20_POLY1305_SHA256 0x1303 /*TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD */
205#define TLS_AES_128_CCM_SHA256 0x1304 /*TLSv1.3 Kx=any Au=any Enc=AESCCM(128) Mac=AEAD */
165 206
166/* Might go to libbb.h */ 207/* Might go to libbb.h */
167#define TLS_MAX_CRYPTBLOCK_SIZE 16 208#define TLS_MAX_CRYPTBLOCK_SIZE 16
@@ -172,7 +213,6 @@ enum {
172 SHA1_OUTSIZE = 20, 213 SHA1_OUTSIZE = 20,
173 SHA256_OUTSIZE = 32, 214 SHA256_OUTSIZE = 32,
174 215
175 AES_BLOCKSIZE = 16,
176 AES128_KEYSIZE = 16, 216 AES128_KEYSIZE = 16,
177 AES256_KEYSIZE = 32, 217 AES256_KEYSIZE = 32,
178 218
@@ -181,10 +221,10 @@ enum {
181 RECHDR_LEN = 5, 221 RECHDR_LEN = 5,
182 222
183 /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */ 223 /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */
184 OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ 224 OUTBUF_PFX = 8 + AES_BLOCK_SIZE, /* header + IV */
185 OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */ 225 OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */
186 226
187 // RFC 5246 227 // RFC 5246:
188 // | 6.2.1. Fragmentation 228 // | 6.2.1. Fragmentation
189 // | The record layer fragments information blocks into TLSPlaintext 229 // | The record layer fragments information blocks into TLSPlaintext
190 // | records carrying data in chunks of 2^14 bytes or less. Client 230 // | records carrying data in chunks of 2^14 bytes or less. Client
@@ -219,6 +259,14 @@ enum {
219 // | The length (in bytes) of the following TLSCiphertext.fragment. 259 // | The length (in bytes) of the following TLSCiphertext.fragment.
220 // | The length MUST NOT exceed 2^14 + 2048. 260 // | The length MUST NOT exceed 2^14 + 2048.
221 MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048, 261 MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048,
262
263 /* Bits for tls->flags */
264 NEED_EC_KEY = 1 << 0,
265 GOT_CERT_RSA_KEY_ALG = 1 << 1,
266 GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused
267 GOT_EC_KEY = 1 << 3,
268 ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1)
269 ENCRYPT_ON_WRITE = 1 << 5,
222}; 270};
223 271
224struct record_hdr { 272struct record_hdr {
@@ -233,12 +281,15 @@ struct tls_handshake_data {
233 281
234 uint8_t client_and_server_rand32[2 * 32]; 282 uint8_t client_and_server_rand32[2 * 32];
235 uint8_t master_secret[48]; 283 uint8_t master_secret[48];
284
236//TODO: store just the DER key here, parse/use/delete it when sending client key 285//TODO: store just the DER key here, parse/use/delete it when sending client key
237//this way it will stay key type agnostic here. 286//this way it will stay key type agnostic here.
238 psRsaKey_t server_rsa_pub_key; 287 psRsaKey_t server_rsa_pub_key;
288 uint8_t ecc_pub_key32[32];
239 289
240 unsigned saved_client_hello_size; 290/* HANDSHAKE HASH: */
241 uint8_t saved_client_hello[1]; 291 //unsigned saved_client_hello_size;
292 //uint8_t saved_client_hello[1];
242}; 293};
243 294
244 295
@@ -248,6 +299,15 @@ static unsigned get24be(const uint8_t *p)
248} 299}
249 300
250#if TLS_DEBUG 301#if TLS_DEBUG
302/* Nondestructively see the current hash value */
303# if TLS_DEBUG_HASH
304static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer)
305{
306 md5sha_ctx_t ctx_copy = *ctx; /* struct copy */
307 return sha_end(&ctx_copy, buffer);
308}
309# endif
310
251static void dump_hex(const char *fmt, const void *vp, int len) 311static void dump_hex(const char *fmt, const void *vp, int len)
252{ 312{
253 char hexbuf[32 * 1024 + 4]; 313 char hexbuf[32 * 1024 + 4];
@@ -287,7 +347,7 @@ static void dump_tls_record(const void *vp, int len)
287# define dump_tls_record(...) ((void)0) 347# define dump_tls_record(...) ((void)0)
288#endif 348#endif
289 349
290void tls_get_random(void *buf, unsigned len) 350void FAST_FUNC tls_get_random(void *buf, unsigned len)
291{ 351{
292#if !ENABLE_PLATFORM_MINGW32 352#if !ENABLE_PLATFORM_MINGW32
293 if (len != open_read_close("/dev/urandom", buf, len)) 353 if (len != open_read_close("/dev/urandom", buf, len))
@@ -299,16 +359,32 @@ void tls_get_random(void *buf, unsigned len)
299#endif 359#endif
300} 360}
301 361
302/* Nondestructively see the current hash value */ 362static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count)
303static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer)
304{ 363{
305 md5sha_ctx_t ctx_copy = *ctx; /* struct copy */ 364 uint8_t *d = dst;
306 return sha_end(&ctx_copy, buffer); 365 const uint8_t *s1 = src1;
366 const uint8_t* s2 = src2;
367 while (count--)
368 *d++ = *s1++ ^ *s2++;
307} 369}
308 370
309static ALWAYS_INLINE unsigned get_handshake_hash(tls_state_t *tls, void *buffer) 371void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count)
310{ 372{
311 return sha_peek(&tls->hsd->handshake_hash_ctx, buffer); 373 xorbuf3(dst, dst, src, count);
374}
375
376void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src)
377{
378 unsigned long *d = dst;
379 const unsigned long *s = src;
380 d[0] ^= s[0];
381#if ULONG_MAX <= 0xffffffffffffffff
382 d[1] ^= s[1];
383 #if ULONG_MAX == 0xffffffff
384 d[2] ^= s[2];
385 d[3] ^= s[3];
386 #endif
387#endif
312} 388}
313 389
314#if !TLS_DEBUG_HASH 390#if !TLS_DEBUG_HASH
@@ -335,7 +411,7 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer
335#endif 411#endif
336} 412}
337 413
338// RFC 2104 414// RFC 2104:
339// HMAC(key, text) based on a hash H (say, sha256) is: 415// HMAC(key, text) based on a hash H (say, sha256) is:
340// ipad = [0x36 x INSIZE] 416// ipad = [0x36 x INSIZE]
341// opad = [0x5c x INSIZE] 417// opad = [0x5c x INSIZE]
@@ -350,35 +426,12 @@ typedef struct hmac_precomputed {
350 md5sha_ctx_t hashed_key_xor_opad; 426 md5sha_ctx_t hashed_key_xor_opad;
351} hmac_precomputed_t; 427} hmac_precomputed_t;
352 428
353static unsigned hmac_sha_precomputed_v(
354 hmac_precomputed_t *pre,
355 uint8_t *out,
356 va_list va)
357{
358 uint8_t *text;
359 unsigned len;
360
361 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
362 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
363
364 /* calculate out = H((key XOR ipad) + text) */
365 while ((text = va_arg(va, uint8_t*)) != NULL) {
366 unsigned text_size = va_arg(va, unsigned);
367 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
368 }
369 len = sha_end(&pre->hashed_key_xor_ipad, out);
370
371 /* out = H((key XOR opad) + out) */
372 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
373 return sha_end(&pre->hashed_key_xor_opad, out);
374}
375
376typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; 429typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
377static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) 430static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
378{ 431{
379 uint8_t key_xor_ipad[SHA_INSIZE]; 432 uint8_t key_xor_ipad[SHA_INSIZE];
380 uint8_t key_xor_opad[SHA_INSIZE]; 433 uint8_t key_xor_opad[SHA_INSIZE];
381 uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE]; 434// uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE];
382 unsigned i; 435 unsigned i;
383 436
384 // "The authentication key can be of any length up to INSIZE, the 437 // "The authentication key can be of any length up to INSIZE, the
@@ -386,10 +439,18 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size,
386 // than INSIZE bytes will first hash the key using H and then use the 439 // than INSIZE bytes will first hash the key using H and then use the
387 // resultant OUTSIZE byte string as the actual key to HMAC." 440 // resultant OUTSIZE byte string as the actual key to HMAC."
388 if (key_size > SHA_INSIZE) { 441 if (key_size > SHA_INSIZE) {
389 md5sha_ctx_t ctx; 442 bb_error_msg_and_die("HMAC key>64"); //does not happen (yet?)
390 begin(&ctx); 443// md5sha_ctx_t ctx;
391 md5sha_hash(&ctx, key, key_size); 444// begin(&ctx);
392 key_size = sha_end(&ctx, tempkey); 445// md5sha_hash(&ctx, key, key_size);
446// key_size = sha_end(&ctx, tempkey);
447// //key = tempkey; - right? RIGHT? why does it work without this?
448// // because SHA_INSIZE is 64, but hmac() is always called with
449// // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32),
450// // and prf_hmac_sha256() -> hmac_sha256() key sizes are:
451// // - RSA_PREMASTER_SIZE is 48
452// // - CURVE25519_KEYSIZE is 32
453// // - master_secret[] is 48
393 } 454 }
394 455
395 for (i = 0; i < key_size; i++) { 456 for (i = 0; i < key_size; i++) {
@@ -407,26 +468,43 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size,
407 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); 468 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
408} 469}
409 470
410static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) 471static unsigned hmac_sha_precomputed_v(
472 hmac_precomputed_t *pre,
473 uint8_t *out,
474 va_list va)
475{
476 uint8_t *text;
477 unsigned len;
478
479 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
480 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
481
482 /* calculate out = H((key XOR ipad) + text) */
483 while ((text = va_arg(va, uint8_t*)) != NULL) {
484 unsigned text_size = va_arg(va, unsigned);
485 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
486 }
487 len = sha_end(&pre->hashed_key_xor_ipad, out);
488
489 /* out = H((key XOR opad) + out) */
490 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
491 return sha_end(&pre->hashed_key_xor_opad, out);
492}
493
494static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...)
411{ 495{
412 hmac_precomputed_t pre; 496 hmac_precomputed_t pre;
413 va_list va; 497 va_list va;
414 unsigned len; 498 unsigned len;
415 499
416 va_start(va, key_size); 500 va_start(va, out);
417 501 pre = *pre_init; /* struct copy */
418 hmac_begin(&pre, key, key_size,
419 (tls->MAC_size == SHA256_OUTSIZE)
420 ? sha256_begin
421 : sha1_begin
422 );
423 len = hmac_sha_precomputed_v(&pre, out, va); 502 len = hmac_sha_precomputed_v(&pre, out, va);
424
425 va_end(va); 503 va_end(va);
426 return len; 504 return len;
427} 505}
428 506
429static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, unsigned key_size, ...) 507static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
430{ 508{
431 hmac_precomputed_t pre; 509 hmac_precomputed_t pre;
432 va_list va; 510 va_list va;
@@ -434,7 +512,11 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un
434 512
435 va_start(va, key_size); 513 va_start(va, key_size);
436 514
437 hmac_begin(&pre, key, key_size, sha256_begin); 515 hmac_begin(&pre, key, key_size,
516 (tls->MAC_size == SHA256_OUTSIZE)
517 ? sha256_begin
518 : sha1_begin
519 );
438 len = hmac_sha_precomputed_v(&pre, out, va); 520 len = hmac_sha_precomputed_v(&pre, out, va);
439 521
440 va_end(va); 522 va_end(va);
@@ -449,8 +531,9 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un
449// document and in TLS documents published prior to this document when 531// document and in TLS documents published prior to this document when
450// TLS 1.2 is negotiated. 532// TLS 1.2 is negotiated.
451// ^^^^^^^^^^^^^ IMPORTANT! 533// ^^^^^^^^^^^^^ IMPORTANT!
452// PRF uses sha256 regardless of cipher (at least for all ciphers 534// PRF uses sha256 regardless of cipher for all ciphers
453// defined by RFC5246). It's not sha1 for AES_128_CBC_SHA! 535// defined by RFC 5246. It's not sha1 for AES_128_CBC_SHA!
536// However, for _SHA384 ciphers, it's sha384. See RFC 5288,5289.
454//... 537//...
455// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + 538// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
456// HMAC_hash(secret, A(2) + seed) + 539// HMAC_hash(secret, A(2) + seed) +
@@ -472,12 +555,19 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un
472// PRF(secret, label, seed) = P_<hash>(secret, label + seed) 555// PRF(secret, label, seed) = P_<hash>(secret, label + seed)
473// 556//
474// The label is an ASCII string. 557// The label is an ASCII string.
558//
559// RFC 5288:
560// For cipher suites ending with _SHA256, the PRF is the TLS PRF
561// with SHA-256 as the hash function.
562// For cipher suites ending with _SHA384, the PRF is the TLS PRF
563// with SHA-384 as the hash function.
475static void prf_hmac_sha256(/*tls_state_t *tls,*/ 564static void prf_hmac_sha256(/*tls_state_t *tls,*/
476 uint8_t *outbuf, unsigned outbuf_size, 565 uint8_t *outbuf, unsigned outbuf_size,
477 uint8_t *secret, unsigned secret_size, 566 uint8_t *secret, unsigned secret_size,
478 const char *label, 567 const char *label,
479 uint8_t *seed, unsigned seed_size) 568 uint8_t *seed, unsigned seed_size)
480{ 569{
570 hmac_precomputed_t pre;
481 uint8_t a[TLS_MAX_MAC_SIZE]; 571 uint8_t a[TLS_MAX_MAC_SIZE];
482 uint8_t *out_p = outbuf; 572 uint8_t *out_p = outbuf;
483 unsigned label_size = strlen(label); 573 unsigned label_size = strlen(label);
@@ -485,28 +575,28 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
485 575
486 /* In P_hash() calculation, "seed" is "label + seed": */ 576 /* In P_hash() calculation, "seed" is "label + seed": */
487#define SEED label, label_size, seed, seed_size 577#define SEED label, label_size, seed, seed_size
488#define SECRET secret, secret_size
489#define A a, MAC_size 578#define A a, MAC_size
490 579
580 hmac_begin(&pre, secret, secret_size, sha256_begin);
581
491 /* A(1) = HMAC_hash(secret, seed) */ 582 /* A(1) = HMAC_hash(secret, seed) */
492 hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL); 583 hmac_sha_precomputed(&pre, a, SEED, NULL);
493//TODO: convert hmac to precomputed
494 584
495 for (;;) { 585 for (;;) {
496 /* HMAC_hash(secret, A(1) + seed) */ 586 /* HMAC_hash(secret, A(1) + seed) */
497 if (outbuf_size <= MAC_size) { 587 if (outbuf_size <= MAC_size) {
498 /* Last, possibly incomplete, block */ 588 /* Last, possibly incomplete, block */
499 /* (use a[] as temp buffer) */ 589 /* (use a[] as temp buffer) */
500 hmac_sha256(/*tls,*/ a, SECRET, A, SEED, NULL); 590 hmac_sha_precomputed(&pre, a, A, SEED, NULL);
501 memcpy(out_p, a, outbuf_size); 591 memcpy(out_p, a, outbuf_size);
502 return; 592 return;
503 } 593 }
504 /* Not last block. Store directly to result buffer */ 594 /* Not last block. Store directly to result buffer */
505 hmac_sha256(/*tls,*/ out_p, SECRET, A, SEED, NULL); 595 hmac_sha_precomputed(&pre, out_p, A, SEED, NULL);
506 out_p += MAC_size; 596 out_p += MAC_size;
507 outbuf_size -= MAC_size; 597 outbuf_size -= MAC_size;
508 /* A(2) = HMAC_hash(secret, A(1)) */ 598 /* A(2) = HMAC_hash(secret, A(1)) */
509 hmac_sha256(/*tls,*/ a, SECRET, A, NULL); 599 hmac_sha_precomputed(&pre, a, A, NULL);
510 } 600 }
511#undef A 601#undef A
512#undef SECRET 602#undef SECRET
@@ -566,17 +656,24 @@ static void *tls_get_outbuf(tls_state_t *tls, int len)
566 return tls->outbuf + OUTBUF_PFX; 656 return tls->outbuf + OUTBUF_PFX;
567} 657}
568 658
569static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) 659static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len)
660{
661 void *record = tls_get_outbuf(tls, len);
662 memset(record, 0, len);
663 return record;
664}
665
666static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type)
570{ 667{
571 uint8_t *buf = tls->outbuf + OUTBUF_PFX; 668 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
572 struct record_hdr *xhdr; 669 struct record_hdr *xhdr;
573 uint8_t padding_length; 670 uint8_t padding_length;
574 671
575 xhdr = (void*)(buf - RECHDR_LEN); 672 xhdr = (void*)(buf - RECHDR_LEN);
576 if (CIPHER_ID1 != TLS_RSA_WITH_NULL_SHA256 /* if "no encryption" can't be selected */ 673 if (!ALLOW_RSA_NULL_SHA256 /* if "no encryption" can't be selected */
577 || tls->cipher_id != TLS_RSA_WITH_NULL_SHA256 /* or if it wasn't selected */ 674 || tls->cipher_id != TLS_RSA_WITH_NULL_SHA256 /* or if it wasn't selected */
578 ) { 675 ) {
579 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */ 676 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCK_SIZE); /* place for IV */
580 } 677 }
581 678
582 xhdr->type = type; 679 xhdr->type = type;
@@ -598,7 +695,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
598 695
599 size += tls->MAC_size; 696 size += tls->MAC_size;
600 697
601 // RFC 5246 698 // RFC 5246:
602 // 6.2.3.1. Null or Standard Stream Cipher 699 // 6.2.3.1. Null or Standard Stream Cipher
603 // 700 //
604 // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) 701 // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6)
@@ -631,7 +728,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
631 // -------- ----------- ---------- -------------- 728 // -------- ----------- ---------- --------------
632 // SHA HMAC-SHA1 20 20 729 // SHA HMAC-SHA1 20 20
633 // SHA256 HMAC-SHA256 32 32 730 // SHA256 HMAC-SHA256 32 32
634 if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256 731 if (ALLOW_RSA_NULL_SHA256
635 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256 732 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256
636 ) { 733 ) {
637 /* No encryption, only signing */ 734 /* No encryption, only signing */
@@ -679,7 +776,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
679 // AES_128_CBC Block 16 16 16 776 // AES_128_CBC Block 16 16 16
680 // AES_256_CBC Block 32 16 16 777 // AES_256_CBC Block 32 16 16
681 778
682 tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ 779 tls_get_random(buf - AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* IV */
683 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", 780 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n",
684 size - tls->MAC_size, tls->MAC_size); 781 size - tls->MAC_size, tls->MAC_size);
685 782
@@ -699,23 +796,23 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
699 // If you need no bytes to reach BLOCKSIZE, you have to pad a full 796 // If you need no bytes to reach BLOCKSIZE, you have to pad a full
700 // BLOCKSIZE with bytes of value (BLOCKSIZE-1). 797 // BLOCKSIZE with bytes of value (BLOCKSIZE-1).
701 // It's ok to have more than minimum padding, but we do minimum. 798 // It's ok to have more than minimum padding, but we do minimum.
702 padding_length = (~size) & (AES_BLOCKSIZE - 1); 799 padding_length = (~size) & (AES_BLOCK_SIZE - 1);
703 do { 800 do {
704 buf[size++] = padding_length; /* padding */ 801 buf[size++] = padding_length; /* padding */
705 } while ((size & (AES_BLOCKSIZE - 1)) != 0); 802 } while ((size & (AES_BLOCK_SIZE - 1)) != 0);
706 803
707 /* Encrypt content+MAC+padding in place */ 804 /* Encrypt content+MAC+padding in place */
708 aes_cbc_encrypt( 805 aes_cbc_encrypt(
709 tls->client_write_key, tls->key_size, /* selects 128/256 */ 806 &tls->aes_encrypt, /* selects 128/256 */
710 buf - AES_BLOCKSIZE, /* IV */ 807 buf - AES_BLOCK_SIZE, /* IV */
711 buf, size, /* plaintext */ 808 buf, size, /* plaintext */
712 buf /* ciphertext */ 809 buf /* ciphertext */
713 ); 810 );
714 811
715 /* Write out */ 812 /* Write out */
716 dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", 813 dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n",
717 AES_BLOCKSIZE, size, padding_length); 814 AES_BLOCK_SIZE, size, padding_length);
718 size += AES_BLOCKSIZE; /* + IV */ 815 size += AES_BLOCK_SIZE; /* + IV */
719 xhdr->len16_hi = size >> 8; 816 xhdr->len16_hi = size >> 8;
720 xhdr->len16_lo = size & 0xff; 817 xhdr->len16_lo = size & 0xff;
721 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); 818 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
@@ -723,28 +820,114 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
723 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); 820 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
724} 821}
725 822
823/* Example how GCM encryption combines nonce, aad, input and generates
824 * "header | exp_nonce | encrypted output | tag":
825 * nonce:0d 6a 26 31 00 00 00 00 00 00 00 01 (implicit 4 bytes (derived from master secret), then explicit 8 bytes)
826 * aad: 00 00 00 00 00 00 00 01 17 03 03 00 1c
827 * in: 47 45 54 20 2f 69 6e 64 65 78 2e 68 74 6d 6c 20 48 54 54 50 2f 31 2e 30 0d 0a 0d 0a "GET /index.html HTTP/1.0\r\n\r\n" (0x1c bytes)
828 * out: f7 8a b2 8f 78 0e f6 d5 76 17 2e b5 6d 46 59 56 8b 46 9f 0b d9 2c 35 28 13 66 19 be
829 * tag: c2 86 ce 4a 50 4a d0 aa 50 b3 76 5c 49 2a 3f 33
830 * sent: 17 03 03 00 34|00 00 00 00 00 00 00 01|f7 8a b2 8f 78 0e f6 d5 76 17 2e b5 6d 46 59 56 8b 46 9f 0b d9 2c 35 28 13 66 19 be|c2 86 ce 4a 50 4a d0 aa 50 b3 76 5c 49 2a 3f 33
831 * .............................................^^ buf points here
832 */
833static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned type)
834{
835#define COUNTER(v) (*(uint32_t*)(v + 12))
836
837 uint8_t aad[13 + 3] ALIGNED_long; /* +3 creates [16] buffer, simplifying GHASH() */
838 uint8_t nonce[12 + 4] ALIGNED_long; /* +4 creates space for AES block counter */
839 uint8_t scratch[AES_BLOCK_SIZE] ALIGNED_long; //[16]
840 uint8_t authtag[AES_BLOCK_SIZE] ALIGNED_long; //[16]
841 uint8_t *buf;
842 struct record_hdr *xhdr;
843 unsigned remaining;
844 unsigned cnt;
845 uint64_t t64;
846
847 buf = tls->outbuf + OUTBUF_PFX; /* see above for the byte it points to */
848 dump_hex("xwrite_encrypted_aesgcm plaintext:%s\n", buf, size);
849
850 xhdr = (void*)(buf - 8 - RECHDR_LEN);
851 xhdr->type = type; /* do it here so that "type" param no longer used */
852
853 aad[8] = type;
854 aad[9] = TLS_MAJ;
855 aad[10] = TLS_MIN;
856 aad[11] = size >> 8;
857 /* set aad[12], and clear aad[13..15] */
858 COUNTER(aad) = SWAP_LE32(size & 0xff);
859
860 memcpy(nonce, tls->client_write_IV, 4);
861 t64 = tls->write_seq64_be;
862 move_to_unaligned64(nonce + 4, t64);
863 move_to_unaligned64(aad, t64);
864 move_to_unaligned64(buf - 8, t64);
865 /* seq64 is not used later in this func, can increment here */
866 tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(t64));
867
868 cnt = 1;
869 remaining = size;
870 while (remaining != 0) {
871 unsigned n;
872
873 cnt++;
874 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
875 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch);
876 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining;
877 xorbuf(buf, scratch, n);
878 buf += n;
879 remaining -= n;
880 }
881
882 aesgcm_GHASH(tls->H, aad, /*sizeof(aad),*/ tls->outbuf + OUTBUF_PFX, size, authtag /*, sizeof(authtag)*/);
883 COUNTER(nonce) = htonl(1);
884 aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch);
885 xorbuf_aligned_AES_BLOCK_SIZE(authtag, scratch);
886
887 memcpy(buf, authtag, sizeof(authtag));
888
889 /* Write out */
890 xhdr = (void*)(tls->outbuf + OUTBUF_PFX - 8 - RECHDR_LEN);
891 size += 8 + sizeof(authtag);
892 /*xhdr->type = type; - already is */
893 xhdr->proto_maj = TLS_MAJ;
894 xhdr->proto_min = TLS_MIN;
895 xhdr->len16_hi = size >> 8;
896 xhdr->len16_lo = size & 0xff;
897 size += RECHDR_LEN;
898 dump_raw_out(">> %s\n", xhdr, size);
899 xwrite(tls->ofd, xhdr, size);
900 dbg("wrote %u bytes\n", size);
901#undef COUNTER
902}
903
904static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
905{
906 if (!(tls->flags & ENCRYPTION_AESGCM)) {
907 xwrite_encrypted_and_hmac_signed(tls, size, type);
908 return;
909 }
910 xwrite_encrypted_aesgcm(tls, size, type);
911}
912
726static void xwrite_handshake_record(tls_state_t *tls, unsigned size) 913static void xwrite_handshake_record(tls_state_t *tls, unsigned size)
727{ 914{
728 //if (!tls->encrypt_on_write) { 915 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
729 uint8_t *buf = tls->outbuf + OUTBUF_PFX; 916 struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN);
730 struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN);
731 917
732 xhdr->type = RECORD_TYPE_HANDSHAKE; 918 xhdr->type = RECORD_TYPE_HANDSHAKE;
733 xhdr->proto_maj = TLS_MAJ; 919 xhdr->proto_maj = TLS_MAJ;
734 xhdr->proto_min = TLS_MIN; 920 xhdr->proto_min = TLS_MIN;
735 xhdr->len16_hi = size >> 8; 921 xhdr->len16_hi = size >> 8;
736 xhdr->len16_lo = size & 0xff; 922 xhdr->len16_lo = size & 0xff;
737 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); 923 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
738 xwrite(tls->ofd, xhdr, RECHDR_LEN + size); 924 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
739 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); 925 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
740 // return;
741 //}
742 //xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
743} 926}
744 927
745static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) 928static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size)
746{ 929{
747 if (!tls->encrypt_on_write) { 930 if (!(tls->flags & ENCRYPT_ON_WRITE)) {
748 uint8_t *buf; 931 uint8_t *buf;
749 932
750 xwrite_handshake_record(tls, size); 933 xwrite_handshake_record(tls, size);
@@ -783,6 +966,51 @@ static const char *alert_text(int code)
783 return itoa(code); 966 return itoa(code);
784} 967}
785 968
969static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size)
970{
971#define COUNTER(v) (*(uint32_t*)(v + 12))
972
973 //uint8_t aad[13 + 3] ALIGNED_long; /* +3 creates [16] buffer, simplifying GHASH() */
974 uint8_t nonce[12 + 4] ALIGNED_long; /* +4 creates space for AES block counter */
975 uint8_t scratch[AES_BLOCK_SIZE] ALIGNED_long; //[16]
976 //uint8_t authtag[AES_BLOCK_SIZE] ALIGNED_long; //[16]
977 unsigned remaining;
978 unsigned cnt;
979
980 //memcpy(aad, buf, 8);
981 //aad[8] = type;
982 //aad[9] = TLS_MAJ;
983 //aad[10] = TLS_MIN;
984 //aad[11] = size >> 8;
985 ///* set aad[12], and clear aad[13..15] */
986 //COUNTER(aad) = SWAP_LE32(size & 0xff);
987
988 memcpy(nonce, tls->server_write_IV, 4);
989 memcpy(nonce + 4, buf, 8);
990
991 cnt = 1;
992 remaining = size;
993 while (remaining != 0) {
994 unsigned n;
995
996 cnt++;
997 COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */
998 aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch);
999 n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining;
1000 xorbuf3(buf, scratch, buf + 8, n);
1001 buf += n;
1002 remaining -= n;
1003 }
1004
1005 //aesgcm_GHASH(tls->H, aad, tls->inbuf + RECHDR_LEN, size, authtag);
1006 //COUNTER(nonce) = htonl(1);
1007 //aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch);
1008 //xorbuf_aligned_AES_BLOCK_SIZE(authtag, scratch);
1009
1010 //memcmp(buf, authtag, sizeof(authtag)) || DIE("HASH DOES NOT MATCH!");
1011#undef COUNTER
1012}
1013
786static int tls_xread_record(tls_state_t *tls, const char *expected) 1014static int tls_xread_record(tls_state_t *tls, const char *expected)
787{ 1015{
788 struct record_hdr *xhdr; 1016 struct record_hdr *xhdr;
@@ -853,34 +1081,43 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
853 sz = target - RECHDR_LEN; 1081 sz = target - RECHDR_LEN;
854 1082
855 /* Needs to be decrypted? */ 1083 /* Needs to be decrypted? */
856 if (tls->min_encrypted_len_on_read > tls->MAC_size) { 1084 if (tls->min_encrypted_len_on_read != 0) {
857 uint8_t *p = tls->inbuf + RECHDR_LEN; 1085 if (sz < (int)tls->min_encrypted_len_on_read)
858 int padding_len; 1086 bb_error_msg_and_die("bad encrypted len:%u", sz);
859 1087
860 if (sz & (AES_BLOCKSIZE-1) 1088 if (tls->flags & ENCRYPTION_AESGCM) {
861 || sz < (int)tls->min_encrypted_len_on_read 1089 /* AESGCM */
862 ) { 1090 uint8_t *p = tls->inbuf + RECHDR_LEN;
863 bb_error_msg_and_die("bad encrypted len:%u < %u", 1091
864 sz, tls->min_encrypted_len_on_read); 1092 sz -= 8 + AES_BLOCK_SIZE; /* we will overwrite nonce, drop hash */
1093 tls_aesgcm_decrypt(tls, p, sz);
1094 dbg("encrypted size:%u\n", sz);
1095 } else
1096 if (tls->min_encrypted_len_on_read > tls->MAC_size) {
1097 /* AES+SHA */
1098 uint8_t *p = tls->inbuf + RECHDR_LEN;
1099 int padding_len;
1100
1101 if (sz & (AES_BLOCK_SIZE-1))
1102 bb_error_msg_and_die("bad encrypted len:%u", sz);
1103
1104 /* Decrypt content+MAC+padding, moving it over IV in the process */
1105 sz -= AES_BLOCK_SIZE; /* we will overwrite IV now */
1106 aes_cbc_decrypt(
1107 &tls->aes_decrypt, /* selects 128/256 */
1108 p, /* IV */
1109 p + AES_BLOCK_SIZE, sz, /* ciphertext */
1110 p /* plaintext */
1111 );
1112 padding_len = p[sz - 1];
1113 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len);
1114 padding_len++;
1115 sz -= tls->MAC_size + padding_len; /* drop MAC and padding */
1116 } else {
1117 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */
1118 /* else: no encryption yet on input, subtract zero = NOP */
1119 sz -= tls->min_encrypted_len_on_read;
865 } 1120 }
866 /* Decrypt content+MAC+padding, moving it over IV in the process */
867 sz -= AES_BLOCKSIZE; /* we will overwrite IV now */
868 aes_cbc_decrypt(
869 tls->server_write_key, tls->key_size, /* selects 128/256 */
870 p, /* IV */
871 p + AES_BLOCKSIZE, sz, /* ciphertext */
872 p /* plaintext */
873 );
874 padding_len = p[sz - 1];
875 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len);
876 padding_len++;
877 sz -= tls->MAC_size + padding_len; /* drop MAC and padding */
878 //if (sz < 0)
879 // bb_error_msg_and_die("bad padding size:%u", padding_len);
880 } else {
881 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */
882 /* else: no encryption yet on input, subtract zero = NOP */
883 sz -= tls->min_encrypted_len_on_read;
884 } 1121 }
885 if (sz < 0) 1122 if (sz < 0)
886 bb_error_msg_and_die("encrypted data too short"); 1123 bb_error_msg_and_die("encrypted data too short");
@@ -921,7 +1158,8 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
921 * in our FINISHED record must include data of incoming packets too! 1158 * in our FINISHED record must include data of incoming packets too!
922 */ 1159 */
923 if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE 1160 if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE
924 && tls->MAC_size != 0 /* do we know which hash to use? (server_hello() does not!) */ 1161/* HANDSHAKE HASH: */
1162 // && do_we_know_which_hash_to_use /* server_hello() might not know it in the future! */
925 ) { 1163 ) {
926 hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz); 1164 hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz);
927 } 1165 }
@@ -930,6 +1168,13 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
930 return sz; 1168 return sz;
931} 1169}
932 1170
1171static void binary_to_pstm(pstm_int *pstm_n, uint8_t *bin_ptr, unsigned len)
1172{
1173 pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len);
1174 pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
1175 //return bin_ptr + len;
1176}
1177
933/* 1178/*
934 * DER parsing routines 1179 * DER parsing routines
935 */ 1180 */
@@ -1001,9 +1246,7 @@ static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end)
1001 unsigned len = get_der_len(&bin_ptr, der, end); 1246 unsigned len = get_der_len(&bin_ptr, der, end);
1002 1247
1003 dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); 1248 dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]);
1004 pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); 1249 binary_to_pstm(pstm_n, bin_ptr, len);
1005 pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
1006 //return bin + len;
1007} 1250}
1008 1251
1009static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) 1252static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
@@ -1086,10 +1329,20 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
1086 * publicKey (BIT STRING) 1329 * publicKey (BIT STRING)
1087 * 1330 *
1088 * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey 1331 * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey
1332 *
1333 * Example of an ECDSA key:
1334 * SEQ 0x59 bytes (subjectPublicKeyInfo): 3059
1335 * SEQ 0x13 bytes (algorithm): 3013
1336 * OID 7 bytes: 0607 2a8648ce3d0201 (OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1)
1337 * OID 8 bytes: 0608 2a8648ce3d030107 (OID_EC_prime256v1 42.134.72.206.61.3.1.7)
1338 * BITSTRING 0x42 bytes (publicKey): 0342
1339 * 0004 53af f65e 50cc 7959 7e29 0171 c75c
1340 * 7335 e07d f45b 9750 b797 3a38 aebb 2ac6
1341 * 8329 2748 e77e 41cb d482 2ce6 05ec a058
1342 * f3ab d561 2f4c d845 9ad3 7252 e3de bd3b
1343 * 9012
1089 */ 1344 */
1090 uint8_t *end = der + len; 1345 uint8_t *end = der + len;
1091 uint8_t tag_class, pc, tag_number;
1092 int version_present;
1093 1346
1094 /* enter "Certificate" item: [der, end) will be only Cert */ 1347 /* enter "Certificate" item: [der, end) will be only Cert */
1095 der = enter_der_item(der, &end); 1348 der = enter_der_item(der, &end);
@@ -1106,13 +1359,11 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
1106 * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2 1359 * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2
1107 * and 8.14). 1360 * and 8.14).
1108 */ 1361 */
1109 tag_class = der[0] >> 6; /* bits 8-7 */ 1362 /* bits 7-6: 10 */
1110 pc = (der[0] & 32) >> 5; /* bit 6 */ 1363 /* bit 5: 1 */
1111 tag_number = der[0] & 31; /* bits 5-1 */ 1364 /* bits 4-0: 00000 */
1112 version_present = tag_class == 2 && pc == 1 && tag_number == 0; 1365 if (der[0] == 0xa0)
1113 if (version_present) {
1114 der = skip_der_item(der, end); /* version */ 1366 der = skip_der_item(der, end); /* version */
1115 }
1116 1367
1117 /* skip up to subjectPublicKeyInfo */ 1368 /* skip up to subjectPublicKeyInfo */
1118 der = skip_der_item(der, end); /* serialNumber */ 1369 der = skip_der_item(der, end); /* serialNumber */
@@ -1124,40 +1375,67 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
1124 /* enter subjectPublicKeyInfo */ 1375 /* enter subjectPublicKeyInfo */
1125 der = enter_der_item(der, &end); 1376 der = enter_der_item(der, &end);
1126 { /* check subjectPublicKeyInfo.algorithm */ 1377 { /* check subjectPublicKeyInfo.algorithm */
1127 static const uint8_t expected[] = { 1378 static const uint8_t OID_RSA_KEY_ALG[] = {
1128 0x30,0x0d, // SEQ 13 bytes 1379 0x30,0x0d, // SEQ 13 bytes
1129 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 1380 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, //OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1
1130 //0x05,0x00, // NULL 1381 //0x05,0x00, // NULL
1131 }; 1382 };
1132 if (memcmp(der, expected, sizeof(expected)) != 0) 1383 static const uint8_t OID_ECDSA_KEY_ALG[] = {
1133 bb_error_msg_and_die("not RSA key"); 1384 0x30,0x13, // SEQ 0x13 bytes
1385 0x06,0x07, 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01, //OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1
1386 //allow any curve code for now...
1387 // 0x06,0x08, 0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07, //OID_EC_prime256v1 42.134.72.206.61.3.1.7
1388 //RFC 3279:
1389 //42.134.72.206.61.3 is ellipticCurve
1390 //42.134.72.206.61.3.0 is c-TwoCurve
1391 //42.134.72.206.61.3.1 is primeCurve
1392 //42.134.72.206.61.3.1.7 is curve_secp256r1
1393 };
1394 if (memcmp(der, OID_RSA_KEY_ALG, sizeof(OID_RSA_KEY_ALG)) == 0) {
1395 dbg("RSA key\n");
1396 tls->flags |= GOT_CERT_RSA_KEY_ALG;
1397 } else
1398 if (memcmp(der, OID_ECDSA_KEY_ALG, sizeof(OID_ECDSA_KEY_ALG)) == 0) {
1399 dbg("ECDSA key\n");
1400 //UNUSED: tls->flags |= GOT_CERT_ECDSA_KEY_ALG;
1401 } else
1402 bb_error_msg_and_die("not RSA or ECDSA cert");
1134 } 1403 }
1135 /* skip subjectPublicKeyInfo.algorithm */
1136 der = skip_der_item(der, end);
1137 /* enter subjectPublicKeyInfo.publicKey */
1138// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */
1139 der = enter_der_item(der, &end);
1140 1404
1141 /* parse RSA key: */ 1405 if (tls->flags & GOT_CERT_RSA_KEY_ALG) {
1142//based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note 1406 /* parse RSA key: */
1143 dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); 1407 //based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note
1144 if (end - der < 14) xfunc_die(); 1408 /* skip subjectPublicKeyInfo.algorithm */
1145 /* example format: 1409 der = skip_der_item(der, end);
1146 * ignore bits: 00 1410 /* enter subjectPublicKeyInfo.publicKey */
1147 * SEQ 0x018a/394 bytes: 3082018a 1411 //die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */
1148 * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX 1412 der = enter_der_item(der, &end);
1149 * INTEGER 3 bytes (exponent): 0203 010001 1413
1414 dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]);
1415 if (end - der < 14)
1416 xfunc_die();
1417 /* example format:
1418 * ignore bits: 00
1419 * SEQ 0x018a/394 bytes: 3082018a
1420 * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX
1421 * INTEGER 3 bytes (exponent): 0203 010001
1422 */
1423 if (*der != 0) /* "ignore bits", should be 0 */
1424 xfunc_die();
1425 der++;
1426 der = enter_der_item(der, &end); /* enter SEQ */
1427 /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */
1428 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */
1429 der = skip_der_item(der, end);
1430 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */
1431 tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N);
1432 dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size);
1433 }
1434 /* else: ECDSA key. It is not used for generating encryption keys,
1435 * it is used only to sign the EC public key (which comes in ServerKey message).
1436 * Since we do not verify cert validity, verifying signature on EC public key
1437 * wouldn't add any security. Thus, we do nothing here.
1150 */ 1438 */
1151 if (*der != 0) /* "ignore bits", should be 0 */
1152 xfunc_die();
1153 der++;
1154 der = enter_der_item(der, &end); /* enter SEQ */
1155 /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */
1156 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */
1157 der = skip_der_item(der, end);
1158 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */
1159 tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N);
1160 dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size);
1161} 1439}
1162 1440
1163/* 1441/*
@@ -1194,6 +1472,56 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un
1194 1472
1195static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 1473static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1196{ 1474{
1475#define NUM_CIPHERS (13 + ALLOW_RSA_NULL_SHA256)
1476 static const uint8_t ciphers[] = {
1477 0x00,(1 + NUM_CIPHERS) * 2, //len16_be
1478 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV
1479 /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1480 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/
1481 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/
1482 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA
1483 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl)
1484 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1485 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1486 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
1487 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1488 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/
1489 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC"
1490//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF?
1491 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1492 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac"
1493 //possibly these too:
1494 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
1495 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
1496 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
1497 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1498 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1499 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1500 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1501 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1502 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
1503 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac"
1504#if ALLOW_RSA_NULL_SHA256
1505 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256
1506#endif
1507 0x01,0x00, //not a cipher - comprtypes_len, comprtype
1508 };
1509 static const uint8_t supported_groups[] = {
1510 0x00,0x0a, //extension_type: "supported_groups"
1511 0x00,0x04, //ext len
1512 0x00,0x02, //list len
1513 0x00,0x1d, //curve_x25519 (RFC 7748)
1514 //0x00,0x17, //curve_secp256r1
1515 //0x00,0x18, //curve_secp384r1
1516 //0x00,0x19, //curve_secp521r1
1517 };
1518 //static const uint8_t signature_algorithms[] = {
1519 // 000d
1520 // 0020
1521 // 001e
1522 // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203
1523 //};
1524
1197 struct client_hello { 1525 struct client_hello {
1198 uint8_t type; 1526 uint8_t type;
1199 uint8_t len24_hi, len24_mid, len24_lo; 1527 uint8_t len24_hi, len24_mid, len24_lo;
@@ -1202,7 +1530,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1202 uint8_t session_id_len; 1530 uint8_t session_id_len;
1203 /* uint8_t session_id[]; */ 1531 /* uint8_t session_id[]; */
1204 uint8_t cipherid_len16_hi, cipherid_len16_lo; 1532 uint8_t cipherid_len16_hi, cipherid_len16_lo;
1205 uint8_t cipherid[2 * (2 + !!CIPHER_ID2)]; /* actually variable */ 1533 uint8_t cipherid[(1 + NUM_CIPHERS) * 2]; /* actually variable */
1206 uint8_t comprtypes_len; 1534 uint8_t comprtypes_len;
1207 uint8_t comprtypes[1]; /* actually variable */ 1535 uint8_t comprtypes[1]; /* actually variable */
1208 /* Extensions (SNI shown): 1536 /* Extensions (SNI shown):
@@ -1227,14 +1555,20 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1227// 0017 0000 - extended master secret 1555// 0017 0000 - extended master secret
1228 }; 1556 };
1229 struct client_hello *record; 1557 struct client_hello *record;
1558 uint8_t *ptr;
1230 int len; 1559 int len;
1231 int sni_len = sni ? strnlen(sni, 127 - 9) : 0; 1560 int ext_len;
1561 int sni_len = sni ? strnlen(sni, 127 - 5) : 0;
1232 1562
1233 len = sizeof(*record); 1563 ext_len = 0;
1564 /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */
1565 ext_len += sizeof(supported_groups);
1234 if (sni_len) 1566 if (sni_len)
1235 len += 11 + sni_len; 1567 ext_len += 9 + sni_len;
1236 record = tls_get_outbuf(tls, len); 1568
1237 memset(record, 0, len); 1569 /* +2 is for "len of all extensions" 2-byte field */
1570 len = sizeof(*record) + 2 + ext_len;
1571 record = tls_get_zeroed_outbuf(tls, len);
1238 1572
1239 fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len); 1573 fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len);
1240 record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ 1574 record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */
@@ -1244,46 +1578,43 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1244 memset(record->rand32, 0x11, sizeof(record->rand32)); 1578 memset(record->rand32, 0x11, sizeof(record->rand32));
1245 /* record->session_id_len = 0; - already is */ 1579 /* record->session_id_len = 0; - already is */
1246 1580
1247 /* record->cipherid_len16_hi = 0; */ 1581 BUILD_BUG_ON(sizeof(ciphers) != 2 + (1 + NUM_CIPHERS) * 2 + 2);
1248 record->cipherid_len16_lo = sizeof(record->cipherid); 1582 memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers));
1249 /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1250 /*record->cipherid[0] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */
1251 record->cipherid[1] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff;
1252 if ((CIPHER_ID1 >> 8) != 0) record->cipherid[2] = CIPHER_ID1 >> 8;
1253 /*************************/ record->cipherid[3] = CIPHER_ID1 & 0xff;
1254#if CIPHER_ID2
1255 if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8;
1256 /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff;
1257#endif
1258
1259 record->comprtypes_len = 1;
1260 /* record->comprtypes[0] = 0; */
1261 1583
1584 ptr = (void*)(record + 1);
1585 *ptr++ = ext_len >> 8;
1586 *ptr++ = ext_len;
1262 if (sni_len) { 1587 if (sni_len) {
1263 uint8_t *p = (void*)(record + 1); 1588 //ptr[0] = 0; //
1264 //p[0] = 0; // 1589 //ptr[1] = 0; //extension_type
1265 p[1] = sni_len + 9; //ext_len 1590 //ptr[2] = 0; //
1266 //p[2] = 0; // 1591 ptr[3] = sni_len + 5; //list len
1267 //p[3] = 0; //extension_type 1592 //ptr[4] = 0; //
1268 //p[4] = 0; // 1593 ptr[5] = sni_len + 3; //len of 1st SNI
1269 p[5] = sni_len + 5; //list len 1594 //ptr[6] = 0; //name type
1270 //p[6] = 0; // 1595 //ptr[7] = 0; //
1271 p[7] = sni_len + 3; //len of 1st SNI 1596 ptr[8] = sni_len; //name len
1272 //p[8] = 0; //name type 1597 ptr = mempcpy(&ptr[9], sni, sni_len);
1273 //p[9] = 0; //
1274 p[10] = sni_len; //name len
1275 memcpy(&p[11], sni, sni_len);
1276 } 1598 }
1599 memcpy(ptr, supported_groups, sizeof(supported_groups));
1277 1600
1278 dbg(">> CLIENT_HELLO\n"); 1601 tls->hsd = xzalloc(sizeof(*tls->hsd));
1279 /* Can hash it only when we know which MAC hash to use */ 1602 /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */
1280 /*xwrite_and_update_handshake_hash(tls, len); - WRONG! */ 1603 memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32));
1281 xwrite_handshake_record(tls, len); 1604/* HANDSHAKE HASH:
1282
1283 tls->hsd = xzalloc(sizeof(*tls->hsd) + len);
1284 tls->hsd->saved_client_hello_size = len; 1605 tls->hsd->saved_client_hello_size = len;
1285 memcpy(tls->hsd->saved_client_hello, record, len); 1606 memcpy(tls->hsd->saved_client_hello, record, len);
1286 memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); 1607 */
1608 dbg(">> CLIENT_HELLO\n");
1609 /* Can hash immediately only if we know which MAC hash to use.
1610 * So far we do know: it's sha256:
1611 */
1612 sha256_begin(&tls->hsd->handshake_hash_ctx);
1613 xwrite_and_update_handshake_hash(tls, len);
1614 /* if this would become infeasible: save tls->hsd->saved_client_hello,
1615 * use "xwrite_handshake_record(tls, len)" here,
1616 * and hash saved_client_hello later.
1617 */
1287} 1618}
1288 1619
1289static void get_server_hello(tls_state_t *tls) 1620static void get_server_hello(tls_state_t *tls)
@@ -1303,7 +1634,7 @@ static void get_server_hello(tls_state_t *tls)
1303 1634
1304 struct server_hello *hp; 1635 struct server_hello *hp;
1305 uint8_t *cipherid; 1636 uint8_t *cipherid;
1306 unsigned cipher; 1637 uint8_t cipherid1;
1307 int len, len24; 1638 int len, len24;
1308 1639
1309 len = tls_xread_handshake_block(tls, 74 - 32); 1640 len = tls_xread_handshake_block(tls, 74 - 32);
@@ -1336,33 +1667,87 @@ static void get_server_hello(tls_state_t *tls)
1336 len24 += 32; /* what len would be if session id would be present */ 1667 len24 += 32; /* what len would be if session id would be present */
1337 } 1668 }
1338 1669
1339 if (len24 < 70 1670 if (len24 < 70)
1340// || cipherid[0] != (CIPHER_ID >> 8)
1341// || cipherid[1] != (CIPHER_ID & 0xff)
1342// || cipherid[2] != 0 /* comprtype */
1343 ) {
1344 bad_record_die(tls, "'server hello'", len); 1671 bad_record_die(tls, "'server hello'", len);
1345 }
1346 dbg("<< SERVER_HELLO\n"); 1672 dbg("<< SERVER_HELLO\n");
1347 1673
1348 memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); 1674 memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32));
1349 1675
1350 tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1]; 1676 /* Set up encryption params based on selected cipher */
1351 dbg("server chose cipher %04x\n", cipher); 1677#if 0
1352 1678 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/
1353 if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) { 1679 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/
1354 tls->key_size = AES128_KEYSIZE; 1680 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA
1355 tls->MAC_size = SHA1_OUTSIZE; 1681 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl)
1356 } 1682 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1357 else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ 1683 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1358 tls->key_size = AES256_KEYSIZE; 1684 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
1359 tls->MAC_size = SHA256_OUTSIZE; 1685 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1686 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/
1687 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC"
1688 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1689 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac"
1690 //possibly these too:
1691 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
1692 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
1693 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
1694 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1695 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1696 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1697 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1698 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1699 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
1700 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac"
1701 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256
1702#endif
1703 cipherid1 = cipherid[1];
1704 tls->cipher_id = 0x100 * cipherid[0] + cipherid1;
1705 tls->key_size = AES256_KEYSIZE;
1706 tls->MAC_size = SHA256_OUTSIZE;
1707 /*tls->IV_size = 0; - already is */
1708 if (cipherid[0] == 0xC0) {
1709 /* All C0xx are ECDHE */
1710 tls->flags |= NEED_EC_KEY;
1711 if (cipherid1 & 1) {
1712 /* Odd numbered C0xx use AES128 (even ones use AES256) */
1713 tls->key_size = AES128_KEYSIZE;
1714 }
1715 if (cipherid1 <= 0x14) {
1716 tls->MAC_size = SHA1_OUTSIZE;
1717 } else
1718 if (cipherid1 >= 0x2B && cipherid1 <= 0x30) {
1719 /* C02B,2C,2F,30 are AES-GCM */
1720 tls->flags |= ENCRYPTION_AESGCM;
1721 tls->MAC_size = 0;
1722 tls->IV_size = 4;
1723 }
1724 } else {
1725 /* All 00xx are RSA */
1726 if (cipherid1 == 0x2F
1727 || cipherid1 == 0x3C
1728 || cipherid1 == 0x9C
1729 ) {
1730 tls->key_size = AES128_KEYSIZE;
1731 }
1732 if (cipherid1 <= 0x35) {
1733 tls->MAC_size = SHA1_OUTSIZE;
1734 } else
1735 if (cipherid1 == 0x9C /*|| cipherid1 == 0x9D*/) {
1736 /* 009C,9D are AES-GCM */
1737 tls->flags |= ENCRYPTION_AESGCM;
1738 tls->MAC_size = 0;
1739 tls->IV_size = 4;
1740 }
1360 } 1741 }
1742 dbg("server chose cipher %04x\n", tls->cipher_id);
1743 dbg("key_size:%u MAC_size:%u IV_size:%u\n", tls->key_size, tls->MAC_size, tls->IV_size);
1744
1361 /* Handshake hash eventually destined to FINISHED record 1745 /* Handshake hash eventually destined to FINISHED record
1362 * is sha256 regardless of cipher 1746 * is sha256 regardless of cipher
1363 * (at least for all ciphers defined by RFC5246). 1747 * (at least for all ciphers defined by RFC5246).
1364 * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash. 1748 * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash.
1365 */ 1749 */
1750/* HANDSHAKE HASH:
1366 sha256_begin(&tls->hsd->handshake_hash_ctx); 1751 sha256_begin(&tls->hsd->handshake_hash_ctx);
1367 hash_handshake(tls, ">> client hello hash:%s", 1752 hash_handshake(tls, ">> client hello hash:%s",
1368 tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size 1753 tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size
@@ -1370,6 +1755,7 @@ static void get_server_hello(tls_state_t *tls)
1370 hash_handshake(tls, "<< server hello hash:%s", 1755 hash_handshake(tls, "<< server hello hash:%s",
1371 tls->inbuf + RECHDR_LEN, len 1756 tls->inbuf + RECHDR_LEN, len
1372 ); 1757 );
1758 */
1373} 1759}
1374 1760
1375static void get_server_cert(tls_state_t *tls) 1761static void get_server_cert(tls_state_t *tls)
@@ -1402,6 +1788,68 @@ static void get_server_cert(tls_state_t *tls)
1402 find_key_in_der_cert(tls, certbuf + 10, len); 1788 find_key_in_der_cert(tls, certbuf + 10, len);
1403} 1789}
1404 1790
1791/* On input, len is known to be >= 4.
1792 * The record is known to be SERVER_KEY_EXCHANGE.
1793 */
1794static void process_server_key(tls_state_t *tls, int len)
1795{
1796 struct record_hdr *xhdr;
1797 uint8_t *keybuf;
1798 int len1;
1799 uint32_t t32;
1800
1801 xhdr = (void*)tls->inbuf;
1802 keybuf = (void*)(xhdr + 1);
1803//seen from is.gd: it selects curve_x25519:
1804// 0c 00006e //SERVER_KEY_EXCHANGE, len
1805// 03 //curve_type: named curve
1806// 001d //curve_x25519
1807//server-chosen EC point, and then signed_params
1808// (RFC 8422: "A hash of the params, with the signature
1809// appropriate to that hash applied. The private key corresponding
1810// to the certified public key in the server's Certificate message is
1811// used for signing.")
1812//follow. Format unclear/guessed:
1813// 20 //eccPubKeyLen
1814// 25511923d73b70dd2f60e66ba2f3fda31a9c25170963c7a3a972e481dbb2835d //eccPubKey (32bytes)
1815// 0203 //hashSigAlg: 2:SHA1 (4:SHA256 5:SHA384 6:SHA512), 3:ECDSA (1:RSA)
1816// 0046 //len (16bit)
1817// 30 44 //SEQ, len
1818// 02 20 //INTEGER, len
1819// 2e18e7c2a9badd0a70cd3059a6ab114539b9f5163568911147386cd77ed7c412 //32bytes
1820//this item ^^^^^ is sometimes 33 bytes (with all container sizes also +1)
1821// 02 20 //INTEGER, len
1822// 64523d6216cb94c43c9b20e377d8c52c55be6703fd6730a155930c705eaf3af6 //32bytes
1823//same about this item ^^^^^
1824
1825//seen from ftp.openbsd.org
1826//(which only accepts ECDHE-RSA-AESnnn-GCM-SHAnnn and ECDHE-RSA-CHACHA20-POLY1305 ciphers):
1827// 0c 000228 //SERVER_KEY_EXCHANGE, len
1828// 03 //curve_type: named curve
1829// 001d //curve_x25519
1830// 20 //eccPubKeyLen
1831// eef7a15c43b71a4c7eaa48a39369399cc4332e569ec90a83274cc92596705c1a //eccPubKey
1832// 0401 //hashSigAlg: 4:SHA256, 1:RSA
1833// 0200 //len
1834// //0x200 bytes follow
1835
1836 /* Get and verify length */
1837 len1 = get24be(keybuf + 1);
1838 if (len1 > len - 4) tls_error_die(tls);
1839 len = len1;
1840 if (len < (1+2+1+32)) tls_error_die(tls);
1841 keybuf += 4;
1842
1843 /* So far we only support curve_x25519 */
1844 move_from_unaligned32(t32, keybuf);
1845 if (t32 != htonl(0x03001d20))
1846 bb_error_msg_and_die("elliptic curve is not x25519");
1847
1848 memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32);
1849 tls->flags |= GOT_EC_KEY;
1850 dbg("got eccPubKey\n");
1851}
1852
1405static void send_empty_client_cert(tls_state_t *tls) 1853static void send_empty_client_cert(tls_state_t *tls)
1406{ 1854{
1407 struct client_empty_cert { 1855 struct client_empty_cert {
@@ -1411,12 +1859,14 @@ static void send_empty_client_cert(tls_state_t *tls)
1411 }; 1859 };
1412 struct client_empty_cert *record; 1860 struct client_empty_cert *record;
1413 1861
1414 record = tls_get_outbuf(tls, sizeof(*record)); 1862 record = tls_get_zeroed_outbuf(tls, sizeof(*record));
1415//FIXME: can just memcpy a ready-made one. 1863 //fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record));
1416 fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); 1864 //record->cert_chain_len24_hi = 0;
1417 record->cert_chain_len24_hi = 0; 1865 //record->cert_chain_len24_mid = 0;
1418 record->cert_chain_len24_mid = 0; 1866 //record->cert_chain_len24_lo = 0;
1419 record->cert_chain_len24_lo = 0; 1867 // same as above:
1868 record->type = HANDSHAKE_CERTIFICATE;
1869 record->len24_lo = 3;
1420 1870
1421 dbg(">> CERTIFICATE\n"); 1871 dbg(">> CERTIFICATE\n");
1422 xwrite_and_update_handshake_hash(tls, sizeof(*record)); 1872 xwrite_and_update_handshake_hash(tls, sizeof(*record));
@@ -1427,36 +1877,72 @@ static void send_client_key_exchange(tls_state_t *tls)
1427 struct client_key_exchange { 1877 struct client_key_exchange {
1428 uint8_t type; 1878 uint8_t type;
1429 uint8_t len24_hi, len24_mid, len24_lo; 1879 uint8_t len24_hi, len24_mid, len24_lo;
1430 /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */ 1880 uint8_t key[2 + 4 * 1024]; // size??
1431 uint8_t keylen16_hi, keylen16_lo;
1432 uint8_t key[4 * 1024]; // size??
1433 }; 1881 };
1434//FIXME: better size estimate 1882//FIXME: better size estimate
1435 struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record)); 1883 struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record));
1436 uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; 1884 uint8_t rsa_premaster[RSA_PREMASTER_SIZE];
1885 uint8_t x25519_premaster[CURVE25519_KEYSIZE];
1886 uint8_t *premaster;
1887 int premaster_size;
1437 int len; 1888 int len;
1438 1889
1439 tls_get_random(rsa_premaster, sizeof(rsa_premaster)); 1890 if (!(tls->flags & NEED_EC_KEY)) {
1440 if (TLS_DEBUG_FIXED_SECRETS) 1891 /* RSA */
1441 memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); 1892 if (!(tls->flags & GOT_CERT_RSA_KEY_ALG))
1442 // RFC 5246 1893 bb_error_msg("server cert is not RSA");
1443 // "Note: The version number in the PreMasterSecret is the version 1894
1444 // offered by the client in the ClientHello.client_version, not the 1895 tls_get_random(rsa_premaster, sizeof(rsa_premaster));
1445 // version negotiated for the connection." 1896 if (TLS_DEBUG_FIXED_SECRETS)
1446 rsa_premaster[0] = TLS_MAJ; 1897 memset(rsa_premaster, 0x44, sizeof(rsa_premaster));
1447 rsa_premaster[1] = TLS_MIN; 1898 // RFC 5246
1448 dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); 1899 // "Note: The version number in the PreMasterSecret is the version
1449 len = psRsaEncryptPub(/*pool:*/ NULL, 1900 // offered by the client in the ClientHello.client_version, not the
1450 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, 1901 // version negotiated for the connection."
1451 rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), 1902 rsa_premaster[0] = TLS_MAJ;
1452 record->key, sizeof(record->key), 1903 rsa_premaster[1] = TLS_MIN;
1453 data_param_ignored 1904 dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster));
1454 ); 1905 len = psRsaEncryptPub(/*pool:*/ NULL,
1455 record->keylen16_hi = len >> 8; 1906 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key,
1456 record->keylen16_lo = len & 0xff; 1907 rsa_premaster, /*inlen:*/ sizeof(rsa_premaster),
1457 len += 2; 1908 record->key + 2, sizeof(record->key) - 2,
1909 data_param_ignored
1910 );
1911 /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */
1912 record->key[0] = len >> 8;
1913 record->key[1] = len & 0xff;
1914 len += 2;
1915 premaster = rsa_premaster;
1916 premaster_size = sizeof(rsa_premaster);
1917 } else {
1918 /* ECDHE */
1919 static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9};
1920 uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
1921
1922 if (!(tls->flags & GOT_EC_KEY))
1923 bb_error_msg("server did not provide EC key");
1924
1925 /* Generate random private key, see RFC 7748 */
1926 tls_get_random(privkey, sizeof(privkey));
1927 privkey[0] &= 0xf8;
1928 privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40);
1929
1930 /* Compute public key */
1931 curve25519(record->key + 1, privkey, basepoint9);
1932
1933 /* Compute premaster using peer's public key */
1934 dbg("computing x25519_premaster\n");
1935 curve25519(x25519_premaster, privkey, tls->hsd->ecc_pub_key32);
1936
1937 len = CURVE25519_KEYSIZE;
1938 record->key[0] = len;
1939 len++;
1940 premaster = x25519_premaster;
1941 premaster_size = sizeof(x25519_premaster);
1942 }
1943
1458 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; 1944 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE;
1459 record->len24_hi = 0; 1945 /* record->len24_hi = 0; - already is */
1460 record->len24_mid = len >> 8; 1946 record->len24_mid = len >> 8;
1461 record->len24_lo = len & 0xff; 1947 record->len24_lo = len & 0xff;
1462 len += 4; 1948 len += 4;
@@ -1476,7 +1962,7 @@ static void send_client_key_exchange(tls_state_t *tls)
1476 // of the premaster secret will vary depending on key exchange method. 1962 // of the premaster secret will vary depending on key exchange method.
1477 prf_hmac_sha256(/*tls,*/ 1963 prf_hmac_sha256(/*tls,*/
1478 tls->hsd->master_secret, sizeof(tls->hsd->master_secret), 1964 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1479 rsa_premaster, sizeof(rsa_premaster), 1965 premaster, premaster_size,
1480 "master secret", 1966 "master secret",
1481 tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32) 1967 tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32)
1482 ); 1968 );
@@ -1523,23 +2009,38 @@ static void send_client_key_exchange(tls_state_t *tls)
1523 memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); 2009 memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32);
1524 2010
1525 prf_hmac_sha256(/*tls,*/ 2011 prf_hmac_sha256(/*tls,*/
1526 tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size), 2012 tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size + tls->IV_size),
1527 // also fills: 2013 // also fills:
1528 // server_write_MAC_key[] 2014 // server_write_MAC_key[]
1529 // client_write_key[] 2015 // client_write_key[]
1530 // server_write_key[] 2016 // server_write_key[]
2017 // client_write_IV[]
2018 // server_write_IV[]
1531 tls->hsd->master_secret, sizeof(tls->hsd->master_secret), 2019 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1532 "key expansion", 2020 "key expansion",
1533 tmp64, 64 2021 tmp64, 64
1534 ); 2022 );
1535 tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size); 2023 tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size);
1536 tls->server_write_key = tls->client_write_key + tls->key_size; 2024 tls->server_write_key = tls->client_write_key + tls->key_size;
2025 tls->client_write_IV = tls->server_write_key + tls->key_size;
2026 tls->server_write_IV = tls->client_write_IV + tls->IV_size;
1537 dump_hex("client_write_MAC_key:%s\n", 2027 dump_hex("client_write_MAC_key:%s\n",
1538 tls->client_write_MAC_key, tls->MAC_size 2028 tls->client_write_MAC_key, tls->MAC_size
1539 ); 2029 );
1540 dump_hex("client_write_key:%s\n", 2030 dump_hex("client_write_key:%s\n",
1541 tls->client_write_key, tls->key_size 2031 tls->client_write_key, tls->key_size
1542 ); 2032 );
2033 dump_hex("client_write_IV:%s\n",
2034 tls->client_write_IV, tls->IV_size
2035 );
2036
2037 aes_setkey(&tls->aes_decrypt, tls->server_write_key, tls->key_size);
2038 aes_setkey(&tls->aes_encrypt, tls->client_write_key, tls->key_size);
2039 {
2040 uint8_t iv[AES_BLOCK_SIZE];
2041 memset(iv, 0, AES_BLOCK_SIZE);
2042 aes_encrypt_one_block(&tls->aes_encrypt, iv, tls->H);
2043 }
1543 } 2044 }
1544} 2045}
1545 2046
@@ -1604,7 +2105,8 @@ static void send_client_finished(tls_state_t *tls)
1604 2105
1605 fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); 2106 fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record));
1606 2107
1607 len = get_handshake_hash(tls, handshake_hash); 2108 len = sha_end(&tls->hsd->handshake_hash_ctx, handshake_hash);
2109
1608 prf_hmac_sha256(/*tls,*/ 2110 prf_hmac_sha256(/*tls,*/
1609 record->prf_result, sizeof(record->prf_result), 2111 record->prf_result, sizeof(record->prf_result),
1610 tls->hsd->master_secret, sizeof(tls->hsd->master_secret), 2112 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
@@ -1663,8 +2165,19 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1663 //SvKey len=455^ 2165 //SvKey len=455^
1664 // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: 2166 // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes:
1665 // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... 2167 // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75...
2168 //
2169 // RFC 8422 5.4. Server Key Exchange
2170 // This message is sent when using the ECDHE_ECDSA, ECDHE_RSA, and
2171 // ECDH_anon key exchange algorithms.
2172 // This message is used to convey the server's ephemeral ECDH public key
2173 // (and the corresponding elliptic curve domain parameters) to the
2174 // client.
1666 dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); 2175 dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len);
1667//probably need to save it 2176 dump_raw_in("<< %s\n", tls->inbuf, RECHDR_LEN + len);
2177 if (tls->flags & NEED_EC_KEY)
2178 process_server_key(tls, len);
2179
2180 // read next handshake block
1668 len = tls_xread_handshake_block(tls, 4); 2181 len = tls_xread_handshake_block(tls, 4);
1669 } 2182 }
1670 2183
@@ -1698,7 +2211,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1698 send_change_cipher_spec(tls); 2211 send_change_cipher_spec(tls);
1699 /* from now on we should send encrypted */ 2212 /* from now on we should send encrypted */
1700 /* tls->write_seq64_be = 0; - already is */ 2213 /* tls->write_seq64_be = 0; - already is */
1701 tls->encrypt_on_write = 1; 2214 tls->flags |= ENCRYPT_ON_WRITE;
1702 2215
1703 send_client_finished(tls); 2216 send_client_finished(tls);
1704 2217
@@ -1707,18 +2220,22 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1707 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) 2220 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0)
1708 bad_record_die(tls, "switch to encrypted traffic", len); 2221 bad_record_die(tls, "switch to encrypted traffic", len);
1709 dbg("<< CHANGE_CIPHER_SPEC\n"); 2222 dbg("<< CHANGE_CIPHER_SPEC\n");
1710 if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256 2223
2224 if (ALLOW_RSA_NULL_SHA256
1711 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256 2225 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256
1712 ) { 2226 ) {
1713 tls->min_encrypted_len_on_read = tls->MAC_size; 2227 tls->min_encrypted_len_on_read = tls->MAC_size;
1714 } else { 2228 } else
1715 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE; 2229 if (!(tls->flags & ENCRYPTION_AESGCM)) {
2230 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE;
1716 /* all incoming packets now should be encrypted and have 2231 /* all incoming packets now should be encrypted and have
1717 * at least IV + (MAC padded to blocksize): 2232 * at least IV + (MAC padded to blocksize):
1718 */ 2233 */
1719 tls->min_encrypted_len_on_read = AES_BLOCKSIZE + (mac_blocks * AES_BLOCKSIZE); 2234 tls->min_encrypted_len_on_read = AES_BLOCK_SIZE + (mac_blocks * AES_BLOCK_SIZE);
1720 dbg("min_encrypted_len_on_read: %u", tls->min_encrypted_len_on_read); 2235 } else {
2236 tls->min_encrypted_len_on_read = 8 + AES_BLOCK_SIZE;
1721 } 2237 }
2238 dbg("min_encrypted_len_on_read: %u\n", tls->min_encrypted_len_on_read);
1722 2239
1723 /* Get (encrypted) FINISHED from the server */ 2240 /* Get (encrypted) FINISHED from the server */
1724 len = tls_xread_record(tls, "'server finished'"); 2241 len = tls_xread_record(tls, "'server finished'");
@@ -1728,6 +2245,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1728 /* application data can be sent/received */ 2245 /* application data can be sent/received */
1729 2246
1730 /* free handshake data */ 2247 /* free handshake data */
2248 psRsaKey_clear(&tls->hsd->server_rsa_pub_key);
1731// if (PARANOIA) 2249// if (PARANOIA)
1732// memset(tls->hsd, 0, tls->hsd->hsd_size); 2250// memset(tls->hsd, 0, tls->hsd->hsd_size);
1733 free(tls->hsd); 2251 free(tls->hsd);
@@ -1742,12 +2260,12 @@ static void tls_xwrite(tls_state_t *tls, int len)
1742 2260
1743// To run a test server using openssl: 2261// To run a test server using openssl:
1744// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' 2262// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1745// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 2263// openssl s_server -key key.pem -cert server.pem -debug -tls1_2
1746// 2264//
1747// Unencryped SHA256 example: 2265// Unencryped SHA256 example:
1748// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' 2266// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1749// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL 2267// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -cipher NULL
1750// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 2268// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -cipher NULL-SHA256
1751 2269
1752void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) 2270void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags)
1753{ 2271{
diff --git a/networking/tls.h b/networking/tls.h
index d487f3810..494ed78c4 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -78,7 +78,14 @@ typedef int16_t int16;
78#define PUBKEY_TYPE 0x01 78#define PUBKEY_TYPE 0x01
79#define PRIVKEY_TYPE 0x02 79#define PRIVKEY_TYPE 0x02
80 80
81void tls_get_random(void *buf, unsigned len); 81#define AES_BLOCK_SIZE 16
82
83void tls_get_random(void *buf, unsigned len) FAST_FUNC;
84
85void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC;
86
87#define ALIGNED_long ALIGNED(sizeof(long))
88void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC;
82 89
83#define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) 90#define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS)
84 91
@@ -94,6 +101,8 @@ void tls_get_random(void *buf, unsigned len);
94 101
95 102
96#include "tls_pstm.h" 103#include "tls_pstm.h"
97#include "tls_rsa.h"
98#include "tls_symmetric.h" 104#include "tls_symmetric.h"
99#include "tls_aes.h" 105#include "tls_aes.h"
106#include "tls_aesgcm.h"
107#include "tls_rsa.h"
108#include "tls_fe.h"
diff --git a/networking/tls_aes.c b/networking/tls_aes.c
index c137442e9..cf6b5fe3d 100644
--- a/networking/tls_aes.c
+++ b/networking/tls_aes.c
@@ -326,8 +326,11 @@ static void InvMixColumns(unsigned astate[16])
326 } 326 }
327} 327}
328 328
329static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey) 329static void aes_encrypt_1(struct tls_aes *aes, unsigned astate[16])
330{ 330{
331 unsigned rounds = aes->rounds;
332 const uint32_t *RoundKey = aes->key;
333
331 for (;;) { 334 for (;;) {
332 AddRoundKey(astate, RoundKey); 335 AddRoundKey(astate, RoundKey);
333 RoundKey += 4; 336 RoundKey += 4;
@@ -340,8 +343,12 @@ static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *
340 AddRoundKey(astate, RoundKey); 343 AddRoundKey(astate, RoundKey);
341} 344}
342 345
343#if 0 // UNUSED 346void FAST_FUNC aes_setkey(struct tls_aes *aes, const void *key, unsigned key_len)
344static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst) 347{
348 aes->rounds = KeyExpansion(aes->key, key, key_len);
349}
350
351void FAST_FUNC aes_encrypt_one_block(struct tls_aes *aes, const void *data, void *dst)
345{ 352{
346 unsigned astate[16]; 353 unsigned astate[16];
347 unsigned i; 354 unsigned i;
@@ -351,23 +358,19 @@ static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, con
351 358
352 for (i = 0; i < 16; i++) 359 for (i = 0; i < 16; i++)
353 astate[i] = pt[i]; 360 astate[i] = pt[i];
354 aes_encrypt_1(astate, rounds, RoundKey); 361 aes_encrypt_1(aes, astate);
355 for (i = 0; i < 16; i++) 362 for (i = 0; i < 16; i++)
356 ct[i] = astate[i]; 363 ct[i] = astate[i];
357} 364}
358#endif
359 365
360void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) 366void FAST_FUNC aes_cbc_encrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst)
361{ 367{
362 uint32_t RoundKey[60];
363 uint8_t iv2[16]; 368 uint8_t iv2[16];
364 unsigned rounds;
365 369
366 const uint8_t *pt = data; 370 const uint8_t *pt = data;
367 uint8_t *ct = dst; 371 uint8_t *ct = dst;
368 372
369 memcpy(iv2, iv, 16); 373 memcpy(iv2, iv, 16);
370 rounds = KeyExpansion(RoundKey, key, klen);
371 while (len > 0) { 374 while (len > 0) {
372 { 375 {
373 /* almost aes_encrypt_one_block(rounds, RoundKey, pt, ct); 376 /* almost aes_encrypt_one_block(rounds, RoundKey, pt, ct);
@@ -378,7 +381,7 @@ void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size
378 unsigned astate[16]; 381 unsigned astate[16];
379 for (i = 0; i < 16; i++) 382 for (i = 0; i < 16; i++)
380 astate[i] = pt[i] ^ iv2[i]; 383 astate[i] = pt[i] ^ iv2[i];
381 aes_encrypt_1(astate, rounds, RoundKey); 384 aes_encrypt_1(aes, astate);
382 for (i = 0; i < 16; i++) 385 for (i = 0; i < 16; i++)
383 iv2[i] = ct[i] = astate[i]; 386 iv2[i] = ct[i] = astate[i];
384 } 387 }
@@ -388,8 +391,11 @@ void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size
388 } 391 }
389} 392}
390 393
391static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey) 394static void aes_decrypt_1(struct tls_aes *aes, unsigned astate[16])
392{ 395{
396 unsigned rounds = aes->rounds;
397 const uint32_t *RoundKey = aes->key;
398
393 RoundKey += rounds * 4; 399 RoundKey += rounds * 4;
394 AddRoundKey(astate, RoundKey); 400 AddRoundKey(astate, RoundKey);
395 for (;;) { 401 for (;;) {
@@ -404,8 +410,10 @@ static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *
404} 410}
405 411
406#if 0 //UNUSED 412#if 0 //UNUSED
407static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst) 413static void aes_decrypt_one_block(struct tls_aes *aes, const void *data, void *dst)
408{ 414{
415 unsigned rounds = aes->rounds;
416 const uint32_t *RoundKey = aes->key;
409 unsigned astate[16]; 417 unsigned astate[16];
410 unsigned i; 418 unsigned i;
411 419
@@ -414,25 +422,22 @@ static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, con
414 422
415 for (i = 0; i < 16; i++) 423 for (i = 0; i < 16; i++)
416 astate[i] = ct[i]; 424 astate[i] = ct[i];
417 aes_decrypt_1(astate, rounds, RoundKey); 425 aes_decrypt_1(aes, astate);
418 for (i = 0; i < 16; i++) 426 for (i = 0; i < 16; i++)
419 pt[i] = astate[i]; 427 pt[i] = astate[i];
420} 428}
421#endif 429#endif
422 430
423void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) 431void FAST_FUNC aes_cbc_decrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst)
424{ 432{
425 uint32_t RoundKey[60];
426 uint8_t iv2[16]; 433 uint8_t iv2[16];
427 uint8_t iv3[16]; 434 uint8_t iv3[16];
428 unsigned rounds;
429 uint8_t *ivbuf; 435 uint8_t *ivbuf;
430 uint8_t *ivnext; 436 uint8_t *ivnext;
431 437
432 const uint8_t *ct = data; 438 const uint8_t *ct = data;
433 uint8_t *pt = dst; 439 uint8_t *pt = dst;
434 440
435 rounds = KeyExpansion(RoundKey, key, klen);
436 ivbuf = memcpy(iv2, iv, 16); 441 ivbuf = memcpy(iv2, iv, 16);
437 while (len) { 442 while (len) {
438 ivnext = (ivbuf==iv2) ? iv3 : iv2; 443 ivnext = (ivbuf==iv2) ? iv3 : iv2;
@@ -444,7 +449,7 @@ void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size
444 unsigned astate[16]; 449 unsigned astate[16];
445 for (i = 0; i < 16; i++) 450 for (i = 0; i < 16; i++)
446 ivnext[i] = astate[i] = ct[i]; 451 ivnext[i] = astate[i] = ct[i];
447 aes_decrypt_1(astate, rounds, RoundKey); 452 aes_decrypt_1(aes, astate);
448 for (i = 0; i < 16; i++) 453 for (i = 0; i < 16; i++)
449 pt[i] = astate[i] ^ ivbuf[i]; 454 pt[i] = astate[i] ^ ivbuf[i];
450 } 455 }
diff --git a/networking/tls_aes.h b/networking/tls_aes.h
index c6791866a..e9e3721f1 100644
--- a/networking/tls_aes.h
+++ b/networking/tls_aes.h
@@ -6,5 +6,9 @@
6 * Selected few declarations for AES. 6 * Selected few declarations for AES.
7 */ 7 */
8 8
9void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); 9void aes_setkey(struct tls_aes *aes, const void *key, unsigned key_len) FAST_FUNC;
10void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); 10
11void aes_encrypt_one_block(struct tls_aes *aes, const void *data, void *dst) FAST_FUNC;
12
13void aes_cbc_encrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst) FAST_FUNC;
14void aes_cbc_decrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst) FAST_FUNC;
diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c
new file mode 100644
index 000000000..688df85fb
--- /dev/null
+++ b/networking/tls_aesgcm.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright (C) 2018 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7#include "tls.h"
8
9typedef uint8_t byte;
10typedef uint32_t word32;
11#define XMEMSET memset
12#define XMEMCPY memcpy
13
14/* from wolfssl-3.15.3/wolfcrypt/src/aes.c */
15
16static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz)
17{
18 /* Multiply the sz by 8 */
19//bbox: these sizes are never even close to 2^32/8
20// word32 szHi = (sz >> (8*sizeof(sz) - 3));
21 sz <<= 3;
22
23 /* copy over the words of the sz into the destination buffer */
24// buf[0] = (szHi >> 24) & 0xff;
25// buf[1] = (szHi >> 16) & 0xff;
26// buf[2] = (szHi >> 8) & 0xff;
27// buf[3] = szHi & 0xff;
28 *(uint32_t*)(buf + 0) = 0;
29// buf[4] = (sz >> 24) & 0xff;
30// buf[5] = (sz >> 16) & 0xff;
31// buf[6] = (sz >> 8) & 0xff;
32// buf[7] = sz & 0xff;
33 *(uint32_t*)(buf + 4) = SWAP_BE32(sz);
34}
35
36static void RIGHTSHIFTX(byte* x)
37{
38 int i;
39 int carryOut = 0;
40 int carryIn = 0;
41 int borrow = x[15] & 0x01;
42
43 for (i = 0; i < AES_BLOCK_SIZE; i++) {
44 carryOut = x[i] & 0x01;
45 x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0);
46 carryIn = carryOut;
47 }
48 if (borrow) x[0] ^= 0xE1;
49}
50
51static void GMULT(byte* X, byte* Y)
52{
53 byte Z[AES_BLOCK_SIZE] ALIGNED_long;
54 byte V[AES_BLOCK_SIZE] ALIGNED_long;
55 int i, j;
56
57 XMEMSET(Z, 0, AES_BLOCK_SIZE);
58 XMEMCPY(V, X, AES_BLOCK_SIZE);
59 for (i = 0; i < AES_BLOCK_SIZE; i++)
60 {
61 byte y = Y[i];
62 for (j = 0; j < 8; j++)
63 {
64 if (y & 0x80) {
65 xorbuf_aligned_AES_BLOCK_SIZE(Z, V);
66 }
67
68 RIGHTSHIFTX(V);
69 y = y << 1;
70 }
71 }
72 XMEMCPY(X, Z, AES_BLOCK_SIZE);
73}
74
75//bbox:
76// for TLS AES-GCM, a (which is AAD) is always 13 bytes long, and bbox code provides
77// extra 3 zeroed bytes, making it a[16], or a[AES_BLOCK_SIZE].
78// Resulting auth tag in s[] is also always AES_BLOCK_SIZE bytes.
79//
80// This allows some simplifications.
81#define aSz 13
82#define sSz AES_BLOCK_SIZE
83void FAST_FUNC aesgcm_GHASH(byte* h,
84 const byte* a, //unsigned aSz,
85 const byte* c, unsigned cSz,
86 byte* s //, unsigned sSz
87)
88{
89 byte x[AES_BLOCK_SIZE] ALIGNED_long;
90// byte scratch[AES_BLOCK_SIZE] ALIGNED_long;
91 unsigned blocks, partial;
92 //was: byte* h = aes->H;
93
94 //XMEMSET(x, 0, AES_BLOCK_SIZE);
95
96 /* Hash in A, the Additional Authentication Data */
97// if (aSz != 0 && a != NULL) {
98// blocks = aSz / AES_BLOCK_SIZE;
99// partial = aSz % AES_BLOCK_SIZE;
100// while (blocks--) {
101 //xorbuf(x, a, AES_BLOCK_SIZE);
102 XMEMCPY(x, a, AES_BLOCK_SIZE);// memcpy(x,a) = memset(x,0)+xorbuf(x,a)
103 GMULT(x, h);
104// a += AES_BLOCK_SIZE;
105// }
106// if (partial != 0) {
107// XMEMSET(scratch, 0, AES_BLOCK_SIZE);
108// XMEMCPY(scratch, a, partial);
109// xorbuf(x, scratch, AES_BLOCK_SIZE);
110// GMULT(x, h);
111// }
112// }
113
114 /* Hash in C, the Ciphertext */
115 if (cSz != 0 /*&& c != NULL*/) {
116 blocks = cSz / AES_BLOCK_SIZE;
117 partial = cSz % AES_BLOCK_SIZE;
118 while (blocks--) {
119 if (BB_UNALIGNED_MEMACCESS_OK) // c is not guaranteed to be aligned
120 xorbuf_aligned_AES_BLOCK_SIZE(x, c);
121 else
122 xorbuf(x, c, AES_BLOCK_SIZE);
123 GMULT(x, h);
124 c += AES_BLOCK_SIZE;
125 }
126 if (partial != 0) {
127 //XMEMSET(scratch, 0, AES_BLOCK_SIZE);
128 //XMEMCPY(scratch, c, partial);
129 //xorbuf(x, scratch, AES_BLOCK_SIZE);
130 xorbuf(x, c, partial);//same result as above
131 GMULT(x, h);
132 }
133 }
134
135 /* Hash in the lengths of A and C in bits */
136 //FlattenSzInBits(&scratch[0], aSz);
137 //FlattenSzInBits(&scratch[8], cSz);
138 //xorbuf_aligned_AES_BLOCK_SIZE(x, scratch);
139 // simpler:
140#define P32(v) ((uint32_t*)v)
141 //P32(x)[0] ^= 0;
142 P32(x)[1] ^= SWAP_BE32(aSz * 8);
143 //P32(x)[2] ^= 0;
144 P32(x)[3] ^= SWAP_BE32(cSz * 8);
145#undef P32
146
147 GMULT(x, h);
148
149 /* Copy the result into s. */
150 XMEMCPY(s, x, sSz);
151}
diff --git a/networking/tls_aesgcm.h b/networking/tls_aesgcm.h
new file mode 100644
index 000000000..d7e672e6e
--- /dev/null
+++ b/networking/tls_aesgcm.h
@@ -0,0 +1,11 @@
1/*
2 * Copyright (C) 2018 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7void aesgcm_GHASH(uint8_t* h,
8 const uint8_t* a, //unsigned aSz,
9 const uint8_t* c, unsigned cSz,
10 uint8_t* s //, unsigned sSz
11) FAST_FUNC;
diff --git a/networking/tls_fe.c b/networking/tls_fe.c
new file mode 100644
index 000000000..f235082f5
--- /dev/null
+++ b/networking/tls_fe.c
@@ -0,0 +1,611 @@
1/*
2 * Copyright (C) 2018 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8typedef uint8_t byte;
9typedef uint16_t word16;
10typedef uint32_t word32;
11#define XMEMSET memset
12
13#define F25519_SIZE CURVE25519_KEYSIZE
14
15/* The code below is taken from wolfssl-3.15.3/wolfcrypt/src/fe_low_mem.c
16 * Header comment is kept intact:
17 */
18
19/* fe_low_mem.c
20 *
21 * Copyright (C) 2006-2017 wolfSSL Inc.
22 *
23 * This file is part of wolfSSL.
24 *
25 * wolfSSL is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * wolfSSL is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
38 */
39
40
41/* Based from Daniel Beer's public domain work. */
42
43#if 0 //UNUSED
44static void fprime_copy(byte *x, const byte *a)
45{
46 int i;
47 for (i = 0; i < F25519_SIZE; i++)
48 x[i] = a[i];
49}
50#endif
51
52static void lm_copy(byte* x, const byte* a)
53{
54 int i;
55 for (i = 0; i < F25519_SIZE; i++)
56 x[i] = a[i];
57}
58
59#if 0 //UNUSED
60static void fprime_select(byte *dst, const byte *zero, const byte *one, byte condition)
61{
62 const byte mask = -condition;
63 int i;
64
65 for (i = 0; i < F25519_SIZE; i++)
66 dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
67}
68#endif
69
70static void fe_select(byte *dst,
71 const byte *zero, const byte *one,
72 byte condition)
73{
74 const byte mask = -condition;
75 int i;
76
77 for (i = 0; i < F25519_SIZE; i++)
78 dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
79}
80
81#if 0 //UNUSED
82static void raw_add(byte *x, const byte *p)
83{
84 word16 c = 0;
85 int i;
86
87 for (i = 0; i < F25519_SIZE; i++) {
88 c += ((word16)x[i]) + ((word16)p[i]);
89 x[i] = (byte)c;
90 c >>= 8;
91 }
92}
93#endif
94
95#if 0 //UNUSED
96static void raw_try_sub(byte *x, const byte *p)
97{
98 byte minusp[F25519_SIZE];
99 word16 c = 0;
100 int i;
101
102 for (i = 0; i < F25519_SIZE; i++) {
103 c = ((word16)x[i]) - ((word16)p[i]) - c;
104 minusp[i] = (byte)c;
105 c = (c >> 8) & 1;
106 }
107
108 fprime_select(x, minusp, x, (byte)c);
109}
110#endif
111
112#if 0 //UNUSED
113static int prime_msb(const byte *p)
114{
115 int i;
116 byte x;
117 int shift = 1;
118 int z = F25519_SIZE - 1;
119
120 /*
121 Test for any hot bits.
122 As soon as one instance is encountered set shift to 0.
123 */
124 for (i = F25519_SIZE - 1; i >= 0; i--) {
125 shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1);
126 z -= shift;
127 }
128 x = p[z];
129 z <<= 3;
130 shift = 1;
131 for (i = 0; i < 8; i++) {
132 shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1);
133 z += shift;
134 }
135
136 return z - 1;
137}
138#endif
139
140#if 0 //UNUSED
141static void fprime_add(byte *r, const byte *a, const byte *modulus)
142{
143 raw_add(r, a);
144 raw_try_sub(r, modulus);
145}
146#endif
147
148#if 0 //UNUSED
149static void fprime_sub(byte *r, const byte *a, const byte *modulus)
150{
151 raw_add(r, modulus);
152 raw_try_sub(r, a);
153 raw_try_sub(r, modulus);
154}
155#endif
156
157#if 0 //UNUSED
158static void fprime_mul(byte *r, const byte *a, const byte *b,
159 const byte *modulus)
160{
161 word16 c = 0;
162 int i,j;
163
164 XMEMSET(r, 0, F25519_SIZE);
165
166 for (i = prime_msb(modulus); i >= 0; i--) {
167 const byte bit = (b[i >> 3] >> (i & 7)) & 1;
168 byte plusa[F25519_SIZE];
169
170 for (j = 0; j < F25519_SIZE; j++) {
171 c |= ((word16)r[j]) << 1;
172 r[j] = (byte)c;
173 c >>= 8;
174 }
175 raw_try_sub(r, modulus);
176
177 fprime_copy(plusa, r);
178 fprime_add(plusa, a, modulus);
179
180 fprime_select(r, r, plusa, bit);
181 }
182}
183#endif
184
185#if 0 //UNUSED
186static void fe_load(byte *x, word32 c)
187{
188 word32 i;
189
190 for (i = 0; i < sizeof(c); i++) {
191 x[i] = c;
192 c >>= 8;
193 }
194
195 for (; i < F25519_SIZE; i++)
196 x[i] = 0;
197}
198#endif
199
200static void fe_normalize(byte *x)
201{
202 byte minusp[F25519_SIZE];
203 word16 c;
204 int i;
205
206 /* Reduce using 2^255 = 19 mod p */
207 c = (x[31] >> 7) * 19;
208 x[31] &= 127;
209
210 for (i = 0; i < F25519_SIZE; i++) {
211 c += x[i];
212 x[i] = (byte)c;
213 c >>= 8;
214 }
215
216 /* The number is now less than 2^255 + 18, and therefore less than
217 * 2p. Try subtracting p, and conditionally load the subtracted
218 * value if underflow did not occur.
219 */
220 c = 19;
221
222 for (i = 0; i + 1 < F25519_SIZE; i++) {
223 c += x[i];
224 minusp[i] = (byte)c;
225 c >>= 8;
226 }
227
228 c += ((word16)x[i]) - 128;
229 minusp[31] = (byte)c;
230
231 /* Load x-p if no underflow */
232 fe_select(x, minusp, x, (c >> 15) & 1);
233}
234
235static void lm_add(byte* r, const byte* a, const byte* b)
236{
237 word16 c = 0;
238 int i;
239
240 /* Add */
241 for (i = 0; i < F25519_SIZE; i++) {
242 c >>= 8;
243 c += ((word16)a[i]) + ((word16)b[i]);
244 r[i] = (byte)c;
245 }
246
247 /* Reduce with 2^255 = 19 mod p */
248 r[31] &= 127;
249 c = (c >> 7) * 19;
250
251 for (i = 0; i < F25519_SIZE; i++) {
252 c += r[i];
253 r[i] = (byte)c;
254 c >>= 8;
255 }
256}
257
258static void lm_sub(byte* r, const byte* a, const byte* b)
259{
260 word32 c = 0;
261 int i;
262
263 /* Calculate a + 2p - b, to avoid underflow */
264 c = 218;
265 for (i = 0; i + 1 < F25519_SIZE; i++) {
266 c += 65280 + ((word32)a[i]) - ((word32)b[i]);
267 r[i] = c;
268 c >>= 8;
269 }
270
271 c += ((word32)a[31]) - ((word32)b[31]);
272 r[31] = c & 127;
273 c = (c >> 7) * 19;
274
275 for (i = 0; i < F25519_SIZE; i++) {
276 c += r[i];
277 r[i] = c;
278 c >>= 8;
279 }
280}
281
282#if 0 //UNUSED
283static void lm_neg(byte* r, const byte* a)
284{
285 word32 c = 0;
286 int i;
287
288 /* Calculate 2p - a, to avoid underflow */
289 c = 218;
290 for (i = 0; i + 1 < F25519_SIZE; i++) {
291 c += 65280 - ((word32)a[i]);
292 r[i] = c;
293 c >>= 8;
294 }
295
296 c -= ((word32)a[31]);
297 r[31] = c & 127;
298 c = (c >> 7) * 19;
299
300 for (i = 0; i < F25519_SIZE; i++) {
301 c += r[i];
302 r[i] = c;
303 c >>= 8;
304 }
305}
306#endif
307
308static void fe_mul__distinct(byte *r, const byte *a, const byte *b)
309{
310 word32 c = 0;
311 int i;
312
313 for (i = 0; i < F25519_SIZE; i++) {
314 int j;
315
316 c >>= 8;
317 for (j = 0; j <= i; j++)
318 c += ((word32)a[j]) * ((word32)b[i - j]);
319
320 for (; j < F25519_SIZE; j++)
321 c += ((word32)a[j]) *
322 ((word32)b[i + F25519_SIZE - j]) * 38;
323
324 r[i] = c;
325 }
326
327 r[31] &= 127;
328 c = (c >> 7) * 19;
329
330 for (i = 0; i < F25519_SIZE; i++) {
331 c += r[i];
332 r[i] = c;
333 c >>= 8;
334 }
335}
336
337#if 0 //UNUSED
338static void lm_mul(byte *r, const byte* a, const byte *b)
339{
340 byte tmp[F25519_SIZE];
341
342 fe_mul__distinct(tmp, a, b);
343 lm_copy(r, tmp);
344}
345#endif
346
347static void fe_mul_c(byte *r, const byte *a, word32 b)
348{
349 word32 c = 0;
350 int i;
351
352 for (i = 0; i < F25519_SIZE; i++) {
353 c >>= 8;
354 c += b * ((word32)a[i]);
355 r[i] = c;
356 }
357
358 r[31] &= 127;
359 c >>= 7;
360 c *= 19;
361
362 for (i = 0; i < F25519_SIZE; i++) {
363 c += r[i];
364 r[i] = c;
365 c >>= 8;
366 }
367}
368
369static void fe_inv__distinct(byte *r, const byte *x)
370{
371 byte s[F25519_SIZE];
372 int i;
373
374 /* This is a prime field, so by Fermat's little theorem:
375 *
376 * x^(p-1) = 1 mod p
377 *
378 * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative
379 * inverse.
380 *
381 * This is a 255-bit binary number with the digits:
382 *
383 * 11111111... 01011
384 *
385 * We compute the result by the usual binary chain, but
386 * alternate between keeping the accumulator in r and s, so as
387 * to avoid copying temporaries.
388 */
389
390 /* 1 1 */
391 fe_mul__distinct(s, x, x);
392 fe_mul__distinct(r, s, x);
393
394 /* 1 x 248 */
395 for (i = 0; i < 248; i++) {
396 fe_mul__distinct(s, r, r);
397 fe_mul__distinct(r, s, x);
398 }
399
400 /* 0 */
401 fe_mul__distinct(s, r, r);
402
403 /* 1 */
404 fe_mul__distinct(r, s, s);
405 fe_mul__distinct(s, r, x);
406
407 /* 0 */
408 fe_mul__distinct(r, s, s);
409
410 /* 1 */
411 fe_mul__distinct(s, r, r);
412 fe_mul__distinct(r, s, x);
413
414 /* 1 */
415 fe_mul__distinct(s, r, r);
416 fe_mul__distinct(r, s, x);
417}
418
419#if 0 //UNUSED
420static void lm_invert(byte *r, const byte *x)
421{
422 byte tmp[F25519_SIZE];
423
424 fe_inv__distinct(tmp, x);
425 lm_copy(r, tmp);
426}
427#endif
428
429#if 0 //UNUSED
430/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary
431 * storage.
432 */
433static void exp2523(byte *r, const byte *x, byte *s)
434{
435 int i;
436
437 /* This number is a 252-bit number with the binary expansion:
438 *
439 * 111111... 01
440 */
441
442 /* 1 1 */
443 fe_mul__distinct(r, x, x);
444 fe_mul__distinct(s, r, x);
445
446 /* 1 x 248 */
447 for (i = 0; i < 248; i++) {
448 fe_mul__distinct(r, s, s);
449 fe_mul__distinct(s, r, x);
450 }
451
452 /* 0 */
453 fe_mul__distinct(r, s, s);
454
455 /* 1 */
456 fe_mul__distinct(s, r, r);
457 fe_mul__distinct(r, s, x);
458}
459#endif
460
461#if 0 //UNUSED
462static void fe_sqrt(byte *r, const byte *a)
463{
464 byte v[F25519_SIZE];
465 byte i[F25519_SIZE];
466 byte x[F25519_SIZE];
467 byte y[F25519_SIZE];
468
469 /* v = (2a)^((p-5)/8) [x = 2a] */
470 fe_mul_c(x, a, 2);
471 exp2523(v, x, y);
472
473 /* i = 2av^2 - 1 */
474 fe_mul__distinct(y, v, v);
475 fe_mul__distinct(i, x, y);
476 fe_load(y, 1);
477 lm_sub(i, i, y);
478
479 /* r = avi */
480 fe_mul__distinct(x, v, a);
481 fe_mul__distinct(r, x, i);
482}
483#endif
484
485/* Differential addition */
486static void xc_diffadd(byte *x5, byte *z5,
487 const byte *x1, const byte *z1,
488 const byte *x2, const byte *z2,
489 const byte *x3, const byte *z3)
490{
491 /* Explicit formulas database: dbl-1987-m3
492 *
493 * source 1987 Montgomery "Speeding the Pollard and elliptic curve
494 * methods of factorization", page 261, fifth display, plus
495 * common-subexpression elimination
496 * compute A = X2+Z2
497 * compute B = X2-Z2
498 * compute C = X3+Z3
499 * compute D = X3-Z3
500 * compute DA = D A
501 * compute CB = C B
502 * compute X5 = Z1(DA+CB)^2
503 * compute Z5 = X1(DA-CB)^2
504 */
505 byte da[F25519_SIZE];
506 byte cb[F25519_SIZE];
507 byte a[F25519_SIZE];
508 byte b[F25519_SIZE];
509
510 lm_add(a, x2, z2);
511 lm_sub(b, x3, z3); /* D */
512 fe_mul__distinct(da, a, b);
513
514 lm_sub(b, x2, z2);
515 lm_add(a, x3, z3); /* C */
516 fe_mul__distinct(cb, a, b);
517
518 lm_add(a, da, cb);
519 fe_mul__distinct(b, a, a);
520 fe_mul__distinct(x5, z1, b);
521
522 lm_sub(a, da, cb);
523 fe_mul__distinct(b, a, a);
524 fe_mul__distinct(z5, x1, b);
525}
526
527/* Double an X-coordinate */
528static void xc_double(byte *x3, byte *z3,
529 const byte *x1, const byte *z1)
530{
531 /* Explicit formulas database: dbl-1987-m
532 *
533 * source 1987 Montgomery "Speeding the Pollard and elliptic
534 * curve methods of factorization", page 261, fourth display
535 * compute X3 = (X1^2-Z1^2)^2
536 * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2)
537 */
538 byte x1sq[F25519_SIZE];
539 byte z1sq[F25519_SIZE];
540 byte x1z1[F25519_SIZE];
541 byte a[F25519_SIZE];
542
543 fe_mul__distinct(x1sq, x1, x1);
544 fe_mul__distinct(z1sq, z1, z1);
545 fe_mul__distinct(x1z1, x1, z1);
546
547 lm_sub(a, x1sq, z1sq);
548 fe_mul__distinct(x3, a, a);
549
550 fe_mul_c(a, x1z1, 486662);
551 lm_add(a, x1sq, a);
552 lm_add(a, z1sq, a);
553 fe_mul__distinct(x1sq, x1z1, a);
554 fe_mul_c(z3, x1sq, 4);
555}
556
557void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q)
558{
559 int i;
560
561 struct {
562 /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */
563 /*static const*/ byte f25519_one[F25519_SIZE]; // = {1};
564
565 /* Current point: P_m */
566 byte xm[F25519_SIZE];
567 byte zm[F25519_SIZE]; // = {1};
568 /* Predecessor: P_(m-1) */
569 byte xm1[F25519_SIZE]; // = {1};
570 byte zm1[F25519_SIZE]; // = {0};
571 } z;
572#define f25519_one z.f25519_one
573#define xm z.xm
574#define zm z.zm
575#define xm1 z.xm1
576#define zm1 z.zm1
577 memset(&z, 0, sizeof(z));
578 f25519_one[0] = 1;
579 zm[0] = 1;
580 xm1[0] = 1;
581
582 /* Note: bit 254 is assumed to be 1 */
583 lm_copy(xm, q);
584
585 for (i = 253; i >= 0; i--) {
586 const int bit = (e[i >> 3] >> (i & 7)) & 1;
587 byte xms[F25519_SIZE];
588 byte zms[F25519_SIZE];
589
590 /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */
591 xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1);
592 xc_double(xm, zm, xm, zm);
593
594 /* Compute P_(2m+1) */
595 xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one);
596
597 /* Select:
598 * bit = 1 --> (P_(2m+1), P_(2m))
599 * bit = 0 --> (P_(2m), P_(2m-1))
600 */
601 fe_select(xm1, xm1, xm, bit);
602 fe_select(zm1, zm1, zm, bit);
603 fe_select(xm, xm, xms, bit);
604 fe_select(zm, zm, zms, bit);
605 }
606
607 /* Freeze out of projective coordinates */
608 fe_inv__distinct(zm1, zm);
609 fe_mul__distinct(result, zm1, xm);
610 fe_normalize(result);
611}
diff --git a/networking/tls_fe.h b/networking/tls_fe.h
new file mode 100644
index 000000000..fe8cff228
--- /dev/null
+++ b/networking/tls_fe.h
@@ -0,0 +1,7 @@
1/*
2 * Copyright (C) 2018 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#define CURVE25519_KEYSIZE 32
7void curve25519(uint8_t *result, const uint8_t *e, const uint8_t *q) FAST_FUNC;
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
index 60c54248e..631397e4d 100644
--- a/networking/tls_rsa.c
+++ b/networking/tls_rsa.c
@@ -179,7 +179,7 @@ done:
179 return res; 179 return res;
180} 180}
181 181
182int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, 182int32 FAST_FUNC psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
183 unsigned char *in, uint32 inlen, 183 unsigned char *in, uint32 inlen,
184 unsigned char *out, uint32 outlen, void *data) 184 unsigned char *out, uint32 outlen, void *data)
185{ 185{
diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h
index c464ed552..82bea2a67 100644
--- a/networking/tls_rsa.h
+++ b/networking/tls_rsa.h
@@ -13,8 +13,20 @@ typedef struct {
13//bbox psPool_t *pool; 13//bbox psPool_t *pool;
14} psRsaKey_t; 14} psRsaKey_t;
15 15
16static ALWAYS_INLINE void psRsaKey_clear(psRsaKey_t *key)
17{
18 pstm_clear(&key->N);
19 pstm_clear(&key->e);
20 pstm_clear(&key->d);
21 pstm_clear(&key->p);
22 pstm_clear(&key->q);
23 pstm_clear(&key->dP);
24 pstm_clear(&key->dQ);
25 pstm_clear(&key->qP);
26}
27
16#define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \ 28#define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \
17 psRsaEncryptPub( key, in, inlen, out, outlen) 29 psRsaEncryptPub( key, in, inlen, out, outlen)
18int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, 30int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
19 unsigned char *in, uint32 inlen, 31 unsigned char *in, uint32 inlen,
20 unsigned char *out, uint32 outlen, void *data); 32 unsigned char *out, uint32 outlen, void *data) FAST_FUNC;
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 66e4b6c6a..3c6129249 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -814,7 +814,9 @@ static NOINLINE int send_d6_renew(uint32_t xid, struct in6_addr *server_ipv6, st
814} 814}
815 815
816/* Unicast a DHCP release message */ 816/* Unicast a DHCP release message */
817static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) 817static
818ALWAYS_INLINE /* one caller, help compiler to use this fact */
819int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
818{ 820{
819 struct d6_packet packet; 821 struct d6_packet packet;
820 uint8_t *opt_ptr; 822 uint8_t *opt_ptr;
@@ -1738,8 +1740,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1738 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ 1740 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */
1739 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; 1741 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2;
1740 /* paranoia: must not be too small */ 1742 /* paranoia: must not be too small */
1741 if (timeout < 0x10) 1743 /* timeout > 60 - ensures at least one unicast renew attempt */
1742 timeout = 0x10; 1744 if (timeout < 61)
1745 timeout = 61;
1743 /* enter bound state */ 1746 /* enter bound state */
1744 d6_run_script(packet.d6_options, packet_end, 1747 d6_run_script(packet.d6_options, packet_end,
1745 (state == REQUESTING ? "bound" : "renew")); 1748 (state == REQUESTING ? "bound" : "renew"));
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index ab3e5a463..4b23e4d39 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -850,7 +850,9 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req
850#endif 850#endif
851 851
852/* Unicast a DHCP release message */ 852/* Unicast a DHCP release message */
853static int send_release(uint32_t server, uint32_t ciaddr) 853static
854ALWAYS_INLINE /* one caller, help compiler to use this fact */
855int send_release(uint32_t server, uint32_t ciaddr)
854{ 856{
855 struct dhcp_packet packet; 857 struct dhcp_packet packet;
856 858
@@ -1725,8 +1727,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1725 move_from_unaligned32(lease_seconds, temp); 1727 move_from_unaligned32(lease_seconds, temp);
1726 lease_seconds = ntohl(lease_seconds); 1728 lease_seconds = ntohl(lease_seconds);
1727 /* paranoia: must not be too small and not prone to overflows */ 1729 /* paranoia: must not be too small and not prone to overflows */
1728 if (lease_seconds < 0x10) 1730 /* timeout > 60 - ensures at least one unicast renew attempt */
1729 lease_seconds = 0x10; 1731 if (lease_seconds < 2 * 61)
1732 lease_seconds = 2 * 61;
1730 //if (lease_seconds > 0x7fffffff) 1733 //if (lease_seconds > 0x7fffffff)
1731 // lease_seconds = 0x7fffffff; 1734 // lease_seconds = 0x7fffffff;
1732 //^^^not necessary since "timeout = lease_seconds / 2" 1735 //^^^not necessary since "timeout = lease_seconds / 2"
diff --git a/networking/wget.c b/networking/wget.c
index bd2f4edcf..ae5c945d0 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -233,20 +233,19 @@ struct globals {
233 char *fname_out; /* where to direct output (-O) */ 233 char *fname_out; /* where to direct output (-O) */
234 const char *proxy_flag; /* Use proxies if env vars are set */ 234 const char *proxy_flag; /* Use proxies if env vars are set */
235 const char *user_agent; /* "User-Agent" header field */ 235 const char *user_agent; /* "User-Agent" header field */
236 int output_fd;
237 int o_flags;
236#if ENABLE_FEATURE_WGET_TIMEOUT 238#if ENABLE_FEATURE_WGET_TIMEOUT
237 unsigned timeout_seconds; 239 unsigned timeout_seconds;
238 bool die_if_timed_out; 240 smallint die_if_timed_out;
239#endif 241#endif
240 int output_fd;
241 int o_flags;
242 smallint chunked; /* chunked transfer encoding */ 242 smallint chunked; /* chunked transfer encoding */
243 smallint got_clen; /* got content-length: from server */ 243 smallint got_clen; /* got content-length: from server */
244 /* Local downloads do benefit from big buffer. 244 /* Local downloads do benefit from big buffer.
245 * With 512 byte buffer, it was measured to be 245 * With 512 byte buffer, it was measured to be
246 * an order of magnitude slower than with big one. 246 * an order of magnitude slower than with big one.
247 */ 247 */
248 uint64_t just_to_align_next_member; 248 char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024] ALIGNED(sizeof(long));
249 char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024];
250} FIX_ALIASING; 249} FIX_ALIASING;
251#define G (*ptr_to_globals) 250#define G (*ptr_to_globals)
252#define INIT_G() do { \ 251#define INIT_G() do { \
@@ -283,13 +282,15 @@ enum {
283#if ENABLE_FEATURE_WGET_STATUSBAR 282#if ENABLE_FEATURE_WGET_STATUSBAR
284static void progress_meter(int flag) 283static void progress_meter(int flag)
285{ 284{
285 int notty;
286
286 if (option_mask32 & WGET_OPT_QUIET) 287 if (option_mask32 & WGET_OPT_QUIET)
287 return; 288 return;
288 289
289 if (flag == PROGRESS_START) 290 if (flag == PROGRESS_START)
290 bb_progress_init(&G.pmt, G.curfile); 291 bb_progress_init(&G.pmt, G.curfile);
291 292
292 bb_progress_update(&G.pmt, 293 notty = bb_progress_update(&G.pmt,
293 G.beg_range, 294 G.beg_range,
294 G.transferred, 295 G.transferred,
295 (G.chunked || !G.got_clen) ? 0 : G.beg_range + G.transferred + G.content_len 296 (G.chunked || !G.got_clen) ? 0 : G.beg_range + G.transferred + G.content_len
@@ -297,7 +298,8 @@ static void progress_meter(int flag)
297 298
298 if (flag == PROGRESS_END) { 299 if (flag == PROGRESS_END) {
299 bb_progress_free(&G.pmt); 300 bb_progress_free(&G.pmt);
300 bb_putchar_stderr('\n'); 301 if (notty == 0)
302 bb_putchar_stderr('\n'); /* it's tty */
301 G.transferred = 0; 303 G.transferred = 0;
302 } 304 }
303} 305}
@@ -346,9 +348,8 @@ static void strip_ipv6_scope_id(char *host)
346/* Base64-encode character string. */ 348/* Base64-encode character string. */
347static char *base64enc(const char *str) 349static char *base64enc(const char *str)
348{ 350{
349 unsigned len = strlen(str); 351 /* paranoia */
350 if (len > sizeof(G.wget_buf)/4*3 - 10) /* paranoia */ 352 unsigned len = strnlen(str, sizeof(G.wget_buf)/4*3 - 10);
351 len = sizeof(G.wget_buf)/4*3 - 10;
352 bb_uuencode(G.wget_buf, str, len, bb_uuenc_tbl_base64); 353 bb_uuencode(G.wget_buf, str, len, bb_uuenc_tbl_base64);
353 return G.wget_buf; 354 return G.wget_buf;
354} 355}
@@ -723,8 +724,10 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags)
723 int pid; 724 int pid;
724 char *servername, *p; 725 char *servername, *p;
725 726
726 if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) 727 if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) {
728 option_mask32 |= WGET_OPT_NO_CHECK_CERT;
727 bb_error_msg("note: TLS certificate validation not implemented"); 729 bb_error_msg("note: TLS certificate validation not implemented");
730 }
728 731
729 servername = xstrdup(host); 732 servername = xstrdup(host);
730 p = strrchr(servername, ':'); 733 p = strrchr(servername, ':');
diff --git a/procps/free.c b/procps/free.c
index 48139c4a3..ee0cd981a 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -53,21 +53,27 @@ static unsigned long long scale(struct globals *g, unsigned long d)
53} 53}
54 54
55/* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ 55/* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */
56static NOINLINE unsigned long parse_cached_kb(void) 56static NOINLINE unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long *available_kb)
57{ 57{
58 char buf[60]; /* actual lines we expect are ~30 chars or less */ 58 char buf[60]; /* actual lines we expect are ~30 chars or less */
59 FILE *fp; 59 FILE *fp;
60 unsigned long cached = 0; 60 int seen_cached_and_available;
61 61
62 fp = xfopen_for_read("/proc/meminfo"); 62 fp = xfopen_for_read("/proc/meminfo");
63 while (fgets(buf, sizeof(buf), fp) != NULL) { 63 *cached_kb = *available_kb = 0;
64 if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1) 64 seen_cached_and_available = 2;
65 break; 65 while (fgets(buf, sizeof(buf), fp)) {
66 if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1)
67 if (--seen_cached_and_available == 0)
68 break;
69 if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1)
70 if (--seen_cached_and_available == 0)
71 break;
66 } 72 }
67 /* Have to close because of NOFORK */ 73 /* Have to close because of NOFORK */
68 fclose(fp); 74 fclose(fp);
69 75
70 return cached; 76 return seen_cached_and_available == 0;
71} 77}
72 78
73int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 79int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -75,7 +81,9 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
75{ 81{
76 struct globals G; 82 struct globals G;
77 struct sysinfo info; 83 struct sysinfo info;
78 unsigned long long cached; 84 unsigned long long cached, cached_plus_free, available;
85 unsigned long cached_kb, available_kb;
86 int seen_available;
79 87
80#if ENABLE_DESKTOP 88#if ENABLE_DESKTOP
81 G.unit_steps = 10; 89 G.unit_steps = 10;
@@ -98,41 +106,46 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
98 } 106 }
99 } 107 }
100#endif 108#endif
101 printf(" %11s%11s%11s%11s%11s%11s\n" 109 printf(" %12s%12s%12s%12s%12s%12s\n"
102 "Mem: ", 110 "Mem: ",
103 "total", 111 "total",
104 "used", 112 "used",
105 "free", 113 "free",
106 "shared", "buffers", "cached" /* swap and total don't have these columns */ 114 "shared", "buff/cache", "available" /* swap and total don't have these columns */
107 ); 115 );
108 116
109 sysinfo(&info); 117 sysinfo(&info);
110 /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ 118 /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
111 G.mem_unit = (info.mem_unit ? info.mem_unit : 1); 119 G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
112 /* Extract cached from /proc/meminfo and convert to mem_units */ 120 /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */
113 cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit; 121 seen_available = parse_meminfo(&cached_kb, &available_kb);
122 available = ((unsigned long long) available_kb * 1024) / G.mem_unit;
123 cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit;
124 cached += info.bufferram;
125 cached_plus_free = cached + info.freeram;
114 126
115#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n" 127#define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n"
116#define FIELDS_3 (FIELDS_6 + 3*6) 128#define FIELDS_3 (FIELDS_6 + 6 + 7 + 7)
117#define FIELDS_2 (FIELDS_6 + 4*6) 129#define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7)
118 130
119 printf(FIELDS_6, 131 printf(FIELDS_6,
120 scale(&G, info.totalram), //total 132 scale(&G, info.totalram), //total
121 scale(&G, info.totalram - info.freeram), //used 133 scale(&G, info.totalram - cached_plus_free), //used
122 scale(&G, info.freeram), //free 134 scale(&G, info.freeram), //free
123 scale(&G, info.sharedram), //shared 135 scale(&G, info.sharedram), //shared
124 scale(&G, info.bufferram), //buffers 136 scale(&G, cached), //buff/cache
125 scale(&G, cached) //cached 137 scale(&G, available) //available
126 ); 138 );
127 /* Show alternate, more meaningful busy/free numbers by counting 139 /* On kernels < 3.14, MemAvailable is not provided.
140 * Show alternate, more meaningful busy/free numbers by counting
128 * buffer cache as free memory. */ 141 * buffer cache as free memory. */
129 printf("-/+ buffers/cache:"); 142 if (!seen_available) {
130 cached += info.freeram; 143 printf("-/+ buffers/cache: ");
131 cached += info.bufferram; 144 printf(FIELDS_2,
132 printf(FIELDS_2, 145 scale(&G, info.totalram - cached_plus_free), //used
133 scale(&G, info.totalram - cached), //used 146 scale(&G, cached_plus_free) //free
134 scale(&G, cached) //free 147 );
135 ); 148 }
136#if BB_MMU 149#if BB_MMU
137 printf("Swap: "); 150 printf("Swap: ");
138 printf(FIELDS_3, 151 printf(FIELDS_3,
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 13de2570f..b0690d794 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -1010,7 +1010,7 @@ static void sig_hangup_handler(int sig_no UNUSED_PARAM)
1010 reopenasap = 1; 1010 reopenasap = 1;
1011} 1011}
1012 1012
1013static void logmatch(struct logdir *ld) 1013static void logmatch(struct logdir *ld, char* lineptr, int lineptr_len)
1014{ 1014{
1015 char *s; 1015 char *s;
1016 1016
@@ -1021,12 +1021,12 @@ static void logmatch(struct logdir *ld)
1021 switch (s[0]) { 1021 switch (s[0]) {
1022 case '+': 1022 case '+':
1023 case '-': 1023 case '-':
1024 if (pmatch(s+1, line, linelen)) 1024 if (pmatch(s+1, lineptr, lineptr_len))
1025 ld->match = s[0]; 1025 ld->match = s[0];
1026 break; 1026 break;
1027 case 'e': 1027 case 'e':
1028 case 'E': 1028 case 'E':
1029 if (pmatch(s+1, line, linelen)) 1029 if (pmatch(s+1, lineptr, lineptr_len))
1030 ld->matcherr = s[0]; 1030 ld->matcherr = s[0];
1031 break; 1031 break;
1032 } 1032 }
@@ -1182,7 +1182,7 @@ int svlogd_main(int argc, char **argv)
1182 if (ld->fddir == -1) 1182 if (ld->fddir == -1)
1183 continue; 1183 continue;
1184 if (ld->inst) 1184 if (ld->inst)
1185 logmatch(ld); 1185 logmatch(ld, lineptr, linelen);
1186 if (ld->matcherr == 'e') { 1186 if (ld->matcherr == 'e') {
1187 /* runit-1.8.0 compat: if timestamping, do it on stderr too */ 1187 /* runit-1.8.0 compat: if timestamping, do it on stderr too */
1188 ////full_write(STDERR_FILENO, printptr, printlen); 1188 ////full_write(STDERR_FILENO, printptr, printlen);
diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts
new file mode 100755
index 000000000..aa7bf3e8a
--- /dev/null
+++ b/scripts/embedded_scripts
@@ -0,0 +1,125 @@
1#!/bin/sh
2
3. ./.config || exit 1
4
5target="$1"
6custom_loc="$2"
7applet_loc="$3"
8
9test "$target" || exit 1
10test "$SED" || SED=sed
11test "$DD" || DD=dd
12
13if [ x"$CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS" != x"y" ]
14then
15 printf '#define NUM_SCRIPTS 0\n' >"$target"
16 exit 0
17fi
18
19# Some people were bitten by their system lacking a (proper) od
20od -v -b </dev/null >/dev/null
21if test $? != 0; then
22 echo 'od tool is not installed or cannot accept "-v -b" options'
23 exit 1
24fi
25
26custom_scripts=""
27if [ -d "$custom_loc" ]
28then
29 custom_scripts=$(cd $custom_loc; ls * 2>/dev/null)
30fi
31all_scripts=$($srctree/applets/busybox.mkscripts)
32
33# all_scripts includes applet scripts and custom scripts, sort them out
34applet_scripts=""
35for i in $all_scripts
36do
37 found=0
38 for j in $custom_scripts
39 do
40 if [ "$i" = "$j" ]
41 then
42 found=1
43 break;
44 fi
45 done
46 if [ $found -eq 0 ]
47 then
48 # anything that isn't a custom script is an applet script
49 applet_scripts="$applet_scripts $i"
50 fi
51done
52
53# we know the custom scripts are present but applet scripts might have
54# become detached from their configuration
55for i in $applet_scripts
56do
57 #if [ ! -f "$applet_loc/$i" -a ! -f "$custom_loc/$i" ]
58 if [ ! -f "$applet_loc/$i" ]
59 then
60 echo "missing applet script $i"
61 exit 1
62 fi
63done
64
65n=$(echo $custom_scripts $applet_scripts | wc -w)
66nall=$(echo $all_scripts | wc -w)
67
68if [ $n -ne $nall ]
69then
70 echo "script mismatch $n != $nall"
71 exit 1
72fi
73
74concatenate_scripts() {
75 for i in $custom_scripts
76 do
77 cat $custom_loc/$i
78 printf '\000'
79 done
80 for i in $applet_scripts
81 do
82 cat $applet_loc/$i
83 printf '\000'
84 done
85}
86
87exec >"$target.$$"
88
89if [ $n -ne 0 ]
90then
91 printf '#ifdef DEFINE_SCRIPT_DATA\n'
92 printf 'const uint16_t applet_numbers[] = {\n'
93 for i in $custom_scripts $applet_scripts
94 do
95 # TODO support applets with names including invalid characters
96 printf '\tAPPLET_NO_%s,\n' $i
97 done
98 printf '};\n'
99 printf '#else\n'
100 printf 'extern const uint16_t applet_numbers[];\n'
101 printf '#endif\n'
102fi
103
104printf "\n"
105printf '#define NUM_SCRIPTS %d\n' $n
106printf "\n"
107
108if [ $n -ne 0 ]
109then
110 printf '#define UNPACKED_SCRIPTS_LENGTH '
111 concatenate_scripts | wc -c
112
113 printf '#define PACKED_SCRIPTS \\\n'
114 concatenate_scripts | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | \
115 od -v -b \
116 | grep -v '^ ' \
117 | $SED -e 's/^[^ ]*//' \
118 -e 's/ //g' \
119 -e '/^$/d' \
120 -e 's/\(...\)/0\1,/g' \
121 -e 's/$/ \\/'
122 printf '\n'
123fi
124
125mv -- "$target.$$" "$target"
diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh
index f79fa2f83..92de681ac 100755
--- a/scripts/gen_build_files.sh
+++ b/scripts/gen_build_files.sh
@@ -17,12 +17,26 @@ status() { printf ' %-8s%s\n' "$1" "$2"; }
17gen() { status "GEN" "$@"; } 17gen() { status "GEN" "$@"; }
18chk() { status "CHK" "$@"; } 18chk() { status "CHK" "$@"; }
19 19
20# scripts in the 'embed' directory are treated as fake applets
21custom_scripts()
22{
23 custom_loc="$1"
24 if [ -d "$custom_loc" ]
25 then
26 for i in $(cd "$custom_loc"; ls * 2>/dev/null)
27 do
28 printf "IF_FEATURE_SH_EMBEDDED_SCRIPTS(APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted))\n" $i;
29 done
30 fi
31}
32
20generate() 33generate()
21{ 34{
22 # NB: data to be inserted at INSERT line is coming on stdin 35 # NB: data to be inserted at INSERT line is coming on stdin
23 src="$1" 36 src="$1"
24 dst="$2" 37 dst="$2"
25 header="$3" 38 header="$3"
39 loc="$4"
26 #chk "${dst}" 40 #chk "${dst}"
27 { 41 {
28 # Need to use printf: different shells have inconsistent 42 # Need to use printf: different shells have inconsistent
@@ -32,6 +46,10 @@ generate()
32 sed -n '/^INSERT$/ q; p' "${src}" 46 sed -n '/^INSERT$/ q; p' "${src}"
33 # copy stdin to stdout 47 # copy stdin to stdout
34 cat 48 cat
49 if [ -n "$loc" ]
50 then
51 custom_scripts "$loc"
52 fi
35 # print everything after INSERT line 53 # print everything after INSERT line
36 sed -n '/^INSERT$/ { 54 sed -n '/^INSERT$/ {
37 :l 55 :l
@@ -53,7 +71,8 @@ sed -n 's@^//applet:@@p' "$srctree"/*/*.c "$srctree"/*/*/*.c \
53| generate \ 71| generate \
54 "$srctree/include/applets.src.h" \ 72 "$srctree/include/applets.src.h" \
55 "include/applets.h" \ 73 "include/applets.h" \
56 "/* DO NOT EDIT. This file is generated from applets.src.h */" 74 "/* DO NOT EDIT. This file is generated from applets.src.h */" \
75 "$srctree/embed"
57 76
58# (Re)generate include/usage.h 77# (Re)generate include/usage.h
59# We add line continuation backslash after each line, 78# We add line continuation backslash after each line,
diff --git a/scripts/trylink b/scripts/trylink
index ba2d265bc..bb6b2de2f 100755
--- a/scripts/trylink
+++ b/scripts/trylink
@@ -149,8 +149,8 @@ try $CC $CFLAGS $LDFLAGS \
149# Stop when no lib can be removed. 149# Stop when no lib can be removed.
150while test "$LDLIBS"; do 150while test "$LDLIBS"; do
151 $debug && echo "Trying libraries: $LDLIBS" 151 $debug && echo "Trying libraries: $LDLIBS"
152 all_needed=true 152 dropped_non_first_lib=false
153 last_needed=false 153 first_lib=true
154 for one in $LDLIBS; do 154 for one in $LDLIBS; do
155 without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs` 155 without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs`
156 # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" 156 # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
@@ -167,20 +167,17 @@ while test "$LDLIBS"; do
167 if test $? = 0; then 167 if test $? = 0; then
168 echo " Library $one is not needed, excluding it" 168 echo " Library $one is not needed, excluding it"
169 LDLIBS="$without_one" 169 LDLIBS="$without_one"
170 all_needed=false 170 $first_lib || dropped_non_first_lib=true
171 last_needed=false
172 else 171 else
173 echo " Library $one is needed, can't exclude it (yet)" 172 echo " Library $one is needed, can't exclude it (yet)"
174 last_needed=true 173 first_lib=false
175 fi 174 fi
176 done 175 done
177 # All libs were needed, can't remove any 176 # We can stop trying to drop libs if either all libs were needed,
178 $all_needed && break 177 # or we excluded only the _first_ few.
179 # Optimization: was the last tried lib needed? 178 # (else: we dropped some intermediate lib(s), maybe now we can succeed
180 if $last_needed; then 179 # in dropping some of the preceding ones)
181 # Was it the only one lib left? Don't test again then. 180 $dropped_non_first_lib || break
182 { echo "$LDLIBS" | grep -q ' '; } || break
183 fi
184done 181done
185 182
186# Make the binary with final, minimal list of libs 183# Make the binary with final, minimal list of libs
diff --git a/shell/Config.src b/shell/Config.src
index 959d3cb42..bc7218fe5 100644
--- a/shell/Config.src
+++ b/shell/Config.src
@@ -161,6 +161,20 @@ config FEATURE_SH_HISTFILESIZE
161 to set shell history size. Note that its max value is capped 161 to set shell history size. Note that its max value is capped
162 by "History size" setting in library tuning section. 162 by "History size" setting in library tuning section.
163 163
164config FEATURE_SH_EMBEDDED_SCRIPTS
165 bool "Embed scripts in the binary"
166 default y
167 depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH
168 help
169 Allow scripts to be compressed and embedded in the busybox
170 binary. The scripts should be placed in the 'embed' directory
171 at build time. Like applets, scripts can be run as
172 'busybox SCRIPT ...' or by linking their name to the binary.
173
174 This also allows applets to be implemented as scripts: place
175 the script in 'applets_sh' and a stub C file containing
176 configuration in the appropriate subsystem directory.
177
164endif # Options common to all shells 178endif # Options common to all shells
165 179
166endmenu 180endmenu
diff --git a/shell/ash.c b/shell/ash.c
index 7131609e4..1b40e3407 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -208,6 +208,11 @@
208#include <sys/times.h> 208#include <sys/times.h>
209#include <sys/utsname.h> /* for setting $HOSTNAME */ 209#include <sys/utsname.h> /* for setting $HOSTNAME */
210#include "busybox.h" /* for applet_names */ 210#include "busybox.h" /* for applet_names */
211#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
212# include "embedded_scripts.h"
213#else
214# define NUM_SCRIPTS 0
215#endif
211 216
212/* So far, all bash compat is controlled by one config option */ 217/* So far, all bash compat is controlled by one config option */
213/* Separate defines document which part of code implements what */ 218/* Separate defines document which part of code implements what */
@@ -2503,13 +2508,12 @@ setvar(const char *name, const char *val, int flags)
2503 } 2508 }
2504 2509
2505 INT_OFF; 2510 INT_OFF;
2506 nameeq = ckmalloc(namelen + vallen + 2); 2511 nameeq = ckzalloc(namelen + vallen + 2);
2507 p = mempcpy(nameeq, name, namelen); 2512 p = mempcpy(nameeq, name, namelen);
2508 if (val) { 2513 if (val) {
2509 *p++ = '='; 2514 *p++ = '=';
2510 p = mempcpy(p, val, vallen); 2515 memcpy(p, val, vallen);
2511 } 2516 }
2512 *p = '\0';
2513 vp = setvareq(nameeq, flags | VNOSAVE); 2517 vp = setvareq(nameeq, flags | VNOSAVE);
2514 INT_ON; 2518 INT_ON;
2515 2519
@@ -8420,6 +8424,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c
8420#else 8424#else
8421 execve(cmd, argv, envp); 8425 execve(cmd, argv, envp);
8422#endif 8426#endif
8427
8423 if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { 8428 if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8424 /* Run "cmd" as a shell script: 8429 /* Run "cmd" as a shell script:
8425 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html 8430 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
@@ -13459,6 +13464,7 @@ parseheredoc(void)
13459 heredoclist = NULL; 13464 heredoclist = NULL;
13460 13465
13461 while (here) { 13466 while (here) {
13467 tokpushback = 0;
13462 setprompt_if(needprompt, 2); 13468 setprompt_if(needprompt, 2);
13463 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX, 13469 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
13464 here->eofmark, here->striptabs); 13470 here->eofmark, here->striptabs);
@@ -14662,12 +14668,16 @@ procargs(char **argv)
14662 14668
14663 xargv = argv; 14669 xargv = argv;
14664 login_sh = xargv[0] && xargv[0][0] == '-'; 14670 login_sh = xargv[0] && xargv[0][0] == '-';
14671#if NUM_SCRIPTS > 0
14672 if (minusc)
14673 goto setarg0;
14674#endif
14665 arg0 = xargv[0]; 14675 arg0 = xargv[0];
14666 /* if (xargv[0]) - mmm, this is always true! */ 14676 /* if (xargv[0]) - mmm, this is always true! */
14667 xargv++; 14677 xargv++;
14678 argptr = xargv;
14668 for (i = 0; i < NOPTS; i++) 14679 for (i = 0; i < NOPTS; i++)
14669 optlist[i] = 2; 14680 optlist[i] = 2;
14670 argptr = xargv;
14671 if (options(/*cmdline:*/ 1, &login_sh)) { 14681 if (options(/*cmdline:*/ 1, &login_sh)) {
14672 /* it already printed err message */ 14682 /* it already printed err message */
14673 raise_exception(EXERROR); 14683 raise_exception(EXERROR);
@@ -14772,7 +14782,12 @@ extern int etext();
14772 * is used to figure out how far we had gotten. 14782 * is used to figure out how far we had gotten.
14773 */ 14783 */
14774int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 14784int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14785#if NUM_SCRIPTS > 0
14786int ash_main(int argc, char **argv)
14787#else
14775int ash_main(int argc UNUSED_PARAM, char **argv) 14788int ash_main(int argc UNUSED_PARAM, char **argv)
14789#endif
14790/* note: 'argc' is used only if embedded scripts are enabled */
14776{ 14791{
14777 volatile smallint state; 14792 volatile smallint state;
14778 struct jmploc jmploc; 14793 struct jmploc jmploc;
@@ -14839,6 +14854,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
14839 bb_error_msg_and_die("forkshell failed"); 14854 bb_error_msg_and_die("forkshell failed");
14840 } 14855 }
14841#endif 14856#endif
14857
14858#if NUM_SCRIPTS > 0
14859 if (argc < 0)
14860 /* Non-NULL minusc tells procargs that an embedded script is being run */
14861 minusc = get_script_content(-argc - 1);
14862#endif
14842 login_sh = procargs(argv); 14863 login_sh = procargs(argv);
14843#if DEBUG 14864#if DEBUG
14844 TRACE(("Shell args: ")); 14865 TRACE(("Shell args: "));
diff --git a/shell/hush.c b/shell/hush.c
index 881331c5b..90191408d 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -157,7 +157,7 @@
157//config: but no separate process group is formed. 157//config: but no separate process group is formed.
158//config: 158//config:
159//config:config HUSH_TICK 159//config:config HUSH_TICK
160//config: bool "Support process substitution" 160//config: bool "Support command substitution"
161//config: default y 161//config: default y
162//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH 162//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
163//config: help 163//config: help
@@ -367,6 +367,11 @@
367# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 367# define PIPE_BUF 4096 /* amount of buffering in a pipe */
368#endif 368#endif
369 369
370#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH)
371# include "embedded_scripts.h"
372#else
373# define NUM_SCRIPTS 0
374#endif
370 375
371/* So far, all bash compat is controlled by one config option */ 376/* So far, all bash compat is controlled by one config option */
372/* Separate defines document which part of code implements what */ 377/* Separate defines document which part of code implements what */
@@ -9951,6 +9956,14 @@ int hush_main(int argc, char **argv)
9951 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ 9956 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
9952 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; 9957 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
9953 builtin_argc = 0; 9958 builtin_argc = 0;
9959#if NUM_SCRIPTS > 0
9960 if (argc < 0) {
9961 optarg = get_script_content(-argc - 1);
9962 optind = 0;
9963 argc = string_array_len(argv);
9964 goto run_script;
9965 }
9966#endif
9954 while (1) { 9967 while (1) {
9955 int opt = getopt(argc, argv, "+c:exinsl" 9968 int opt = getopt(argc, argv, "+c:exinsl"
9956#if !BB_MMU 9969#if !BB_MMU
@@ -9974,6 +9987,9 @@ int hush_main(int argc, char **argv)
9974 * Note: the form without ARG0 never happens: 9987 * Note: the form without ARG0 never happens:
9975 * sh ... -c 'builtin' BARGV... "" 9988 * sh ... -c 'builtin' BARGV... ""
9976 */ 9989 */
9990#if NUM_SCRIPTS > 0
9991 run_script:
9992#endif
9977 if (!G.root_pid) { 9993 if (!G.root_pid) {
9978 G.root_pid = getpid(); 9994 G.root_pid = getpid();
9979 G.root_ppid = getppid(); 9995 G.root_ppid = getppid();
diff --git a/testsuite/echo/echo-prints-dash b/testsuite/echo/echo-prints-dash
index ddcdbadf7..f1f31a034 100644
--- a/testsuite/echo/echo-prints-dash
+++ b/testsuite/echo/echo-prints-dash
@@ -1 +1,2 @@
1# FEATURE: CONFIG_DESKTOP
1test "`busybox echo - | od -t x1 | head -n 1`" = "0000000 2d 0a" 2test "`busybox echo - | od -t x1 | head -n 1`" = "0000000 2d 0a"
diff --git a/testsuite/echo/echo-prints-non-opts b/testsuite/echo/echo-prints-non-opts
index c7d1e201a..4e642a143 100644
--- a/testsuite/echo/echo-prints-non-opts
+++ b/testsuite/echo/echo-prints-non-opts
@@ -1 +1,2 @@
1# FEATURE: CONFIG_DESKTOP
1test "`busybox echo -neEZ | od -t x1 | head -n 1`" = "0000000 2d 6e 65 45 5a 0a" 2test "`busybox echo -neEZ | od -t x1 | head -n 1`" = "0000000 2d 6e 65 45 5a 0a"
diff --git a/testsuite/echo/echo-prints-slash-zero b/testsuite/echo/echo-prints-slash-zero
index d97ed8e66..948f899da 100644
--- a/testsuite/echo/echo-prints-slash-zero
+++ b/testsuite/echo/echo-prints-slash-zero
@@ -1,3 +1,3 @@
1# FEATURE: CONFIG_FEATURE_FANCY_ECHO 1# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP
2 2
3test "`busybox echo -e -n 'msg\n\0' | od -t x1 | head -n 1`" = "0000000 6d 73 67 0a 00" 3test "`busybox echo -e -n 'msg\n\0' | od -t x1 | head -n 1`" = "0000000 6d 73 67 0a 00"
diff --git a/testsuite/echo/echo-prints-slash_00041 b/testsuite/echo/echo-prints-slash_00041
index 9cffabde0..7ea217bc5 100644
--- a/testsuite/echo/echo-prints-slash_00041
+++ b/testsuite/echo/echo-prints-slash_00041
@@ -1,3 +1,3 @@
1# FEATURE: CONFIG_FEATURE_FANCY_ECHO 1# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP
2 2
3test "`busybox echo -ne '\00041z' | od -t x1 | head -n 1`" = "0000000 04 31 7a" 3test "`busybox echo -ne '\00041z' | od -t x1 | head -n 1`" = "0000000 04 31 7a"
diff --git a/testsuite/echo/echo-prints-slash_0041 b/testsuite/echo/echo-prints-slash_0041
index b07429dfd..941faca08 100644
--- a/testsuite/echo/echo-prints-slash_0041
+++ b/testsuite/echo/echo-prints-slash_0041
@@ -1,3 +1,3 @@
1# FEATURE: CONFIG_FEATURE_FANCY_ECHO 1# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP
2 2
3test "`busybox echo -ne '\0041z' | od -t x1 | head -n 1`" = "0000000 21 7a" 3test "`busybox echo -ne '\0041z' | od -t x1 | head -n 1`" = "0000000 21 7a"
diff --git a/testsuite/echo/echo-prints-slash_041 b/testsuite/echo/echo-prints-slash_041
index 1d70cec92..60cbfca3d 100644
--- a/testsuite/echo/echo-prints-slash_041
+++ b/testsuite/echo/echo-prints-slash_041
@@ -1,3 +1,3 @@
1# FEATURE: CONFIG_FEATURE_FANCY_ECHO 1# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP
2 2
3test "`busybox echo -ne '\041z' | od -t x1 | head -n 1`" = "0000000 21 7a" 3test "`busybox echo -ne '\041z' | od -t x1 | head -n 1`" = "0000000 21 7a"
diff --git a/testsuite/echo/echo-prints-slash_41 b/testsuite/echo/echo-prints-slash_41
index 6d8999b4e..afd7c36d1 100644
--- a/testsuite/echo/echo-prints-slash_41
+++ b/testsuite/echo/echo-prints-slash_41
@@ -1,3 +1,3 @@
1# FEATURE: CONFIG_FEATURE_FANCY_ECHO 1# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP
2 2
3test "`busybox echo -ne '\41z' | od -t x1 | head -n 1`" = "0000000 21 7a" 3test "`busybox echo -ne '\41z' | od -t x1 | head -n 1`" = "0000000 21 7a"
diff --git a/testsuite/printf.tests b/testsuite/printf.tests
index 963ded94b..34a65926e 100755
--- a/testsuite/printf.tests
+++ b/testsuite/printf.tests
@@ -79,6 +79,39 @@ testing "printf understands %Ld" \
79 "-5\n""0\n" \ 79 "-5\n""0\n" \
80 "" "" 80 "" ""
81 81
82testing "printf handles positive numbers for %d" \
83 "${bb}printf '%d\n' 3 +3 ' 3' ' +3' 2>&1; echo \$?" \
84 "3\n"\
85"3\n"\
86"3\n"\
87"3\n""0\n" \
88 "" ""
89
90testing "printf handles positive numbers for %i" \
91 "${bb}printf '%i\n' 3 +3 ' 3' ' +3' 2>&1; echo \$?" \
92 "3\n"\
93"3\n"\
94"3\n"\
95"3\n""0\n" \
96 "" ""
97
98testing "printf handles positive numbers for %x" \
99 "${bb}printf '%x\n' 42 +42 ' 42' ' +42' 2>&1; echo \$?" \
100 "2a\n"\
101"2a\n"\
102"2a\n"\
103"2a\n""0\n" \
104 "" ""
105
106testing "printf handles positive numbers for %f" \
107 "${bb}printf '%0.3f\n' .42 +.42 ' .42' ' +.42' 2>&1; echo \$?" \
108 "0.420\n"\
109"0.420\n"\
110"0.420\n"\
111"0.420\n""0\n" \
112 "" ""
113
114
82# "FIXED" now to act compatibly 115# "FIXED" now to act compatibly
83## We are "more correct" here than bash/coreutils: they happily print -2 116## We are "more correct" here than bash/coreutils: they happily print -2
84## as if it is a huge unsigned number 117## as if it is a huge unsigned number
diff --git a/util-linux/nologin.c b/util-linux/nologin.c
new file mode 100644
index 000000000..e4b192508
--- /dev/null
+++ b/util-linux/nologin.c
@@ -0,0 +1,27 @@
1//config:config NOLOGIN
2//config: bool "nologin"
3//config: default n
4//config: depends on FEATURE_SH_EMBEDDED_SCRIPTS
5//config: help
6//config: Politely refuse a login
7//config:
8//config:config NOLOGIN_DEPENDENCIES
9//config: bool "Enable dependencies for nologin"
10//config: default y
11//config: depends on NOLOGIN
12//config: select CAT
13//config: select ECHO
14//config: select SLEEP
15//config: help
16//config: nologin is implemented as a shell script. It requires the
17//config: following in the runtime environment:
18//config: cat echo sleep
19//config: If you know these will be available externally you can
20//config: disable this option.
21
22//applet:IF_NOLOGIN(APPLET_SCRIPTED(nologin, scripted, BB_DIR_USR_SBIN, BB_SUID_DROP, nologin))
23
24//usage:#define nologin_trivial_usage
25//usage: ""
26//usage:#define nologin_full_usage "\n\n"
27//usage: "Politely refuse a login"