From 7effa31cd4b5c76d20f63882002eb023f05aaa46 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Fri, 2 Mar 2018 17:39:36 +0100 Subject: brctl: use a single buffer for brname and ifname function old new delta brctl_main 1681 1675 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-6) Total: -6 bytes Signed-off-by: Bernhard Reutner-Fischer --- networking/brctl.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) 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) #if ENABLE_FEATURE_BRCTL_SHOW if (key == ARG_show) { /* show */ - char brname[IFNAMSIZ]; + char buf[IFNAMSIZ]; int bridx[MAX_PORTS]; int i, num; arm_ioctl(args, BRCTL_GET_BRIDGES, @@ -249,19 +249,18 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) num = xioctl(fd, SIOCGIFBR, args); puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); for (i = 0; i < num; i++) { - char ifname[IFNAMSIZ]; int j, tabs; struct __bridge_info bi; unsigned char *x; - if (!if_indextoname(bridx[i], brname)) + if (!if_indextoname(bridx[i], buf)) bb_perror_msg_and_die("can't get bridge name for index %d", i); - strncpy_IFNAMSIZ(ifr.ifr_name, brname); + strncpy_IFNAMSIZ(ifr.ifr_name, buf); arm_ioctl(args, BRCTL_GET_BRIDGE_INFO, (unsigned long) &bi, 0); xioctl(fd, SIOCDEVPRIVATE, &ifr); - printf("%s\t\t", brname); + printf("%s\t\t", buf); /* print bridge id */ x = (unsigned char *) &bi.bridge_id; @@ -280,13 +279,13 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) for (j = 0; j < MAX_PORTS; j++) { if (!ifidx[j]) continue; - if (!if_indextoname(ifidx[j], ifname)) + if (!if_indextoname(ifidx[j], buf)) bb_perror_msg_and_die("can't get interface name for index %d", j); if (tabs) printf("\t\t\t\t\t"); else tabs = 1; - printf("\t\t%s\n", ifname); + printf("\t\t%s\n", buf); } if (!tabs) /* bridge has no interfaces */ bb_putchar('\n'); -- cgit v1.2.3-55-g6feb From 3db4e7f84cf795de8559ea0d96eaa491999ccf24 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Fri, 19 Oct 2018 15:25:41 +0200 Subject: printf: fix printing +-prefixed numbers Thanks to Cristian Ionescu-Idbohrn for noticing. Also fix "%d" ' 42' to skip leading whitespace. function old new delta print_direc 435 454 +19 bb_strtoll 99 103 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 23/0) Total: 23 bytes Signed-off-by: Bernhard Reutner-Fischer --- coreutils/printf.c | 5 +++-- libbb/bb_strtonum.c | 2 +- testsuite/printf.tests | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/coreutils/printf.c b/coreutils/printf.c index a666ff7ac..b2429c5cf 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -191,6 +191,7 @@ static void print_direc(char *format, unsigned fmt_length, if (have_width - 1 == have_prec) have_width = NULL; + /* multiconvert sets errno = 0, but %s needs it cleared */ errno = 0; switch (format[fmt_length - 1]) { @@ -199,7 +200,7 @@ static void print_direc(char *format, unsigned fmt_length, break; case 'd': case 'i': - llv = my_xstrtoll(argument); + llv = my_xstrtoll(skip_whitespace(argument)); print_long: if (!have_width) { if (!have_prec) @@ -217,7 +218,7 @@ static void print_direc(char *format, unsigned fmt_length, case 'u': case 'x': case 'X': - llv = my_xstrtoull(argument); + llv = my_xstrtoull(skip_whitespace(argument)); /* cheat: unsigned long and long have same width, so... */ goto print_long; case 's': diff --git a/libbb/bb_strtonum.c b/libbb/bb_strtonum.c index 2185017b0..cb70f1053 100644 --- a/libbb/bb_strtonum.c +++ b/libbb/bb_strtonum.c @@ -81,7 +81,7 @@ long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base) /* Check for the weird "feature": * a "-" string is apparently a valid "number" for strto[u]l[l]! * It returns zero and errno is 0! :( */ - first = (arg[0] != '-' ? arg[0] : arg[1]); + first = (arg[0] != '-' && arg[0] != '+' ? arg[0] : arg[1]); if (!isalnum(first)) return ret_ERANGE(); errno = 0; 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" \ "-5\n""0\n" \ "" "" +testing "printf handles positive numbers for %d" \ + "${bb}printf '%d\n' 3 +3 ' 3' ' +3' 2>&1; echo \$?" \ + "3\n"\ +"3\n"\ +"3\n"\ +"3\n""0\n" \ + "" "" + +testing "printf handles positive numbers for %i" \ + "${bb}printf '%i\n' 3 +3 ' 3' ' +3' 2>&1; echo \$?" \ + "3\n"\ +"3\n"\ +"3\n"\ +"3\n""0\n" \ + "" "" + +testing "printf handles positive numbers for %x" \ + "${bb}printf '%x\n' 42 +42 ' 42' ' +42' 2>&1; echo \$?" \ + "2a\n"\ +"2a\n"\ +"2a\n"\ +"2a\n""0\n" \ + "" "" + +testing "printf handles positive numbers for %f" \ + "${bb}printf '%0.3f\n' .42 +.42 ' .42' ' +.42' 2>&1; echo \$?" \ + "0.420\n"\ +"0.420\n"\ +"0.420\n"\ +"0.420\n""0\n" \ + "" "" + + # "FIXED" now to act compatibly ## We are "more correct" here than bash/coreutils: they happily print -2 ## as if it is a huge unsigned number -- cgit v1.2.3-55-g6feb From 4329116b6d036b19a92cabf51dc388fab4787b53 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Oct 2018 15:51:38 +0200 Subject: nbd-client: support newstyle protocol, -b, -d, -p, -N Recognize the "newstyle" protocol and switch to it automatically. Add options for setting blocksize (-b) and for disconnecting a nbd device (-d). function old new delta nbdclient_main 492 1179 +687 static.long_options - 80 +80 print_direc 438 457 +19 brctl_main 1169 1183 +14 bb_strtoll 84 89 +5 packed_usage 33082 33066 -16 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/1 up/down: 805/-16) Total: 789 bytes Signed-off-by: Elvira Khabirova Signed-off-by: Denys Vlasenko --- networking/nbd-client.c | 230 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 186 insertions(+), 44 deletions(-) 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 @@ #include "libbb.h" #include #include +#include #define NBD_SET_SOCK _IO(0xab, 0) #define NBD_SET_BLKSIZE _IO(0xab, 1) @@ -27,57 +28,144 @@ #define NBD_SET_SIZE_BLOCKS _IO(0xab, 7) #define NBD_DISCONNECT _IO(0xab, 8) #define NBD_SET_TIMEOUT _IO(0xab, 9) +#define NBD_SET_FLAGS _IO(0xab, 10) //usage:#define nbdclient_trivial_usage -//usage: "HOST PORT BLOCKDEV" +//usage: "{ [-b BLKSIZE] [-N NAME] [-t SEC] [-p] HOST [PORT] | -d } BLOCKDEV" //usage:#define nbdclient_full_usage "\n\n" -//usage: "Connect to HOST and provide a network block device on BLOCKDEV" +//usage: "Connect to HOST and provide network block device on BLOCKDEV" -//TODO: more compat with nbd-client version 2.9.13 - -//Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-persist] [-nofork] -//Or : nbd-client -d nbd_device -//Or : nbd-client -c nbd_device -//Default value for blocksize is 1024 (recommended for ethernet) +//TODO: more compat with nbd-client version 3.17 - +//nbd-client host [ port ] nbd-device [ -connections num ] [ -sdp ] [ -swap ] +// [ -persist ] [ -nofork ] [ -nonetlink ] [ -systemd-mark ] +// [ -block-size block size ] [ -timeout seconds ] [ -name name ] +// [ -certfile certfile ] [ -keyfile keyfile ] [ -cacertfile cacertfile ] +// [ -tlshostname hostname ] +//nbd-client -unix path nbd-device [ -connections num ] [ -sdp ] [ -swap ] +// [ -persist ] [ -nofork ] [ -nonetlink ] [ -systemd-mark ] +// [ -block-size block size ] [ -timeout seconds ] [ -name name ] +//nbd-client nbd-device +//nbd-client -d nbd-device +//nbd-client -c nbd-device +//nbd-client -l host [ port ] +//nbd-client [ -netlink ] -l host +// +//Default value for blocksize is 4096 //Allowed values for blocksize are 512,1024,2048,4096 -//Note, that kernel 2.4.2 and older ones do not work correctly with -//blocksizes other than 1024 without patches int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int nbdclient_main(int argc UNUSED_PARAM, char **argv) +int nbdclient_main(int argc, char **argv) { - unsigned long timeout = 0; #if BB_MMU - int nofork = 0; + bool nofork; #endif - char *host, *port, *device; + bool opt_d; + bool opt_p; + const char *host, *port, *device; + const char *name; + unsigned blksize, size_blocks; + unsigned timeout; + int ch; struct nbd_header_t { uint64_t magic1; // "NBDMAGIC" - uint64_t magic2; // 0x420281861253 big endian + uint64_t magic2; // old style: 0x420281861253 big endian + // // new style: 0x49484156454F5054 (IHAVEOPT) + } nbd_header; + struct old_nbd_header_t { uint64_t devsize; uint32_t flags; char data[124]; - } nbd_header; + } old_nbd_header; + struct new_nbd_header_t { + uint64_t devsize; + uint16_t transmission_flags; + char data[124]; + } new_nbd_header; + struct nbd_opt_t { + uint64_t magic; + uint32_t opt; + uint32_t len; + } nbd_opts; - BUILD_BUG_ON(offsetof(struct nbd_header_t, data) != 8+8+8+4); + static const struct option long_options[] = { + { "block-size", required_argument, NULL, 'b' }, + { "timeout" , required_argument, NULL, 't' }, + { "name" , required_argument, NULL, 'n' }, + { "persist" , no_argument , NULL, 'p' }, + { NULL } + }; - // Parse command line stuff (just a stub now) - if (!argv[1] || !argv[2] || !argv[3] || argv[4]) - bb_show_usage(); + BUILD_BUG_ON(offsetof(struct old_nbd_header_t, data) != 8 + 4); + BUILD_BUG_ON(offsetof(struct new_nbd_header_t, data) != 8 + 2); #if !BB_MMU bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv); #endif - host = argv[1]; - port = argv[2]; - device = argv[3]; + // Parse args. nbd-client uses stupid "one-dash long options" style :( + // Even though short forms (-b,-t,-N,-p) exist for all long opts, + // older manpages only contained long forms, which probably resulted + // in many scripts using them. + blksize = 4096; + timeout = 0; + name = ""; // use of "" instead of NULL simplifies strlen() later + opt_d = opt_p = 0; + while ((ch = getopt_long_only(argc, argv, "dN:", long_options, NULL)) != -1) { + switch (ch) { + case 'p': // -persist + opt_p = 1; + break; + case 'd': // -d + opt_d = 1; + break; + case 'b': // -block-size + blksize = xatou(optarg); + break; + case 't': // -timeout + timeout = xatou(optarg); + break; + case 'N': // -N + case 'n': // -name + name = optarg; + break; + default: + bb_show_usage(); + } + } + argv += optind; + + if (opt_d) { // -d + if (argv[0] && !argv[1]) { + int nbd = xopen(argv[0], O_RDWR); + ioctl(nbd, NBD_DISCONNECT); + ioctl(nbd, NBD_CLEAR_SOCK); + if (ENABLE_FEATURE_CLEAN_UP) + close(nbd); + return 0; + } + bb_show_usage(); + } + + // Allow only argv[] of: HOST [PORT] BLOCKDEV + if (!argv[0] || !argv[1] || (argv[2] && argv[3])) { + bb_show_usage(); + } - // Repeat until spanked (-persist behavior) - for (;;) { + host = argv[0]; + port = argv[2] ? argv[1] : "10809"; + device = argv[2] ? argv[2] : argv[1]; + + // Repeat until spanked if -persist +#if BB_MMU + nofork = 0; +#endif + do { int sock, nbd; int ro; + int proto_new; // 0 for old, 1 for new + char *data; - // Make sure the /dev/nbd exists + // Make sure BLOCKDEV exists nbd = xopen(device, O_RDWR); // Find and connect to server @@ -85,40 +173,95 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv) setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY); // Log on to the server - xread(sock, &nbd_header, 8+8+8+4 + 124); - if (memcmp(&nbd_header.magic1, "NBDMAGIC""\x00\x00\x42\x02\x81\x86\x12\x53", 16) != 0) + xread(sock, &nbd_header, 8 + 8); + if (memcmp(&nbd_header.magic1, "NBDMAGIC", + sizeof(nbd_header.magic1)) != 0 + ) { + bb_error_msg_and_die("login failed"); + } + if (memcmp(&nbd_header.magic2, + "\x00\x00\x42\x02\x81\x86\x12\x53", + sizeof(nbd_header.magic2)) == 0 + ) { + proto_new = 0; + } else if (memcmp(&nbd_header.magic2, "IHAVEOPT", 8) == 0) { + proto_new = 1; + } else { bb_error_msg_and_die("login failed"); + } + + if (!proto_new) { + xread(sock, &old_nbd_header, + sizeof(old_nbd_header.devsize) + + sizeof(old_nbd_header.flags) + + sizeof(old_nbd_header.data)); + size_blocks = SWAP_BE64(old_nbd_header.devsize) / blksize; + ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long) blksize); + ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks); + ioctl(nbd, NBD_CLEAR_SOCK); + ro = !!(old_nbd_header.flags & htons(2)); + data = old_nbd_header.data; + } else { + unsigned namelen; + uint16_t handshake_flags; + + xread(sock, &handshake_flags, sizeof(handshake_flags)); + xwrite(sock, &const_int_0, sizeof(const_int_0)); // client_flags + + memcpy(&nbd_opts.magic, "IHAVEOPT", + sizeof(nbd_opts.magic)); + nbd_opts.opt = htonl(1); // NBD_OPT_EXPORT_NAME + namelen = strlen(name); + nbd_opts.len = htonl(namelen); + xwrite(sock, &nbd_opts, + sizeof(nbd_opts.magic) + + sizeof(nbd_opts.opt) + + sizeof(nbd_opts.len)); + xwrite(sock, name, namelen); - // Set 4k block size. Everything uses that these days - ioctl(nbd, NBD_SET_BLKSIZE, 4096); - ioctl(nbd, NBD_SET_SIZE_BLOCKS, SWAP_BE64(nbd_header.devsize) / 4096); - ioctl(nbd, NBD_CLEAR_SOCK); + xread(sock, &new_nbd_header, + sizeof(new_nbd_header.devsize) + + sizeof(new_nbd_header.transmission_flags) + + sizeof(new_nbd_header.data)); + size_blocks = SWAP_BE64(new_nbd_header.devsize) / blksize; + ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long) blksize); + ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks); + ioctl(nbd, NBD_CLEAR_SOCK); + ioctl(nbd, NBD_SET_FLAGS, + ntohs(new_nbd_header.transmission_flags)); + ro = !!(new_nbd_header.transmission_flags & htons(2)); + data = new_nbd_header.data; + } - // If the sucker was exported read only, respect that locally - ro = (nbd_header.flags & SWAP_BE32(2)) / SWAP_BE32(2); - if (ioctl(nbd, BLKROSET, &ro) < 0) + if (ioctl(nbd, BLKROSET, &ro) < 0) { bb_perror_msg_and_die("BLKROSET"); + } - if (timeout) - if (ioctl(nbd, NBD_SET_TIMEOUT, timeout)) + if (timeout) { + if (ioctl(nbd, NBD_SET_TIMEOUT, (unsigned long) timeout)) { bb_perror_msg_and_die("NBD_SET_TIMEOUT"); - if (ioctl(nbd, NBD_SET_SOCK, sock)) - bb_perror_msg_and_die("NBD_SET_SOCK"); + } + } - // if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); + if (ioctl(nbd, NBD_SET_SOCK, sock)) { + bb_perror_msg_and_die("NBD_SET_SOCK"); + } + //if (swap) mlockall(MCL_CURRENT|MCL_FUTURE); #if BB_MMU // Open the device to force reread of the partition table. // Need to do it in a separate process, since open(device) // needs some other process to sit in ioctl(nbd, NBD_DO_IT). if (fork() == 0) { + /* child */ char *s = strrchr(device, '/'); - sprintf(nbd_header.data, "/sys/block/%.32s/pid", s ? s + 1 : device); + sprintf(data, "/sys/block/%.32s/pid", s ? s + 1 : device); // Is it up yet? for (;;) { - int fd = open(nbd_header.data, O_RDONLY); + int fd = open(data, O_RDONLY); if (fd >= 0) { - //close(fd); + if (ENABLE_FEATURE_CLEAN_UP) + close(fd); break; } sleep(1); @@ -133,7 +276,6 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv) nofork = 1; } #endif - // This turns us (the process that calls this ioctl) // into a dedicated NBD request handler. // We block here for a long time. @@ -148,7 +290,7 @@ int nbdclient_main(int argc UNUSED_PARAM, char **argv) close(sock); close(nbd); - } + } while (opt_p); return 0; } -- cgit v1.2.3-55-g6feb From a541314b1f5e7392608cdef91e9098330823ed31 Mon Sep 17 00:00:00 2001 From: "Brandon P. Enochs" Date: Sat, 27 Oct 2018 18:55:59 +0200 Subject: ntpd: add support for MD5/SHA1 message authentication Add support for MD5 message authentication as described in RFC 5905. This patch also supports SHA1 authentication. The key file format is the same file format as used by ntpd. The configuration file format follows standard Unix conventions (# comments) with lines consist of the following fields separated by whitespace: . https://www.ietf.org/rfc/rfc5905.txt function old new delta ntp_init 473 987 +514 hash - 125 +125 recv_and_process_peer_pkt 889 961 +72 packed_usage 33066 33130 +64 ntpd_main 1226 1277 +51 find_key_entry - 29 +29 add_peers 195 207 +12 recv_and_process_client_pkt 509 514 +5 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 6/0 up/down: 872/0) Total: 872 bytes Signed-off-by: Brandon P. Enochs Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 241 insertions(+), 25 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 1ebdc34c3..354bff897 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -62,13 +62,19 @@ //config: help //config: Make ntpd look in /etc/ntp.conf for peers. Only "server address" //config: is supported. +//config:config FEATURE_NTP_AUTH +//config: bool "Support md5/sha1 message authentication codes" +//config: default n +//config: depends on NTPD //applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_NTPD) += ntpd.o //usage:#define ntpd_trivial_usage -//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..." +//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l] [-I IFACE")"] [-S PROG]" +//usage: IF_NOT_FEATURE_NTP_AUTH(" [-p PEER]...") +//usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...") //usage:#define ntpd_full_usage "\n\n" //usage: "NTP client/server\n" //usage: "\n -d Verbose (may be repeated)" @@ -76,8 +82,16 @@ //usage: "\n -q Quit after clock is set" //usage: "\n -N Run at high priority" //usage: "\n -w Do not set time (only query peers), implies -n" -//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" +//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 min" +//usage: IF_NOT_FEATURE_NTP_AUTH( //usage: "\n -p PEER Obtain time from PEER (may be repeated)" +//usage: ) +//usage: IF_FEATURE_NTP_AUTH( +//usage: "\n -k FILE Key file (ntp.keys compatible)" +//usage: "\n -p [keyno:NUM:]PEER" +//usage: "\n Obtain time from PEER (may be repeated)" +//usage: "\n Use key NUM for authentication" +//usage: ) //usage: IF_FEATURE_NTPD_CONF( //usage: "\n If -p is not given, 'server HOST' lines" //usage: "\n from /etc/ntp.conf are used" @@ -228,14 +242,18 @@ /* Parameter averaging constant */ #define AVG 4 +#define MAX_KEY_NUMBER 65535 +#define KEYID_SIZE sizeof(uint32_t) enum { NTP_VERSION = 4, NTP_MAXSTRATUM = 15, - NTP_DIGESTSIZE = 16, - NTP_MSGSIZE_NOAUTH = 48, - NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE), + NTP_MD5_DIGESTSIZE = 16, + NTP_MSGSIZE_NOAUTH = 48, + NTP_MSGSIZE_MD5_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_MD5_DIGESTSIZE, + NTP_SHA1_DIGESTSIZE = 20, + NTP_MSGSIZE_SHA1_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_SHA1_DIGESTSIZE, /* Status Masks */ MODE_MASK = (7 << 0), @@ -288,7 +306,7 @@ typedef struct { l_fixedpt_t m_rectime; l_fixedpt_t m_xmttime; uint32_t m_keyid; - uint8_t m_digest[NTP_DIGESTSIZE]; + uint8_t m_digest[ENABLE_FEATURE_NTP_AUTH ? NTP_SHA1_DIGESTSIZE : NTP_MD5_DIGESTSIZE]; } msg_t; typedef struct { @@ -297,9 +315,26 @@ typedef struct { double d_dispersion; } datapoint_t; +#if ENABLE_FEATURE_NTP_AUTH +enum { + HASH_MD5, + HASH_SHA1, +}; +typedef struct { + unsigned id; //try uint16_t? + smalluint type; + smalluint msg_size; + smalluint key_length; + char key[0]; +} key_entry_t; +#endif + typedef struct { len_and_sockaddr *p_lsa; char *p_dotted; +#if ENABLE_FEATURE_NTP_AUTH + key_entry_t *key_entry; +#endif int p_fd; int datapoint_idx; uint32_t lastpkt_refid; @@ -337,13 +372,14 @@ enum { OPT_q = (1 << 1), OPT_N = (1 << 2), OPT_x = (1 << 3), + OPT_k = (1 << 4) * ENABLE_FEATURE_NTP_AUTH, /* Insert new options above this line. */ /* Non-compat options: */ - OPT_w = (1 << 4), - OPT_p = (1 << 5), - OPT_S = (1 << 6), - OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, - OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER, + OPT_w = (1 << (4+ENABLE_FEATURE_NTP_AUTH)), + OPT_p = (1 << (5+ENABLE_FEATURE_NTP_AUTH)), + OPT_S = (1 << (6+ENABLE_FEATURE_NTP_AUTH)), + OPT_l = (1 << (7+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER, + OPT_I = (1 << (8+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER, /* We hijack some bits for other purposes */ OPT_qq = (1 << 31), }; @@ -816,8 +852,12 @@ resolve_peer_hostname(peer_t *p) return lsa; } +#if !ENABLE_FEATURE_NTP_AUTH +#define add_peers(s, key_entry) \ + add_peers(s) +#endif static void -add_peers(const char *s) +add_peers(const char *s, key_entry_t *key_entry) { llist_t *item; peer_t *p; @@ -846,6 +886,7 @@ add_peers(const char *s) } } + IF_FEATURE_NTP_AUTH(p->key_entry = key_entry;) llist_add_to(&G.ntp_peers, p); G.peer_cnt++; } @@ -870,6 +911,48 @@ do_sendto(int fd, return 0; } +#if ENABLE_FEATURE_NTP_AUTH +static void +hash(key_entry_t *key_entry, const msg_t *msg, uint8_t *output) +{ + union { + md5_ctx_t m; + sha1_ctx_t s; + } ctx; + unsigned hash_size = sizeof(*msg) - sizeof(msg->m_keyid) - sizeof(msg->m_digest); + + switch (key_entry->type) { + case HASH_MD5: + md5_begin(&ctx.m); + md5_hash(&ctx.m, key_entry->key, key_entry->key_length); + md5_hash(&ctx.m, msg, hash_size); + md5_end(&ctx.m, output); + break; + default: /* it's HASH_SHA1 */ + sha1_begin(&ctx.s); + sha1_hash(&ctx.s, key_entry->key, key_entry->key_length); + sha1_hash(&ctx.s, msg, hash_size); + sha1_end(&ctx.s, output); + break; + } +} + +static void +hash_peer(peer_t *p) +{ + p->p_xmt_msg.m_keyid = htonl(p->key_entry->id); + hash(p->key_entry, &p->p_xmt_msg, p->p_xmt_msg.m_digest); +} + +static int +hashes_differ(peer_t *p, const msg_t *msg) +{ + uint8_t digest[NTP_SHA1_DIGESTSIZE]; + hash(p->key_entry, msg, digest); + return memcmp(digest, msg->m_digest, p->key_entry->msg_size - NTP_MSGSIZE_NOAUTH - KEYID_SIZE); +} +#endif + static void send_query_to_peer(peer_t *p) { @@ -946,9 +1029,18 @@ send_query_to_peer(peer_t *p) */ p->reachable_bits <<= 1; +#if ENABLE_FEATURE_NTP_AUTH + if (p->key_entry) + hash_peer(p); if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, - &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 - ) { + &p->p_xmt_msg, !p->key_entry ? NTP_MSGSIZE_NOAUTH : p->key_entry->msg_size) == -1 + ) +#else + if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, + &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 + ) +#endif + { close(p->p_fd); p->p_fd = -1; /* @@ -1924,10 +2016,21 @@ recv_and_process_peer_pkt(peer_t *p) bb_perror_msg_and_die("recv(%s) error", p->p_dotted); } - if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { +#if ENABLE_FEATURE_NTP_AUTH + if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH) { + bb_error_msg("malformed packet received from %s", p->p_dotted); + return; + } + if (p->key_entry && hashes_differ(p, &msg)) { + bb_error_msg("invalid cryptographic hash received from %s", p->p_dotted); + return; + } +#else + if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH) { bb_error_msg("malformed packet received from %s", p->p_dotted); return; } +#endif if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl @@ -2135,7 +2238,12 @@ recv_and_process_client_pkt(void /*int fd*/) from = xzalloc(to->len); size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len); - if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { +#if ENABLE_FEATURE_NTP_AUTH + if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH) +#else + if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH) +#endif + { char *addr; if (size < 0) { if (errno == EAGAIN) @@ -2278,6 +2386,19 @@ recv_and_process_client_pkt(void /*int fd*/) * with the -g and -q options. See the tinker command for other options. * Note: The kernel time discipline is disabled with this option. */ +#if ENABLE_FEATURE_NTP_AUTH +static key_entry_t * +find_key_entry(llist_t *key_entries, unsigned id) +{ + while (key_entries) { + key_entry_t *cur = (key_entry_t*) key_entries->data; + if (cur->id == id) + return cur; + key_entries = key_entries->link; + } + bb_error_msg_and_die("key %u is not defined", id); +} +#endif /* By doing init in a separate function we decrease stack usage * in main loop. @@ -2286,6 +2407,10 @@ static NOINLINE void ntp_init(char **argv) { unsigned opts; llist_t *peers; +#if ENABLE_FEATURE_NTP_AUTH + llist_t *key_entries; + char *key_file_path; +#endif srand(getpid()); @@ -2302,8 +2427,10 @@ static NOINLINE void ntp_init(char **argv) /* Parse options */ peers = NULL; + IF_FEATURE_NTP_AUTH(key_entries = NULL;) opts = getopt32(argv, "^" "nqNx" /* compat */ + IF_FEATURE_NTP_AUTH("k:") /* compat */ "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ IF_FEATURE_NTPD_SERVER("I:") /* compat */ "d" /* compat */ @@ -2311,11 +2438,11 @@ static NOINLINE void ntp_init(char **argv) "\0" "dd:wn" /* -d: counter; -p: list; -w implies -n */ IF_FEATURE_NTPD_SERVER(":Il") /* -I implies -l */ - , &peers, &G.script_name, -#if ENABLE_FEATURE_NTPD_SERVER - &G.if_name, -#endif - &G.verbose); + IF_FEATURE_NTP_AUTH(, &key_file_path) + , &peers, &G.script_name + IF_FEATURE_NTPD_SERVER(, &G.if_name) + , &G.verbose + ); // if (opts & OPT_x) /* disable stepping, only slew is allowed */ // G.time_was_stepped = 1; @@ -2341,19 +2468,107 @@ static NOINLINE void ntp_init(char **argv) logmode = LOGMODE_NONE; } +#if ENABLE_FEATURE_NTP_AUTH + if (opts & OPT_k) { + char *tokens[4]; + parser_t *parser; + + parser = config_open(key_file_path); + while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL | PARSE_MIN_DIE) == 3) { + key_entry_t *key_entry; + char buffer[40]; + smalluint hash_type; + smalluint msg_size; + smalluint key_length; + char *key; + + if ((tokens[1][0] | 0x20) == 'm') + /* supports 'M' and 'md5' formats */ + hash_type = HASH_MD5; + else + if (strncasecmp(tokens[1], "sha", 3) == 0) + /* supports 'sha' and 'sha1' formats */ + hash_type = HASH_SHA1; + else + bb_error_msg_and_die("only MD5 and SHA1 keys supported"); +/* man ntp.keys: + * MD5 The key is 1 to 16 printable characters terminated by an EOL, + * whitespace, or a # (which is the "start of comment" character). + * SHA + * SHA1 + * RMD160 The key is a hex-encoded ASCII string of 40 characters, which + * is truncated as necessary. + */ + key_length = strnlen(tokens[2], sizeof(buffer)+1); + if (key_length >= sizeof(buffer)+1) { + err: + bb_error_msg_and_die("malformed key at line %u", parser->lineno); + } + if (hash_type == HASH_MD5) { + key = tokens[2]; + msg_size = NTP_MSGSIZE_MD5_AUTH; + } else /* it's hash_type == HASH_SHA1 */ + if (!(key_length & 1)) { + key_length >>= 1; + if (!hex2bin(buffer, tokens[2], key_length)) + goto err; + key = buffer; + msg_size = NTP_MSGSIZE_SHA1_AUTH; + } else { + goto err; + } + key_entry = xzalloc(sizeof(*key_entry) + key_length); + key_entry->type = hash_type; + key_entry->msg_size = msg_size; + key_entry->key_length = key_length; + memcpy(key_entry->key, key, key_length); + key_entry->id = xatou_range(tokens[0], 1, MAX_KEY_NUMBER); + llist_add_to(&key_entries, key_entry); + } + config_close(parser); + } +#endif if (peers) { +#if ENABLE_FEATURE_NTP_AUTH + while (peers) { + char *peer = llist_pop(&peers); + key_entry_t *key_entry = NULL; + if (strncmp(peer, "keyno:", 6) == 0) { + char *end; + int key_id; + peer += 6; + end = strchr(peer, ':'); + *end = '\0'; + key_id = xatou_range(peer, 1, MAX_KEY_NUMBER); + *end = ':'; + key_entry = find_key_entry(key_entries, key_id); + peer = end + 1; + } + add_peers(peer, key_entry); + } +#else while (peers) - add_peers(llist_pop(&peers)); + add_peers(llist_pop(&peers), NULL); +#endif } #if ENABLE_FEATURE_NTPD_CONF else { parser_t *parser; - char *token[3]; + char *token[3 + 2*ENABLE_FEATURE_NTP_AUTH]; parser = config_open("/etc/ntp.conf"); - while (config_read(parser, token, 3, 1, "# \t", PARSE_NORMAL)) { + while (config_read(parser, token, 3 + 2*ENABLE_FEATURE_NTP_AUTH, 1, "# \t", PARSE_NORMAL)) { if (strcmp(token[0], "server") == 0 && token[1]) { - add_peers(token[1]); +# if ENABLE_FEATURE_NTP_AUTH + key_entry_t *key_entry = NULL; + if (token[2] && token[3] && strcmp(token[2], "key") == 0) { + unsigned key_id = xatou_range(token[3], 1, MAX_KEY_NUMBER); + key_entry = find_key_entry(key_entries, key_id); + } + add_peers(token[1], key_entry); +# else + add_peers(token[1], NULL); +# endif continue; } bb_error_msg("skipping %s:%u: unimplemented command '%s'", @@ -2394,6 +2609,7 @@ static NOINLINE void ntp_init(char **argv) | (1 << SIGCHLD) , SIG_IGN ); +//TODO: free unused elements of key_entries? } int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; -- cgit v1.2.3-55-g6feb From c05aa6a776ab2420a42c041a3b5d45db587fd9ef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 11:56:18 +0100 Subject: udhcpc: ensure at least one unicast renew attempt Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 5 +++-- networking/udhcp/dhcpc.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 66e4b6c6a..e2f8a6a9c 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1738,8 +1738,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; /* paranoia: must not be too small */ - if (timeout < 0x10) - timeout = 0x10; + /* timeout > 60 - ensures at least one unicast renew attempt */ + if (timeout < 61) + timeout = 61; /* enter bound state */ d6_run_script(packet.d6_options, packet_end, (state == REQUESTING ? "bound" : "renew")); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index ab3e5a463..d2f165904 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1725,8 +1725,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) move_from_unaligned32(lease_seconds, temp); lease_seconds = ntohl(lease_seconds); /* paranoia: must not be too small and not prone to overflows */ - if (lease_seconds < 0x10) - lease_seconds = 0x10; + /* timeout > 60 - ensures at least one unicast renew attempt */ + if (lease_seconds < 2 * 61) + lease_seconds = 2 * 61; //if (lease_seconds > 0x7fffffff) // lease_seconds = 0x7fffffff; //^^^not necessary since "timeout = lease_seconds / 2" -- cgit v1.2.3-55-g6feb From 47839ae6797bcded0178893cb950d2e2f8be1f6f Mon Sep 17 00:00:00 2001 From: Jiří Prchal Date: Thu, 4 Oct 2018 09:02:27 +0200 Subject: examples/udhcp/simple.script: add possibility to use modern "ip" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Script uses "ifconfig" only, not up-to-date so much. This patch adds "ip" in condition if exists. Signed-off-by: Jiří Prchal Signed-off-by: Denys Vlasenko --- examples/udhcp/simple.script | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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" [ -n "$1" ] || { echo "Error: should be called from udhcpc"; exit 1; } NETMASK="" -[ -n "$subnet" ] && NETMASK="netmask $subnet" +if command -v ip >/dev/null; then + [ -n "$subnet" ] && NETMASK="/$subnet" +else + [ -n "$subnet" ] && NETMASK="netmask $subnet" +fi BROADCAST="broadcast +" [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" case "$1" in deconfig) echo "Setting IP address 0.0.0.0 on $interface" - ifconfig $interface 0.0.0.0 + if command -v ip >/dev/null; then + ip addr flush dev $interface + else + ifconfig $interface 0.0.0.0 + fi ;; renew|bound) echo "Setting IP address $ip on $interface" - ifconfig $interface $ip $NETMASK $BROADCAST + if command -v ip >/dev/null; then + ip addr add $ip$NETMASK $BROADCAST dev $interface + else + ifconfig $interface $ip $NETMASK $BROADCAST + fi if [ -n "$router" ] ; then echo "Deleting routers" -- cgit v1.2.3-55-g6feb From c8e3922ad838751e45bf4b3cb8608b228ee83c71 Mon Sep 17 00:00:00 2001 From: Guillermo Rodriguez Date: Tue, 30 Oct 2018 13:49:51 +0100 Subject: free: add 'available' memory if provided by the kernel Show estimated available memory if this is provided by the kernel. See [1] for the full story. [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 function old new delta free_main 537 633 +96 parse_cached_kb 85 - -85 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 96/-85) Total: 11 bytes Signed-off-by: Guillermo Rodriguez Signed-off-by: Denys Vlasenko --- procps/free.c | 59 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/procps/free.c b/procps/free.c index 48139c4a3..e41601e08 100644 --- a/procps/free.c +++ b/procps/free.c @@ -53,21 +53,27 @@ static unsigned long long scale(struct globals *g, unsigned long d) } /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ -static NOINLINE unsigned long parse_cached_kb(void) +static NOINLINE unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long *available_kb) { char buf[60]; /* actual lines we expect are ~30 chars or less */ FILE *fp; - unsigned long cached = 0; + int seen_cached_and_available; fp = xfopen_for_read("/proc/meminfo"); - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1) - break; + *cached_kb = *available_kb = 0; + seen_cached_and_available = 2; + while (fgets(buf, sizeof(buf), fp)) { + if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1) + if (--seen_cached_and_available == 0) + break; + if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1) + if (--seen_cached_and_available == 0) + break; } /* Have to close because of NOFORK */ fclose(fp); - return cached; + return seen_cached_and_available == 0; } int 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)) { struct globals G; struct sysinfo info; - unsigned long long cached; + unsigned long long cached, cached_plus_free, available; + unsigned long cached_kb, available_kb; + int seen_available; #if ENABLE_DESKTOP G.unit_steps = 10; @@ -98,41 +106,46 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) } } #endif - printf(" %11s%11s%11s%11s%11s%11s\n" + printf(" %12s%12s%12s%12s%12s%12s\n" "Mem: ", "total", "used", "free", - "shared", "buffers", "cached" /* swap and total don't have these columns */ + "shared", "buff/cache", "available" /* swap and total don't have these columns */ ); sysinfo(&info); /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ G.mem_unit = (info.mem_unit ? info.mem_unit : 1); - /* Extract cached from /proc/meminfo and convert to mem_units */ - cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit; + /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ + seen_available = parse_meminfo(&cached_kb, &available_kb); + available = ((unsigned long long) available_kb * 1024) / G.mem_unit; + cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit; + cached += info.bufferram; + cached_plus_free = cached + info.freeram; -#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n" +#define FIELDS_6 "%12llu%12llu%12llu%12llu%12llu%12llu\n" #define FIELDS_3 (FIELDS_6 + 3*6) #define FIELDS_2 (FIELDS_6 + 4*6) printf(FIELDS_6, scale(&G, info.totalram), //total - scale(&G, info.totalram - info.freeram), //used + scale(&G, info.totalram - cached_plus_free), //used scale(&G, info.freeram), //free scale(&G, info.sharedram), //shared - scale(&G, info.bufferram), //buffers - scale(&G, cached) //cached + scale(&G, cached), //buff/cache + scale(&G, available) //available ); - /* Show alternate, more meaningful busy/free numbers by counting + /* On kernels < 3.14, MemAvailable is not provided. + * Show alternate, more meaningful busy/free numbers by counting * buffer cache as free memory. */ - printf("-/+ buffers/cache:"); - cached += info.freeram; - cached += info.bufferram; - printf(FIELDS_2, - scale(&G, info.totalram - cached), //used - scale(&G, cached) //free - ); + if (!seen_available) { + printf("-/+ buffers/cache: "); + printf(FIELDS_2, + scale(&G, info.totalram - cached_plus_free), //used + scale(&G, cached_plus_free) //free + ); + } #if BB_MMU printf("Swap: "); printf(FIELDS_3, -- cgit v1.2.3-55-g6feb From f3e2838fc4e6bd0713d7ee5a17e752a19870a0f8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 14:40:17 +0100 Subject: xargs: fix exit code if command exits nonzero, closes 11381 No code size change on x86. Signed-off-by: Denys Vlasenko --- findutils/xargs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/findutils/xargs.c b/findutils/xargs.c index c369bdaf5..0dedb6356 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -204,14 +204,15 @@ static int xargs_exec(void) status = (errno == ENOENT) ? 127 : 126; } else if (status >= 0x180) { - bb_error_msg("'%s' terminated by signal %d", + bb_error_msg("'%s' terminated by signal %u", G.args[0], status - 0x180); status = 125; } else if (status != 0) { if (status == 255) { bb_error_msg("%s: exited with status 255; aborting", G.args[0]); - return 124; + status = 124; + goto ret; } /* "123 if any invocation of the command exited with status 1-125" * This implies that nonzero exit code is remembered, @@ -220,7 +221,7 @@ static int xargs_exec(void) G.xargs_exitcode = 123; status = 0; } - + ret: if (status != 0) G.xargs_exitcode = status; return status; -- cgit v1.2.3-55-g6feb From 3f6a978a0dabe08e9df15b3f9ee2bd3cf8e3c441 Mon Sep 17 00:00:00 2001 From: Rostislav Skudnov Date: Mon, 15 Oct 2018 10:26:15 +0000 Subject: dd: add 'oflag=seek_bytes' Allow specifying position in the output file in bytes instead of obs-sized blocks, improve compatibility with GNU dd. function old new delta dd_main 1632 1693 +61 packed_usage 33130 33150 +20 static.oflag_words - 12 +12 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 93/0) Total: 93 bytes Signed-off-by: Rostislav Skudnov Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 33 ++++++++++++++++++++++++--------- docs/posix_conformance.txt | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 0f130bcad..129637e24 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -37,7 +37,7 @@ //config: elapsed time and speed. //config: //config:config FEATURE_DD_IBS_OBS -//config: bool "Enable ibs, obs, iflag and conv options" +//config: bool "Enable ibs, obs, iflag, oflag and conv options" //config: default y //config: depends on DD //config: help @@ -57,7 +57,7 @@ //usage:#define dd_trivial_usage //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" -//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock]") +//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock] [oflag=seek_bytes]") //usage:#define dd_full_usage "\n\n" //usage: "Copy a file with converting and formatting\n" //usage: "\n if=FILE Read from FILE instead of stdin" @@ -80,6 +80,7 @@ //usage: "\n conv=swab Swap every pair of bytes" //usage: "\n iflag=skip_bytes skip=N is in bytes" //usage: "\n iflag=fullblock Read full blocks" +//usage: "\n oflag=seek_bytes seek=N is in bytes" //usage: ) //usage: IF_FEATURE_DD_STATUS( //usage: "\n status=noxfer Suppress rate output" @@ -133,10 +134,14 @@ enum { FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, /* end of input flags */ - FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_COUNT = 1 << 8, - FLAG_STATUS_NONE = 1 << 9, - FLAG_STATUS_NOXFER = 1 << 10, + /* start of output flags */ + FLAG_OFLAG_SHIFT = 7, + FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, + /* end of output flags */ + FLAG_TWOBUFS = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_COUNT = 1 << 9, + FLAG_STATUS_NONE = 1 << 10, + FLAG_STATUS_NOXFER = 1 << 11, }; static void dd_output_status(int UNUSED_PARAM cur_signal) @@ -250,7 +255,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) static const char keywords[] ALIGN1 = "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") #if ENABLE_FEATURE_DD_IBS_OBS - "ibs\0""obs\0""conv\0""iflag\0" + "ibs\0""obs\0""conv\0""iflag\0""oflag\0" #endif ; #if ENABLE_FEATURE_DD_IBS_OBS @@ -258,6 +263,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; static const char iflag_words[] ALIGN1 = "skip_bytes\0""fullblock\0"; + static const char oflag_words[] ALIGN1 = + "seek_bytes\0"; #endif #if ENABLE_FEATURE_DD_STATUS static const char status_words[] ALIGN1 = @@ -276,6 +283,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) OP_obs, OP_conv, OP_iflag, + OP_oflag, /* Must be in the same order as FLAG_XXX! */ OP_conv_notrunc = 0, OP_conv_sync, @@ -297,6 +305,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) //swab swap every pair of input bytes: will abort on non-even reads OP_iflag_skip_bytes, OP_iflag_fullblock, + OP_oflag_seek_bytes, #endif }; smallint exitcode = EXIT_FAILURE; @@ -368,6 +377,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT; /*continue;*/ } + if (what == OP_oflag) { + G.flags |= parse_comma_flags(val, oflag_words, "oflag") << FLAG_OFLAG_SHIFT; + /*continue;*/ + } #endif if (what == OP_bs) { ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); @@ -439,7 +452,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) xmove_fd(xopen(outfile, oflag), ofd); if (seek && !(G.flags & FLAG_NOTRUNC)) { - if (ftruncate(ofd, seek * obs) < 0) { + size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; + if (ftruncate(ofd, seek * blocksz) < 0) { struct stat st; if (fstat(ofd, &st) < 0 @@ -472,7 +486,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) } } if (seek) { - if (lseek(ofd, seek * obs, SEEK_CUR) < 0) + size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; + if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0) goto die_outfile; } 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: conv=fsync | yes | | iflag=skip_bytes| yes | | iflag=fullblock | yes | | + oflag=seek_bytes| yes | | df POSIX options option | exists | compliant | remarks -- cgit v1.2.3-55-g6feb From 9ab5a8d56068261eb4117e4a743a30d05cc6c2c5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 17:04:52 +0100 Subject: dd: do not have 'ocount' variable if ibs/obs support is not enabled function old new delta packed_usage 32964 32961 -3 dd_main 1033 1021 -12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-15) Total: -15 bytes Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 129637e24..39ce5019f 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -56,8 +56,11 @@ //kbuild:lib-$(CONFIG_DD) += dd.o //usage:#define dd_trivial_usage -//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" -//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock] [oflag=seek_bytes]") +//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n" +//usage: IF_FEATURE_DD_IBS_OBS( +//usage: " [conv=notrunc|noerror|sync|fsync]\n" +//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes]" +//usage: ) //usage:#define dd_full_usage "\n\n" //usage: "Copy a file with converting and formatting\n" //usage: "\n if=FILE Read from FILE instead of stdin" @@ -321,13 +324,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #endif /* These are all zeroed at once! */ struct { - size_t oc; + IF_FEATURE_DD_IBS_OBS(size_t ocount;) ssize_t prev_read_size; /* for detecting swab failure */ off_t count; off_t seek, skip; const char *infile, *outfile; } Z; -#define oc (Z.oc ) +#define ocount (Z.ocount ) #define prev_read_size (Z.prev_read_size) #define count (Z.count ) #define seek (Z.seek ) @@ -542,24 +545,26 @@ int dd_main(int argc UNUSED_PARAM, char **argv) n = ibs; } } +#if ENABLE_FEATURE_DD_IBS_OBS if (G.flags & FLAG_TWOBUFS) { char *tmp = ibuf; while (n) { - size_t d = obs - oc; - + size_t d = obs - ocount; if (d > (size_t)n) d = n; - memcpy(obuf + oc, tmp, d); + memcpy(obuf + ocount, tmp, d); n -= d; tmp += d; - oc += d; - if (oc == obs) { + ocount += d; + if (ocount == obs) { if (write_and_stats(obuf, obs, obs, outfile)) goto out_status; - oc = 0; + ocount = 0; } } - } else { + } else +#endif + { if (write_and_stats(ibuf, n, obs, outfile)) goto out_status; } @@ -570,10 +575,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) goto die_outfile; } - if (ENABLE_FEATURE_DD_IBS_OBS && oc) { - if (write_and_stats(obuf, oc, obs, outfile)) +#if ENABLE_FEATURE_DD_IBS_OBS + if (ocount != 0) { + if (write_and_stats(obuf, ocount, obs, outfile)) goto out_status; } +#endif if (close(ifd) < 0) { die_infile: bb_simple_perror_msg_and_die(infile); -- cgit v1.2.3-55-g6feb From 63d053d8c3e991d86cbacccb9ba6ff03aedee5cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 23:07:26 +0100 Subject: ntpd: default to FEATURE_NTP_AUTH=y Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 354bff897..4f8607244 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -62,9 +62,10 @@ //config: help //config: Make ntpd look in /etc/ntp.conf for peers. Only "server address" //config: is supported. +//config: //config:config FEATURE_NTP_AUTH //config: bool "Support md5/sha1 message authentication codes" -//config: default n +//config: default y //config: depends on NTPD //applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) -- cgit v1.2.3-55-g6feb From 93ef5dd640ef41edc72c80fa59c7cc9427b5945b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 30 Oct 2018 23:24:18 +0100 Subject: printf: fix printf "%u\n" +18446744073709551614 function old new delta conv_strtoll 19 32 +13 conv_strtoull 49 61 +12 bb_strtoll 89 84 -5 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 25/-5) Total: 20 bytes Signed-off-by: Denys Vlasenko --- coreutils/printf.c | 8 ++++++++ libbb/bb_strtonum.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/coreutils/printf.c b/coreutils/printf.c index b2429c5cf..67d3b2eda 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -95,6 +95,12 @@ static int multiconvert(const char *arg, void *result, converter convert) static void FAST_FUNC conv_strtoull(const char *arg, void *result) { + /* Allow leading '+' - bb_strtoull() by itself does not allow it, + * and probably shouldn't (other callers might require purely numeric + * inputs to be allowed. + */ + if (arg[0] == '+') + arg++; *(unsigned long long*)result = bb_strtoull(arg, NULL, 0); /* both coreutils 6.10 and bash 3.2: * $ printf '%x\n' -2 @@ -107,6 +113,8 @@ static void FAST_FUNC conv_strtoull(const char *arg, void *result) } static void FAST_FUNC conv_strtoll(const char *arg, void *result) { + if (arg[0] == '+') + arg++; *(long long*)result = bb_strtoll(arg, NULL, 0); } static void FAST_FUNC conv_strtod(const char *arg, void *result) diff --git a/libbb/bb_strtonum.c b/libbb/bb_strtonum.c index cb70f1053..2185017b0 100644 --- a/libbb/bb_strtonum.c +++ b/libbb/bb_strtonum.c @@ -81,7 +81,7 @@ long long FAST_FUNC bb_strtoll(const char *arg, char **endp, int base) /* Check for the weird "feature": * a "-" string is apparently a valid "number" for strto[u]l[l]! * It returns zero and errno is 0! :( */ - first = (arg[0] != '-' && arg[0] != '+' ? arg[0] : arg[1]); + first = (arg[0] != '-' ? arg[0] : arg[1]); if (!isalnum(first)) return ret_ERANGE(); errno = 0; -- cgit v1.2.3-55-g6feb From 571e525a141a2de87b9c2ced485745e96418d921 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Sep 2018 16:06:36 +0200 Subject: libbb: optionally honour libc provided SIGRTMIN/SIGRTMAX in get_signum() When an application documents that it responds such and such to SIGRTMIN+n, that almost always means with respect to the libc-provided SIGRTMIN. Hence I disagree with the "more correct" in commit 7b276fc17594. In any case, this is rather unfortunate: 36 34 (the first shell is bash). We probably can't change default behaviour after 7 years, but at least we can provide a config option. We avoid a little code generation (repeated calls to __libc_current_sigrtmin) by stashing SIGRTMIN/SIGRTMAX in local variables, but it does cost ~50 bytes. The next patch serves as penance for that. Signed-off-by: Rasmus Villemoes Signed-off-by: Denys Vlasenko --- libbb/u_signal_names.c | 76 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index b3038e32d..866ca85fd 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c @@ -12,6 +12,18 @@ //config: help //config: Support RTMIN[+n] and RTMAX[-n] signal names //config: in kill, killall etc. This costs ~250 bytes. +//config: +//config:config FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS +//config: bool "Use the definitions of SIGRTMIN/SIGRTMAX provided by libc" +//config: default y +//config: depends on FEATURE_RTMINMAX +//config: help +//config: Some C libraries reserve a few real-time signals for internal +//config: use, and adjust the values of SIGRTMIN/SIGRTMAX seen by +//config: applications accordingly. Saying yes here means that a signal +//config: name RTMIN+n will be interpreted according to the libc definition +//config: of SIGRTMIN, and not the raw definition provided by the kernel. +//config: This behavior matches "kill -l RTMIN+n" from bash. #include "libbb.h" @@ -123,7 +135,7 @@ static const char signals[][7] ALIGN1 = { #ifdef SIGSYS [SIGSYS ] = "SYS", #endif -#if ENABLE_FEATURE_RTMINMAX +#if ENABLE_FEATURE_RTMINMAX && !ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS # ifdef __SIGRTMIN [__SIGRTMIN] = "RTMIN", # endif @@ -168,36 +180,46 @@ int FAST_FUNC get_signum(const char *name) # endif #endif -#if ENABLE_FEATURE_RTMINMAX -# if defined(SIGRTMIN) && defined(SIGRTMAX) -/* libc may use some rt sigs for pthreads and therefore "remap" SIGRTMIN/MAX, - * but we want to use "raw" SIGRTMIN/MAX. Underscored names, if exist, provide - * them. If they don't exist, fall back to non-underscored ones: */ +#if ENABLE_FEATURE_RTMINMAX && defined(SIGRTMIN) && defined(SIGRTMAX) + { +# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS + /* Use the libc provided values. */ + unsigned sigrtmin = SIGRTMIN; + unsigned sigrtmax = SIGRTMAX; +# else + /* Use the "raw" SIGRTMIN/MAX. Underscored names, if exist, provide + * them. If they don't exist, fall back to non-underscored ones: */ # if !defined(__SIGRTMIN) # define __SIGRTMIN SIGRTMIN # endif # if !defined(__SIGRTMAX) # define __SIGRTMAX SIGRTMAX # endif - if (strncasecmp(name, "RTMIN", 5) == 0) { - if (!name[5]) - return __SIGRTMIN; - if (name[5] == '+') { - i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= __SIGRTMAX - __SIGRTMIN) - return __SIGRTMIN + i; + +# define sigrtmin __SIGRTMIN +# define sigrtmax __SIGRTMAX +# endif + if (strncasecmp(name, "RTMIN", 5) == 0) { + if (!name[5]) + return sigrtmin; + if (name[5] == '+') { + i = bb_strtou(name + 6, NULL, 10); + if (!errno && i <= sigrtmax - sigrtmin) + return sigrtmin + i; + } } - } - else if (strncasecmp(name, "RTMAX", 5) == 0) { - if (!name[5]) - return __SIGRTMAX; - if (name[5] == '-') { - i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= __SIGRTMAX - __SIGRTMIN) - return __SIGRTMAX - i; + else if (strncasecmp(name, "RTMAX", 5) == 0) { + if (!name[5]) + return sigrtmax; + if (name[5] == '-') { + i = bb_strtou(name + 6, NULL, 10); + if (!errno && i <= sigrtmax - sigrtmin) + return sigrtmax - i; + } } +# undef sigrtmin +# undef sigrtmax } -# endif #endif return -1; @@ -228,8 +250,16 @@ void FAST_FUNC print_signames(void) printf("%2u) %s\n", signo, name); } #if ENABLE_FEATURE_RTMINMAX -# ifdef __SIGRTMAX +# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS +# if defined(SIGRTMIN) && defined(SIGRTMAX) + printf("%2u) %s\n", SIGRTMIN, "RTMIN"); + printf("%2u) %s\n", SIGRTMAX, "RTMAX"); +# endif +# else +// __SIGRTMIN is included in signals[] array. +# ifdef __SIGRTMAX printf("%2u) %s\n", __SIGRTMAX, "RTMAX"); +# endif # endif #endif } -- cgit v1.2.3-55-g6feb From 656ca7bdd992f6aabbdd5cadbac5241f6e1971a1 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Wed, 12 Sep 2018 16:06:37 +0200 Subject: libbb/u_signal_names.c: don't check errno after bb_strtou Since we're comparing the return value to a smallish integer anyway, we might as well use that bb_strtou() returns UINT_MAX for malformed input. Referencing errno is kinda bloaty on glibc. While NSIG is not in POSIX, we do already rely on it being defined, compile-time const and smallish, since arrays in struct globals_misc are defined in terms of it. function old new delta get_signum 312 286 -26 Signed-off-by: Rasmus Villemoes Signed-off-by: Denys Vlasenko --- libbb/u_signal_names.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index 866ca85fd..f7d598c7a 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c @@ -153,8 +153,12 @@ int FAST_FUNC get_signum(const char *name) { unsigned i; + /* bb_strtou returns UINT_MAX on error. NSIG is smaller + * than UINT_MAX on any sane Unix. Hence no need + * to check errno after bb_strtou(). + */ i = bb_strtou(name, NULL, 10); - if (!errno && i < NSIG) /* for shells, we allow 0 too */ + if (i < NSIG) /* for shells, we allow 0 too */ return i; if (strncasecmp(name, "SIG", 3) == 0) name += 3; @@ -204,7 +208,7 @@ int FAST_FUNC get_signum(const char *name) return sigrtmin; if (name[5] == '+') { i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= sigrtmax - sigrtmin) + if (i <= sigrtmax - sigrtmin) return sigrtmin + i; } } @@ -213,7 +217,7 @@ int FAST_FUNC get_signum(const char *name) return sigrtmax; if (name[5] == '-') { i = bb_strtou(name + 6, NULL, 10); - if (!errno && i <= sigrtmax - sigrtmin) + if (i <= sigrtmax - sigrtmin) return sigrtmax - i; } } -- cgit v1.2.3-55-g6feb From 552796791f8c5aa12dfb790e3a94c2d905f367ee Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 26 Apr 2016 15:23:38 +0100 Subject: vi: remove duplicated code At worst show_status_line() might be called needlessly when the user presses ^L/^R, but I don't think we'll get many complaints about that. function old new delta do_cmd 4592 4558 -34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-34) Total: -34 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index f103e0dc0..2aa0ad9dd 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -3586,12 +3586,7 @@ static void do_cmd(int c) break; case 12: // ctrl-L force redraw whole screen case 18: // ctrl-R force redraw - place_cursor(0, 0); - clear_to_eos(); - //mysleep(10); // why??? - screen_erase(); // erase the internal screen buffer - last_status_cksum = 0; // force status update - refresh(TRUE); // this will redraw the entire display + redraw(TRUE); // this will redraw the entire display break; case 13: // Carriage Return ^M case '+': // +- goto next line -- cgit v1.2.3-55-g6feb From 4f2ef4a836be37b25808c94f41c7c85895db6f93 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 09:53:25 +0100 Subject: ash: allow shell scripts to be embedded in the binary To assist in the deployment of shell scripts it may be convenient to embed them in the BusyBox binary. 'Embed scripts in the binary' takes any files in the directory 'embed', concatenates them with null separators, compresses them and embeds them in the binary. When scripts are embedded in the binary, scripts can be run as 'busybox SCRIPT [ARGS]' or by usual (sym)link mechanism. embed/nologin is provided as an example. function old new delta packed_scripts - 123 +123 unpack_scripts - 87 +87 ash_main 1103 1171 +68 run_applet_and_exit 78 128 +50 get_script_content - 32 +32 script_names - 10 +10 expmeta 663 659 -4 ------------------------------------------------------------------------------ (add/remove: 4/0 grow/shrink: 2/1 up/down: 370/-4) Total: 366 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- Makefile | 6 ++- applets_sh/nologin | 4 -- archival/libarchive/Kbuild.src | 1 + embed/nologin | 4 ++ include/.gitignore | 1 + include/libbb.h | 8 ++++ libbb/appletlib.c | 83 +++++++++++++++++++++++++++++++++++++++++- libbb/lineedit.c | 6 +++ scripts/embedded_scripts | 66 +++++++++++++++++++++++++++++++++ shell/ash.c | 33 ++++++++++++++++- 10 files changed, 205 insertions(+), 7 deletions(-) delete mode 100755 applets_sh/nologin create mode 100755 embed/nologin create mode 100755 scripts/embedded_scripts diff --git a/Makefile b/Makefile index 59ec83a6a..8a0dbdf49 100644 --- a/Makefile +++ b/Makefile @@ -850,11 +850,14 @@ quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h cmd_gen_common_bufsiz = $(srctree)/scripts/generate_BUFSIZ.sh include/common_bufsiz.h quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config +quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h + cmd_gen_embedded_scripts = scripts/embedded_scripts include/embedded_scripts.h embed #bbox# piggybacked generation of few .h files -include/config/MARKER: scripts/basic/split-include include/autoconf.h +include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts $(call cmd,split_autoconf) $(call cmd,gen_bbconfigopts) $(call cmd,gen_common_bufsiz) + $(call cmd,gen_embedded_scripts) @touch $@ # Generate some files @@ -974,6 +977,7 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \ include/autoconf.h \ include/bbconfigopts.h \ include/bbconfigopts_bz2.h \ + include/embedded_scripts.h \ include/usage_compressed.h \ include/applet_tables.h \ include/applets.h \ diff --git a/applets_sh/nologin b/applets_sh/nologin deleted file mode 100755 index 3768eaaa7..000000000 --- a/applets_sh/nologin +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" -sleep 5 -exit 1 diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index e1a8a7529..12e66a88b 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. lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o +lib-$(CONFIG_ASH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o ifneq ($(lib-y),) lib-y += $(COMMON_FILES) diff --git a/embed/nologin b/embed/nologin new file mode 100755 index 000000000..3768eaaa7 --- /dev/null +++ b/embed/nologin @@ -0,0 +1,4 @@ +#!/bin/sh +cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" +sleep 5 +exit 1 diff --git a/include/.gitignore b/include/.gitignore index 75afff9ca..13a96e018 100644 --- a/include/.gitignore +++ b/include/.gitignore @@ -5,6 +5,7 @@ /autoconf.h /bbconfigopts_bz2.h /bbconfigopts.h +/embedded_scripts.h /NUM_APPLETS.h /usage_compressed.h /usage.h diff --git a/include/libbb.h b/include/libbb.h index 140404ff5..affff5874 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1321,9 +1321,17 @@ void bb_logenv_override(void) FAST_FUNC; #define MAIN_EXTERNALLY_VISIBLE #endif +/* Embedded script support */ +//int find_script_by_name(const char *arg IF_FEATURE_SH_STANDALONE(, int offset)) FAST_FUNC; +char *get_script_content(unsigned n) FAST_FUNC; /* Applets which are useful from another applets */ int bb_cat(char** argv) FAST_FUNC; +int ash_main(int argc, char** argv) +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH + MAIN_EXTERNALLY_VISIBLE +#endif +; /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 319bcc263..08720082e 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -50,6 +50,16 @@ #include "usage_compressed.h" +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# define DEFINE_script_names 1 +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif +#if NUM_SCRIPTS > 0 +# include "bb_archive.h" +static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; +#endif /* "Do not compress usage text if uncompressed text is small * and we don't include bunzip2 code for other reasons" @@ -953,7 +963,71 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar } # endif /* NUM_APPLETS > 0 */ -# if ENABLE_BUSYBOX || NUM_APPLETS > 0 +# if NUM_SCRIPTS > 0 +static char * +unpack_scripts(void) +{ + char *outbuf = NULL; + bunzip_data *bd; + int i; + jmp_buf jmpbuf; + + /* Setup for I/O error handling via longjmp */ + i = setjmp(jmpbuf); + if (i == 0) { + i = start_bunzip(&jmpbuf, + &bd, + /* src_fd: */ -1, + /* inbuf: */ packed_scripts, + /* len: */ sizeof(packed_scripts) + ); + } + /* read_bunzip can longjmp and end up here with i != 0 + * on read data errors! Not trivial */ + if (i == 0) { + outbuf = xmalloc(UNPACKED_SCRIPTS_LENGTH); + read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH); + } + dealloc_bunzip(bd); + return outbuf; +} + +/* + * In standalone shell mode we sometimes want the index of the script + * and sometimes the index offset by NUM_APPLETS. + */ +static int +find_script_by_name(const char *arg) +{ + const char *s = script_names; + int i = 0; + + while (*s) { + if (strcmp(arg, s) == 0) + return i; + i++; + while (*s++ != '\0') + continue; + } + return -1; +} + +char* FAST_FUNC +get_script_content(unsigned n) +{ + char *t = unpack_scripts(); + if (t) { + while (n != 0) { + while (*t++ != '\0') + continue; + n--; + } + } + return t; +} +# endif /* NUM_SCRIPTS > 0 */ + +# if ENABLE_BUSYBOX || NUM_APPLETS > 0 || NUM_SCRIPTS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { # if ENABLE_BUSYBOX @@ -968,6 +1042,13 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) run_applet_no_and_exit(applet, name, argv); } # endif +# if NUM_SCRIPTS > 0 + { + int script = find_script_by_name(name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + } +# endif /*bb_error_msg_and_die("applet not found"); - links in printf */ full_write2_str(applet_name); diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b1e971f88..aef1911d9 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -41,6 +41,12 @@ #include "busybox.h" #include "NUM_APPLETS.h" #include "unicode.h" +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif + #ifndef _POSIX_VDISABLE # define _POSIX_VDISABLE '\0' #endif diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts new file mode 100755 index 000000000..986e85160 --- /dev/null +++ b/scripts/embedded_scripts @@ -0,0 +1,66 @@ +#!/bin/sh + +target="$1" +loc="$2" + +test "$target" || exit 1 +test "$SED" || SED=sed +test "$DD" || DD=dd + +# Some people were bitten by their system lacking a (proper) od +od -v -b /dev/null +if test $? != 0; then + echo 'od tool is not installed or cannot accept "-v -b" options' + exit 1 +fi + +exec >"$target.$$" + +scripts="" +if [ -d "$loc" ] +then + scripts=$(cd $loc; ls * 2>/dev/null) +fi + +n=$(echo $scripts | wc -w) + +if [ $n -ne 0 ] +then + printf '#ifdef DEFINE_script_names\n' + printf 'const char script_names[] ALIGN1 = ' + for i in $scripts + do + printf '"%s\\0"' $i + done + printf '"\\0";\n' + printf '#else\n' + printf 'extern const char script_names[] ALIGN1;\n' + printf '#endif\n' +fi +printf "#define NUM_SCRIPTS $n\n\n" + +if [ $n -ne 0 ] +then + printf '#define UNPACKED_SCRIPTS_LENGTH ' + for i in $scripts + do + cat $loc/$i + printf '\000' + done | wc -c + + printf '#define PACKED_SCRIPTS \\\n' + for i in $scripts + do + cat $loc/$i + printf '\000' + done | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \ + | grep -v '^ ' \ + | $SED -e 's/^[^ ]*//' \ + -e 's/ //g' \ + -e '/^$/d' \ + -e 's/\(...\)/0\1,/g' \ + -e 's/$/ \\/' + printf '\n' +fi + +mv -- "$target.$$" "$target" diff --git a/shell/ash.c b/shell/ash.c index dc1a55a6b..25468d796 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -148,6 +148,21 @@ //config: you to run the specified command or builtin, //config: even when there is a function with the same name. //config: +//config:config ASH_EMBEDDED_SCRIPTS +//config: bool "Embed scripts in the binary" +//config: default y +//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: help +//config: Allow scripts to be compressed and embedded in the BusyBox +//config: binary. The scripts should be placed in the 'embed' directory +//config: at build time. In standalone shell mode such scripts can be +//config: run directly and are subject to tab completion; otherwise they +//config: can be run by giving their name as an argument to the shell. +//config: For convenience shell aliases are created. The '-L' shell +//config: argument lists the names of the scripts. Like applets scripts +//config: can be run as 'busybox name ...' or by linking their name to +//config: the binary. +//config: //config:endif # ash options //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) @@ -181,6 +196,11 @@ #include #include /* for setting $HOSTNAME */ #include "busybox.h" /* for applet_names */ +#if ENABLE_ASH_EMBEDDED_SCRIPTS +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif /* So far, all bash compat is controlled by one config option */ /* Separate defines document which part of code implements what */ @@ -14021,13 +14041,17 @@ procargs(char **argv) int login_sh; xargv = argv; +#if NUM_SCRIPTS > 0 + if (minusc) + goto setarg0; +#endif login_sh = xargv[0] && xargv[0][0] == '-'; arg0 = xargv[0]; /* if (xargv[0]) - mmm, this is always true! */ xargv++; + argptr = xargv; for (i = 0; i < NOPTS; i++) optlist[i] = 2; - argptr = xargv; if (options(/*cmdline:*/ 1, &login_sh)) { /* it already printed err message */ raise_exception(EXERROR); @@ -14130,6 +14154,7 @@ extern int etext(); */ int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ash_main(int argc UNUSED_PARAM, char **argv) +/* note: 'argc' is used only if embedded scripts are enabled */ { volatile smallint state; struct jmploc jmploc; @@ -14183,6 +14208,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv) init(); setstackmark(&smark); + +#if NUM_SCRIPTS > 0 + if (argc < 0) + /* Non-NULL minusc tells procargs that an embedded script is being run */ + minusc = get_script_content(-argc - 1); +#endif login_sh = procargs(argv); #if DEBUG TRACE(("Shell args: ")); -- cgit v1.2.3-55-g6feb From aa2959c90d9c3217ddb6f482b82fef7234ad9bde Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 10:28:04 +0100 Subject: claenups for previous commit Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 36 ++++++++++++++++-------------------- shell/ash.c | 11 +++-------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 08720082e..4e6d1c3d6 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -964,6 +964,22 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 +static int +find_script_by_name(const char *arg) +{ + const char *s = script_names; + int i = 0; + + while (*s) { + if (strcmp(arg, s) == 0) + return i; + i++; + while (*s++ != '\0') + continue; + } + return -1; +} + static char * unpack_scripts(void) { @@ -992,26 +1008,6 @@ unpack_scripts(void) return outbuf; } -/* - * In standalone shell mode we sometimes want the index of the script - * and sometimes the index offset by NUM_APPLETS. - */ -static int -find_script_by_name(const char *arg) -{ - const char *s = script_names; - int i = 0; - - while (*s) { - if (strcmp(arg, s) == 0) - return i; - i++; - while (*s++ != '\0') - continue; - } - return -1; -} - char* FAST_FUNC get_script_content(unsigned n) { diff --git a/shell/ash.c b/shell/ash.c index 25468d796..3adb6d0d2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -153,15 +153,10 @@ //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: help -//config: Allow scripts to be compressed and embedded in the BusyBox +//config: Allow scripts to be compressed and embedded in the busybox //config: binary. The scripts should be placed in the 'embed' directory -//config: at build time. In standalone shell mode such scripts can be -//config: run directly and are subject to tab completion; otherwise they -//config: can be run by giving their name as an argument to the shell. -//config: For convenience shell aliases are created. The '-L' shell -//config: argument lists the names of the scripts. Like applets scripts -//config: can be run as 'busybox name ...' or by linking their name to -//config: the binary. +//config: at build time. Like applets, scripts can be run as +//config: 'busybox SCRIPT ...' or by linking their name to the binary. //config: //config:endif # ash options -- cgit v1.2.3-55-g6feb From 151de441e7a19ce3afba0c59b083240a801222cf Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 1 Nov 2018 11:04:47 +0100 Subject: ash: recognize embedded scripts in SH_STANDALONE mode function old new delta find_script_by_name - 51 +51 shellexec 254 271 +17 find_command 990 1007 +17 evalcommand 1653 1661 +8 doCommands 2233 2222 -11 run_applet_and_exit 128 100 -28 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 6/4 up/down: 104/-52) Total: 52 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/appletlib.c | 8 ++++---- shell/ash.c | 12 ++++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index affff5874..a32608ebd 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1322,7 +1322,7 @@ void bb_logenv_override(void) FAST_FUNC; #endif /* Embedded script support */ -//int find_script_by_name(const char *arg IF_FEATURE_SH_STANDALONE(, int offset)) FAST_FUNC; +int find_script_by_name(const char *name) FAST_FUNC; char *get_script_content(unsigned n) FAST_FUNC; /* Applets which are useful from another applets */ diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 4e6d1c3d6..92d99fbe8 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -964,20 +964,20 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 -static int -find_script_by_name(const char *arg) +int FAST_FUNC +find_script_by_name(const char *name) { const char *s = script_names; int i = 0; while (*s) { - if (strcmp(arg, s) == 0) + if (strcmp(name, s) == 0) return i; i++; while (*s++ != '\0') continue; } - return -1; + return -0x10000; /* make it so that NUM_APPLETS + is still < 0 */ } static char * diff --git a/shell/ash.c b/shell/ash.c index 3adb6d0d2..58ecf6d2c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8085,6 +8085,9 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) if (strchr(prog, '/') != NULL #if ENABLE_FEATURE_SH_STANDALONE || (applet_no = find_applet_by_name(prog)) >= 0 +# if NUM_SCRIPTS > 0 + || (applet_no = NUM_APPLETS + find_script_by_name(prog)) >= 0 +# endif #endif ) { tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); @@ -10186,6 +10189,10 @@ evalcommand(union node *cmd, int flags) */ /* find_command() encodes applet_no as (-2 - applet_no) */ int applet_no = (- cmdentry.u.index - 2); +# if NUM_SCRIPTS > 0 + /* Applets are ok, but not embedded scripts */ + if (applet_no < NUM_APPLETS) +# endif if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { char **sv_environ; @@ -13368,6 +13375,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #if ENABLE_FEATURE_SH_STANDALONE { int applet_no = find_applet_by_name(name); +# if NUM_SCRIPTS > 0 + if (applet_no < 0) + /* embedded script indices are offset by NUM_APPLETS */ + applet_no = NUM_APPLETS + find_script_by_name(name); +# endif if (applet_no >= 0) { entry->cmdtype = CMDNORMAL; entry->u.index = -2 - applet_no; -- cgit v1.2.3-55-g6feb From ca82b5354feca83374c78a7bdd43ef3aab9204e9 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 1 Nov 2018 11:45:03 +0100 Subject: ash: in tryexec(), ensure we don't try to run embedded scripts as applets Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shell/ash.c b/shell/ash.c index 58ecf6d2c..19004aad8 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8017,6 +8017,10 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c { #if ENABLE_FEATURE_SH_STANDALONE if (applet_no >= 0) { +# if NUM_SCRIPTS > 0 + if (applet_no >= NUM_APPLETS) + goto run_script; +# endif if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); while (*envp) @@ -8039,7 +8043,11 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c #else execve(cmd, argv, envp); #endif + if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { +#if ENABLE_FEATURE_SH_STANDALONE && NUM_SCRIPTS > 0 + run_script: +#endif /* Run "cmd" as a shell script: * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html * "If the execve() function fails with ENOEXEC, the shell -- cgit v1.2.3-55-g6feb From b0df5af0fad7969a10d3910465bfd0ff518b1358 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 12:50:33 +0100 Subject: ash: fix thinko in last commit Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 19004aad8..88f2b5bd6 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8018,8 +8018,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c #if ENABLE_FEATURE_SH_STANDALONE if (applet_no >= 0) { # if NUM_SCRIPTS > 0 - if (applet_no >= NUM_APPLETS) - goto run_script; + if (applet_no < NUM_APPLETS) # endif if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); @@ -8045,9 +8044,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c #endif if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { -#if ENABLE_FEATURE_SH_STANDALONE && NUM_SCRIPTS > 0 - run_script: -#endif /* Run "cmd" as a shell script: * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html * "If the execve() function fails with ENOEXEC, the shell -- cgit v1.2.3-55-g6feb From c9e161277eae5d2af39704e220ca5652e69bc428 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 1 Nov 2018 12:51:10 +0100 Subject: lineedit: autocompletion for embedded scripts function old new delta complete_cmd_dir_file 811 826 +15 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index aef1911d9..618e7c221 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -812,14 +812,20 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) } pf_len = strlen(pfind); -# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 +# if ENABLE_FEATURE_SH_STANDALONE && (NUM_APPLETS != 1 || NUM_SCRIPTS > 0) if (type == FIND_EXE_ONLY && !dirbuf) { - const char *p = applet_names; - + const char *p; +# if NUM_APPLETS != 1 && NUM_SCRIPTS > 0 + for (i = 0, p = applet_names; i < 2; i++, p = script_names) +# elif NUM_APPLETS != 1 /* and NUM_SCRIPTS == 0 */ + p = applet_names; +# else /* NUM_APPLETS == 1 && NUM_SCRIPTS > 0 */ + p = script_names; +# endif while (*p) { if (strncmp(pfind, p, pf_len) == 0) add_match(xstrdup(p)); - while (*p++ != '\0') + while (*p++) continue; } } -- cgit v1.2.3-55-g6feb From 0575c9932d203d93633104e12054dcf5da522061 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 13:58:16 +0100 Subject: busybox: show embedded scripts in applet list function old new delta busybox_main 624 642 +18 Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 92d99fbe8..d48b2ea60 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -839,24 +839,30 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) "Currently defined functions:\n" ); col = 0; - a = applet_names; /* prevent last comma to be in the very last pos */ output_width--; - while (*a) { - int len2 = strlen(a) + 2; - if (col >= (int)output_width - len2) { - full_write2_str(",\n"); - col = 0; - } - if (col == 0) { - col = 6; - full_write2_str("\t"); - } else { - full_write2_str(", "); + a = applet_names; + { +# if NUM_SCRIPTS > 0 + int i; + for (i = 0; i < 2; i++, a = script_names) +# endif + while (*a) { + int len2 = strlen(a) + 2; + if (col >= (int)output_width - len2) { + full_write2_str(",\n"); + col = 0; + } + if (col == 0) { + col = 6; + full_write2_str("\t"); + } else { + full_write2_str(", "); + } + full_write2_str(a); + col += len2; + a += len2 - 1; } - full_write2_str(a); - col += len2; - a += len2 - 1; } full_write2_str("\n"); return 0; -- cgit v1.2.3-55-g6feb From 0df289f427da6279e3ca198d14e90015c079af44 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Nov 2018 14:53:04 +0100 Subject: svlogd: fix pattern matching when using timestamps function old new delta svlogd_main 1488 1496 +8 Signed-off-by: Denys Vlasenko --- runit/svlogd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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) reopenasap = 1; } -static void logmatch(struct logdir *ld) +static void logmatch(struct logdir *ld, char* lineptr, int lineptr_len) { char *s; @@ -1021,12 +1021,12 @@ static void logmatch(struct logdir *ld) switch (s[0]) { case '+': case '-': - if (pmatch(s+1, line, linelen)) + if (pmatch(s+1, lineptr, lineptr_len)) ld->match = s[0]; break; case 'e': case 'E': - if (pmatch(s+1, line, linelen)) + if (pmatch(s+1, lineptr, lineptr_len)) ld->matcherr = s[0]; break; } @@ -1182,7 +1182,7 @@ int svlogd_main(int argc, char **argv) if (ld->fddir == -1) continue; if (ld->inst) - logmatch(ld); + logmatch(ld, lineptr, linelen); if (ld->matcherr == 'e') { /* runit-1.8.0 compat: if timestamping, do it on stderr too */ ////full_write(STDERR_FILENO, printptr, printlen); -- cgit v1.2.3-55-g6feb From c339c7f7b393fbcd51b0f96df837baa1edad7fd8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 2 Nov 2018 14:14:31 +0100 Subject: libarchive: add a function to unpack embedded data Similar code to unpack embedded data is used to decompress usage messages, embedded scripts and the config file (in the non-default bbconfig applet). Moving this code to a common function reduces the size of the default build and hides more of the internals of libarchive. function old new delta unpack_bz2_data - 135 +135 bb_show_usage 137 157 +20 get_script_content 32 47 +15 unpack_scripts 119 - -119 unpack_usage_messages 124 - -124 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 2/0 up/down: 170/-243) Total: -73 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_bunzip2.c | 38 +++++++++++++-- include/bb_archive.h | 7 +-- libbb/appletlib.c | 81 ++++++-------------------------- miscutils/bbconfig.c | 27 ++--------- 4 files changed, 54 insertions(+), 99 deletions(-) diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 7ef4e035f..6f2c49fbc 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c @@ -107,7 +107,7 @@ struct bunzip_data { uint8_t selectors[32768]; /* nSelectors=15 bits */ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ }; -/* typedef struct bunzip_data bunzip_data; -- done in .h file */ +typedef struct bunzip_data bunzip_data; /* 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) in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. (Why? This allows to get rid of one local variable) */ -int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) +static int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) { const uint32_t *dbuf; int pos, current, previous; @@ -699,7 +699,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() should work for NOFORK applets too, we must be extremely careful to not leak any allocations! */ -int FAST_FUNC start_bunzip( +static int FAST_FUNC start_bunzip( void *jmpbuf, bunzip_data **bdp, int in_fd, @@ -759,7 +759,7 @@ int FAST_FUNC start_bunzip( return RETVAL_OK; } -void FAST_FUNC dealloc_bunzip(bunzip_data *bd) +static void FAST_FUNC dealloc_bunzip(bunzip_data *bd) { free(bd->dbuf); free(bd); @@ -847,6 +847,36 @@ unpack_bz2_stream(transformer_state_t *xstate) return i ? i : IF_DESKTOP(total_written) + 0; } +char* FAST_FUNC +unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) +{ + char *outbuf = NULL; + bunzip_data *bd; + int i; + jmp_buf jmpbuf; + + /* Setup for I/O error handling via longjmp */ + i = setjmp(jmpbuf); + if (i == 0) { + i = start_bunzip(&jmpbuf, + &bd, + /* src_fd: */ -1, + /* inbuf: */ packed, + /* len: */ packed_len + ); + } + /* read_bunzip can longjmp and end up here with i != 0 + * on read data errors! Not trivial */ + if (i == 0) { + /* Cannot use xmalloc: will leak bd in NOFORK case! */ + outbuf = malloc_or_warn(unpacked_len); + if (outbuf) + read_bunzip(bd, outbuf, unpacked_len); + } + dealloc_bunzip(bd); + return outbuf; +} + #ifdef TESTING static char *const bunzip_errors[] = { diff --git a/include/bb_archive.h b/include/bb_archive.h index d2022336b..561dd0c9d 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -214,12 +214,7 @@ const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_F const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; /* A bit of bunzip2 internals are exposed for compressed help support: */ -typedef struct bunzip_data bunzip_data; -int start_bunzip(void *, bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; -/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes - * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ -int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; -void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; +char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC; /* Meaning and direction (input/output) of the fields are transformer-specific */ typedef struct transformer_state_t { diff --git a/libbb/appletlib.c b/libbb/appletlib.c index d48b2ea60..6dfaf1f41 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -107,34 +107,8 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; # include "bb_archive.h" -static const char *unpack_usage_messages(void) -{ - char *outbuf = NULL; - bunzip_data *bd; - int i; - jmp_buf jmpbuf; - - /* Setup for I/O error handling via longjmp */ - i = setjmp(jmpbuf); - if (i == 0) { - i = start_bunzip(&jmpbuf, - &bd, - /* src_fd: */ -1, - /* inbuf: */ packed_usage, - /* len: */ sizeof(packed_usage) - ); - } - /* read_bunzip can longjmp and end up here with i != 0 - * on read data errors! Not trivial */ - if (i == 0) { - /* Cannot use xmalloc: will leak bd in NOFORK case! */ - outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE)); - if (outbuf) - read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE)); - } - dealloc_bunzip(bd); - return outbuf; -} +# define unpack_usage_messages() \ + unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) # define dealloc_usage_messages(s) free(s) #else @@ -152,21 +126,23 @@ void FAST_FUNC bb_show_usage(void) /* Imagine that this applet is "true". Dont suck in printf! */ const char *usage_string = unpack_usage_messages(); - if (*usage_string == '\b') { - full_write2_str("No help available.\n\n"); - } else { - full_write2_str("Usage: "SINGLE_APPLET_STR" "); - full_write2_str(usage_string); - full_write2_str("\n\n"); + if (usage_string) { + if (*usage_string == '\b') { + full_write2_str("No help available.\n\n"); + } else { + full_write2_str("Usage: "SINGLE_APPLET_STR" "); + full_write2_str(usage_string); + full_write2_str("\n\n"); + } + if (ENABLE_FEATURE_CLEAN_UP) + dealloc_usage_messages((char*)usage_string); } - if (ENABLE_FEATURE_CLEAN_UP) - dealloc_usage_messages((char*)usage_string); #else const char *p; const char *usage_string = p = unpack_usage_messages(); int ap = find_applet_by_name(applet_name); - if (ap < 0) /* never happens, paranoia */ + if (ap < 0 || usage_string == NULL) xfunc_die(); while (ap) { while (*p++) continue; @@ -986,38 +962,11 @@ find_script_by_name(const char *name) return -0x10000; /* make it so that NUM_APPLETS + is still < 0 */ } -static char * -unpack_scripts(void) -{ - char *outbuf = NULL; - bunzip_data *bd; - int i; - jmp_buf jmpbuf; - - /* Setup for I/O error handling via longjmp */ - i = setjmp(jmpbuf); - if (i == 0) { - i = start_bunzip(&jmpbuf, - &bd, - /* src_fd: */ -1, - /* inbuf: */ packed_scripts, - /* len: */ sizeof(packed_scripts) - ); - } - /* read_bunzip can longjmp and end up here with i != 0 - * on read data errors! Not trivial */ - if (i == 0) { - outbuf = xmalloc(UNPACKED_SCRIPTS_LENGTH); - read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH); - } - dealloc_bunzip(bd); - return outbuf; -} - char* FAST_FUNC get_script_content(unsigned n) { - char *t = unpack_scripts(); + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), + UNPACKED_SCRIPTS_LENGTH); if (t) { while (n != 0) { while (*t++ != '\0') diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c index 501349548..fe02516a8 100644 --- a/miscutils/bbconfig.c +++ b/miscutils/bbconfig.c @@ -43,29 +43,10 @@ int bbconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { #if ENABLE_FEATURE_COMPRESS_BBCONFIG - bunzip_data *bd; - int i; - jmp_buf jmpbuf; - - /* Setup for I/O error handling via longjmp */ - i = setjmp(jmpbuf); - if (i == 0) { - i = start_bunzip(&jmpbuf, - &bd, - /* src_fd: */ -1, - /* inbuf: */ bbconfig_config_bz2, - /* len: */ sizeof(bbconfig_config_bz2) - ); - } - /* read_bunzip can longjmp and end up here with i != 0 - * on read data errors! Not trivial */ - if (i == 0) { - /* Cannot use xmalloc: will leak bd in NOFORK case! */ - char *outbuf = malloc_or_warn(sizeof(bbconfig_config)); - if (outbuf) { - read_bunzip(bd, outbuf, sizeof(bbconfig_config)); - full_write1_str(outbuf); - } + const char *outbuf = unpack_bz2_data(bbconfig_config_bz2, + sizeof(bbconfig_config_bz2), sizeof(bbconfig_config)); + if (outbuf) { + full_write1_str(outbuf); } #else full_write1_str(bbconfig_config); -- cgit v1.2.3-55-g6feb From 43794ff45d18d807d6dcd80a5eb5f451d479370c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Nov 2018 14:18:36 +0100 Subject: scripts/embedded_scripts: do not add superfluous NUL to script_names[] Signed-off-by: Denys Vlasenko --- scripts/embedded_scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 986e85160..7245ba6e0 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -32,7 +32,7 @@ then do printf '"%s\\0"' $i done - printf '"\\0";\n' + printf ';\n' printf '#else\n' printf 'extern const char script_names[] ALIGN1;\n' printf '#endif\n' -- cgit v1.2.3-55-g6feb From 97c2a6d0828f2b70de623c6642e5507f36e16cb4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Nov 2018 14:20:54 +0100 Subject: remove FAST_FUNC on a static function Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_bunzip2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index 6f2c49fbc..78366f26a 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c @@ -575,7 +575,7 @@ static int get_next_block(bunzip_data *bd) in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. (Why? This allows to get rid of one local variable) */ -static int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) +static int read_bunzip(bunzip_data *bd, char *outbuf, int len) { const uint32_t *dbuf; int pos, current, previous; @@ -809,7 +809,7 @@ unpack_bz2_stream(transformer_state_t *xstate) /* Observed case when i == RETVAL_OK: * "bzcat z.bz2", where "z.bz2" is a bzipped zero-length file * (to be exact, z.bz2 is exactly these 14 bytes: - * 42 5a 68 39 17 72 45 38 50 90 00 00 00 00). + * 42 5a 68 39 17 72 45 38 50 90 00 00 00 00). */ && i != RETVAL_OK ) { -- cgit v1.2.3-55-g6feb From 9d05ad087e1cb1295463ea1133bb619b67125f1d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Nov 2018 23:34:03 +0100 Subject: udhcpc: code shrink function old new delta perform_release 112 172 +60 send_release 81 - -81 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/0 up/down: 60/-81) Total: -21 bytes Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 4 +++- networking/udhcp/dhcpc.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index e2f8a6a9c..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 } /* Unicast a DHCP release message */ -static int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) +static +ALWAYS_INLINE /* one caller, help compiler to use this fact */ +int send_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6) { struct d6_packet packet; uint8_t *opt_ptr; diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index d2f165904..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 #endif /* Unicast a DHCP release message */ -static int send_release(uint32_t server, uint32_t ciaddr) +static +ALWAYS_INLINE /* one caller, help compiler to use this fact */ +int send_release(uint32_t server, uint32_t ciaddr) { struct dhcp_packet packet; -- cgit v1.2.3-55-g6feb From 9b0ce4d608a34f113d4757d326f8c4288a0b5352 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Nov 2018 20:53:54 +0100 Subject: tls: add more cipher ids, no code changes Signed-off-by: Denys Vlasenko --- networking/tls.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index c8d9e9697..eeacf34d7 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -56,6 +56,8 @@ // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" #define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA +// bug #11456: host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) + #define TLS_DEBUG 0 #define TLS_DEBUG_HASH 0 @@ -108,7 +110,7 @@ #define SSL_RSA_WITH_RC4_128_MD5 0x0004 #define SSL_RSA_WITH_RC4_128_SHA 0x0005 #define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /*SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 */ #define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ #define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */ @@ -135,34 +137,65 @@ #define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ #define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */ -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */ -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 */ #define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */ -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */ -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 */ #define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ #define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */ -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ #define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */ -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */ -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 */ #define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ #define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ /* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */ -#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ -#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ -#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */ -#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */ +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */ #define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */ -#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */ -#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */ +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /*TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD */ +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ #define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ +/* From http://wiki.mozilla.org/Security/Server_Side_TLS */ +/* and 'openssl ciphers -V -stdname' */ +#define TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(256) Mac=AEAD */ +#define TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ +#define TLS_RSA_WITH_AES_128_CCM 0xC09C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(128) Mac=AEAD */ +#define TLS_RSA_WITH_AES_256_CCM 0xC09D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(128) Mac=AEAD */ +#define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(128) Mac=AEAD */ +#define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(128) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(256) Mac=AEAD */ +#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /*TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /*TLSv1.2 Kx=DH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(128) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(128) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(256) Mac=AEAD */ + +#define TLS_AES_256_GCM_SHA384 0x1302 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD */ +#define TLS_CHACHA20_POLY1305_SHA256 0x1303 /*TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_AES_128_GCM_SHA256 0x1301 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD */ +#define TLS_AES_128_CCM_SHA256 0x1304 /*TLSv1.3 Kx=any Au=any Enc=AESCCM(128) Mac=AEAD */ + /* Might go to libbb.h */ #define TLS_MAX_CRYPTBLOCK_SIZE 16 #define TLS_MAX_OUTBUF (1 << 14) -- cgit v1.2.3-55-g6feb From b29d0455816fc7b384ef1a59d1895486317128da Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Nov 2018 21:18:29 +0100 Subject: tls: move TLS_AES_128_GCM_SHA256 definition up Signed-off-by: Denys Vlasenko --- networking/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/tls.c b/networking/tls.c index eeacf34d7..b36d7fa84 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -191,9 +191,9 @@ #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(128) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(256) Mac=AEAD */ +#define TLS_AES_128_GCM_SHA256 0x1301 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD */ #define TLS_AES_256_GCM_SHA384 0x1302 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD */ #define TLS_CHACHA20_POLY1305_SHA256 0x1303 /*TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD */ -#define TLS_AES_128_GCM_SHA256 0x1301 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD */ #define TLS_AES_128_CCM_SHA256 0x1304 /*TLSv1.3 Kx=any Au=any Enc=AESCCM(128) Mac=AEAD */ /* Might go to libbb.h */ -- cgit v1.2.3-55-g6feb From 5df3b12241526af543c5acd2088ce22f3524de32 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Nov 2018 21:25:41 +0100 Subject: tls: reorder a few more cipher ids Signed-off-by: Denys Vlasenko --- networking/tls.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index b36d7fa84..7cd6a61ba 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -104,46 +104,46 @@ #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 /* 0x10 */ #define HANDSHAKE_FINISHED 20 /* 0x14 */ +#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF /* not a real cipher id... */ + #define SSL_NULL_WITH_NULL_NULL 0x0000 #define SSL_RSA_WITH_NULL_MD5 0x0001 #define SSL_RSA_WITH_NULL_SHA 0x0002 #define SSL_RSA_WITH_RC4_128_MD5 0x0004 #define SSL_RSA_WITH_RC4_128_SHA 0x0005 +#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */ #define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ -#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /*SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 */ -#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ -#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */ - -#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF -#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */ #define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */ #define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */ #define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /*SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 */ #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */ -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */ -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */ #define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */ #define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */ +#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */ #define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */ #define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */ -#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */ #define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */ -#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ -#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ #define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */ #define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */ #define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ +#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ +#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ #define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */ #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1 */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /*TLSv1 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ #define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */ #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 */ #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 */ -#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ -#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ @@ -168,17 +168,17 @@ /* From http://wiki.mozilla.org/Security/Server_Side_TLS */ /* and 'openssl ciphers -V -stdname' */ #define TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ #define TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ -#define TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(256) Mac=AEAD */ -#define TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(128) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(256) Mac=AEAD */ #define TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ #define TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ #define TLS_RSA_WITH_AES_128_CCM 0xC09C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(128) Mac=AEAD */ #define TLS_RSA_WITH_AES_256_CCM 0xC09D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(256) Mac=AEAD */ -#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(128) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(256) Mac=AEAD */ #define TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(128) Mac=AEAD */ #define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(128) Mac=AEAD */ -- cgit v1.2.3-55-g6feb From 084bac472b02f307a093f56a262312accd6fb014 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Nov 2018 00:18:18 +0100 Subject: tls: code shrink function old new delta tls_handshake 1643 1619 -24 Signed-off-by: Denys Vlasenko --- networking/tls.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 7cd6a61ba..0f637a3d7 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1115,8 +1115,6 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey */ uint8_t *end = der + len; - uint8_t tag_class, pc, tag_number; - int version_present; /* enter "Certificate" item: [der, end) will be only Cert */ der = enter_der_item(der, &end); @@ -1133,13 +1131,11 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) * (constructed), and a tag number of 0 (see ITU-T X.690 sections 8.1.2 * and 8.14). */ - tag_class = der[0] >> 6; /* bits 8-7 */ - pc = (der[0] & 32) >> 5; /* bit 6 */ - tag_number = der[0] & 31; /* bits 5-1 */ - version_present = tag_class == 2 && pc == 1 && tag_number == 0; - if (version_present) { + /* bits 7-6: 10 */ + /* bit 5: 1 */ + /* bits 4-0: 00000 */ + if (der[0] == 0xa0) der = skip_der_item(der, end); /* version */ - } /* skip up to subjectPublicKeyInfo */ der = skip_der_item(der, end); /* serialNumber */ -- cgit v1.2.3-55-g6feb From 8767c12774d9392565f20d3ea4e28bb1b6075a31 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 5 Nov 2018 13:13:08 +0000 Subject: ash: minor fixes Ensure that login_sh is initialised in procargs even when running an embedded script. The argc argument to ash_main isn't unused when embedded scripts are present. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 88f2b5bd6..90eaf6faf 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14052,11 +14052,11 @@ procargs(char **argv) int login_sh; xargv = argv; + login_sh = xargv[0] && xargv[0][0] == '-'; #if NUM_SCRIPTS > 0 if (minusc) goto setarg0; #endif - login_sh = xargv[0] && xargv[0][0] == '-'; arg0 = xargv[0]; /* if (xargv[0]) - mmm, this is always true! */ xargv++; @@ -14164,7 +14164,11 @@ extern int etext(); * is used to figure out how far we had gotten. */ int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +#if NUM_SCRIPTS > 0 +int ash_main(int argc, char **argv) +#else int ash_main(int argc UNUSED_PARAM, char **argv) +#endif /* note: 'argc' is used only if embedded scripts are enabled */ { volatile smallint state; -- cgit v1.2.3-55-g6feb From bddb6545a982696bde417a9ae621f9e2d3c22b3d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Nov 2018 02:16:24 +0100 Subject: tls: add support for ECDHE-ECDSA-AES-128-CBC-SHA and x25519 curve function old new delta curve25519 - 835 +835 tls_handshake 1619 1935 +316 xc_diffadd - 230 +230 fe_mul__distinct - 149 +149 lm_sub - 103 +103 lm_add - 82 +82 fe_mul_c - 74 +74 fe_select - 45 +45 static.f25519_one - 32 +32 static.basepoint9 - 32 +32 static.OID_ECDSA_KEY_ALG - 21 +21 static.OID_RSA_KEY_ALG - 13 +13 static.supported_groups - 8 +8 static.empty_client_cert - 7 +7 der_binary_to_pstm 40 42 +2 static.expected 13 - -13 ------------------------------------------------------------------------------ (add/remove: 14/1 grow/shrink: 2/0 up/down: 1949/-13) Total: 1936 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 334 ++++++++++++++++++++++------- networking/tls.h | 3 +- networking/tls_fe.c | 601 ++++++++++++++++++++++++++++++++++++++++++++++++++++ networking/tls_fe.h | 7 + 4 files changed, 865 insertions(+), 80 deletions(-) create mode 100644 networking/tls_fe.c create mode 100644 networking/tls_fe.h diff --git a/networking/tls.c b/networking/tls.c index 0f637a3d7..694fbf34d 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -12,8 +12,9 @@ //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o -//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o //kbuild:lib-$(CONFIG_TLS) += tls_aes.o +//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o +//kbuild:lib-$(CONFIG_TLS) += tls_fe.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o #include "tls.h" @@ -57,6 +58,7 @@ #define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA // bug #11456: host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) +#define CIPHER_ID3 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA #define TLS_DEBUG 0 @@ -260,15 +262,22 @@ struct record_hdr { uint8_t len16_hi, len16_lo; }; +enum { + KEY_ALG_RSA, + KEY_ALG_ECDSA, +}; struct tls_handshake_data { /* In bbox, md5/sha1/sha256 ctx's are the same structure */ md5sha_ctx_t handshake_hash_ctx; uint8_t client_and_server_rand32[2 * 32]; uint8_t master_secret[48]; + + smallint key_alg; //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; + uint8_t ecc_pub_key32[32]; unsigned saved_client_hello_size; uint8_t saved_client_hello[1]; @@ -1022,15 +1031,25 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) return new_der; } +// +static void binary_to_pstm(pstm_int *pstm_n, uint8_t *bin_ptr, unsigned len) +{ + pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); + pstm_read_unsigned_bin(pstm_n, bin_ptr, len); + //return bin_ptr + len; +} +// + static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) { uint8_t *bin_ptr; unsigned len = get_der_len(&bin_ptr, der, end); dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); - pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); - pstm_read_unsigned_bin(pstm_n, bin_ptr, len); - //return bin + len; + binary_to_pstm(pstm_n, bin_ptr, len); + //pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); + //pstm_read_unsigned_bin(pstm_n, bin_ptr, len); + ////return bin_ptr + len; } static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) @@ -1113,6 +1132,18 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) * publicKey (BIT STRING) * * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey + * + * Example of an ECDSA key: + * SEQ 0x59 bytes (subjectPublicKeyInfo): 3059 + * SEQ 0x13 bytes (algorithm): 3013 + * OID 7 bytes: 0607 2a8648ce3d0201 (OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1) + * OID 8 bytes: 0608 2a8648ce3d030107 (OID_EC_prime256v1 42.134.72.206.61.3.1.7) + * BITSTRING 0x42 bytes (publicKey): 0342 + * 0004 53af f65e 50cc 7959 7e29 0171 c75c + * 7335 e07d f45b 9750 b797 3a38 aebb 2ac6 + * 8329 2748 e77e 41cb d482 2ce6 05ec a058 + * f3ab d561 2f4c d845 9ad3 7252 e3de bd3b + * 9012 */ uint8_t *end = der + len; @@ -1147,40 +1178,61 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) /* enter subjectPublicKeyInfo */ der = enter_der_item(der, &end); { /* check subjectPublicKeyInfo.algorithm */ - static const uint8_t expected[] = { + static const uint8_t OID_RSA_KEY_ALG[] = { 0x30,0x0d, // SEQ 13 bytes 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 //0x05,0x00, // NULL }; - if (memcmp(der, expected, sizeof(expected)) != 0) - bb_error_msg_and_die("not RSA key"); + static const uint8_t OID_ECDSA_KEY_ALG[] = { + 0x30,0x13, // SEQ 0x13 bytes + 0x06,0x07, 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01, //OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1 + 0x06,0x08, 0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07, //OID_EC_prime256v1 42.134.72.206.61.3.1.7 + //rfc3279: + //42.134.72.206.61.3 is ellipticCurve + //42.134.72.206.61.3.0 is c-TwoCurve + //42.134.72.206.61.3.1 is primeCurve + //42.134.72.206.61.3.1.7 is prime256v1 + }; + if (memcmp(der, OID_RSA_KEY_ALG, sizeof(OID_RSA_KEY_ALG)) == 0) { + dbg("RSA key\n"); + tls->hsd->key_alg = KEY_ALG_RSA; + } else + if (memcmp(der, OID_ECDSA_KEY_ALG, sizeof(OID_ECDSA_KEY_ALG)) == 0) { + dbg("ECDSA key\n"); + tls->hsd->key_alg = KEY_ALG_ECDSA; + } else + bb_error_msg_and_die("not RSA or ECDSA key"); } - /* skip subjectPublicKeyInfo.algorithm */ - der = skip_der_item(der, end); - /* enter subjectPublicKeyInfo.publicKey */ -// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ - der = enter_der_item(der, &end); - /* parse RSA key: */ -//based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note - dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); - if (end - der < 14) xfunc_die(); - /* example format: - * ignore bits: 00 - * SEQ 0x018a/394 bytes: 3082018a - * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX - * INTEGER 3 bytes (exponent): 0203 010001 - */ - if (*der != 0) /* "ignore bits", should be 0 */ - xfunc_die(); - der++; - der = enter_der_item(der, &end); /* enter SEQ */ - /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */ - der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */ - der = skip_der_item(der, end); - der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */ - tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); - dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); + if (tls->hsd->key_alg == KEY_ALG_RSA) { + /* parse RSA key: */ + //based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note + /* skip subjectPublicKeyInfo.algorithm */ + der = skip_der_item(der, end); + /* enter subjectPublicKeyInfo.publicKey */ +// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ + der = enter_der_item(der, &end); + + dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); + if (end - der < 14) + xfunc_die(); + /* example format: + * ignore bits: 00 + * SEQ 0x018a/394 bytes: 3082018a + * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX + * INTEGER 3 bytes (exponent): 0203 010001 + */ + if (*der != 0) /* "ignore bits", should be 0 */ + xfunc_die(); + der++; + der = enter_der_item(der, &end); /* enter SEQ */ + /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */ + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */ + der = skip_der_item(der, end); + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */ + tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); + dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); + } } /* @@ -1217,6 +1269,22 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { + static const uint8_t supported_groups[] = { + 0x00,0x0a, //extension_type: "supported_groups" + 0x00,0x04, //ext len + 0x00,0x02, //list len + 0x00,0x1d, //curve_x25519 (rfc7748) + //0x00,0x17, //curve_secp256r1 + //0x00,0x18, //curve_secp384r1 + //0x00,0x19, //curve_secp521r1 + }; + //static const uint8_t signature_algorithms[] = { + // 000d + // 0020 + // 001e + // 0601 0602 0603 0501 0502 0503 0401 0402 0403 0301 0302 0303 0201 0202 0203 + //}; + struct client_hello { uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; @@ -1225,7 +1293,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * (2 + !!CIPHER_ID2)]; /* actually variable */ + uint8_t cipherid[2 * (2 + !!CIPHER_ID2 + !!CIPHER_ID3)]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): @@ -1250,12 +1318,19 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) // 0017 0000 - extended master secret }; struct client_hello *record; + uint8_t *ptr; int len; - int sni_len = sni ? strnlen(sni, 127 - 9) : 0; + int ext_len; + int sni_len = sni ? strnlen(sni, 127 - 5) : 0; - len = sizeof(*record); + ext_len = 0; + /* is.gd responds with "handshake failure" to our hello if there's no supported_groups element */ + ext_len += sizeof(supported_groups); if (sni_len) - len += 11 + sni_len; + ext_len += 9 + sni_len; + + /* +2 is for "len of all extensions" 2-byte field */ + len = sizeof(*record) + 2 + ext_len; record = tls_get_outbuf(tls, len); memset(record, 0, len); @@ -1278,25 +1353,30 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8; /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff; #endif +#if CIPHER_ID3 + if ((CIPHER_ID3 >> 8) != 0) record->cipherid[6] = CIPHER_ID3 >> 8; + /*************************/ record->cipherid[7] = CIPHER_ID3 & 0xff; +#endif record->comprtypes_len = 1; /* record->comprtypes[0] = 0; */ + ptr = (void*)(record + 1); + *ptr++ = ext_len >> 8; + *ptr++ = ext_len; if (sni_len) { - uint8_t *p = (void*)(record + 1); - //p[0] = 0; // - p[1] = sni_len + 9; //ext_len - //p[2] = 0; // - //p[3] = 0; //extension_type - //p[4] = 0; // - p[5] = sni_len + 5; //list len - //p[6] = 0; // - p[7] = sni_len + 3; //len of 1st SNI - //p[8] = 0; //name type - //p[9] = 0; // - p[10] = sni_len; //name len - memcpy(&p[11], sni, sni_len); + //ptr[0] = 0; // + //ptr[1] = 0; //extension_type + //ptr[2] = 0; // + ptr[3] = sni_len + 5; //list len + //ptr[4] = 0; // + ptr[5] = sni_len + 3; //len of 1st SNI + //ptr[6] = 0; //name type + //ptr[7] = 0; // + ptr[8] = sni_len; //name len + ptr = mempcpy(&ptr[9], sni, sni_len); } + mempcpy(ptr, supported_groups, sizeof(supported_groups)); dbg(">> CLIENT_HELLO\n"); /* Can hash it only when we know which MAC hash to use */ @@ -1373,7 +1453,9 @@ static void get_server_hello(tls_state_t *tls) tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1]; dbg("server chose cipher %04x\n", cipher); - if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) { + if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA + || cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + ) { tls->key_size = AES128_KEYSIZE; tls->MAC_size = SHA1_OUTSIZE; } @@ -1425,6 +1507,55 @@ static void get_server_cert(tls_state_t *tls) find_key_in_der_cert(tls, certbuf + 10, len); } +/* On input, len is known to be >= 4. + * The record is known to be SERVER_KEY_EXCHANGE. + */ +static void process_server_key(tls_state_t *tls, int len) +{ + struct record_hdr *xhdr; + uint8_t *keybuf; + int len1; + uint32_t t32; + + xhdr = (void*)tls->inbuf; + keybuf = (void*)(xhdr + 1); +//seen from is.gd: it selects curve_x25519: +// 0c 00006e //SERVER_KEY_EXCHANGE +// 03 //curve_type: named curve +// 001d //curve_x25519 +//server-chosen EC point, and then signed_params +// (rfc8422: "A hash of the params, with the signature +// appropriate to that hash applied. The private key corresponding +// to the certified public key in the server's Certificate message is +// used for signing.") +//follow. Format unclear/guessed: +// 20 //eccPubKeyLen +// 25511923d73b70dd2f60e66ba2f3fda31a9c25170963c7a3a972e481dbb2835d //eccPubKey (32bytes) +// 0203 //hashSigAlg: 2:SHA1 (4:SHA256 5:SHA384 6:SHA512), 3:ECDSA (1:RSA) +// 0046 //len (16bit) +// 30 44 //SEQ, len +// 02 20 //INTEGER, len +// 2e18e7c2a9badd0a70cd3059a6ab114539b9f5163568911147386cd77ed7c412 //32bytes +//this item ^^^^^ is sometimes 33 bytes (with all container sizes also +1) +// 02 20 //INTEGER, len +// 64523d6216cb94c43c9b20e377d8c52c55be6703fd6730a155930c705eaf3af6 //32bytes +//same about this item ^^^^^ + /* Get and verify length */ + len1 = get24be(keybuf + 1); + if (len1 > len - 4) tls_error_die(tls); + len = len1; + if (len < (1+2+1+32)) tls_error_die(tls); + keybuf += 4; + + /* So far we only support curve_x25519 */ + move_from_unaligned32(t32, keybuf); + if (t32 != htonl(0x03001d20)) + tls_error_die(tls); + + memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32); + dbg("got eccPubKey\n"); +} + static void send_empty_client_cert(tls_state_t *tls) { struct client_empty_cert { @@ -1433,13 +1564,18 @@ static void send_empty_client_cert(tls_state_t *tls) uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo; }; struct client_empty_cert *record; + static const uint8_t empty_client_cert[] = { + HANDSHAKE_CERTIFICATE, + 0, 0, 3, //len24 + 0, 0, 0, //cert_chain_len24 + }; record = tls_get_outbuf(tls, sizeof(*record)); -//FIXME: can just memcpy a ready-made one. - fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); - record->cert_chain_len24_hi = 0; - record->cert_chain_len24_mid = 0; - record->cert_chain_len24_lo = 0; + //fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); + //record->cert_chain_len24_hi = 0; + //record->cert_chain_len24_mid = 0; + //record->cert_chain_len24_lo = 0; + memcpy(record, empty_client_cert, sizeof(empty_client_cert)); dbg(">> CERTIFICATE\n"); xwrite_and_update_handshake_hash(tls, sizeof(*record)); @@ -1450,34 +1586,63 @@ static void send_client_key_exchange(tls_state_t *tls) struct client_key_exchange { uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; - /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */ - uint8_t keylen16_hi, keylen16_lo; - uint8_t key[4 * 1024]; // size?? + uint8_t key[2 + 4 * 1024]; // size?? }; //FIXME: better size estimate struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record)); uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; + uint8_t x25519_premaster[CURVE25519_KEYSIZE]; + uint8_t *premaster; + int premaster_size; int len; - tls_get_random(rsa_premaster, sizeof(rsa_premaster)); - if (TLS_DEBUG_FIXED_SECRETS) - memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); - // RFC 5246 - // "Note: The version number in the PreMasterSecret is the version - // offered by the client in the ClientHello.client_version, not the - // version negotiated for the connection." - rsa_premaster[0] = TLS_MAJ; - rsa_premaster[1] = TLS_MIN; - dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); - len = psRsaEncryptPub(/*pool:*/ NULL, - /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, - rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), - record->key, sizeof(record->key), - data_param_ignored - ); - record->keylen16_hi = len >> 8; - record->keylen16_lo = len & 0xff; - len += 2; + if (tls->hsd->key_alg == KEY_ALG_RSA) { + tls_get_random(rsa_premaster, sizeof(rsa_premaster)); + if (TLS_DEBUG_FIXED_SECRETS) + memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); + // RFC 5246 + // "Note: The version number in the PreMasterSecret is the version + // offered by the client in the ClientHello.client_version, not the + // version negotiated for the connection." + rsa_premaster[0] = TLS_MAJ; + rsa_premaster[1] = TLS_MIN; + dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); + len = psRsaEncryptPub(/*pool:*/ NULL, + /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, + rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), + record->key + 2, sizeof(record->key) - 2, + data_param_ignored + ); + /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */ + record->key[0] = len >> 8; + record->key[1] = len & 0xff; + len += 2; + premaster = rsa_premaster; + premaster_size = sizeof(rsa_premaster); + } else { + /* KEY_ALG_ECDSA */ + static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9}; + uint8_t privkey[CURVE25519_KEYSIZE]; //[32] + + /* Generate random private key, see RFC 7748 */ + tls_get_random(privkey, sizeof(privkey)); + privkey[0] &= 0xf8; + privkey[CURVE25519_KEYSIZE-1] = ((privkey[CURVE25519_KEYSIZE-1] & 0x7f) | 0x40); + + /* Compute public key */ + curve25519(record->key + 1, privkey, basepoint9); + + /* Compute premaster using peer's public key */ + dbg("computing x25519_premaster\n"); + curve25519(x25519_premaster, privkey, tls->hsd->ecc_pub_key32); + + len = CURVE25519_KEYSIZE; + record->key[0] = len; + len++; + premaster = x25519_premaster; + premaster_size = sizeof(x25519_premaster); + } + record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; record->len24_hi = 0; record->len24_mid = len >> 8; @@ -1499,7 +1664,7 @@ static void send_client_key_exchange(tls_state_t *tls) // of the premaster secret will vary depending on key exchange method. prf_hmac_sha256(/*tls,*/ tls->hsd->master_secret, sizeof(tls->hsd->master_secret), - rsa_premaster, sizeof(rsa_premaster), + premaster, premaster_size, "master secret", tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32) ); @@ -1686,8 +1851,19 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) //SvKey len=455^ // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: // 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... + // + // RFC 8422 5.4. Server Key Exchange + // This message is sent when using the ECDHE_ECDSA, ECDHE_RSA, and + // ECDH_anon key exchange algorithms. + // This message is used to convey the server's ephemeral ECDH public key + // (and the corresponding elliptic curve domain parameters) to the + // client. dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); -//probably need to save it + dump_raw_in("<< %s\n", tls->inbuf, RECHDR_LEN + len); + if (tls->hsd->key_alg == KEY_ALG_ECDSA) + process_server_key(tls, len); + + // read next handshake block len = tls_xread_handshake_block(tls, 4); } diff --git a/networking/tls.h b/networking/tls.h index d487f3810..66d25eff5 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -94,6 +94,7 @@ void tls_get_random(void *buf, unsigned len); #include "tls_pstm.h" -#include "tls_rsa.h" #include "tls_symmetric.h" #include "tls_aes.h" +#include "tls_rsa.h" +#include "tls_fe.h" diff --git a/networking/tls_fe.c b/networking/tls_fe.c new file mode 100644 index 000000000..37fea34f7 --- /dev/null +++ b/networking/tls_fe.c @@ -0,0 +1,601 @@ +/* + * Copyright (C) 2018 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +typedef uint8_t byte; +typedef uint16_t word16; +typedef uint32_t word32; +#define XMEMSET memset + +#define F25519_SIZE CURVE25519_KEYSIZE + +/* The code below is taken from wolfssl-3.15.3/wolfcrypt/src/fe_low_mem.c + * Header comment is kept intact: + */ + +/* fe_low_mem.c + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* Based from Daniel Beer's public domain work. */ + +#if 0 //UNUSED +static void fprime_copy(byte *x, const byte *a) +{ + int i; + for (i = 0; i < F25519_SIZE; i++) + x[i] = a[i]; +} +#endif + +static void lm_copy(byte* x, const byte* a) +{ + int i; + for (i = 0; i < F25519_SIZE; i++) + x[i] = a[i]; +} + +#if 0 //UNUSED +static void fprime_select(byte *dst, const byte *zero, const byte *one, byte condition) +{ + const byte mask = -condition; + int i; + + for (i = 0; i < F25519_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} +#endif + +static void fe_select(byte *dst, + const byte *zero, const byte *one, + byte condition) +{ + const byte mask = -condition; + int i; + + for (i = 0; i < F25519_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} + +#if 0 //UNUSED +static void raw_add(byte *x, const byte *p) +{ + word16 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c += ((word16)x[i]) + ((word16)p[i]); + x[i] = (byte)c; + c >>= 8; + } +} +#endif + +#if 0 //UNUSED +static void raw_try_sub(byte *x, const byte *p) +{ + byte minusp[F25519_SIZE]; + word16 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c = ((word16)x[i]) - ((word16)p[i]) - c; + minusp[i] = (byte)c; + c = (c >> 8) & 1; + } + + fprime_select(x, minusp, x, (byte)c); +} +#endif + +#if 0 //UNUSED +static int prime_msb(const byte *p) +{ + int i; + byte x; + int shift = 1; + int z = F25519_SIZE - 1; + + /* + Test for any hot bits. + As soon as one instance is encountered set shift to 0. + */ + for (i = F25519_SIZE - 1; i >= 0; i--) { + shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1); + z -= shift; + } + x = p[z]; + z <<= 3; + shift = 1; + for (i = 0; i < 8; i++) { + shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1); + z += shift; + } + + return z - 1; +} +#endif + +#if 0 //UNUSED +static void fprime_add(byte *r, const byte *a, const byte *modulus) +{ + raw_add(r, a); + raw_try_sub(r, modulus); +} +#endif + +#if 0 //UNUSED +static void fprime_sub(byte *r, const byte *a, const byte *modulus) +{ + raw_add(r, modulus); + raw_try_sub(r, a); + raw_try_sub(r, modulus); +} +#endif + +#if 0 //UNUSED +static void fprime_mul(byte *r, const byte *a, const byte *b, + const byte *modulus) +{ + word16 c = 0; + int i,j; + + XMEMSET(r, 0, F25519_SIZE); + + for (i = prime_msb(modulus); i >= 0; i--) { + const byte bit = (b[i >> 3] >> (i & 7)) & 1; + byte plusa[F25519_SIZE]; + + for (j = 0; j < F25519_SIZE; j++) { + c |= ((word16)r[j]) << 1; + r[j] = (byte)c; + c >>= 8; + } + raw_try_sub(r, modulus); + + fprime_copy(plusa, r); + fprime_add(plusa, a, modulus); + + fprime_select(r, r, plusa, bit); + } +} +#endif + +#if 0 //UNUSED +static void fe_load(byte *x, word32 c) +{ + word32 i; + + for (i = 0; i < sizeof(c); i++) { + x[i] = c; + c >>= 8; + } + + for (; i < F25519_SIZE; i++) + x[i] = 0; +} +#endif + +static void fe_normalize(byte *x) +{ + byte minusp[F25519_SIZE]; + word16 c; + int i; + + /* Reduce using 2^255 = 19 mod p */ + c = (x[31] >> 7) * 19; + x[31] &= 127; + + for (i = 0; i < F25519_SIZE; i++) { + c += x[i]; + x[i] = (byte)c; + c >>= 8; + } + + /* The number is now less than 2^255 + 18, and therefore less than + * 2p. Try subtracting p, and conditionally load the subtracted + * value if underflow did not occur. + */ + c = 19; + + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += x[i]; + minusp[i] = (byte)c; + c >>= 8; + } + + c += ((word16)x[i]) - 128; + minusp[31] = (byte)c; + + /* Load x-p if no underflow */ + fe_select(x, minusp, x, (c >> 15) & 1); +} + +static void lm_add(byte* r, const byte* a, const byte* b) +{ + word16 c = 0; + int i; + + /* Add */ + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += ((word16)a[i]) + ((word16)b[i]); + r[i] = (byte)c; + } + + /* Reduce with 2^255 = 19 mod p */ + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = (byte)c; + c >>= 8; + } +} + +static void lm_sub(byte* r, const byte* a, const byte* b) +{ + word32 c = 0; + int i; + + /* Calculate a + 2p - b, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 + ((word32)a[i]) - ((word32)b[i]); + r[i] = c; + c >>= 8; + } + + c += ((word32)a[31]) - ((word32)b[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +#if 0 //UNUSED +static void lm_neg(byte* r, const byte* a) +{ + word32 c = 0; + int i; + + /* Calculate 2p - a, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 - ((word32)a[i]); + r[i] = c; + c >>= 8; + } + + c -= ((word32)a[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} +#endif + +static void fe_mul__distinct(byte *r, const byte *a, const byte *b) +{ + word32 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + int j; + + c >>= 8; + for (j = 0; j <= i; j++) + c += ((word32)a[j]) * ((word32)b[i - j]); + + for (; j < F25519_SIZE; j++) + c += ((word32)a[j]) * + ((word32)b[i + F25519_SIZE - j]) * 38; + + r[i] = c; + } + + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +#if 0 //UNUSED +static void lm_mul(byte *r, const byte* a, const byte *b) +{ + byte tmp[F25519_SIZE]; + + fe_mul__distinct(tmp, a, b); + lm_copy(r, tmp); +} +#endif + +static void fe_mul_c(byte *r, const byte *a, word32 b) +{ + word32 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += b * ((word32)a[i]); + r[i] = c; + } + + r[31] &= 127; + c >>= 7; + c *= 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +static void fe_inv__distinct(byte *r, const byte *x) +{ + byte s[F25519_SIZE]; + int i; + + /* This is a prime field, so by Fermat's little theorem: + * + * x^(p-1) = 1 mod p + * + * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative + * inverse. + * + * This is a 255-bit binary number with the digits: + * + * 11111111... 01011 + * + * We compute the result by the usual binary chain, but + * alternate between keeping the accumulator in r and s, so as + * to avoid copying temporaries. + */ + + /* 1 1 */ + fe_mul__distinct(s, x, x); + fe_mul__distinct(r, s, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); + } + + /* 0 */ + fe_mul__distinct(s, r, r); + + /* 1 */ + fe_mul__distinct(r, s, s); + fe_mul__distinct(s, r, x); + + /* 0 */ + fe_mul__distinct(r, s, s); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); +} + +#if 0 //UNUSED +static void lm_invert(byte *r, const byte *x) +{ + byte tmp[F25519_SIZE]; + + fe_inv__distinct(tmp, x); + lm_copy(r, tmp); +} +#endif + +#if 0 //UNUSED +/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary + * storage. + */ +static void exp2523(byte *r, const byte *x, byte *s) +{ + int i; + + /* This number is a 252-bit number with the binary expansion: + * + * 111111... 01 + */ + + /* 1 1 */ + fe_mul__distinct(r, x, x); + fe_mul__distinct(s, r, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + fe_mul__distinct(r, s, s); + fe_mul__distinct(s, r, x); + } + + /* 0 */ + fe_mul__distinct(r, s, s); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); +} +#endif + +#if 0 //UNUSED +static void fe_sqrt(byte *r, const byte *a) +{ + byte v[F25519_SIZE]; + byte i[F25519_SIZE]; + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + + /* v = (2a)^((p-5)/8) [x = 2a] */ + fe_mul_c(x, a, 2); + exp2523(v, x, y); + + /* i = 2av^2 - 1 */ + fe_mul__distinct(y, v, v); + fe_mul__distinct(i, x, y); + fe_load(y, 1); + lm_sub(i, i, y); + + /* r = avi */ + fe_mul__distinct(x, v, a); + fe_mul__distinct(r, x, i); +} +#endif + +/* Differential addition */ +static void xc_diffadd(byte *x5, byte *z5, + const byte *x1, const byte *z1, + const byte *x2, const byte *z2, + const byte *x3, const byte *z3) +{ + /* Explicit formulas database: dbl-1987-m3 + * + * source 1987 Montgomery "Speeding the Pollard and elliptic curve + * methods of factorization", page 261, fifth display, plus + * common-subexpression elimination + * compute A = X2+Z2 + * compute B = X2-Z2 + * compute C = X3+Z3 + * compute D = X3-Z3 + * compute DA = D A + * compute CB = C B + * compute X5 = Z1(DA+CB)^2 + * compute Z5 = X1(DA-CB)^2 + */ + byte da[F25519_SIZE]; + byte cb[F25519_SIZE]; + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + + lm_add(a, x2, z2); + lm_sub(b, x3, z3); /* D */ + fe_mul__distinct(da, a, b); + + lm_sub(b, x2, z2); + lm_add(a, x3, z3); /* C */ + fe_mul__distinct(cb, a, b); + + lm_add(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(x5, z1, b); + + lm_sub(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(z5, x1, b); +} + +/* Double an X-coordinate */ +static void xc_double(byte *x3, byte *z3, + const byte *x1, const byte *z1) +{ + /* Explicit formulas database: dbl-1987-m + * + * source 1987 Montgomery "Speeding the Pollard and elliptic + * curve methods of factorization", page 261, fourth display + * compute X3 = (X1^2-Z1^2)^2 + * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2) + */ + byte x1sq[F25519_SIZE]; + byte z1sq[F25519_SIZE]; + byte x1z1[F25519_SIZE]; + byte a[F25519_SIZE]; + + fe_mul__distinct(x1sq, x1, x1); + fe_mul__distinct(z1sq, z1, z1); + fe_mul__distinct(x1z1, x1, z1); + + lm_sub(a, x1sq, z1sq); + fe_mul__distinct(x3, a, a); + + fe_mul_c(a, x1z1, 486662); + lm_add(a, x1sq, a); + lm_add(a, z1sq, a); + fe_mul__distinct(x1sq, x1z1, a); + fe_mul_c(z3, x1sq, 4); +} + +void curve25519(byte *result, const byte *e, const byte *q) +{ + /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ + static const byte f25519_one[F25519_SIZE] = {1}; + + /* Current point: P_m */ + byte xm[F25519_SIZE]; + byte zm[F25519_SIZE] = {1}; + + /* Predecessor: P_(m-1) */ + byte xm1[F25519_SIZE] = {1}; + byte zm1[F25519_SIZE] = {0}; + + int i; + + /* Note: bit 254 is assumed to be 1 */ + lm_copy(xm, q); + + for (i = 253; i >= 0; i--) { + const int bit = (e[i >> 3] >> (i & 7)) & 1; + byte xms[F25519_SIZE]; + byte zms[F25519_SIZE]; + + /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ + xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); + xc_double(xm, zm, xm, zm); + + /* Compute P_(2m+1) */ + xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one); + + /* Select: + * bit = 1 --> (P_(2m+1), P_(2m)) + * bit = 0 --> (P_(2m), P_(2m-1)) + */ + fe_select(xm1, xm1, xm, bit); + fe_select(zm1, zm1, zm, bit); + fe_select(xm, xm, xms, bit); + fe_select(zm, zm, zms, bit); + } + + /* Freeze out of projective coordinates */ + fe_inv__distinct(zm1, zm); + fe_mul__distinct(result, zm1, xm); + fe_normalize(result); +} diff --git a/networking/tls_fe.h b/networking/tls_fe.h new file mode 100644 index 000000000..bd2f2b3da --- /dev/null +++ b/networking/tls_fe.h @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2018 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#define CURVE25519_KEYSIZE 32 +void curve25519(uint8_t *result, const uint8_t *e, const uint8_t *q); -- cgit v1.2.3-55-g6feb From 375fc78d51f128f36c4fe17df0d284cecd28d55e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Nov 2018 03:15:15 +0100 Subject: tls: code shrink function old new delta static.f25519_one 32 - -32 curve25519 835 802 -33 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-65) Total: -65 bytes Signed-off-by: Denys Vlasenko --- networking/tls_fe.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/networking/tls_fe.c b/networking/tls_fe.c index 37fea34f7..dcb41468a 100644 --- a/networking/tls_fe.c +++ b/networking/tls_fe.c @@ -556,19 +556,29 @@ static void xc_double(byte *x3, byte *z3, void curve25519(byte *result, const byte *e, const byte *q) { - /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ - static const byte f25519_one[F25519_SIZE] = {1}; - - /* Current point: P_m */ - byte xm[F25519_SIZE]; - byte zm[F25519_SIZE] = {1}; - - /* Predecessor: P_(m-1) */ - byte xm1[F25519_SIZE] = {1}; - byte zm1[F25519_SIZE] = {0}; - int i; + struct { + /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ + /*static const*/ byte f25519_one[F25519_SIZE]; // = {1}; + + /* Current point: P_m */ + byte xm[F25519_SIZE]; + byte zm[F25519_SIZE]; // = {1}; + /* Predecessor: P_(m-1) */ + byte xm1[F25519_SIZE]; // = {1}; + byte zm1[F25519_SIZE]; // = {0}; + } z; +#define f25519_one z.f25519_one +#define xm z.xm +#define zm z.zm +#define xm1 z.xm1 +#define zm1 z.zm1 + memset(&z, 0, sizeof(z)); + f25519_one[0] = 1; + zm[0] = 1; + xm1[0] = 1; + /* Note: bit 254 is assumed to be 1 */ lm_copy(xm, q); -- cgit v1.2.3-55-g6feb From de7b5bb59a5d89f8b63284c6a9de5a5a95f02db3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Nov 2018 11:44:32 +0100 Subject: tls: tidy up recently added ECDSA code function old new delta tls_handshake 1935 1930 -5 static.OID_ECDSA_KEY_ALG 21 11 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-15) Total: -15 bytes text data bss dec hex filename 950036 477 7296 957809 e9d71 busybox_old 950048 477 7296 957821 e9d7d busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/tls.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 694fbf34d..20343bc0a 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -966,6 +966,13 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) return sz; } +static void binary_to_pstm(pstm_int *pstm_n, uint8_t *bin_ptr, unsigned len) +{ + pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); + pstm_read_unsigned_bin(pstm_n, bin_ptr, len); + //return bin_ptr + len; +} + /* * DER parsing routines */ @@ -1031,15 +1038,6 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) return new_der; } -// -static void binary_to_pstm(pstm_int *pstm_n, uint8_t *bin_ptr, unsigned len) -{ - pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); - pstm_read_unsigned_bin(pstm_n, bin_ptr, len); - //return bin_ptr + len; -} -// - static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) { uint8_t *bin_ptr; @@ -1047,9 +1045,6 @@ static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); binary_to_pstm(pstm_n, bin_ptr, len); - //pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); - //pstm_read_unsigned_bin(pstm_n, bin_ptr, len); - ////return bin_ptr + len; } static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) @@ -1180,18 +1175,19 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) { /* check subjectPublicKeyInfo.algorithm */ static const uint8_t OID_RSA_KEY_ALG[] = { 0x30,0x0d, // SEQ 13 bytes - 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 + 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, //OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 //0x05,0x00, // NULL }; static const uint8_t OID_ECDSA_KEY_ALG[] = { 0x30,0x13, // SEQ 0x13 bytes 0x06,0x07, 0x2a,0x86,0x48,0xce,0x3d,0x02,0x01, //OID_ECDSA_KEY_ALG 42.134.72.206.61.2.1 - 0x06,0x08, 0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07, //OID_EC_prime256v1 42.134.72.206.61.3.1.7 - //rfc3279: + //allow any curve code for now... + // 0x06,0x08, 0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07, //OID_EC_prime256v1 42.134.72.206.61.3.1.7 + //RFC 3279: //42.134.72.206.61.3 is ellipticCurve //42.134.72.206.61.3.0 is c-TwoCurve //42.134.72.206.61.3.1 is primeCurve - //42.134.72.206.61.3.1.7 is prime256v1 + //42.134.72.206.61.3.1.7 is curve_secp256r1 }; if (memcmp(der, OID_RSA_KEY_ALG, sizeof(OID_RSA_KEY_ALG)) == 0) { dbg("RSA key\n"); @@ -1210,7 +1206,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) /* skip subjectPublicKeyInfo.algorithm */ der = skip_der_item(der, end); /* enter subjectPublicKeyInfo.publicKey */ -// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ + //die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ der = enter_der_item(der, &end); dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); @@ -1233,6 +1229,11 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); } + /* else: ECDSA key. It is not used for generating encryption keys, + * it is used only to sign the EC public key (which comes in ServerKey message). + * Since we do not verify cert validity, verifying signature on EC public key + * wouldn't add any security. Thus, we do nothing here. + */ } /* @@ -1376,7 +1377,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) ptr[8] = sni_len; //name len ptr = mempcpy(&ptr[9], sni, sni_len); } - mempcpy(ptr, supported_groups, sizeof(supported_groups)); + memcpy(ptr, supported_groups, sizeof(supported_groups)); dbg(">> CLIENT_HELLO\n"); /* Can hash it only when we know which MAC hash to use */ @@ -1550,7 +1551,7 @@ static void process_server_key(tls_state_t *tls, int len) /* So far we only support curve_x25519 */ move_from_unaligned32(t32, keybuf); if (t32 != htonl(0x03001d20)) - tls_error_die(tls); + bb_error_msg_and_die("elliptic curve is not x25519"); memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32); dbg("got eccPubKey\n"); @@ -1575,6 +1576,7 @@ static void send_empty_client_cert(tls_state_t *tls) //record->cert_chain_len24_hi = 0; //record->cert_chain_len24_mid = 0; //record->cert_chain_len24_lo = 0; + // same as above: memcpy(record, empty_client_cert, sizeof(empty_client_cert)); dbg(">> CERTIFICATE\n"); -- cgit v1.2.3-55-g6feb From d5a0405a6fa2d17bf86e059dfc35efcba52f120c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Nov 2018 11:58:53 +0100 Subject: tls: code shrink function old new delta tls_get_zeroed_outbuf - 28 +28 static.empty_client_cert 7 - -7 tls_handshake 1930 1890 -40 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/1 up/down: 28/-47) Total: -19 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 20343bc0a..90a1bcf35 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -602,6 +602,13 @@ static void *tls_get_outbuf(tls_state_t *tls, int len) return tls->outbuf + OUTBUF_PFX; } +static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len) +{ + void *record = tls_get_outbuf(tls, len); + memset(record, 0, len); + return record; +} + static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) { uint8_t *buf = tls->outbuf + OUTBUF_PFX; @@ -1332,8 +1339,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) /* +2 is for "len of all extensions" 2-byte field */ len = sizeof(*record) + 2 + ext_len; - record = tls_get_outbuf(tls, len); - memset(record, 0, len); + record = tls_get_zeroed_outbuf(tls, len); fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len); record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ @@ -1565,19 +1571,15 @@ static void send_empty_client_cert(tls_state_t *tls) uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo; }; struct client_empty_cert *record; - static const uint8_t empty_client_cert[] = { - HANDSHAKE_CERTIFICATE, - 0, 0, 3, //len24 - 0, 0, 0, //cert_chain_len24 - }; - record = tls_get_outbuf(tls, sizeof(*record)); + record = tls_get_zeroed_outbuf(tls, sizeof(*record)); //fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); //record->cert_chain_len24_hi = 0; //record->cert_chain_len24_mid = 0; //record->cert_chain_len24_lo = 0; // same as above: - memcpy(record, empty_client_cert, sizeof(empty_client_cert)); + record->type = HANDSHAKE_CERTIFICATE; + record->len24_lo = 3; dbg(">> CERTIFICATE\n"); xwrite_and_update_handshake_hash(tls, sizeof(*record)); @@ -1591,7 +1593,7 @@ static void send_client_key_exchange(tls_state_t *tls) uint8_t key[2 + 4 * 1024]; // size?? }; //FIXME: better size estimate - struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record)); + struct client_key_exchange *record = tls_get_zeroed_outbuf(tls, sizeof(*record)); uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; uint8_t x25519_premaster[CURVE25519_KEYSIZE]; uint8_t *premaster; @@ -1646,7 +1648,7 @@ static void send_client_key_exchange(tls_state_t *tls) } record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; - record->len24_hi = 0; + /* record->len24_hi = 0; - already is */ record->len24_mid = len >> 8; record->len24_lo = len & 0xff; len += 4; -- cgit v1.2.3-55-g6feb From dbe95682b4bf1192d2860646617f157e6c44f2d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 13 Nov 2018 12:00:19 +0100 Subject: wget: print "TLS certificate validation not implemented" only once on redirects function old new delta spawn_ssl_client 209 219 +10 Signed-off-by: Denys Vlasenko --- networking/wget.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/networking/wget.c b/networking/wget.c index 33c93bad3..a9a0f5f8c 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -716,8 +716,10 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) int pid; char *servername, *p; - if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) + if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { bb_error_msg("note: TLS certificate validation not implemented"); + option_mask32 |= WGET_OPT_NO_CHECK_CERT; + } servername = xstrdup(host); p = strrchr(servername, ':'); -- cgit v1.2.3-55-g6feb From fe836d84554c007916adc1c2e5f5daae2f878947 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 14 Nov 2018 11:35:36 +0100 Subject: tls: code shrink function old new delta spawn_ssl_client 219 218 -1 Signed-off-by: Denys Vlasenko --- networking/wget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/wget.c b/networking/wget.c index a9a0f5f8c..65262e19d 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -717,8 +717,8 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) char *servername, *p; if (!(option_mask32 & WGET_OPT_NO_CHECK_CERT)) { - bb_error_msg("note: TLS certificate validation not implemented"); option_mask32 |= WGET_OPT_NO_CHECK_CERT; + bb_error_msg("note: TLS certificate validation not implemented"); } servername = xstrdup(host); -- cgit v1.2.3-55-g6feb From 060f0a050a13a37c642f9b1a9d70c1e9861823cf Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 9 Nov 2018 12:00:39 +0000 Subject: hush: correct description for HUSH_TICK config option The HUSH_TICK configuration option enables command substitution, not process substitution. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index 881331c5b..431010f09 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -157,7 +157,7 @@ //config: but no separate process group is formed. //config: //config:config HUSH_TICK -//config: bool "Support process substitution" +//config: bool "Support command substitution" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: help -- cgit v1.2.3-55-g6feb From e6a63bf683f47027d36dc21b62b2f5cc3eb30a30 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 12 Nov 2018 21:10:54 +0000 Subject: ash: ensure variables are fully initialised when unset When a variable is unset by calling setvar(name, NULL, 0) the code to initialise the new, empty variable fails to initialise the last character of the string. Attempts to read the contents of the unset variable will result in the uninitialised character at the end of the string being accessed. For example, running BusyBox under Valgrind and unsetting PATH: $ valgrind ./busybox_unstripped sh ==21249== Memcheck, a memory error detector ==21249== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==21249== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info ==21249== Command: ./busybox_unstripped sh ==21249== /data2/git/build_fix_8721 $ unset PATH /data2/git/build_fix_8721 $ 0 ==21249== Conditional jump or move depends on uninitialised value(s) ==21249== at 0x451371: path_advance (ash.c:2555) ==21249== by 0x456E22: find_command (ash.c:13407) ==21249== by 0x458425: evalcommand (ash.c:10139) ==21249== by 0x454CBC: evaltree (ash.c:9131) ==21249== by 0x456C80: cmdloop (ash.c:13164) Closes https://bugs.busybox.net/show_bug.cgi?id=8721 v2: On the dash mailing list Harald van Dijk was kind enough to point out a flaw in my reasoning and provide an alternative patch. Sadly his patch adds 2 bytes of bloat. Using xzalloc to zero the whole string gives a bloat of -3 bytes. function old new delta setvar 172 169 -3 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 90eaf6faf..b1f8f15d2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2420,13 +2420,12 @@ setvar(const char *name, const char *val, int flags) } INT_OFF; - nameeq = ckmalloc(namelen + vallen + 2); + nameeq = ckzalloc(namelen + vallen + 2); p = mempcpy(nameeq, name, namelen); if (val) { *p++ = '='; - p = mempcpy(p, val, vallen); + memcpy(p, val, vallen); } - *p = '\0'; vp = setvareq(nameeq, flags | VNOSAVE); INT_ON; -- cgit v1.2.3-55-g6feb From 3778898f97a64e7b42b53194af7f3b93cc9c07a3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sat, 17 Nov 2018 17:48:14 +0000 Subject: Treat custom and applet scripts as applets BusyBox has support for embedded shell scripts. Two types can be distinguished: custom scripts and scripts implementing applets. Custom scripts should be placed in the 'embed' directory at build time. They are given a default applet configuration and appear as applets to the user but no further configuration is possible. Applet scripts are integrated with the BusyBox build system and are intended to be used to ship standard applets that just happen to be implemented as scripts. They can be configured at build time and appear just like native applets. Such scripts should be placed in the 'applets_sh' directory. A stub C program should be written to provide the usual applet configuration details and placed in a suitable subsystem directory. It may be helpful to have a configuration option to enable any dependencies the script requires: see the 'nologin' applet for an example. function old new delta scripted_main - 41 +41 applet_names 2773 2781 +8 applet_main 1600 1604 +4 i2cdetect_main 672 674 +2 applet_suid 100 101 +1 applet_install_loc 200 201 +1 applet_flags 100 101 +1 packed_usage 33180 33179 -1 tryexec 159 152 -7 evalcommand 1661 1653 -8 script_names 9 - -9 packed_scripts 123 114 -9 complete_cmd_dir_file 826 811 -15 shellexec 271 254 -17 find_command 1007 990 -17 busybox_main 642 624 -18 run_applet_and_exit 100 78 -22 find_script_by_name 51 - -51 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 6/9 up/down: 58/-174) Total: -116 bytes text data bss dec hex filename 950034 477 7296 957807 e9d6f busybox_old 949918 477 7296 957691 e9cfb busybox_unstripped Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- .gitignore | 5 +++ Makefile | 4 +- applets/busybox.mkscripts | 16 +++++++ applets_sh/README | 5 --- applets_sh/dos2unix | 5 --- applets_sh/nologin | 3 ++ applets_sh/tac | 7 --- applets_sh/unix2dos | 5 --- embed/nologin | 4 -- include/applets.src.h | 21 +++++++++ include/libbb.h | 2 +- libbb/appletlib.c | 72 ++++++++++++++---------------- libbb/lineedit.c | 20 ++------- scripts/embedded_scripts | 107 ++++++++++++++++++++++++++++++++++----------- scripts/gen_build_files.sh | 21 ++++++++- shell/ash.c | 19 ++------ util-linux/nologin.c | 27 ++++++++++++ 17 files changed, 217 insertions(+), 126 deletions(-) create mode 100755 applets/busybox.mkscripts delete mode 100644 applets_sh/README delete mode 100755 applets_sh/dos2unix create mode 100755 applets_sh/nologin delete mode 100755 applets_sh/tac delete mode 100755 applets_sh/unix2dos delete mode 100755 embed/nologin create mode 100644 util-linux/nologin.c diff --git a/.gitignore b/.gitignore index c03c2e8a6..becd9bf6d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,8 @@ cscope.po.out # tags TAGS + +# +# user-supplied scripts +# +/embed diff --git a/Makefile b/Makefile index 8a0dbdf49..c19280476 100644 --- a/Makefile +++ b/Makefile @@ -361,7 +361,7 @@ scripts/basic/%: scripts_basic ; # This target generates Kbuild's and Config.in's from *.c files PHONY += gen_build_files -gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) +gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) $(wildcard embed/*) $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) # bbox: we have helpers in applets/ @@ -851,7 +851,7 @@ quiet_cmd_gen_common_bufsiz = GEN include/common_bufsiz.h quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* cmd_split_autoconf = scripts/basic/split-include include/autoconf.h include/config quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h - cmd_gen_embedded_scripts = scripts/embedded_scripts include/embedded_scripts.h embed + cmd_gen_embedded_scripts = $(srctree)/scripts/embedded_scripts include/embedded_scripts.h $(srctree)/embed $(srctree)/applets_sh #bbox# piggybacked generation of few .h files include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts $(call cmd,split_autoconf) 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 @@ +#!/bin/sh +# Make busybox scripted applet list file. + +# input $1: full path to Config.h +# input $2: full path to applets.h +# output (stdout): list of pathnames that should be linked to busybox + +export LC_ALL=POSIX +export LC_CTYPE=POSIX + +CONFIG_H=${1:-include/autoconf.h} +APPLETS_H=${2:-include/applets.h} +$HOSTCC -E -DMAKE_SCRIPTS -include $CONFIG_H $APPLETS_H | + awk '/^[ \t]*SCRIPT/{ + print $2 + }' 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 @@ -This directory contains examples of applets implemented as shell scripts. - -So far these scripts are not hooked to the build system and are not -installed by "make install". If you want to use them, -you 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 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -[ $# -ne 0 ] && DASH_I=-i -sed $DASH_I -e 's/\r$//' "$@" diff --git a/applets_sh/nologin b/applets_sh/nologin new file mode 100755 index 000000000..4ed5f6ca3 --- /dev/null +++ b/applets_sh/nologin @@ -0,0 +1,3 @@ +cat /etc/nologin.txt 2>/dev/null || echo This account is not available +sleep 5 +exit 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 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -for i in "$@" -do -sed -e '1!G;h;$!d' "$i" -done 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 @@ -#!/bin/sh -# TODO: use getopt to avoid parsing options as filenames, -# and to support -- and --help -[ $# -ne 0 ] && DASH_I=-i -sed $DASH_I -e 's/$/\r/' "$@" diff --git a/embed/nologin b/embed/nologin deleted file mode 100755 index 3768eaaa7..000000000 --- a/embed/nologin +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cat /etc/nologin.txt 2>/dev/null || echo "This account is not available" -sleep 5 -exit 1 diff --git a/include/applets.src.h b/include/applets.src.h index 2ddf120ad..a9db5d160 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -22,41 +22,60 @@ s - suid type: BB_SUID_REQUIRE or BB_SUID_MAYBE applet. */ +#define NOUSAGE_STR "\b" + +#define dummy_trivial_usage NOUSAGE_STR \ + +#define dummy_full_usage "" \ + #if defined(PROTOTYPES) # define APPLET(name,l,s) int name##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_NOEXEC(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_NOFORK(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +# define APPLET_SCRIPTED(name,main,l,s,help) #elif defined(NAME_MAIN) # define APPLET(name,l,s) name name##_main # define APPLET_ODDNAME(name,main,l,s,help) name main##_main # define APPLET_NOEXEC(name,main,l,s,help) name main##_main # define APPLET_NOFORK(name,main,l,s,help) name main##_main +# define APPLET_SCRIPTED(name,main,l,s,help) name scripted_main #elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage name##_full_usage) # define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) # define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) # define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) +# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage help##_full_usage) #elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) MAKE_USAGE(#name, name##_trivial_usage) # define APPLET_ODDNAME(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) # define APPLET_NOEXEC(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) # define APPLET_NOFORK(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) +# define APPLET_SCRIPTED(name,main,l,s,help) MAKE_USAGE(#name, help##_trivial_usage) #elif defined(MAKE_LINKS) # define APPLET(name,l,c) LINK l name # define APPLET_ODDNAME(name,main,l,s,help) LINK l name # define APPLET_NOEXEC(name,main,l,s,help) LINK l name # define APPLET_NOFORK(name,main,l,s,help) LINK l name +# define APPLET_SCRIPTED(name,main,l,s,help) LINK l name #elif defined(MAKE_SUID) # define APPLET(name,l,s) SUID s l name # define APPLET_ODDNAME(name,main,l,s,help) SUID s l name # define APPLET_NOEXEC(name,main,l,s,help) SUID s l name # define APPLET_NOFORK(name,main,l,s,help) SUID s l name +# define APPLET_SCRIPTED(name,main,l,s,help) SUID s l name + +#elif defined(MAKE_SCRIPTS) +# define APPLET(name,l,s) +# define APPLET_ODDNAME(name,main,l,s,help) +# define APPLET_NOEXEC(name,main,l,s,help) +# define APPLET_NOFORK(name,main,l,s,help) +# define APPLET_SCRIPTED(name,main,l,s,help) SCRIPT name #else static struct bb_applet applets[] = { /* name, main, location, need_suid */ @@ -64,6 +83,7 @@ s - suid type: # define APPLET_ODDNAME(name,main,l,s,help) { #name, #main, l, s }, # define APPLET_NOEXEC(name,main,l,s,help) { #name, #main, l, s, 1 }, # define APPLET_NOFORK(name,main,l,s,help) { #name, #main, l, s, 1, 1 }, +# define APPLET_SCRIPTED(name,main,l,s,help) { #name, #main, l, s }, #endif #if ENABLE_INSTALL_NO_USR @@ -84,3 +104,4 @@ INSERT #undef APPLET_ODDNAME #undef APPLET_NOEXEC #undef APPLET_NOFORK +#undef APPLET_SCRIPTED diff --git a/include/libbb.h b/include/libbb.h index a32608ebd..aa9e9d019 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1322,8 +1322,8 @@ void bb_logenv_override(void) FAST_FUNC; #endif /* Embedded script support */ -int find_script_by_name(const char *name) FAST_FUNC; char *get_script_content(unsigned n) FAST_FUNC; +int scripted_main(int argc, char** argv); /* Applets which are useful from another applets */ int bb_cat(char** argv) FAST_FUNC; diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 6dfaf1f41..a0ebaca29 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -51,7 +51,7 @@ #include "usage_compressed.h" #if ENABLE_ASH_EMBEDDED_SCRIPTS -# define DEFINE_script_names 1 +# define DEFINE_SCRIPT_DATA 1 # include "embedded_scripts.h" #else # define NUM_SCRIPTS 0 @@ -818,27 +818,21 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) /* prevent last comma to be in the very last pos */ output_width--; a = applet_names; - { -# if NUM_SCRIPTS > 0 - int i; - for (i = 0; i < 2; i++, a = script_names) -# endif - while (*a) { - int len2 = strlen(a) + 2; - if (col >= (int)output_width - len2) { - full_write2_str(",\n"); - col = 0; - } - if (col == 0) { - col = 6; - full_write2_str("\t"); - } else { - full_write2_str(", "); - } - full_write2_str(a); - col += len2; - a += len2 - 1; + while (*a) { + int len2 = strlen(a) + 2; + if (col >= (int)output_width - len2) { + full_write2_str(",\n"); + col = 0; + } + if (col == 0) { + col = 6; + full_write2_str("\t"); + } else { + full_write2_str(", "); } + full_write2_str(a); + col += len2; + a += len2 - 1; } full_write2_str("\n"); return 0; @@ -946,20 +940,25 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar # endif /* NUM_APPLETS > 0 */ # if NUM_SCRIPTS > 0 -int FAST_FUNC -find_script_by_name(const char *name) +static int find_script_by_name(const char *name) { - const char *s = script_names; - int i = 0; + int i; + int applet = find_applet_by_name(name); - while (*s) { - if (strcmp(name, s) == 0) - return i; - i++; - while (*s++ != '\0') - continue; + if (applet >= 0) { + for (i = 0; i < NUM_SCRIPTS; ++i) + if (applet_numbers[i] == applet) + return i; } - return -0x10000; /* make it so that NUM_APPLETS + is still < 0 */ + return -1; +} + +int scripted_main(int argc UNUSED_PARAM, char **argv) +{ + int script = find_script_by_name(applet_name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + return 0; } char* FAST_FUNC @@ -978,7 +977,7 @@ get_script_content(unsigned n) } # endif /* NUM_SCRIPTS > 0 */ -# if ENABLE_BUSYBOX || NUM_APPLETS > 0 || NUM_SCRIPTS > 0 +# if ENABLE_BUSYBOX || NUM_APPLETS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { # if ENABLE_BUSYBOX @@ -993,13 +992,6 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv) run_applet_no_and_exit(applet, name, argv); } # endif -# if NUM_SCRIPTS > 0 - { - int script = find_script_by_name(name); - if (script >= 0) - exit(ash_main(-script - 1, argv)); - } -# endif /*bb_error_msg_and_die("applet not found"); - links in printf */ full_write2_str(applet_name); diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 618e7c221..b1e971f88 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -41,12 +41,6 @@ #include "busybox.h" #include "NUM_APPLETS.h" #include "unicode.h" -#if ENABLE_ASH_EMBEDDED_SCRIPTS -# include "embedded_scripts.h" -#else -# define NUM_SCRIPTS 0 -#endif - #ifndef _POSIX_VDISABLE # define _POSIX_VDISABLE '\0' #endif @@ -812,20 +806,14 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) } pf_len = strlen(pfind); -# if ENABLE_FEATURE_SH_STANDALONE && (NUM_APPLETS != 1 || NUM_SCRIPTS > 0) +# if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 if (type == FIND_EXE_ONLY && !dirbuf) { - const char *p; -# if NUM_APPLETS != 1 && NUM_SCRIPTS > 0 - for (i = 0, p = applet_names; i < 2; i++, p = script_names) -# elif NUM_APPLETS != 1 /* and NUM_SCRIPTS == 0 */ - p = applet_names; -# else /* NUM_APPLETS == 1 && NUM_SCRIPTS > 0 */ - p = script_names; -# endif + const char *p = applet_names; + while (*p) { if (strncmp(pfind, p, pf_len) == 0) add_match(xstrdup(p)); - while (*p++) + while (*p++ != '\0') continue; } } diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 7245ba6e0..b7a023ce0 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -1,7 +1,8 @@ #!/bin/sh target="$1" -loc="$2" +custom_loc="$2" +applet_loc="$3" test "$target" || exit 1 test "$SED" || SED=sed @@ -14,46 +15,102 @@ if test $? != 0; then exit 1 fi -exec >"$target.$$" - -scripts="" -if [ -d "$loc" ] +custom_scripts="" +if [ -d "$custom_loc" ] then - scripts=$(cd $loc; ls * 2>/dev/null) + custom_scripts=$(cd $custom_loc; ls * 2>/dev/null) fi +all_scripts=$(applets/busybox.mkscripts) + +# all_scripts includes applet scripts and custom scripts, sort them out +applet_scripts="" +for i in $all_scripts +do + found=0 + for j in $custom_scripts + do + if [ "$i" = "$j" ] + then + found=1 + break; + fi + done + if [ $found -eq 0 ] + then + # anything that isn't a custom script is an applet script + applet_scripts="$applet_scripts $i" + fi +done -n=$(echo $scripts | wc -w) +# we know the custom scripts are present but applet scripts might have +# become detached from their configuration +for i in $applet_scripts +do + #if [ ! -f "$applet_loc/$i" -a ! -f "$custom_loc/$i" ] + if [ ! -f "$applet_loc/$i" ] + then + echo "missing applet script $i" + exit 1 + fi +done -if [ $n -ne 0 ] +n=$(echo $custom_scripts $applet_scripts | wc -w) +nall=$(echo $all_scripts | wc -w) + +if [ $n -ne $nall ] then - printf '#ifdef DEFINE_script_names\n' - printf 'const char script_names[] ALIGN1 = ' - for i in $scripts + echo "script mismatch $n != $nall" + exit 1 +fi + +concatenate_scripts() { + for i in $custom_scripts + do + cat $custom_loc/$i + printf '\000' + done + for i in $applet_scripts do - printf '"%s\\0"' $i + cat $applet_loc/$i + printf '\000' done - printf ';\n' +} + +exec >"$target.$$" + +if [ $n -ne 0 ] +then + printf '#ifdef DEFINE_SCRIPT_DATA\n' + if [ $n -ne 0 ] + then + printf 'const uint16_t applet_numbers[] = {\n' + for i in $custom_scripts $applet_scripts + do + # TODO support applets with names including invalid characters + printf '\tAPPLET_NO_%s,\n' $i + done + printf '};\n' + fi printf '#else\n' - printf 'extern const char script_names[] ALIGN1;\n' + if [ $n -ne 0 ] + then + printf 'extern const uint16_t applet_numbers[];\n' + fi printf '#endif\n' fi -printf "#define NUM_SCRIPTS $n\n\n" + +printf "\n" +printf '#define NUM_SCRIPTS %d\n' $n +printf "\n" if [ $n -ne 0 ] then printf '#define UNPACKED_SCRIPTS_LENGTH ' - for i in $scripts - do - cat $loc/$i - printf '\000' - done | wc -c + concatenate_scripts | wc -c printf '#define PACKED_SCRIPTS \\\n' - for i in $scripts - do - cat $loc/$i - printf '\000' - done | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | od -v -b \ + concatenate_scripts | bzip2 -1 | $DD bs=2 skip=1 2>/dev/null | \ + od -v -b \ | grep -v '^ ' \ | $SED -e 's/^[^ ]*//' \ -e 's/ //g' \ diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index f79fa2f83..64e4bffa9 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -17,12 +17,26 @@ status() { printf ' %-8s%s\n' "$1" "$2"; } gen() { status "GEN" "$@"; } chk() { status "CHK" "$@"; } +# scripts in the 'embed' directory are treated as fake applets +custom_scripts() +{ + custom_loc="$1" + if [ -d "$custom_loc" ] + then + for i in $(cd "$custom_loc"; ls *) + do + printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, dummy)\n" $i; + done + fi +} + generate() { # NB: data to be inserted at INSERT line is coming on stdin src="$1" dst="$2" header="$3" + loc="$4" #chk "${dst}" { # Need to use printf: different shells have inconsistent @@ -32,6 +46,10 @@ generate() sed -n '/^INSERT$/ q; p' "${src}" # copy stdin to stdout cat + if [ -n "$loc" ] + then + custom_scripts "$loc" + fi # print everything after INSERT line sed -n '/^INSERT$/ { :l @@ -53,7 +71,8 @@ sed -n 's@^//applet:@@p' "$srctree"/*/*.c "$srctree"/*/*/*.c \ | generate \ "$srctree/include/applets.src.h" \ "include/applets.h" \ - "/* DO NOT EDIT. This file is generated from applets.src.h */" + "/* DO NOT EDIT. This file is generated from applets.src.h */" \ + "$srctree/embed" # (Re)generate include/usage.h # We add line continuation backslash after each line, diff --git a/shell/ash.c b/shell/ash.c index b1f8f15d2..44b3569dc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -158,6 +158,10 @@ //config: at build time. Like applets, scripts can be run as //config: 'busybox SCRIPT ...' or by linking their name to the binary. //config: +//config: This also allows applets to be implemented as scripts: place +//config: the script in 'applets_sh' and a stub C file containing +//config: configuration in the appropriate subsystem directory. +//config: //config:endif # ash options //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) @@ -8016,9 +8020,6 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, c { #if ENABLE_FEATURE_SH_STANDALONE if (applet_no >= 0) { -# if NUM_SCRIPTS > 0 - if (applet_no < NUM_APPLETS) -# endif if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); while (*envp) @@ -8088,9 +8089,6 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) if (strchr(prog, '/') != NULL #if ENABLE_FEATURE_SH_STANDALONE || (applet_no = find_applet_by_name(prog)) >= 0 -# if NUM_SCRIPTS > 0 - || (applet_no = NUM_APPLETS + find_script_by_name(prog)) >= 0 -# endif #endif ) { tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp); @@ -10192,10 +10190,6 @@ evalcommand(union node *cmd, int flags) */ /* find_command() encodes applet_no as (-2 - applet_no) */ int applet_no = (- cmdentry.u.index - 2); -# if NUM_SCRIPTS > 0 - /* Applets are ok, but not embedded scripts */ - if (applet_no < NUM_APPLETS) -# endif if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { char **sv_environ; @@ -13378,11 +13372,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #if ENABLE_FEATURE_SH_STANDALONE { int applet_no = find_applet_by_name(name); -# if NUM_SCRIPTS > 0 - if (applet_no < 0) - /* embedded script indices are offset by NUM_APPLETS */ - applet_no = NUM_APPLETS + find_script_by_name(name); -# endif if (applet_no >= 0) { entry->cmdtype = CMDNORMAL; entry->u.index = -2 - applet_no; diff --git a/util-linux/nologin.c b/util-linux/nologin.c new file mode 100644 index 000000000..cc619bf8a --- /dev/null +++ b/util-linux/nologin.c @@ -0,0 +1,27 @@ +//config:config NOLOGIN +//config: bool "nologin" +//config: default y +//config: depends on ASH_EMBEDDED_SCRIPTS +//config: help +//config: Politely refuse a login +//config: +//config:config NOLOGIN_DEPENDENCIES +//config: bool "Dependencies for nologin" +//config: default y +//config: depends on NOLOGIN +//config: select CAT +//config: select ECHO +//config: select SLEEP +//config: help +//config: nologin is implemented as a shell script. It requires the +//config: following in the runtime environment: +//config: cat echo sleep +//config: If you know these will be available externally you can +//config: disable this option. + +//applet:IF_NOLOGIN(APPLET_SCRIPTED(nologin, scripted, BB_DIR_USR_SBIN, BB_SUID_DROP, nologin)) + +//usage:#define nologin_trivial_usage +//usage: "" +//usage:#define nologin_full_usage "\n\n" +//usage: "Politely refuse a login" -- cgit v1.2.3-55-g6feb From d1b2ae2d04eae05d76ad3c1a07e9092c7d46c773 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 18 Nov 2018 19:12:26 +0100 Subject: busybox: add '--show SCRIPT' option to display scripts Add an option to allow the content of embedded scripts to be displayed. This includes applet scripts, custom scripts and the .profile script. function old new delta busybox_main 624 701 +77 find_script_by_name - 24 +24 scripted_main 41 35 -6 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 101/-6) Total: 95 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- Config.in | 5 +++ libbb/appletlib.c | 92 ++++++++++++++++++++++++++++++++----------------------- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/Config.in b/Config.in index ae21f52ef..01680af1f 100644 --- a/Config.in +++ b/Config.in @@ -178,6 +178,11 @@ config BUSYBOX Running "busybox APPLET [ARGS...]" will still work, of course. +config FEATURE_SHOW_SCRIPT + bool "Support --show SCRIPT" + default y + depends on BUSYBOX + config FEATURE_INSTALLER bool "Support --install [-s] to install applet links at runtime" default y diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a0ebaca29..a79a37efb 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -756,6 +756,44 @@ static void install_links(const char *busybox UNUSED_PARAM, static void run_applet_and_exit(const char *name, char **argv) NORETURN; +# if NUM_SCRIPTS > 0 +static int find_script_by_name(const char *name) +{ + int i; + int applet = find_applet_by_name(name); + + if (applet >= 0) { + for (i = 0; i < NUM_SCRIPTS; ++i) + if (applet_numbers[i] == applet) + return i; + } + return -1; +} + +int scripted_main(int argc UNUSED_PARAM, char **argv) +{ + int script = find_script_by_name(applet_name); + if (script >= 0) + exit(ash_main(-script - 1, argv)); + return 0; +} + +char* FAST_FUNC +get_script_content(unsigned n) +{ + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), + UNPACKED_SCRIPTS_LENGTH); + if (t) { + while (n != 0) { + while (*t++ != '\0') + continue; + n--; + } + } + return t; +} +# endif /* NUM_SCRIPTS > 0 */ + # if ENABLE_BUSYBOX # if ENABLE_FEATURE_SH_STANDALONE && ENABLE_FEATURE_TAB_COMPLETION /* @@ -793,6 +831,9 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) "\n" "Usage: busybox [function [arguments]...]\n" " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" +# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 + " or: busybox --show SCRIPT\n" +# endif IF_FEATURE_INSTALLER( " or: busybox --install [-s] [DIR]\n" ) @@ -838,6 +879,19 @@ int busybox_main(int argc UNUSED_PARAM, char **argv) return 0; } +# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 + if (strcmp(argv[1], "--show") == 0) { + int n; + if (!argv[2]) + bb_error_msg_and_die(bb_msg_requires_arg, "--show"); + n = find_script_by_name(argv[2]); + if (n < 0) + bb_error_msg_and_die("script '%s' not found", argv[2]); + full_write1_str(get_script_content(n)); + return 0; + } +# endif + if (is_prefixed_with(argv[1], "--list")) { unsigned i = 0; const char *a = applet_names; @@ -939,44 +993,6 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar } # endif /* NUM_APPLETS > 0 */ -# if NUM_SCRIPTS > 0 -static int find_script_by_name(const char *name) -{ - int i; - int applet = find_applet_by_name(name); - - if (applet >= 0) { - for (i = 0; i < NUM_SCRIPTS; ++i) - if (applet_numbers[i] == applet) - return i; - } - return -1; -} - -int scripted_main(int argc UNUSED_PARAM, char **argv) -{ - int script = find_script_by_name(applet_name); - if (script >= 0) - exit(ash_main(-script - 1, argv)); - return 0; -} - -char* FAST_FUNC -get_script_content(unsigned n) -{ - char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), - UNPACKED_SCRIPTS_LENGTH); - if (t) { - while (n != 0) { - while (*t++ != '\0') - continue; - n--; - } - } - return t; -} -# endif /* NUM_SCRIPTS > 0 */ - # if ENABLE_BUSYBOX || NUM_APPLETS > 0 static NORETURN void run_applet_and_exit(const char *name, char **argv) { -- cgit v1.2.3-55-g6feb From af694a4b290e9c664919c8c7bcc98a89dd2fbb7d Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 18 Nov 2018 07:40:40 +0000 Subject: Ensure build works when KBUILD_OUTPUT is set, closes 11511 The build process for embedded scripts didn't have consistent support for saving output to a different directory. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- scripts/embedded_scripts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c19280476..4b5a01df9 100644 --- a/Makefile +++ b/Makefile @@ -361,7 +361,7 @@ scripts/basic/%: scripts_basic ; # This target generates Kbuild's and Config.in's from *.c files PHONY += gen_build_files -gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) $(wildcard embed/*) +gen_build_files: $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) $(wildcard $(srctree)/embed/*) $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) # bbox: we have helpers in applets/ @@ -853,7 +853,7 @@ quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h cmd_gen_embedded_scripts = $(srctree)/scripts/embedded_scripts include/embedded_scripts.h $(srctree)/embed $(srctree)/applets_sh #bbox# piggybacked generation of few .h files -include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard embed/*) scripts/embedded_scripts +include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard $(srctree)/embed/*) $(srctree)/scripts/embedded_scripts $(call cmd,split_autoconf) $(call cmd,gen_bbconfigopts) $(call cmd,gen_common_bufsiz) diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index b7a023ce0..c2e7c6961 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -20,7 +20,7 @@ if [ -d "$custom_loc" ] then custom_scripts=$(cd $custom_loc; ls * 2>/dev/null) fi -all_scripts=$(applets/busybox.mkscripts) +all_scripts=$($srctree/applets/busybox.mkscripts) # all_scripts includes applet scripts and custom scripts, sort them out applet_scripts="" -- cgit v1.2.3-55-g6feb From 4e46b98a4574aee0a77055741d460016faa11b75 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 18 Nov 2018 19:50:24 +0100 Subject: tls: add comment, no code changes Signed-off-by: Denys Vlasenko --- networking/tls.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 90a1bcf35..fba66f6f0 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1527,11 +1527,11 @@ static void process_server_key(tls_state_t *tls, int len) xhdr = (void*)tls->inbuf; keybuf = (void*)(xhdr + 1); //seen from is.gd: it selects curve_x25519: -// 0c 00006e //SERVER_KEY_EXCHANGE +// 0c 00006e //SERVER_KEY_EXCHANGE, len // 03 //curve_type: named curve // 001d //curve_x25519 //server-chosen EC point, and then signed_params -// (rfc8422: "A hash of the params, with the signature +// (RFC 8422: "A hash of the params, with the signature // appropriate to that hash applied. The private key corresponding // to the certified public key in the server's Certificate message is // used for signing.") @@ -1547,6 +1547,18 @@ static void process_server_key(tls_state_t *tls, int len) // 02 20 //INTEGER, len // 64523d6216cb94c43c9b20e377d8c52c55be6703fd6730a155930c705eaf3af6 //32bytes //same about this item ^^^^^ + +//seen from www.openbsd.org +//(which only accepts ECDHE-RSA-AESnnn-GCM-SHAnnn and ECDHE-RSA-CHACHA20-POLY1305 ciphers): +// 0c 000228 //SERVER_KEY_EXCHANGE, len +// 03 //curve_type: named curve +// 001d //curve_x25519 +// 20 //eccPubKeyLen +// eef7a15c43b71a4c7eaa48a39369399cc4332e569ec90a83274cc92596705c1a //eccPubKey +// 0401 //hashSigAlg: 4:SHA256, 1:RSA +// 0200 //len +// //0x200 bytes follow + /* Get and verify length */ len1 = get24be(keybuf + 1); if (len1 > len - 4) tls_error_die(tls); -- cgit v1.2.3-55-g6feb From 32511da87ddaea0824801eafebd27e11409bf444 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Nov 2018 20:36:16 +0100 Subject: scripts/trylink: be more clever when deciding that "lib elimination" has finished: Before: Trying libraries: crypt m resolv Library crypt is not needed, excluding it Library m is needed, can't exclude it (yet) Library resolv is needed, can't exclude it (yet) Library m is needed, can't exclude it (yet) Library resolv is needed, can't exclude it (yet) Final link with: m resolv After: Trying libraries: crypt m resolv Library crypt is not needed, excluding it Library m is needed, can't exclude it (yet) Library resolv is needed, can't exclude it (yet) Final link with: m resolv Signed-off-by: Denys Vlasenko --- scripts/trylink | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) 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 \ # Stop when no lib can be removed. while test "$LDLIBS"; do $debug && echo "Trying libraries: $LDLIBS" - all_needed=true - last_needed=false + dropped_non_first_lib=false + first_lib=true for one in $LDLIBS; do without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs` # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" @@ -167,20 +167,17 @@ while test "$LDLIBS"; do if test $? = 0; then echo " Library $one is not needed, excluding it" LDLIBS="$without_one" - all_needed=false - last_needed=false + $first_lib || dropped_non_first_lib=true else echo " Library $one is needed, can't exclude it (yet)" - last_needed=true + first_lib=false fi done - # All libs were needed, can't remove any - $all_needed && break - # Optimization: was the last tried lib needed? - if $last_needed; then - # Was it the only one lib left? Don't test again then. - { echo "$LDLIBS" | grep -q ' '; } || break - fi + # We can stop trying to drop libs if either all libs were needed, + # or we excluded only the _first_ few. + # (else: we dropped some intermediate lib(s), maybe now we can succeed + # in dropping some of the preceding ones) + $dropped_non_first_lib || break done # Make the binary with final, minimal list of libs -- cgit v1.2.3-55-g6feb From 03ad7ae08189ed88dd7e0fcb6c6001fbf3b12efb Mon Sep 17 00:00:00 2001 From: Christoph Schulz Date: Tue, 20 Nov 2018 17:45:52 +0100 Subject: ash: reset tokpushback before prompting while parsing heredoc The parser reads from an already freed memory location, thereby causing unpredictable results, in the following situation: - ENABLE_ASH_EXPAND_PRMT is enabled - heredoc is being parsed - command substitution is used within heredoc Examples where this bug crops up are (PS2 is set to "> "): $ cat < `echo abc` > EOF -sh: O: not found $ cat < $(echo abc) > EOF -sh: {garbage}: not found The presumable reason is that setprompt_if() causes a nested expansion when ENABLE_ASH_EXPAND_PRMT is enabled, therefore leaving "wordtext" in an unusable state. However, when parseheredoc() is called, "tokpushback" is non-zero, which causes the next call to xxreadtoken() to return TWORD, causing the caller to use the invalid "wordtoken" instead of reading the next valid token. The call chain is: list() -> peektoken() [sets tokpushback to 1] -> parseheredoc() -> setprompt_if() -> pushstackmark() -> expandstr() -> readtoken1() [sets lasttoken to TWORD, wordtoken points to expanded prompt] -> popstackmark() [invalidates wordtoken, leaves lasttoken as is] -> readtoken1() -> ...parsebackq -> list() -> andor() -> pipeline() -> readtoken() -> xxreadtoken() [tokpushback non-zero, reuse lasttoken and wordtext] Note that in almost all other contexts, each call to setprompt_if() is preceded by setting "tokpushback" to zero. One exception is "oldstyle" backquote parsing in readtoken1(), but there "tokpushback" is reset afterwards. The other exception is nlprompt(), but this function is only used within readtoken1() (but in contexts where no nested calls to xxreadtoken() occur) and xxreadtoken() (where "tokpushback" is guaranteed to be zero). function old new delta parseheredoc 124 131 +7 Signed-off-by: Christoph Schulz Signed-off-by: Denys Vlasenko --- shell/ash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/ash.c b/shell/ash.c index 44b3569dc..04e4006c8 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12961,6 +12961,7 @@ parseheredoc(void) heredoclist = NULL; while (here) { + tokpushback = 0; setprompt_if(needprompt, 2); readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX, here->eofmark, here->striptabs); -- cgit v1.2.3-55-g6feb From 83e5c627e1b2c7f34d694696d0c3d5a3ce25dc59 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 17:21:38 +0100 Subject: tls: add support for TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher function old new delta xwrite_encrypted 209 605 +396 GHASH - 395 +395 aes_encrypt_1 - 382 +382 GMULT - 192 +192 tls_xread_record 489 659 +170 aes_encrypt_one_block - 65 +65 aesgcm_setkey - 58 +58 FlattenSzInBits - 52 +52 tls_handshake 1890 1941 +51 xwrite_and_update_handshake_hash 46 81 +35 xorbuf - 24 +24 aes_setkey - 16 +16 psRsaEncryptPub 413 421 +8 stty_main 1221 1227 +6 ssl_client_main 138 143 +5 next_token 841 845 +4 spawn_ssl_client 218 219 +1 volume_id_probe_hfs_hfsplus 564 563 -1 read_package_field 232 230 -2 i2cdetect_main 674 672 -2 fail_hunk 139 136 -3 parse_expr 891 883 -8 curve25519 802 793 -9 aes_cbc_decrypt 971 958 -13 xwrite_handshake_record 43 - -43 aes_cbc_encrypt 644 172 -472 ------------------------------------------------------------------------------ (add/remove: 9/1 grow/shrink: 9/8 up/down: 1860/-553) Total: 1307 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 17 +++ networking/tls.c | 360 +++++++++++++++++++++++++++++++++++++----------- networking/tls.h | 3 + networking/tls_aes.c | 15 +- networking/tls_aes.h | 8 +- networking/tls_aesgcm.c | 148 ++++++++++++++++++++ networking/tls_aesgcm.h | 15 ++ networking/tls_fe.c | 2 +- networking/tls_fe.h | 2 +- networking/tls_rsa.c | 2 +- networking/tls_rsa.h | 2 +- 11 files changed, 480 insertions(+), 94 deletions(-) create mode 100644 networking/tls_aesgcm.c create mode 100644 networking/tls_aesgcm.h diff --git a/include/libbb.h b/include/libbb.h index aa9e9d019..b041ce047 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -736,10 +736,17 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC; // + inet_common.c has additional IPv4-only stuff +struct tls_aes { + uint32_t key[60]; + unsigned rounds; +}; #define TLS_MAX_MAC_SIZE 32 #define TLS_MAX_KEY_SIZE 32 +#define TLS_MAX_IV_SIZE 4 struct tls_handshake_data; /* opaque */ typedef struct tls_state { + unsigned flags; + int ofd; int ifd; @@ -748,6 +755,7 @@ typedef struct tls_state { uint8_t encrypt_on_write; unsigned MAC_size; unsigned key_size; + unsigned IV_size; uint8_t *outbuf; int outbuf_size; @@ -769,12 +777,21 @@ typedef struct tls_state { /*uint64_t read_seq64_be;*/ uint64_t write_seq64_be; + /*uint8_t *server_write_MAC_key;*/ uint8_t *client_write_key; uint8_t *server_write_key; + uint8_t *client_write_IV; + uint8_t *server_write_IV; uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE]; uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE]; uint8_t client_write_k__[TLS_MAX_KEY_SIZE]; uint8_t server_write_k__[TLS_MAX_KEY_SIZE]; + uint8_t client_write_I_[TLS_MAX_IV_SIZE]; + uint8_t server_write_I_[TLS_MAX_IV_SIZE]; + + struct tls_aes aes_encrypt; + struct tls_aes aes_decrypt; + uint8_t H[16]; //used by AES_GCM } tls_state_t; static inline tls_state_t *new_tls_state(void) diff --git a/networking/tls.c b/networking/tls.c index fba66f6f0..38a965ad6 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -13,16 +13,17 @@ //kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o //kbuild:lib-$(CONFIG_TLS) += tls_aes.o +//kbuild:lib-$(CONFIG_TLS) += tls_aesgcm.o //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o //kbuild:lib-$(CONFIG_TLS) += tls_fe.o -////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o #include "tls.h" -//Tested against kernel.org: //TLS 1.2 #define TLS_MAJ 3 #define TLS_MIN 3 + +//Tested against kernel.org: //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE @@ -36,7 +37,7 @@ //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE -//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? +//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE // works against "openssl s_server -cipher NULL" // and against wolfssl-3.9.10-stable/examples/server/server.c: @@ -60,6 +61,11 @@ // bug #11456: host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) #define CIPHER_ID3 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +// ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 +#define CIPHER_ID4 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + +#define NUM_CIPHERS 4 + #define TLS_DEBUG 0 #define TLS_DEBUG_HASH 0 @@ -207,7 +213,6 @@ enum { SHA1_OUTSIZE = 20, SHA256_OUTSIZE = 32, - AES_BLOCKSIZE = 16, AES128_KEYSIZE = 16, AES256_KEYSIZE = 32, @@ -216,7 +221,7 @@ enum { RECHDR_LEN = 5, /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */ - OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ + OUTBUF_PFX = 8 + AES_BLOCK_SIZE, /* header + IV */ OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */ // RFC 5246 @@ -263,8 +268,11 @@ struct record_hdr { }; enum { - KEY_ALG_RSA, - KEY_ALG_ECDSA, + NEED_EC_KEY = 1 << 0, + GOT_CERT_RSA_KEY_ALG = 1 << 1, + GOT_CERT_ECDSA_KEY_ALG = 1 << 2, + GOT_EC_KEY = 1 << 3, + ENCRYPTION_AESGCM = 1 << 4, }; struct tls_handshake_data { /* In bbox, md5/sha1/sha256 ctx's are the same structure */ @@ -273,14 +281,14 @@ struct tls_handshake_data { uint8_t client_and_server_rand32[2 * 32]; uint8_t master_secret[48]; - smallint key_alg; //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; uint8_t ecc_pub_key32[32]; - unsigned saved_client_hello_size; - uint8_t saved_client_hello[1]; +/* HANDSHAKE HASH: */ + //unsigned saved_client_hello_size; + //uint8_t saved_client_hello[1]; }; @@ -609,7 +617,7 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len) return record; } -static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) +static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) { uint8_t *buf = tls->outbuf + OUTBUF_PFX; struct record_hdr *xhdr; @@ -619,7 +627,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) if (CIPHER_ID1 != TLS_RSA_WITH_NULL_SHA256 /* if "no encryption" can't be selected */ || tls->cipher_id != TLS_RSA_WITH_NULL_SHA256 /* or if it wasn't selected */ ) { - xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */ + xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCK_SIZE); /* place for IV */ } xhdr->type = type; @@ -722,7 +730,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 - tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ + tls_get_random(buf - AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* IV */ dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size - tls->MAC_size, tls->MAC_size); @@ -742,23 +750,24 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // If you need no bytes to reach BLOCKSIZE, you have to pad a full // BLOCKSIZE with bytes of value (BLOCKSIZE-1). // It's ok to have more than minimum padding, but we do minimum. - padding_length = (~size) & (AES_BLOCKSIZE - 1); + padding_length = (~size) & (AES_BLOCK_SIZE - 1); do { buf[size++] = padding_length; /* padding */ - } while ((size & (AES_BLOCKSIZE - 1)) != 0); + } while ((size & (AES_BLOCK_SIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ +//optimize key setup aes_cbc_encrypt( tls->client_write_key, tls->key_size, /* selects 128/256 */ - buf - AES_BLOCKSIZE, /* IV */ + buf - AES_BLOCK_SIZE, /* IV */ buf, size, /* plaintext */ buf /* ciphertext */ ); /* Write out */ dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", - AES_BLOCKSIZE, size, padding_length); - size += AES_BLOCKSIZE; /* + IV */ + AES_BLOCK_SIZE, size, padding_length); + size += AES_BLOCK_SIZE; /* + IV */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); @@ -766,23 +775,109 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } +/* Example how GCM encryption combines nonce, aad, input and generates + * "header | exp_nonce | encrypted output | tag": + * nonce:0d 6a 26 31 00 00 00 00 00 00 00 01 (implicit 4 bytes (derived from master secret), then explicit 8 bytes) + * aad: 00 00 00 00 00 00 00 01 17 03 03 00 1c + * 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) + * 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 + * tag: c2 86 ce 4a 50 4a d0 aa 50 b3 76 5c 49 2a 3f 33 + * 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 + * .............................................^^ buf points here + */ +static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned type) +{ +//go for [16] + uint8_t aad[13]; + uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE]; //[16] + uint8_t authtag[AES_BLOCK_SIZE]; //[16] + uint8_t *buf; + struct record_hdr *xhdr; + unsigned remaining; + unsigned cnt; + + buf = tls->outbuf + OUTBUF_PFX; /* see above for the byte it points to */ + dump_hex("xwrite_encrypted_aesgcm plaintext:%s\n", buf, size); + + xhdr = (void*)(buf - 8 - RECHDR_LEN); + xhdr->type = type; /* do it here so that "type" param no longer used */ + + aad[8] = type; + aad[9] = TLS_MAJ; + aad[10] = TLS_MIN; + aad[11] = size >> 8; + aad[12] = size & 0xff; + + memcpy(nonce, tls->client_write_IV, 4); + memcpy(nonce + 4, &tls->write_seq64_be, 8); + memcpy(aad, &tls->write_seq64_be, 8); + memcpy(buf - 8, &tls->write_seq64_be, 8); +//optimize + /* seq64 is not used later in this func, can increment here */ + tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + +#define COUNTER(v) (*(uint32_t*)(v + 12)) + + cnt = 1; + remaining = size; + while (remaining != 0) { + unsigned n; + + cnt++; + COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ + aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); + n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; + xorbuf(buf, scratch, n); + buf += n; + remaining -= n; + } + +//optimize fixed sizes + aesgcm_GHASH(tls->H, aad, sizeof(aad), tls->outbuf + OUTBUF_PFX, size, authtag, sizeof(authtag)); + COUNTER(nonce) = htonl(1); + aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); + xorbuf(authtag, scratch, sizeof(authtag)); + + memcpy(buf, authtag, sizeof(authtag)); +#undef COUNTER + + /* Write out */ + xhdr = (void*)(tls->outbuf + OUTBUF_PFX - 8 - RECHDR_LEN); + size += 8 + sizeof(authtag); + /*xhdr->type = type; - already is */ + xhdr->proto_maj = TLS_MAJ; + xhdr->proto_min = TLS_MIN; + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + size += RECHDR_LEN; + dump_raw_out(">> %s\n", xhdr, size); + xwrite(tls->ofd, xhdr, size); + dbg("wrote %u bytes\n", size); +} + +static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) +{ + if (!(tls->flags & ENCRYPTION_AESGCM)) { + xwrite_encrypted_and_hmac_signed(tls, size, type); + return; + } + xwrite_encrypted_aesgcm(tls, size, type); +} + static void xwrite_handshake_record(tls_state_t *tls, unsigned size) { - //if (!tls->encrypt_on_write) { - uint8_t *buf = tls->outbuf + OUTBUF_PFX; - struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN); + uint8_t *buf = tls->outbuf + OUTBUF_PFX; + struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN); - xhdr->type = RECORD_TYPE_HANDSHAKE; - xhdr->proto_maj = TLS_MAJ; - xhdr->proto_min = TLS_MIN; - xhdr->len16_hi = size >> 8; - xhdr->len16_lo = size & 0xff; - dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->ofd, xhdr, RECHDR_LEN + size); - dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); - // return; - //} - //xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); + xhdr->type = RECORD_TYPE_HANDSHAKE; + xhdr->proto_maj = TLS_MAJ; + xhdr->proto_min = TLS_MIN; + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); + dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) @@ -826,6 +921,52 @@ static const char *alert_text(int code) return itoa(code); } +static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) +{ +//go for [16] + //uint8_t aad[13]; + uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE]; //[16] + //uint8_t authtag[AES_BLOCK_SIZE]; //[16] + unsigned remaining; + unsigned cnt; + + //aad[8] = type; + //aad[9] = TLS_MAJ; + //aad[10] = TLS_MIN; + //aad[11] = size >> 8; + //aad[12] = size & 0xff; + + memcpy(nonce, tls->server_write_IV, 4); + memcpy(nonce + 4, buf, 8); + buf += 8; + +#define COUNTER(v) (*(uint32_t*)(v + 12)) + + cnt = 1; + remaining = size; + while (remaining != 0) { + unsigned n; + + cnt++; + COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ + aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); + n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; + xorbuf(buf, scratch, n); + buf += n; + remaining -= n; + } + +////optimize fixed sizes + //aesgcm_GHASH(tls->H, aad, sizeof(aad), tls->outbuf + OUTBUF_PFX, size, authtag, sizeof(authtag)); + //COUNTER(nonce) = htonl(1); + //aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); + //xorbuf(authtag, scratch, sizeof(authtag)); + + //memcmp(buf, authtag, sizeof(authtag)) || DIE("HASH DOES NOT MATCH!"); +#undef COUNTER +} + static int tls_xread_record(tls_state_t *tls, const char *expected) { struct record_hdr *xhdr; @@ -896,34 +1037,44 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) sz = target - RECHDR_LEN; /* Needs to be decrypted? */ - if (tls->min_encrypted_len_on_read > tls->MAC_size) { - uint8_t *p = tls->inbuf + RECHDR_LEN; - int padding_len; - - if (sz & (AES_BLOCKSIZE-1) - || sz < (int)tls->min_encrypted_len_on_read - ) { - bb_error_msg_and_die("bad encrypted len:%u < %u", - sz, tls->min_encrypted_len_on_read); + if (tls->min_encrypted_len_on_read != 0) { + if (sz < (int)tls->min_encrypted_len_on_read) + bb_error_msg_and_die("bad encrypted len:%u", sz); + + if (tls->flags & ENCRYPTION_AESGCM) { + /* AESGCM */ + uint8_t *p = tls->inbuf + RECHDR_LEN; + + sz -= 8 + AES_BLOCK_SIZE; /* we will overwrite nonce, drop hash */ + tls_aesgcm_decrypt(tls, p, sz); + memmove(p, p + 8, sz); + dbg("encrypted size:%u\n", sz); + } else + if (tls->min_encrypted_len_on_read > tls->MAC_size) { + /* AES+SHA */ + uint8_t *p = tls->inbuf + RECHDR_LEN; + int padding_len; + + if (sz & (AES_BLOCK_SIZE-1)) + bb_error_msg_and_die("bad encrypted len:%u", sz); + + /* Decrypt content+MAC+padding, moving it over IV in the process */ + sz -= AES_BLOCK_SIZE; /* we will overwrite IV now */ + aes_cbc_decrypt( + tls->server_write_key, tls->key_size, /* selects 128/256 */ + p, /* IV */ + p + AES_BLOCK_SIZE, sz, /* ciphertext */ + p /* plaintext */ + ); + padding_len = p[sz - 1]; + dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); + padding_len++; + sz -= tls->MAC_size + padding_len; /* drop MAC and padding */ + } else { + /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ + /* else: no encryption yet on input, subtract zero = NOP */ + sz -= tls->min_encrypted_len_on_read; } - /* Decrypt content+MAC+padding, moving it over IV in the process */ - sz -= AES_BLOCKSIZE; /* we will overwrite IV now */ - aes_cbc_decrypt( - tls->server_write_key, tls->key_size, /* selects 128/256 */ - p, /* IV */ - p + AES_BLOCKSIZE, sz, /* ciphertext */ - p /* plaintext */ - ); - padding_len = p[sz - 1]; - dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); - padding_len++; - sz -= tls->MAC_size + padding_len; /* drop MAC and padding */ - //if (sz < 0) - // bb_error_msg_and_die("bad padding size:%u", padding_len); - } else { - /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ - /* else: no encryption yet on input, subtract zero = NOP */ - sz -= tls->min_encrypted_len_on_read; } if (sz < 0) bb_error_msg_and_die("encrypted data too short"); @@ -964,7 +1115,8 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE - && tls->MAC_size != 0 /* do we know which hash to use? (server_hello() does not!) */ +/* HANDSHAKE HASH: */ + // && do_we_know_which_hash_to_use /* server_hello() might not know it in the future! */ ) { hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz); } @@ -1198,16 +1350,16 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) }; if (memcmp(der, OID_RSA_KEY_ALG, sizeof(OID_RSA_KEY_ALG)) == 0) { dbg("RSA key\n"); - tls->hsd->key_alg = KEY_ALG_RSA; + tls->flags |= GOT_CERT_RSA_KEY_ALG; } else if (memcmp(der, OID_ECDSA_KEY_ALG, sizeof(OID_ECDSA_KEY_ALG)) == 0) { dbg("ECDSA key\n"); - tls->hsd->key_alg = KEY_ALG_ECDSA; + tls->flags |= GOT_CERT_ECDSA_KEY_ALG; } else - bb_error_msg_and_die("not RSA or ECDSA key"); + bb_error_msg_and_die("not RSA or ECDSA cert"); } - if (tls->hsd->key_alg == KEY_ALG_RSA) { + if (tls->flags & GOT_CERT_RSA_KEY_ALG) { /* parse RSA key: */ //based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note /* skip subjectPublicKeyInfo.algorithm */ @@ -1301,7 +1453,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * (2 + !!CIPHER_ID2 + !!CIPHER_ID3)]; /* actually variable */ + uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): @@ -1364,6 +1516,10 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) if ((CIPHER_ID3 >> 8) != 0) record->cipherid[6] = CIPHER_ID3 >> 8; /*************************/ record->cipherid[7] = CIPHER_ID3 & 0xff; #endif +#if CIPHER_ID4 + if ((CIPHER_ID4 >> 8) != 0) record->cipherid[6] = CIPHER_ID4 >> 8; + /*************************/ record->cipherid[7] = CIPHER_ID4 & 0xff; +#endif record->comprtypes_len = 1; /* record->comprtypes[0] = 0; */ @@ -1385,15 +1541,23 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) } memcpy(ptr, supported_groups, sizeof(supported_groups)); - dbg(">> CLIENT_HELLO\n"); - /* Can hash it only when we know which MAC hash to use */ - /*xwrite_and_update_handshake_hash(tls, len); - WRONG! */ - xwrite_handshake_record(tls, len); - - tls->hsd = xzalloc(sizeof(*tls->hsd) + len); + tls->hsd = xzalloc(sizeof(*tls->hsd)); + /* HANDSHAKE HASH: ^^^ + len if need to save saved_client_hello */ + memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); +/* HANDSHAKE HASH: tls->hsd->saved_client_hello_size = len; memcpy(tls->hsd->saved_client_hello, record, len); - memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); + */ + dbg(">> CLIENT_HELLO\n"); + /* Can hash immediately only if we know which MAC hash to use. + * So far we do know: it's sha256: + */ + sha256_begin(&tls->hsd->handshake_hash_ctx); + xwrite_and_update_handshake_hash(tls, len); + /* if this would become infeasible: save tls->hsd->saved_client_hello, + * use "xwrite_handshake_record(tls, len)" here, + * and hash saved_client_hello later. + */ } static void get_server_hello(tls_state_t *tls) @@ -1463,18 +1627,28 @@ static void get_server_hello(tls_state_t *tls) if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA || cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA ) { + if (cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) + tls->flags |= NEED_EC_KEY; tls->key_size = AES128_KEYSIZE; tls->MAC_size = SHA1_OUTSIZE; } - else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ + else + if (cipher == TLS_RSA_WITH_AES_256_CBC_SHA256) { tls->key_size = AES256_KEYSIZE; tls->MAC_size = SHA256_OUTSIZE; } + else { /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ + tls->flags |= NEED_EC_KEY | ENCRYPTION_AESGCM; + tls->key_size = AES128_KEYSIZE; + /* tls->MAC_size = 0; */ + tls->IV_size = 4; + } /* Handshake hash eventually destined to FINISHED record * is sha256 regardless of cipher * (at least for all ciphers defined by RFC5246). * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash. */ +/* HANDSHAKE HASH: sha256_begin(&tls->hsd->handshake_hash_ctx); hash_handshake(tls, ">> client hello hash:%s", tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size @@ -1482,6 +1656,7 @@ static void get_server_hello(tls_state_t *tls) hash_handshake(tls, "<< server hello hash:%s", tls->inbuf + RECHDR_LEN, len ); + */ } static void get_server_cert(tls_state_t *tls) @@ -1548,7 +1723,7 @@ static void process_server_key(tls_state_t *tls, int len) // 64523d6216cb94c43c9b20e377d8c52c55be6703fd6730a155930c705eaf3af6 //32bytes //same about this item ^^^^^ -//seen from www.openbsd.org +//seen from ftp.openbsd.org //(which only accepts ECDHE-RSA-AESnnn-GCM-SHAnnn and ECDHE-RSA-CHACHA20-POLY1305 ciphers): // 0c 000228 //SERVER_KEY_EXCHANGE, len // 03 //curve_type: named curve @@ -1572,6 +1747,7 @@ static void process_server_key(tls_state_t *tls, int len) bb_error_msg_and_die("elliptic curve is not x25519"); memcpy(tls->hsd->ecc_pub_key32, keybuf + 4, 32); + tls->flags |= GOT_EC_KEY; dbg("got eccPubKey\n"); } @@ -1612,7 +1788,11 @@ static void send_client_key_exchange(tls_state_t *tls) int premaster_size; int len; - if (tls->hsd->key_alg == KEY_ALG_RSA) { + if (!(tls->flags & NEED_EC_KEY)) { + /* RSA */ + if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) + bb_error_msg("server cert is not RSA"); + tls_get_random(rsa_premaster, sizeof(rsa_premaster)); if (TLS_DEBUG_FIXED_SECRETS) memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); @@ -1636,10 +1816,13 @@ static void send_client_key_exchange(tls_state_t *tls) premaster = rsa_premaster; premaster_size = sizeof(rsa_premaster); } else { - /* KEY_ALG_ECDSA */ + /* ECDHE */ static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9}; uint8_t privkey[CURVE25519_KEYSIZE]; //[32] + if (!(tls->flags & GOT_EC_KEY)) + bb_error_msg("server did not provide EC key"); + /* Generate random private key, see RFC 7748 */ tls_get_random(privkey, sizeof(privkey)); privkey[0] &= 0xf8; @@ -1727,23 +1910,32 @@ static void send_client_key_exchange(tls_state_t *tls) memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); prf_hmac_sha256(/*tls,*/ - tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size), + tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size + tls->IV_size), // also fills: // server_write_MAC_key[] // client_write_key[] // server_write_key[] + // client_write_IV[] + // server_write_IV[] tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "key expansion", tmp64, 64 ); tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size); tls->server_write_key = tls->client_write_key + tls->key_size; + tls->client_write_IV = tls->server_write_key + tls->key_size; + tls->server_write_IV = tls->client_write_IV + tls->IV_size; dump_hex("client_write_MAC_key:%s\n", tls->client_write_MAC_key, tls->MAC_size ); dump_hex("client_write_key:%s\n", tls->client_write_key, tls->key_size ); + dump_hex("client_write_IV:%s\n", + tls->client_write_IV, tls->IV_size + ); + aesgcm_setkey(tls->H, &tls->aes_encrypt, tls->client_write_key, tls->key_size); + aes_setkey(&tls->aes_decrypt, tls->server_write_key, tls->key_size); } } @@ -1876,7 +2068,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // client. dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); dump_raw_in("<< %s\n", tls->inbuf, RECHDR_LEN + len); - if (tls->hsd->key_alg == KEY_ALG_ECDSA) + if (tls->flags & NEED_EC_KEY) process_server_key(tls, len); // read next handshake block @@ -1922,18 +2114,22 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) bad_record_die(tls, "switch to encrypted traffic", len); dbg("<< CHANGE_CIPHER_SPEC\n"); + if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256 ) { tls->min_encrypted_len_on_read = tls->MAC_size; - } else { - unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE; + } else + if (!(tls->flags & ENCRYPTION_AESGCM)) { + unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE; /* all incoming packets now should be encrypted and have * at least IV + (MAC padded to blocksize): */ - tls->min_encrypted_len_on_read = AES_BLOCKSIZE + (mac_blocks * AES_BLOCKSIZE); - dbg("min_encrypted_len_on_read: %u", tls->min_encrypted_len_on_read); + tls->min_encrypted_len_on_read = AES_BLOCK_SIZE + (mac_blocks * AES_BLOCK_SIZE); + } else { + tls->min_encrypted_len_on_read = 8 + AES_BLOCK_SIZE; } + dbg("min_encrypted_len_on_read: %u\n", tls->min_encrypted_len_on_read); /* Get (encrypted) FINISHED from the server */ len = tls_xread_record(tls, "'server finished'"); diff --git a/networking/tls.h b/networking/tls.h index 66d25eff5..1d379c193 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -78,6 +78,8 @@ typedef int16_t int16; #define PUBKEY_TYPE 0x01 #define PRIVKEY_TYPE 0x02 +#define AES_BLOCK_SIZE 16 + void tls_get_random(void *buf, unsigned len); #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) @@ -96,5 +98,6 @@ void tls_get_random(void *buf, unsigned len); #include "tls_pstm.h" #include "tls_symmetric.h" #include "tls_aes.h" +#include "tls_aesgcm.h" #include "tls_rsa.h" #include "tls_fe.h" diff --git a/networking/tls_aes.c b/networking/tls_aes.c index c137442e9..4d2b68975 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -340,8 +340,12 @@ static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t * AddRoundKey(astate, RoundKey); } -#if 0 // UNUSED -static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst) +void FAST_FUNC aes_setkey(struct tls_aes *aes, const void *key, unsigned key_len) +{ + aes->rounds = KeyExpansion(aes->key, key, key_len); +} + +void FAST_FUNC aes_encrypt_one_block(struct tls_aes *aes, const void *data, void *dst) { unsigned astate[16]; unsigned i; @@ -351,13 +355,12 @@ static void aes_encrypt_one_block(unsigned rounds, const uint32_t *RoundKey, con for (i = 0; i < 16; i++) astate[i] = pt[i]; - aes_encrypt_1(astate, rounds, RoundKey); + aes_encrypt_1(astate, aes->rounds, aes->key); for (i = 0; i < 16; i++) ct[i] = astate[i]; } -#endif -void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +void FAST_FUNC aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) { uint32_t RoundKey[60]; uint8_t iv2[16]; @@ -420,7 +423,7 @@ static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, con } #endif -void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +void FAST_FUNC aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) { uint32_t RoundKey[60]; uint8_t iv2[16]; diff --git a/networking/tls_aes.h b/networking/tls_aes.h index c6791866a..fc3881793 100644 --- a/networking/tls_aes.h +++ b/networking/tls_aes.h @@ -6,5 +6,9 @@ * Selected few declarations for AES. */ -void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); -void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); +void aes_setkey(struct tls_aes *aes, const void *key, unsigned key_len) FAST_FUNC; + +void aes_encrypt_one_block(struct tls_aes *aes, const void *data, void *dst) FAST_FUNC; + +void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) FAST_FUNC; +void aes_cbc_decrypt(const void *key, int klen, 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..584cee98e --- /dev/null +++ b/networking/tls_aesgcm.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + +#include "tls.h" + +typedef uint8_t byte; +typedef uint32_t word32; +#define XMEMSET memset +#define XMEMCPY memcpy + +#define TLS_MAJ 3 +#define TLS_MIN 3 +#define RECHDR_LEN 5 +#define OUTBUF_PFX (8 + AES_BLOCK_SIZE) + +void FAST_FUNC xorbuf(void* buf, const void* mask, unsigned count) +{ + word32 i; + byte* b = (byte*)buf; + const byte* m = (const byte*)mask; + for (i = 0; i < count; i++) + b[i] ^= m[i]; +} + +/* wolfssl-3.15.3/wolfcrypt/src/aes.c */ + +static void FlattenSzInBits(byte* buf, word32 sz) +{ + /* Multiply the sz by 8 */ + word32 szHi = (sz >> (8*sizeof(sz) - 3)); + sz <<= 3; + + /* copy over the words of the sz into the destination buffer */ + buf[0] = (szHi >> 24) & 0xff; + buf[1] = (szHi >> 16) & 0xff; + buf[2] = (szHi >> 8) & 0xff; + buf[3] = szHi & 0xff; + buf[4] = (sz >> 24) & 0xff; + buf[5] = (sz >> 16) & 0xff; + buf[6] = (sz >> 8) & 0xff; + buf[7] = sz & 0xff; +} + +static void RIGHTSHIFTX(byte* x) +{ + int i; + int carryOut = 0; + int carryIn = 0; + int borrow = x[15] & 0x01; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + carryOut = x[i] & 0x01; + x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); + carryIn = carryOut; + } + if (borrow) x[0] ^= 0xE1; +} + +static void GMULT(byte* X, byte* Y) +{ + byte Z[AES_BLOCK_SIZE]; + byte V[AES_BLOCK_SIZE]; + int i, j; + + XMEMSET(Z, 0, AES_BLOCK_SIZE); + XMEMCPY(V, X, AES_BLOCK_SIZE); + for (i = 0; i < AES_BLOCK_SIZE; i++) + { + byte y = Y[i]; + for (j = 0; j < 8; j++) + { + if (y & 0x80) { + xorbuf(Z, V, AES_BLOCK_SIZE); + } + + RIGHTSHIFTX(V); + y = y << 1; + } + } + XMEMCPY(X, Z, AES_BLOCK_SIZE); +} + +void FAST_FUNC aesgcm_GHASH(byte* h, const byte* a, unsigned aSz, const byte* c, + unsigned cSz, byte* s, unsigned sSz) +{ + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + word32 blocks, partial; + //was: byte* h = aes->H; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, h); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, h); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + +void FAST_FUNC aesgcm_setkey(uint8_t H[16], struct tls_aes *aes, const byte* key, unsigned len) +{ + byte iv[AES_BLOCK_SIZE]; + + aes_setkey(aes, key, len); + + memset(iv, 0, AES_BLOCK_SIZE); + aes_encrypt_one_block(aes, iv, H); +} diff --git a/networking/tls_aesgcm.h b/networking/tls_aesgcm.h new file mode 100644 index 000000000..d4cde01f9 --- /dev/null +++ b/networking/tls_aesgcm.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2018 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + +void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; + +void aesgcm_GHASH(uint8_t* h, + const uint8_t* a, unsigned aSz, + const uint8_t* c, unsigned cSz, + uint8_t* s, unsigned sSz +) FAST_FUNC; + +void aesgcm_setkey(uint8_t H[16], struct tls_aes *aes, const uint8_t* key, unsigned len) FAST_FUNC; diff --git a/networking/tls_fe.c b/networking/tls_fe.c index dcb41468a..f235082f5 100644 --- a/networking/tls_fe.c +++ b/networking/tls_fe.c @@ -554,7 +554,7 @@ static void xc_double(byte *x3, byte *z3, fe_mul_c(z3, x1sq, 4); } -void curve25519(byte *result, const byte *e, const byte *q) +void FAST_FUNC curve25519(byte *result, const byte *e, const byte *q) { int i; diff --git a/networking/tls_fe.h b/networking/tls_fe.h index bd2f2b3da..fe8cff228 100644 --- a/networking/tls_fe.h +++ b/networking/tls_fe.h @@ -4,4 +4,4 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ #define CURVE25519_KEYSIZE 32 -void curve25519(uint8_t *result, const uint8_t *e, const uint8_t *q); +void 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: return res; } -int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, +int32 FAST_FUNC psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, void *data) { diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h index c464ed552..f42923ff5 100644 --- a/networking/tls_rsa.h +++ b/networking/tls_rsa.h @@ -17,4 +17,4 @@ typedef struct { psRsaEncryptPub( key, in, inlen, out, outlen) int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, unsigned char *in, uint32 inlen, - unsigned char *out, uint32 outlen, void *data); + unsigned char *out, uint32 outlen, void *data) FAST_FUNC; -- cgit v1.2.3-55-g6feb From 5e4236d226309a32842a6928878fd0e1cd5937e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 18:02:44 +0100 Subject: tls: in AES-CBC code, do not set key for every record - do it once function old new delta aes_setkey 16 212 +196 tls_handshake 1941 1977 +36 aes_encrypt_1 382 396 +14 xwrite_encrypted 605 604 -1 tls_xread_record 659 656 -3 aes_encrypt_one_block 65 59 -6 aes_cbc_encrypt 172 121 -51 aesgcm_setkey 58 - -58 aes_cbc_decrypt 958 881 -77 KeyExpansion 188 - -188 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 3/5 up/down: 246/-384) Total: -138 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 12 +++++++++--- networking/tls_aes.c | 32 +++++++++++++++++--------------- networking/tls_aes.h | 4 ++-- networking/tls_aesgcm.c | 10 ---------- networking/tls_aesgcm.h | 2 -- 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 38a965ad6..23622d76e 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -758,7 +758,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un /* Encrypt content+MAC+padding in place */ //optimize key setup aes_cbc_encrypt( - tls->client_write_key, tls->key_size, /* selects 128/256 */ + &tls->aes_decrypt, /* selects 128/256 */ buf - AES_BLOCK_SIZE, /* IV */ buf, size, /* plaintext */ buf /* ciphertext */ @@ -1061,7 +1061,7 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) /* Decrypt content+MAC+padding, moving it over IV in the process */ sz -= AES_BLOCK_SIZE; /* we will overwrite IV now */ aes_cbc_decrypt( - tls->server_write_key, tls->key_size, /* selects 128/256 */ + &tls->aes_decrypt, /* selects 128/256 */ p, /* IV */ p + AES_BLOCK_SIZE, sz, /* ciphertext */ p /* plaintext */ @@ -1934,8 +1934,14 @@ static void send_client_key_exchange(tls_state_t *tls) dump_hex("client_write_IV:%s\n", tls->client_write_IV, tls->IV_size ); - aesgcm_setkey(tls->H, &tls->aes_encrypt, tls->client_write_key, tls->key_size); + aes_setkey(&tls->aes_decrypt, tls->server_write_key, tls->key_size); + aes_setkey(&tls->aes_encrypt, tls->client_write_key, tls->key_size); + { + uint8_t iv[AES_BLOCK_SIZE]; + memset(iv, 0, AES_BLOCK_SIZE); + aes_encrypt_one_block(&tls->aes_encrypt, iv, tls->H); + } } } diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 4d2b68975..cf6b5fe3d 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -326,8 +326,11 @@ static void InvMixColumns(unsigned astate[16]) } } -static void aes_encrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey) +static void aes_encrypt_1(struct tls_aes *aes, unsigned astate[16]) { + unsigned rounds = aes->rounds; + const uint32_t *RoundKey = aes->key; + for (;;) { AddRoundKey(astate, RoundKey); RoundKey += 4; @@ -355,22 +358,19 @@ void FAST_FUNC aes_encrypt_one_block(struct tls_aes *aes, const void *data, void for (i = 0; i < 16; i++) astate[i] = pt[i]; - aes_encrypt_1(astate, aes->rounds, aes->key); + aes_encrypt_1(aes, astate); for (i = 0; i < 16; i++) ct[i] = astate[i]; } -void FAST_FUNC aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +void FAST_FUNC aes_cbc_encrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst) { - uint32_t RoundKey[60]; uint8_t iv2[16]; - unsigned rounds; const uint8_t *pt = data; uint8_t *ct = dst; memcpy(iv2, iv, 16); - rounds = KeyExpansion(RoundKey, key, klen); while (len > 0) { { /* almost aes_encrypt_one_block(rounds, RoundKey, pt, ct); @@ -381,7 +381,7 @@ void FAST_FUNC aes_cbc_encrypt(const void *key, int klen, void *iv, const void * unsigned astate[16]; for (i = 0; i < 16; i++) astate[i] = pt[i] ^ iv2[i]; - aes_encrypt_1(astate, rounds, RoundKey); + aes_encrypt_1(aes, astate); for (i = 0; i < 16; i++) iv2[i] = ct[i] = astate[i]; } @@ -391,8 +391,11 @@ void FAST_FUNC aes_cbc_encrypt(const void *key, int klen, void *iv, const void * } } -static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t *RoundKey) +static void aes_decrypt_1(struct tls_aes *aes, unsigned astate[16]) { + unsigned rounds = aes->rounds; + const uint32_t *RoundKey = aes->key; + RoundKey += rounds * 4; AddRoundKey(astate, RoundKey); for (;;) { @@ -407,8 +410,10 @@ static void aes_decrypt_1(unsigned astate[16], unsigned rounds, const uint32_t * } #if 0 //UNUSED -static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, const void *data, void *dst) +static void aes_decrypt_one_block(struct tls_aes *aes, const void *data, void *dst) { + unsigned rounds = aes->rounds; + const uint32_t *RoundKey = aes->key; unsigned astate[16]; unsigned i; @@ -417,25 +422,22 @@ static void aes_decrypt_one_block(unsigned rounds, const uint32_t *RoundKey, con for (i = 0; i < 16; i++) astate[i] = ct[i]; - aes_decrypt_1(astate, rounds, RoundKey); + aes_decrypt_1(aes, astate); for (i = 0; i < 16; i++) pt[i] = astate[i]; } #endif -void FAST_FUNC aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +void FAST_FUNC aes_cbc_decrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst) { - uint32_t RoundKey[60]; uint8_t iv2[16]; uint8_t iv3[16]; - unsigned rounds; uint8_t *ivbuf; uint8_t *ivnext; const uint8_t *ct = data; uint8_t *pt = dst; - rounds = KeyExpansion(RoundKey, key, klen); ivbuf = memcpy(iv2, iv, 16); while (len) { ivnext = (ivbuf==iv2) ? iv3 : iv2; @@ -447,7 +449,7 @@ void FAST_FUNC aes_cbc_decrypt(const void *key, int klen, void *iv, const void * unsigned astate[16]; for (i = 0; i < 16; i++) ivnext[i] = astate[i] = ct[i]; - aes_decrypt_1(astate, rounds, RoundKey); + aes_decrypt_1(aes, astate); for (i = 0; i < 16; i++) pt[i] = astate[i] ^ ivbuf[i]; } diff --git a/networking/tls_aes.h b/networking/tls_aes.h index fc3881793..e9e3721f1 100644 --- a/networking/tls_aes.h +++ b/networking/tls_aes.h @@ -10,5 +10,5 @@ void aes_setkey(struct tls_aes *aes, const void *key, unsigned key_len) FAST_FUN void aes_encrypt_one_block(struct tls_aes *aes, const void *data, void *dst) FAST_FUNC; -void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) FAST_FUNC; -void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) FAST_FUNC; +void aes_cbc_encrypt(struct tls_aes *aes, void *iv, const void *data, size_t len, void *dst) FAST_FUNC; +void 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 index 584cee98e..eb32f4c05 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -136,13 +136,3 @@ void FAST_FUNC aesgcm_GHASH(byte* h, const byte* a, unsigned aSz, const byte* c, /* Copy the result into s. */ XMEMCPY(s, x, sSz); } - -void FAST_FUNC aesgcm_setkey(uint8_t H[16], struct tls_aes *aes, const byte* key, unsigned len) -{ - byte iv[AES_BLOCK_SIZE]; - - aes_setkey(aes, key, len); - - memset(iv, 0, AES_BLOCK_SIZE); - aes_encrypt_one_block(aes, iv, H); -} diff --git a/networking/tls_aesgcm.h b/networking/tls_aesgcm.h index d4cde01f9..a71eced54 100644 --- a/networking/tls_aesgcm.h +++ b/networking/tls_aesgcm.h @@ -11,5 +11,3 @@ void aesgcm_GHASH(uint8_t* h, const uint8_t* c, unsigned cSz, uint8_t* s, unsigned sSz ) FAST_FUNC; - -void aesgcm_setkey(uint8_t H[16], struct tls_aes *aes, const uint8_t* key, unsigned len) FAST_FUNC; -- cgit v1.2.3-55-g6feb From ecc9090cfcccf412288147f385808f8f9df97ebe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 18:31:26 +0100 Subject: tls: simplify aesgcm_GHASH() function old new delta xwrite_encrypted 604 599 -5 FlattenSzInBits 52 - -52 aesgcm_GHASH 395 262 -133 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/2 up/down: 0/-190) Total: -190 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 30 ++++++++++---------- networking/tls_aesgcm.c | 73 +++++++++++++++++++++++++++++-------------------- networking/tls_aesgcm.h | 4 +-- 3 files changed, 60 insertions(+), 47 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 23622d76e..3b4f1b7e2 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -270,7 +270,7 @@ struct record_hdr { enum { NEED_EC_KEY = 1 << 0, GOT_CERT_RSA_KEY_ALG = 1 << 1, - GOT_CERT_ECDSA_KEY_ALG = 1 << 2, + GOT_CERT_ECDSA_KEY_ALG = 1 << 2, GOT_EC_KEY = 1 << 3, ENCRYPTION_AESGCM = 1 << 4, }; @@ -756,7 +756,6 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un } while ((size & (AES_BLOCK_SIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ -//optimize key setup aes_cbc_encrypt( &tls->aes_decrypt, /* selects 128/256 */ buf - AES_BLOCK_SIZE, /* IV */ @@ -787,8 +786,9 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un */ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned type) { -//go for [16] - uint8_t aad[13]; +#define COUNTER(v) (*(uint32_t*)(v + 12)) + + uint8_t aad[13 + 3]; /* +3 creates [16] buffer, simplifying GHASH() */ uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ uint8_t scratch[AES_BLOCK_SIZE]; //[16] uint8_t authtag[AES_BLOCK_SIZE]; //[16] @@ -807,7 +807,8 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty aad[9] = TLS_MAJ; aad[10] = TLS_MIN; aad[11] = size >> 8; - aad[12] = size & 0xff; + /* set aad[12], and clear aad[13..15] */ + COUNTER(aad) = SWAP_LE32(size & 0xff); memcpy(nonce, tls->client_write_IV, 4); memcpy(nonce + 4, &tls->write_seq64_be, 8); @@ -817,8 +818,6 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty /* seq64 is not used later in this func, can increment here */ tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); -#define COUNTER(v) (*(uint32_t*)(v + 12)) - cnt = 1; remaining = size; while (remaining != 0) { @@ -833,8 +832,7 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty remaining -= n; } -//optimize fixed sizes - aesgcm_GHASH(tls->H, aad, sizeof(aad), tls->outbuf + OUTBUF_PFX, size, authtag, sizeof(authtag)); + aesgcm_GHASH(tls->H, aad, /*sizeof(aad),*/ tls->outbuf + OUTBUF_PFX, size, authtag /*, sizeof(authtag)*/); COUNTER(nonce) = htonl(1); aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); xorbuf(authtag, scratch, sizeof(authtag)); @@ -923,8 +921,9 @@ static const char *alert_text(int code) static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) { -//go for [16] - //uint8_t aad[13]; +#define COUNTER(v) (*(uint32_t*)(v + 12)) + + //uint8_t aad[13 + 3]; /* +3 creates [16] buffer, simplifying GHASH() */ uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ uint8_t scratch[AES_BLOCK_SIZE]; //[16] //uint8_t authtag[AES_BLOCK_SIZE]; //[16] @@ -935,14 +934,14 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) //aad[9] = TLS_MAJ; //aad[10] = TLS_MIN; //aad[11] = size >> 8; - //aad[12] = size & 0xff; + ///* set aad[12], and clear aad[13..15] */ + //COUNTER(aad) = SWAP_LE32(size & 0xff); + //memcpy(aad, &tls->write_seq64_be, 8); memcpy(nonce, tls->server_write_IV, 4); memcpy(nonce + 4, buf, 8); buf += 8; -#define COUNTER(v) (*(uint32_t*)(v + 12)) - cnt = 1; remaining = size; while (remaining != 0) { @@ -957,8 +956,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) remaining -= n; } -////optimize fixed sizes - //aesgcm_GHASH(tls->H, aad, sizeof(aad), tls->outbuf + OUTBUF_PFX, size, authtag, sizeof(authtag)); + //aesgcm_GHASH(tls->H, aad, tls->outbuf + OUTBUF_PFX, size, authtag); //COUNTER(nonce) = htonl(1); //aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); //xorbuf(authtag, scratch, sizeof(authtag)); diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index eb32f4c05..1a7ddb2e2 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -25,23 +25,26 @@ void FAST_FUNC xorbuf(void* buf, const void* mask, unsigned count) b[i] ^= m[i]; } -/* wolfssl-3.15.3/wolfcrypt/src/aes.c */ +/* from wolfssl-3.15.3/wolfcrypt/src/aes.c */ -static void FlattenSzInBits(byte* buf, word32 sz) +static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) { /* Multiply the sz by 8 */ - word32 szHi = (sz >> (8*sizeof(sz) - 3)); +//bbox: these sizes are never even close to 2^32/8 +// word32 szHi = (sz >> (8*sizeof(sz) - 3)); sz <<= 3; /* copy over the words of the sz into the destination buffer */ - buf[0] = (szHi >> 24) & 0xff; - buf[1] = (szHi >> 16) & 0xff; - buf[2] = (szHi >> 8) & 0xff; - buf[3] = szHi & 0xff; - buf[4] = (sz >> 24) & 0xff; - buf[5] = (sz >> 16) & 0xff; - buf[6] = (sz >> 8) & 0xff; - buf[7] = sz & 0xff; +// buf[0] = (szHi >> 24) & 0xff; +// buf[1] = (szHi >> 16) & 0xff; +// buf[2] = (szHi >> 8) & 0xff; +// buf[3] = szHi & 0xff; + move_to_unaligned32(buf, 0); +// buf[4] = (sz >> 24) & 0xff; +// buf[5] = (sz >> 16) & 0xff; +// buf[6] = (sz >> 8) & 0xff; +// buf[7] = sz & 0xff; + move_to_unaligned32(buf + 4, SWAP_BE32(sz)); } static void RIGHTSHIFTX(byte* x) @@ -83,35 +86,47 @@ static void GMULT(byte* X, byte* Y) XMEMCPY(X, Z, AES_BLOCK_SIZE); } -void FAST_FUNC aesgcm_GHASH(byte* h, const byte* a, unsigned aSz, const byte* c, - unsigned cSz, byte* s, unsigned sSz) +//bbox: +// for TLS AES-GCM, a (which as AAD) is always 13 bytes long, and bbox code provides +// extra 3 zeroed bytes, making it a[16], or a[AES_BLOCK_SIZE]. +// Resulting auth tag in s is also always AES_BLOCK_SIZE bytes. +// +// This allows some simplifications. +#define aSz AES_BLOCK_SIZE +#define sSz AES_BLOCK_SIZE +void FAST_FUNC aesgcm_GHASH(byte* h, + const byte* a, //unsigned aSz, + const byte* c, unsigned cSz, + byte* s //, unsigned sSz +) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; word32 blocks, partial; //was: byte* h = aes->H; - XMEMSET(x, 0, AES_BLOCK_SIZE); + //XMEMSET(x, 0, AES_BLOCK_SIZE); /* Hash in A, the Additional Authentication Data */ - if (aSz != 0 && a != NULL) { - blocks = aSz / AES_BLOCK_SIZE; - partial = aSz % AES_BLOCK_SIZE; - while (blocks--) { - xorbuf(x, a, AES_BLOCK_SIZE); - GMULT(x, h); - a += AES_BLOCK_SIZE; - } - if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, a, partial); - xorbuf(x, scratch, AES_BLOCK_SIZE); +// if (aSz != 0 && a != NULL) { +// blocks = aSz / AES_BLOCK_SIZE; +// partial = aSz % AES_BLOCK_SIZE; +// while (blocks--) { + //xorbuf(x, a, AES_BLOCK_SIZE); + XMEMCPY(x, a, AES_BLOCK_SIZE);// memcpy(x,a) = memset(x,0)+xorbuf(x,a) GMULT(x, h); - } - } +// a += AES_BLOCK_SIZE; +// } +// if (partial != 0) { +// XMEMSET(scratch, 0, AES_BLOCK_SIZE); +// XMEMCPY(scratch, a, partial); +// xorbuf(x, scratch, AES_BLOCK_SIZE); +// GMULT(x, h); +// } +// } /* Hash in C, the Ciphertext */ - if (cSz != 0 && c != NULL) { + if (cSz != 0 /*&& c != NULL*/) { blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; while (blocks--) { diff --git a/networking/tls_aesgcm.h b/networking/tls_aesgcm.h index a71eced54..75694f3fa 100644 --- a/networking/tls_aesgcm.h +++ b/networking/tls_aesgcm.h @@ -7,7 +7,7 @@ void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; void aesgcm_GHASH(uint8_t* h, - const uint8_t* a, unsigned aSz, + const uint8_t* a, //unsigned aSz, const uint8_t* c, unsigned cSz, - uint8_t* s, unsigned sSz + uint8_t* s //, unsigned sSz ) FAST_FUNC; -- cgit v1.2.3-55-g6feb From 219c9d4b5d12b3b965da838eb467b955ef928170 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 18:48:20 +0100 Subject: tls: code shrink function old new delta xwrite_encrypted 599 585 -14 Signed-off-by: Denys Vlasenko --- include/platform.h | 5 +++++ networking/tls.c | 31 ++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/platform.h b/include/platform.h index c365d5c8c..50365a31c 100644 --- a/include/platform.h +++ b/include/platform.h @@ -236,6 +236,7 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; # define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p)) # define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v)) # define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v)) +# define move_to_unaligned64(u64p, v) (*(bb__aliased_uint64_t*)(u64p) = (v)) /* #elif ... - add your favorite arch today! */ #else # define BB_UNALIGNED_MEMACCESS_OK 0 @@ -252,6 +253,10 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; uint32_t __t = (v); \ memcpy((u32p), &__t, 4); \ } while (0) +# define move_to_unaligned64(u64p, v) do { \ + uint64_t __t = (v); \ + memcpy((u64p), &__t, 8); \ +} while (0) #endif /* Unaligned, fixed-endian accessors */ diff --git a/networking/tls.c b/networking/tls.c index 3b4f1b7e2..2a0098674 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -788,14 +788,15 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty { #define COUNTER(v) (*(uint32_t*)(v + 12)) - uint8_t aad[13 + 3]; /* +3 creates [16] buffer, simplifying GHASH() */ - uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ - uint8_t scratch[AES_BLOCK_SIZE]; //[16] - uint8_t authtag[AES_BLOCK_SIZE]; //[16] + uint8_t aad[13 + 3] ALIGNED(4); /* +3 creates [16] buffer, simplifying GHASH() */ + uint8_t nonce[12 + 4] ALIGNED(4); /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE] ALIGNED(4); //[16] + uint8_t authtag[AES_BLOCK_SIZE] ALIGNED(4); //[16] uint8_t *buf; struct record_hdr *xhdr; unsigned remaining; unsigned cnt; + uint64_t t64; buf = tls->outbuf + OUTBUF_PFX; /* see above for the byte it points to */ dump_hex("xwrite_encrypted_aesgcm plaintext:%s\n", buf, size); @@ -810,13 +811,13 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty /* set aad[12], and clear aad[13..15] */ COUNTER(aad) = SWAP_LE32(size & 0xff); - memcpy(nonce, tls->client_write_IV, 4); - memcpy(nonce + 4, &tls->write_seq64_be, 8); - memcpy(aad, &tls->write_seq64_be, 8); - memcpy(buf - 8, &tls->write_seq64_be, 8); -//optimize + memcpy(nonce, tls->client_write_IV, 4); + t64 = tls->write_seq64_be; + move_to_unaligned64(nonce + 4, t64); + move_to_unaligned64(aad, t64); + move_to_unaligned64(buf - 8, t64); /* seq64 is not used later in this func, can increment here */ - tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(t64)); cnt = 1; remaining = size; @@ -923,13 +924,14 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) { #define COUNTER(v) (*(uint32_t*)(v + 12)) - //uint8_t aad[13 + 3]; /* +3 creates [16] buffer, simplifying GHASH() */ - uint8_t nonce[12 + 4]; /* +4 creates space for AES block counter */ - uint8_t scratch[AES_BLOCK_SIZE]; //[16] - //uint8_t authtag[AES_BLOCK_SIZE]; //[16] + //uint8_t aad[13 + 3] ALIGNED(4); /* +3 creates [16] buffer, simplifying GHASH() */ + uint8_t nonce[12 + 4] ALIGNED(4); /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE] ALIGNED(4); //[16] + //uint8_t authtag[AES_BLOCK_SIZE] ALIGNED(4); //[16] unsigned remaining; unsigned cnt; + //memcpy(aad, buf, 8); //aad[8] = type; //aad[9] = TLS_MAJ; //aad[10] = TLS_MIN; @@ -937,7 +939,6 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) ///* set aad[12], and clear aad[13..15] */ //COUNTER(aad) = SWAP_LE32(size & 0xff); - //memcpy(aad, &tls->write_seq64_be, 8); memcpy(nonce, tls->server_write_IV, 4); memcpy(nonce + 4, buf, 8); buf += 8; -- cgit v1.2.3-55-g6feb From 25569c3ca987f37075e457d5203fb7b6c3d6ae84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 18:55:15 +0100 Subject: tls: make local buffers in aesgcm_GHASH() explicitly 32-bit aligned Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 1a7ddb2e2..360e6f4ff 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -11,11 +11,6 @@ typedef uint32_t word32; #define XMEMSET memset #define XMEMCPY memcpy -#define TLS_MAJ 3 -#define TLS_MIN 3 -#define RECHDR_LEN 5 -#define OUTBUF_PFX (8 + AES_BLOCK_SIZE) - void FAST_FUNC xorbuf(void* buf, const void* mask, unsigned count) { word32 i; @@ -39,12 +34,12 @@ static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) // buf[1] = (szHi >> 16) & 0xff; // buf[2] = (szHi >> 8) & 0xff; // buf[3] = szHi & 0xff; - move_to_unaligned32(buf, 0); + *(uint32_t*)(buf + 0) = 0; // buf[4] = (sz >> 24) & 0xff; // buf[5] = (sz >> 16) & 0xff; // buf[6] = (sz >> 8) & 0xff; // buf[7] = sz & 0xff; - move_to_unaligned32(buf + 4, SWAP_BE32(sz)); + *(uint32_t*)(buf + 4) = SWAP_BE32(sz); } static void RIGHTSHIFTX(byte* x) @@ -100,8 +95,8 @@ void FAST_FUNC aesgcm_GHASH(byte* h, byte* s //, unsigned sSz ) { - byte x[AES_BLOCK_SIZE]; - byte scratch[AES_BLOCK_SIZE]; + byte x[AES_BLOCK_SIZE] ALIGNED(4); + byte scratch[AES_BLOCK_SIZE] ALIGNED(4); word32 blocks, partial; //was: byte* h = aes->H; -- cgit v1.2.3-55-g6feb From d496b4002a944af5832b8589cbc5f967abaf3dc4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 19:00:12 +0100 Subject: tls: typo fix in comment Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 360e6f4ff..a06f8c8c5 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -82,9 +82,9 @@ static void GMULT(byte* X, byte* Y) } //bbox: -// for TLS AES-GCM, a (which as AAD) is always 13 bytes long, and bbox code provides +// for TLS AES-GCM, a (which is AAD) is always 13 bytes long, and bbox code provides // extra 3 zeroed bytes, making it a[16], or a[AES_BLOCK_SIZE]. -// Resulting auth tag in s is also always AES_BLOCK_SIZE bytes. +// Resulting auth tag in s[] is also always AES_BLOCK_SIZE bytes. // // This allows some simplifications. #define aSz AES_BLOCK_SIZE -- cgit v1.2.3-55-g6feb From fbf5e6363b11c3381d077c6bb24f224f4e3bc802 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 19:07:05 +0100 Subject: tls: code shrink function old new delta aesgcm_GHASH 262 233 -29 Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index a06f8c8c5..84c90314f 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -130,9 +130,10 @@ void FAST_FUNC aesgcm_GHASH(byte* h, c += AES_BLOCK_SIZE; } if (partial != 0) { - XMEMSET(scratch, 0, AES_BLOCK_SIZE); - XMEMCPY(scratch, c, partial); - xorbuf(x, scratch, AES_BLOCK_SIZE); + //XMEMSET(scratch, 0, AES_BLOCK_SIZE); + //XMEMCPY(scratch, c, partial); + //xorbuf(x, scratch, AES_BLOCK_SIZE); + xorbuf(x, c, partial); GMULT(x, h); } } -- cgit v1.2.3-55-g6feb From 26602b85a3f679017b4366d3c1b2f6c5aa950aa5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 19:14:52 +0100 Subject: wget: print the final newline only for non-tty output $ busybox wget URL 2>&1 | cat Connecting to .... install.iso 0% | | 2629k 0:02:05 ETA install.iso 7% |** | 25.7M 0:00:23 ETA install.iso 16% |***** | 54.1M 0:00:14 ETA install.iso 20% |****** | 67.4M 0:00:15 ETA install.iso 25% |******** | 81.0M 0:00:14 ETA install.iso 30% |********* | 97.3M 0:00:13 ETA install.iso 36% |*********** | 117M 0:00:12 ETA install.iso 41% |************* | 134M 0:00:11 ETA install.iso 47% |*************** | 152M 0:00:10 ETA install.iso 54% |***************** | 176M 0:00:08 ETA install.iso 61% |******************* | 200M 0:00:06 ETA install.iso 66% |********************* | 215M 0:00:06 ETA install.iso 71% |********************** | 231M 0:00:05 ETA install.iso 75% |************************ | 244M 0:00:04 ETA install.iso 79% |************************* | 257M 0:00:03 ETA install.iso 84% |*************************** | 275M 0:00:02 ETA install.iso 91% |***************************** | 297M 0:00:01 ETA install.iso 99% |******************************* | 321M 0:00:00 ETA install.iso 100% |********************************| 323M 0:00:00 ETA <-- no empty line here $ function old new delta bb_progress_update 622 632 +10 progress_meter 152 158 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 16/0) Total: 16 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/progress.c | 5 +++-- networking/wget.c | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index b041ce047..883457c0d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2007,7 +2007,7 @@ typedef struct bb_progress_t { (p)->curfile = NULL; \ } while (0) void bb_progress_init(bb_progress_t *p, const char *curfile) FAST_FUNC; -void bb_progress_update(bb_progress_t *p, +int bb_progress_update(bb_progress_t *p, uoff_t beg_range, uoff_t transferred, uoff_t totalsize) FAST_FUNC; 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) * will be "totalsize" bytes. * If totalsize == 0, then it is unknown. */ -void FAST_FUNC bb_progress_update(bb_progress_t *p, +int FAST_FUNC bb_progress_update(bb_progress_t *p, uoff_t beg_size, uoff_t transferred, uoff_t totalsize) @@ -94,7 +94,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, * Do not update on every call * (we can be called on every network read!) */ - return; + return -1; } /* 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, } if (notty) fputc('\n', stderr); + return notty; } diff --git a/networking/wget.c b/networking/wget.c index 65262e19d..44c481a99 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -283,13 +283,15 @@ enum { #if ENABLE_FEATURE_WGET_STATUSBAR static void progress_meter(int flag) { + int notty; + if (option_mask32 & WGET_OPT_QUIET) return; if (flag == PROGRESS_START) bb_progress_init(&G.pmt, G.curfile); - bb_progress_update(&G.pmt, + notty = bb_progress_update(&G.pmt, G.beg_range, G.transferred, (G.chunked || !G.got_clen) ? 0 : G.beg_range + G.transferred + G.content_len @@ -297,7 +299,8 @@ static void progress_meter(int flag) if (flag == PROGRESS_END) { bb_progress_free(&G.pmt); - bb_putchar_stderr('\n'); + if (notty == 0) + bb_putchar_stderr('\n'); /* it's tty */ G.transferred = 0; } } -- cgit v1.2.3-55-g6feb From 624066f0cce8acaf2feb973f24942883b0600a0b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Nov 2018 19:24:57 +0100 Subject: tls: make tls_get_random() FAST_FUNC function old new delta tls_handshake 1977 1985 +8 tls_get_random 32 28 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 8/-4) Total: 4 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 2 +- networking/tls.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 2a0098674..1e0e0991c 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -337,7 +337,7 @@ static void dump_tls_record(const void *vp, int len) # define dump_tls_record(...) ((void)0) #endif -void tls_get_random(void *buf, unsigned len) +void FAST_FUNC tls_get_random(void *buf, unsigned len) { if (len != open_read_close("/dev/urandom", buf, len)) xfunc_die(); diff --git a/networking/tls.h b/networking/tls.h index 1d379c193..f2ef67aac 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -80,7 +80,7 @@ typedef int16_t int16; #define AES_BLOCK_SIZE 16 -void tls_get_random(void *buf, unsigned len); +void tls_get_random(void *buf, unsigned len) FAST_FUNC; #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) -- cgit v1.2.3-55-g6feb From 985702c892d94ac9656754b94402dee933abb156 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Nov 2018 13:47:44 +0100 Subject: tls: fix a thinko in GHASH optimization Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 84c90314f..b9a6a9b0a 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -87,7 +87,7 @@ static void GMULT(byte* X, byte* Y) // Resulting auth tag in s[] is also always AES_BLOCK_SIZE bytes. // // This allows some simplifications. -#define aSz AES_BLOCK_SIZE +#define aSz 13 #define sSz AES_BLOCK_SIZE void FAST_FUNC aesgcm_GHASH(byte* h, const byte* a, //unsigned aSz, -- cgit v1.2.3-55-g6feb From 941440cf166ef77ad82c4ead9eae3a8a2552a418 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Nov 2018 13:51:46 +0100 Subject: tls: in AES-GCM decoding, avoid memmove function old new delta xorbuf3 - 36 +36 xorbuf 24 12 -12 tls_xread_record 656 634 -22 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 36/-34) Total: 2 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 20 ++++++++++++++++---- networking/tls.h | 1 + networking/tls_aesgcm.c | 9 --------- networking/tls_aesgcm.h | 2 -- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 1e0e0991c..1f8c21f8b 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -343,6 +343,20 @@ void FAST_FUNC tls_get_random(void *buf, unsigned len) xfunc_die(); } +static void xorbuf3(void *dst, const void *src1, const void *src2, unsigned count) +{ + uint8_t *d = dst; + const uint8_t *s1 = src1; + const uint8_t* s2 = src2; + while (count--) + *d++ = *s1++ ^ *s2++; +} + +void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count) +{ + xorbuf3(dst, dst, src, count); +} + /* Nondestructively see the current hash value */ static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) { @@ -941,7 +955,6 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) memcpy(nonce, tls->server_write_IV, 4); memcpy(nonce + 4, buf, 8); - buf += 8; cnt = 1; remaining = size; @@ -952,12 +965,12 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) COUNTER(nonce) = htonl(cnt); /* yes, first cnt here is 2 (!) */ aes_encrypt_one_block(&tls->aes_decrypt, nonce, scratch); n = remaining > AES_BLOCK_SIZE ? AES_BLOCK_SIZE : remaining; - xorbuf(buf, scratch, n); + xorbuf3(buf, scratch, buf + 8, n); buf += n; remaining -= n; } - //aesgcm_GHASH(tls->H, aad, tls->outbuf + OUTBUF_PFX, size, authtag); + //aesgcm_GHASH(tls->H, aad, tls->inbuf + RECHDR_LEN, size, authtag); //COUNTER(nonce) = htonl(1); //aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); //xorbuf(authtag, scratch, sizeof(authtag)); @@ -1046,7 +1059,6 @@ static int tls_xread_record(tls_state_t *tls, const char *expected) sz -= 8 + AES_BLOCK_SIZE; /* we will overwrite nonce, drop hash */ tls_aesgcm_decrypt(tls, p, sz); - memmove(p, p + 8, sz); dbg("encrypted size:%u\n", sz); } else if (tls->min_encrypted_len_on_read > tls->MAC_size) { diff --git a/networking/tls.h b/networking/tls.h index f2ef67aac..4b0dc7459 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -81,6 +81,7 @@ typedef int16_t int16; #define AES_BLOCK_SIZE 16 void tls_get_random(void *buf, unsigned len) FAST_FUNC; +void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index b9a6a9b0a..db720e5f6 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -11,15 +11,6 @@ typedef uint32_t word32; #define XMEMSET memset #define XMEMCPY memcpy -void FAST_FUNC xorbuf(void* buf, const void* mask, unsigned count) -{ - word32 i; - byte* b = (byte*)buf; - const byte* m = (const byte*)mask; - for (i = 0; i < count; i++) - b[i] ^= m[i]; -} - /* from wolfssl-3.15.3/wolfcrypt/src/aes.c */ static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz) diff --git a/networking/tls_aesgcm.h b/networking/tls_aesgcm.h index 75694f3fa..d7e672e6e 100644 --- a/networking/tls_aesgcm.h +++ b/networking/tls_aesgcm.h @@ -4,8 +4,6 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ -void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; - void aesgcm_GHASH(uint8_t* h, const uint8_t* a, //unsigned aSz, const uint8_t* c, unsigned cSz, -- cgit v1.2.3-55-g6feb From 03569bc50f0d731aa3af94ab600adc59eaac3162 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Nov 2018 14:08:29 +0100 Subject: tls: speed up xor'ing of aligned 16-byte buffers function old new delta xorbuf_aligned_AES_BLOCK_SIZE - 23 +23 xwrite_encrypted 585 580 -5 aesgcm_GHASH 233 228 -5 GMULT 192 187 -5 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/3 up/down: 23/-15) Total: 8 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 34 ++++++++++++++++++++++++---------- networking/tls.h | 4 ++++ networking/tls_aesgcm.c | 15 ++++++++------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 1f8c21f8b..b774340ae 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -357,6 +357,20 @@ void FAST_FUNC xorbuf(void *dst, const void *src, unsigned count) xorbuf3(dst, dst, src, count); } +void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src) +{ + unsigned long *d = dst; + const unsigned long *s = src; + d[0] ^= s[0]; +#if ULONG_MAX <= 0xffffffffffffffff + d[1] ^= s[1]; + #if ULONG_MAX == 0xffffffff + d[2] ^= s[2]; + d[3] ^= s[3]; + #endif +#endif +} + /* Nondestructively see the current hash value */ static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) { @@ -802,10 +816,10 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty { #define COUNTER(v) (*(uint32_t*)(v + 12)) - uint8_t aad[13 + 3] ALIGNED(4); /* +3 creates [16] buffer, simplifying GHASH() */ - uint8_t nonce[12 + 4] ALIGNED(4); /* +4 creates space for AES block counter */ - uint8_t scratch[AES_BLOCK_SIZE] ALIGNED(4); //[16] - uint8_t authtag[AES_BLOCK_SIZE] ALIGNED(4); //[16] + uint8_t aad[13 + 3] ALIGNED_long; /* +3 creates [16] buffer, simplifying GHASH() */ + uint8_t nonce[12 + 4] ALIGNED_long; /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE] ALIGNED_long; //[16] + uint8_t authtag[AES_BLOCK_SIZE] ALIGNED_long; //[16] uint8_t *buf; struct record_hdr *xhdr; unsigned remaining; @@ -850,7 +864,7 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty aesgcm_GHASH(tls->H, aad, /*sizeof(aad),*/ tls->outbuf + OUTBUF_PFX, size, authtag /*, sizeof(authtag)*/); COUNTER(nonce) = htonl(1); aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); - xorbuf(authtag, scratch, sizeof(authtag)); + xorbuf_aligned_AES_BLOCK_SIZE(authtag, scratch); memcpy(buf, authtag, sizeof(authtag)); #undef COUNTER @@ -938,10 +952,10 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) { #define COUNTER(v) (*(uint32_t*)(v + 12)) - //uint8_t aad[13 + 3] ALIGNED(4); /* +3 creates [16] buffer, simplifying GHASH() */ - uint8_t nonce[12 + 4] ALIGNED(4); /* +4 creates space for AES block counter */ - uint8_t scratch[AES_BLOCK_SIZE] ALIGNED(4); //[16] - //uint8_t authtag[AES_BLOCK_SIZE] ALIGNED(4); //[16] + //uint8_t aad[13 + 3] ALIGNED_long; /* +3 creates [16] buffer, simplifying GHASH() */ + uint8_t nonce[12 + 4] ALIGNED_long; /* +4 creates space for AES block counter */ + uint8_t scratch[AES_BLOCK_SIZE] ALIGNED_long; //[16] + //uint8_t authtag[AES_BLOCK_SIZE] ALIGNED_long; //[16] unsigned remaining; unsigned cnt; @@ -973,7 +987,7 @@ static void tls_aesgcm_decrypt(tls_state_t *tls, uint8_t *buf, int size) //aesgcm_GHASH(tls->H, aad, tls->inbuf + RECHDR_LEN, size, authtag); //COUNTER(nonce) = htonl(1); //aes_encrypt_one_block(&tls->aes_encrypt, nonce, scratch); - //xorbuf(authtag, scratch, sizeof(authtag)); + //xorbuf_aligned_AES_BLOCK_SIZE(authtag, scratch); //memcmp(buf, authtag, sizeof(authtag)) || DIE("HASH DOES NOT MATCH!"); #undef COUNTER diff --git a/networking/tls.h b/networking/tls.h index 4b0dc7459..494ed78c4 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -81,8 +81,12 @@ typedef int16_t int16; #define AES_BLOCK_SIZE 16 void tls_get_random(void *buf, unsigned len) FAST_FUNC; + void xorbuf(void* buf, const void* mask, unsigned count) FAST_FUNC; +#define ALIGNED_long ALIGNED(sizeof(long)) +void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC; + #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) #define psFree(p, pool) free(p) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index db720e5f6..fd72540c4 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -50,8 +50,8 @@ static void RIGHTSHIFTX(byte* x) static void GMULT(byte* X, byte* Y) { - byte Z[AES_BLOCK_SIZE]; - byte V[AES_BLOCK_SIZE]; + byte Z[AES_BLOCK_SIZE] ALIGNED_long; + byte V[AES_BLOCK_SIZE] ALIGNED_long; int i, j; XMEMSET(Z, 0, AES_BLOCK_SIZE); @@ -62,7 +62,7 @@ static void GMULT(byte* X, byte* Y) for (j = 0; j < 8; j++) { if (y & 0x80) { - xorbuf(Z, V, AES_BLOCK_SIZE); + xorbuf_aligned_AES_BLOCK_SIZE(Z, V); } RIGHTSHIFTX(V); @@ -86,8 +86,8 @@ void FAST_FUNC aesgcm_GHASH(byte* h, byte* s //, unsigned sSz ) { - byte x[AES_BLOCK_SIZE] ALIGNED(4); - byte scratch[AES_BLOCK_SIZE] ALIGNED(4); + byte x[AES_BLOCK_SIZE] ALIGNED_long; + byte scratch[AES_BLOCK_SIZE] ALIGNED_long; word32 blocks, partial; //was: byte* h = aes->H; @@ -116,6 +116,7 @@ void FAST_FUNC aesgcm_GHASH(byte* h, blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; while (blocks--) { + //xorbuf_aligned_AES_BLOCK_SIZE(x, c); - c is not guaranteed to be aligned xorbuf(x, c, AES_BLOCK_SIZE); GMULT(x, h); c += AES_BLOCK_SIZE; @@ -124,7 +125,7 @@ void FAST_FUNC aesgcm_GHASH(byte* h, //XMEMSET(scratch, 0, AES_BLOCK_SIZE); //XMEMCPY(scratch, c, partial); //xorbuf(x, scratch, AES_BLOCK_SIZE); - xorbuf(x, c, partial); + xorbuf(x, c, partial);//same result as above GMULT(x, h); } } @@ -132,7 +133,7 @@ void FAST_FUNC aesgcm_GHASH(byte* h, /* Hash in the lengths of A and C in bits */ FlattenSzInBits(&scratch[0], aSz); FlattenSzInBits(&scratch[8], cSz); - xorbuf(x, scratch, AES_BLOCK_SIZE); + xorbuf_aligned_AES_BLOCK_SIZE(x, scratch); GMULT(x, h); /* Copy the result into s. */ -- cgit v1.2.3-55-g6feb From d2923b3d239d55565427533d3a9702cf1d27eb92 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Nov 2018 21:26:20 +0100 Subject: tls: fix is.gd again, fix AES-CBC using decrypt key instead of encrypt Signed-off-by: Denys Vlasenko --- networking/tls.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index b774340ae..f337bc0c9 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -58,11 +58,13 @@ // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" #define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA -// bug #11456: host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) -#define CIPHER_ID3 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - +// bug #11456: // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 -#define CIPHER_ID4 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +// host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009), +// and immediately throws alert 40 "handshake failure" in response to our hello record +// if ECDHE-ECDSA-AES-CBC-SHA is *before* ECDHE-RSA-AES-GCM cipher in the list! Server bug? +#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA #define NUM_CIPHERS 4 @@ -785,7 +787,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un /* Encrypt content+MAC+padding in place */ aes_cbc_encrypt( - &tls->aes_decrypt, /* selects 128/256 */ + &tls->aes_encrypt, /* selects 128/256 */ buf - AES_BLOCK_SIZE, /* IV */ buf, size, /* plaintext */ buf /* ciphertext */ -- cgit v1.2.3-55-g6feb From 5084bae61aac86fc6d13d48e59f5b98908de7d31 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Nov 2018 21:56:21 +0100 Subject: wget: code shrink function old new delta base64enc 53 46 -7 Signed-off-by: Denys Vlasenko --- networking/wget.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 44c481a99..58a51d9ff 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -233,20 +233,19 @@ struct globals { char *fname_out; /* where to direct output (-O) */ const char *proxy_flag; /* Use proxies if env vars are set */ const char *user_agent; /* "User-Agent" header field */ + int output_fd; + int o_flags; #if ENABLE_FEATURE_WGET_TIMEOUT unsigned timeout_seconds; - bool die_if_timed_out; + smallint die_if_timed_out; #endif - int output_fd; - int o_flags; smallint chunked; /* chunked transfer encoding */ smallint got_clen; /* got content-length: from server */ /* Local downloads do benefit from big buffer. * With 512 byte buffer, it was measured to be * an order of magnitude slower than with big one. */ - uint64_t just_to_align_next_member; - char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024]; + char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024] ALIGNED(sizeof(long)); } FIX_ALIASING; #define G (*ptr_to_globals) #define INIT_G() do { \ @@ -349,9 +348,8 @@ static void strip_ipv6_scope_id(char *host) /* Base64-encode character string. */ static char *base64enc(const char *str) { - unsigned len = strlen(str); - if (len > sizeof(G.wget_buf)/4*3 - 10) /* paranoia */ - len = sizeof(G.wget_buf)/4*3 - 10; + /* paranoia */ + unsigned len = strnlen(str, sizeof(G.wget_buf)/4*3 - 10); bb_uuencode(G.wget_buf, str, len, bb_uuenc_tbl_base64); return G.wget_buf; } -- cgit v1.2.3-55-g6feb From 0d18e5cab2159b55cb56962711d428246c197929 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 00:42:56 +0100 Subject: ntpd: do not SEGV on "-p keyno:192.168.1.1", show --help instead Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/networking/ntpd.c b/networking/ntpd.c index 4f8607244..041cac762 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -2539,6 +2539,7 @@ static NOINLINE void ntp_init(char **argv) int key_id; peer += 6; end = strchr(peer, ':'); + if (!end) bb_show_usage(); *end = '\0'; key_id = xatou_range(peer, 1, MAX_KEY_NUMBER); *end = ':'; -- cgit v1.2.3-55-g6feb From ab3c5e4c44c73dafeb01439882b48e2259611e34 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 00:53:19 +0100 Subject: tls: actually fill in CIPHER_ID3 value in hello message Signed-off-by: Denys Vlasenko --- networking/tls.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index f337bc0c9..7bdd58018 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -61,9 +61,7 @@ // bug #11456: // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 #define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -// host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009), -// and immediately throws alert 40 "handshake failure" in response to our hello record -// if ECDHE-ECDSA-AES-CBC-SHA is *before* ECDHE-RSA-AES-GCM cipher in the list! Server bug? +// host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) #define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA #define NUM_CIPHERS 4 @@ -1544,8 +1542,8 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) /*************************/ record->cipherid[7] = CIPHER_ID3 & 0xff; #endif #if CIPHER_ID4 - if ((CIPHER_ID4 >> 8) != 0) record->cipherid[6] = CIPHER_ID4 >> 8; - /*************************/ record->cipherid[7] = CIPHER_ID4 & 0xff; + if ((CIPHER_ID4 >> 8) != 0) record->cipherid[8] = CIPHER_ID4 >> 8; + /*************************/ record->cipherid[9] = CIPHER_ID4 & 0xff; #endif record->comprtypes_len = 1; -- cgit v1.2.3-55-g6feb From 23d0d8caf42b6b55e531b2405d949c6606ed3e85 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 12:01:44 +0100 Subject: tls: on x86, use xorbuf_aligned_AES_BLOCK_SIZE() even with non-aligned source function old new delta aesgcm_GHASH 228 223 -5 Signed-off-by: Denys Vlasenko --- networking/tls_aesgcm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index fd72540c4..32ca40260 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -116,8 +116,10 @@ void FAST_FUNC aesgcm_GHASH(byte* h, blocks = cSz / AES_BLOCK_SIZE; partial = cSz % AES_BLOCK_SIZE; while (blocks--) { - //xorbuf_aligned_AES_BLOCK_SIZE(x, c); - c is not guaranteed to be aligned - xorbuf(x, c, AES_BLOCK_SIZE); + if (BB_UNALIGNED_MEMACCESS_OK) // c is not guaranteed to be aligned + xorbuf_aligned_AES_BLOCK_SIZE(x, c); + else + xorbuf(x, c, AES_BLOCK_SIZE); GMULT(x, h); c += AES_BLOCK_SIZE; } -- cgit v1.2.3-55-g6feb From be5ca42e8d5f36145cca6c2120899e7e2ad4f0b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 14:03:59 +0100 Subject: tls: code shrink function old new delta aesgcm_GHASH 223 196 -27 Signed-off-by: Denys Vlasenko --- networking/tls.c | 2 +- networking/tls_aesgcm.c | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 7bdd58018..85a4e21dd 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -867,7 +867,6 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty xorbuf_aligned_AES_BLOCK_SIZE(authtag, scratch); memcpy(buf, authtag, sizeof(authtag)); -#undef COUNTER /* Write out */ xhdr = (void*)(tls->outbuf + OUTBUF_PFX - 8 - RECHDR_LEN); @@ -881,6 +880,7 @@ static void xwrite_encrypted_aesgcm(tls_state_t *tls, unsigned size, unsigned ty dump_raw_out(">> %s\n", xhdr, size); xwrite(tls->ofd, xhdr, size); dbg("wrote %u bytes\n", size); +#undef COUNTER } static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c index 32ca40260..688df85fb 100644 --- a/networking/tls_aesgcm.c +++ b/networking/tls_aesgcm.c @@ -87,8 +87,8 @@ void FAST_FUNC aesgcm_GHASH(byte* h, ) { byte x[AES_BLOCK_SIZE] ALIGNED_long; - byte scratch[AES_BLOCK_SIZE] ALIGNED_long; - word32 blocks, partial; +// byte scratch[AES_BLOCK_SIZE] ALIGNED_long; + unsigned blocks, partial; //was: byte* h = aes->H; //XMEMSET(x, 0, AES_BLOCK_SIZE); @@ -133,9 +133,17 @@ void FAST_FUNC aesgcm_GHASH(byte* h, } /* Hash in the lengths of A and C in bits */ - FlattenSzInBits(&scratch[0], aSz); - FlattenSzInBits(&scratch[8], cSz); - xorbuf_aligned_AES_BLOCK_SIZE(x, scratch); + //FlattenSzInBits(&scratch[0], aSz); + //FlattenSzInBits(&scratch[8], cSz); + //xorbuf_aligned_AES_BLOCK_SIZE(x, scratch); + // simpler: +#define P32(v) ((uint32_t*)v) + //P32(x)[0] ^= 0; + P32(x)[1] ^= SWAP_BE32(aSz * 8); + //P32(x)[2] ^= 0; + P32(x)[3] ^= SWAP_BE32(cSz * 8); +#undef P32 + GMULT(x, h); /* Copy the result into s. */ -- cgit v1.2.3-55-g6feb From a33b0082408a2c9b2b45db205aca41393ba826a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 14:28:32 +0100 Subject: tls: code shrink function old new delta tls_handshake 1993 1987 -6 Signed-off-by: Denys Vlasenko --- networking/tls.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 85a4e21dd..149f55ee4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -19,10 +19,6 @@ #include "tls.h" -//TLS 1.2 -#define TLS_MAJ 3 -#define TLS_MIN 3 - //Tested against kernel.org: //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE @@ -94,6 +90,11 @@ # define dbg_der(...) ((void)0) #endif + +//TLS 1.2 +#define TLS_MAJ 3 +#define TLS_MIN 3 + #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 /* 0x14 */ #define RECORD_TYPE_ALERT 21 /* 0x15 */ #define RECORD_TYPE_HANDSHAKE 22 /* 0x16 */ @@ -191,13 +192,13 @@ #define TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM8(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(128) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM8(256) Mac=AEAD */ -#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /*TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ -#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ -#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /*TLSv1.2 Kx=DH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(128) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM(256) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(128) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESCCM8(256) Mac=AEAD */ +#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /*TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /*TLSv1.2 Kx=DH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD */ #define TLS_AES_128_GCM_SHA256 0x1301 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD */ #define TLS_AES_256_GCM_SHA384 0x1302 /*TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD */ @@ -259,6 +260,13 @@ enum { // | The length (in bytes) of the following TLSCiphertext.fragment. // | The length MUST NOT exceed 2^14 + 2048. MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048, + + /* Bits for tls->flags */ + NEED_EC_KEY = 1 << 0, + GOT_CERT_RSA_KEY_ALG = 1 << 1, + GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused + GOT_EC_KEY = 1 << 3, + ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if CIPHER_ID1 set to allow one) }; struct record_hdr { @@ -267,13 +275,6 @@ struct record_hdr { uint8_t len16_hi, len16_lo; }; -enum { - NEED_EC_KEY = 1 << 0, - GOT_CERT_RSA_KEY_ALG = 1 << 1, - GOT_CERT_ECDSA_KEY_ALG = 1 << 2, - GOT_EC_KEY = 1 << 3, - ENCRYPTION_AESGCM = 1 << 4, -}; struct tls_handshake_data { /* In bbox, md5/sha1/sha256 ctx's are the same structure */ md5sha_ctx_t handshake_hash_ctx; @@ -1379,7 +1380,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) } else if (memcmp(der, OID_ECDSA_KEY_ALG, sizeof(OID_ECDSA_KEY_ALG)) == 0) { dbg("ECDSA key\n"); - tls->flags |= GOT_CERT_ECDSA_KEY_ALG; + //UNUSED: tls->flags |= GOT_CERT_ECDSA_KEY_ALG; } else bb_error_msg_and_die("not RSA or ECDSA cert"); } -- cgit v1.2.3-55-g6feb From eb53d01be54caf0208e4006c089d7841fe4a0f57 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 14:45:55 +0100 Subject: tls: code shrink function old new delta xwrite_and_update_handshake_hash 81 80 -1 tls_handshake 1987 1957 -30 Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 - networking/tls.c | 27 ++++++++++++--------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 883457c0d..ebd090e18 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -752,7 +752,6 @@ typedef struct tls_state { unsigned min_encrypted_len_on_read; uint16_t cipher_id; - uint8_t encrypt_on_write; unsigned MAC_size; unsigned key_size; unsigned IV_size; diff --git a/networking/tls.c b/networking/tls.c index 149f55ee4..9b4298de7 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -267,6 +267,7 @@ enum { GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused GOT_EC_KEY = 1 << 3, ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if CIPHER_ID1 set to allow one) + ENCRYPT_ON_WRITE = 1 << 5, }; struct record_hdr { @@ -299,6 +300,13 @@ static unsigned get24be(const uint8_t *p) } #if TLS_DEBUG +/* Nondestructively see the current hash value */ +static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) +{ + md5sha_ctx_t ctx_copy = *ctx; /* struct copy */ + return sha_end(&ctx_copy, buffer); +} + static void dump_hex(const char *fmt, const void *vp, int len) { char hexbuf[32 * 1024 + 4]; @@ -372,18 +380,6 @@ void FAST_FUNC xorbuf_aligned_AES_BLOCK_SIZE(void *dst, const void *src) #endif } -/* Nondestructively see the current hash value */ -static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) -{ - md5sha_ctx_t ctx_copy = *ctx; /* struct copy */ - return sha_end(&ctx_copy, buffer); -} - -static ALWAYS_INLINE unsigned get_handshake_hash(tls_state_t *tls, void *buffer) -{ - return sha_peek(&tls->hsd->handshake_hash_ctx, buffer); -} - #if !TLS_DEBUG_HASH # define hash_handshake(tls, fmt, buffer, len) \ hash_handshake(tls, buffer, len) @@ -910,7 +906,7 @@ static void xwrite_handshake_record(tls_state_t *tls, unsigned size) static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) { - if (!tls->encrypt_on_write) { + if (!(tls->flags & ENCRYPT_ON_WRITE)) { uint8_t *buf; xwrite_handshake_record(tls, size); @@ -2032,7 +2028,8 @@ static void send_client_finished(tls_state_t *tls) fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); - len = get_handshake_hash(tls, handshake_hash); + len = sha_end(&tls->hsd->handshake_hash_ctx, handshake_hash); + prf_hmac_sha256(/*tls,*/ record->prf_result, sizeof(record->prf_result), tls->hsd->master_secret, sizeof(tls->hsd->master_secret), @@ -2137,7 +2134,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) send_change_cipher_spec(tls); /* from now on we should send encrypted */ /* tls->write_seq64_be = 0; - already is */ - tls->encrypt_on_write = 1; + tls->flags |= ENCRYPT_ON_WRITE; send_client_finished(tls); -- cgit v1.2.3-55-g6feb From a6192f347fb87289c9cfdc4d57b126d704eba0de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 16:17:26 +0100 Subject: tls: do not leak RSA key function old new delta tls_handshake 1957 2059 +102 Signed-off-by: Denys Vlasenko --- networking/tls.c | 1 + networking/tls_rsa.h | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/networking/tls.c b/networking/tls.c index 9b4298de7..9833a0adb 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -2168,6 +2168,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) /* application data can be sent/received */ /* free handshake data */ + psRsaKey_clear(&tls->hsd->server_rsa_pub_key); // if (PARANOIA) // memset(tls->hsd, 0, tls->hsd->hsd_size); free(tls->hsd); diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h index f42923ff5..82bea2a67 100644 --- a/networking/tls_rsa.h +++ b/networking/tls_rsa.h @@ -13,6 +13,18 @@ typedef struct { //bbox psPool_t *pool; } psRsaKey_t; +static ALWAYS_INLINE void psRsaKey_clear(psRsaKey_t *key) +{ + pstm_clear(&key->N); + pstm_clear(&key->e); + pstm_clear(&key->d); + pstm_clear(&key->p); + pstm_clear(&key->q); + pstm_clear(&key->dP); + pstm_clear(&key->dQ); + pstm_clear(&key->qP); +} + #define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \ psRsaEncryptPub( key, in, inlen, out, outlen) int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, -- cgit v1.2.3-55-g6feb From 330d7f53f7890c0fbafa5b4769ce4ef23e734659 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 17:27:48 +0100 Subject: tls: add a comment on expanding list of supported ciphers Signed-off-by: Denys Vlasenko --- networking/tls.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 9833a0adb..e64e84fcd 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -50,17 +50,39 @@ // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) -#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer +#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" -#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA +#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x003C // bug #11456: // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 -#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F // host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) -#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009 #define NUM_CIPHERS 4 +//TODO: we can support all these: +// TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C +// TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D +// TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C +// TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D +// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +// TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A +// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +// TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 +// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 +////TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 - can't do SHA384 yet +// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 +////TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 - can't do SHA384 yet +// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B +// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C +// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F +// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 +//possibly these too: +// TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 +// TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 +// TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 +////TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 - can't do SHA384 yet #define TLS_DEBUG 0 @@ -142,6 +164,10 @@ #define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */ #define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ #define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD */ +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ #define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ @@ -161,10 +187,7 @@ #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384 */ #define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ #define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ - /* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */ -#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD */ -#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD */ #define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */ -- cgit v1.2.3-55-g6feb From 838b88c044f04af07a260313f0f18ead5eb0fc6f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Nov 2018 18:52:47 +0100 Subject: tls: fix comments Signed-off-by: Denys Vlasenko --- networking/tls.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/networking/tls.c b/networking/tls.c index e64e84fcd..66d62fe3d 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -52,7 +52,7 @@ // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) #define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" -#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x003C +#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F // bug #11456: // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 @@ -62,6 +62,8 @@ #define NUM_CIPHERS 4 //TODO: we can support all these: +// TLS_RSA_WITH_AES_128_CBC_SHA 0x002F +// TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 // TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C // TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D // TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C @@ -324,11 +326,13 @@ static unsigned get24be(const uint8_t *p) #if TLS_DEBUG /* Nondestructively see the current hash value */ +# if TLS_DEBUG_HASH static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) { md5sha_ctx_t ctx_copy = *ctx; /* struct copy */ return sha_end(&ctx_copy, buffer); } +# endif static void dump_hex(const char *fmt, const void *vp, int len) { -- cgit v1.2.3-55-g6feb From ca7cdd4b0350d47445f9c02adc161ebcb41b4c20 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 00:17:10 +0100 Subject: tls: add support for 8 more cipher ids - all tested to work function old new delta tls_handshake 2059 2116 +57 static.ciphers - 30 +30 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 87/0) Total: 87 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 204 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 87 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 66d62fe3d..e76a78585 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -19,6 +19,10 @@ #include "tls.h" +// works against "openssl s_server -cipher NULL" +// and against wolfssl-3.9.10-stable/examples/server/server.c: +#define ALLOW_RSA_NULL_SHA256 0 // for testing (does everything except encrypting) + //Tested against kernel.org: //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE @@ -35,10 +39,6 @@ //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE -// works against "openssl s_server -cipher NULL" -// and against wolfssl-3.9.10-stable/examples/server/server.c: -//#define CIPHER_ID1 TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) - // works against wolfssl-3.9.10-stable/examples/server/server.c // works for kernel.org // does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) @@ -50,41 +50,15 @@ // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) -#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D +//#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" -#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F +//#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F // bug #11456: // ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305 -#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F +//#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F // host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009) -#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009 - -#define NUM_CIPHERS 4 -//TODO: we can support all these: -// TLS_RSA_WITH_AES_128_CBC_SHA 0x002F -// TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 -// TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C -// TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D -// TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C -// TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D -// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 -// TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A -// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 -// TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 -// TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 -////TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 - can't do SHA384 yet -// TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 -////TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 - can't do SHA384 yet -// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B -// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C -// TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F -// TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 -//possibly these too: -// TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 -// TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 -// TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 -////TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 - can't do SHA384 yet +//#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009 #define TLS_DEBUG 0 @@ -291,7 +265,7 @@ enum { GOT_CERT_RSA_KEY_ALG = 1 << 1, GOT_CERT_ECDSA_KEY_ALG = 1 << 2, // so far unused GOT_EC_KEY = 1 << 3, - ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if CIPHER_ID1 set to allow one) + ENCRYPTION_AESGCM = 1 << 4, // else AES-SHA (or NULL-SHA if ALLOW_RSA_NULL_SHA256=1) ENCRYPT_ON_WRITE = 1 << 5, }; @@ -676,7 +650,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un uint8_t padding_length; xhdr = (void*)(buf - RECHDR_LEN); - if (CIPHER_ID1 != TLS_RSA_WITH_NULL_SHA256 /* if "no encryption" can't be selected */ + if (!ALLOW_RSA_NULL_SHA256 /* if "no encryption" can't be selected */ || tls->cipher_id != TLS_RSA_WITH_NULL_SHA256 /* or if it wasn't selected */ ) { xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCK_SIZE); /* place for IV */ @@ -734,7 +708,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un // -------- ----------- ---------- -------------- // SHA HMAC-SHA1 20 20 // SHA256 HMAC-SHA256 32 32 - if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256 + if (ALLOW_RSA_NULL_SHA256 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256 ) { /* No encryption, only signing */ @@ -1478,6 +1452,39 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { +#define NUM_CIPHERS (12 + ALLOW_RSA_NULL_SHA256) + static const uint8_t ciphers[] = { + 0x00,(1 + NUM_CIPHERS) * 2, //len16_be + 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV + /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ + 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ + 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ + 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA + // 0xC0,0x14, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - openssl s_server ... -cipher ECDHE-RSA-AES256-SHA: "No ciphers enabled for max supported SSL/TLS version" + 0xC0,0x23, // 4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ + // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0xC0,0x27, // 5 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 + // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0xC0,0x2B, // 6 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ + // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" + 0xC0,0x2F, // 7 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 + // 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" + //possibly these too: + // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0x00,0x2F, // 8 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA + 0x00,0x35, // 9 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA + 0x00,0x3C, //10 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 + 0x00,0x3D, //11 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 + 0x00,0x9C, //12 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 + // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" +#if ALLOW_RSA_NULL_SHA256 + 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 +#endif + 0x01,0x00, //not a cipher - comprtypes_len, comprtype + }; static const uint8_t supported_groups[] = { 0x00,0x0a, //extension_type: "supported_groups" 0x00,0x04, //ext len @@ -1502,7 +1509,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */ + uint8_t cipherid[(1 + NUM_CIPHERS) * 2]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): @@ -1550,28 +1557,8 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) memset(record->rand32, 0x11, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ - /* record->cipherid_len16_hi = 0; */ - record->cipherid_len16_lo = sizeof(record->cipherid); - /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ - /*record->cipherid[0] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */ - record->cipherid[1] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff; - if ((CIPHER_ID1 >> 8) != 0) record->cipherid[2] = CIPHER_ID1 >> 8; - /*************************/ record->cipherid[3] = CIPHER_ID1 & 0xff; -#if CIPHER_ID2 - if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8; - /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff; -#endif -#if CIPHER_ID3 - if ((CIPHER_ID3 >> 8) != 0) record->cipherid[6] = CIPHER_ID3 >> 8; - /*************************/ record->cipherid[7] = CIPHER_ID3 & 0xff; -#endif -#if CIPHER_ID4 - if ((CIPHER_ID4 >> 8) != 0) record->cipherid[8] = CIPHER_ID4 >> 8; - /*************************/ record->cipherid[9] = CIPHER_ID4 & 0xff; -#endif - - record->comprtypes_len = 1; - /* record->comprtypes[0] = 0; */ + BUILD_BUG_ON(sizeof(ciphers) != 2 + (1 + NUM_CIPHERS) * 2 + 2); + memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); ptr = (void*)(record + 1); *ptr++ = ext_len >> 8; @@ -1626,6 +1613,7 @@ static void get_server_hello(tls_state_t *tls) struct server_hello *hp; uint8_t *cipherid; + uint8_t cipherid1; unsigned cipher; int len, len24; @@ -1659,39 +1647,81 @@ static void get_server_hello(tls_state_t *tls) len24 += 32; /* what len would be if session id would be present */ } - if (len24 < 70 -// || cipherid[0] != (CIPHER_ID >> 8) -// || cipherid[1] != (CIPHER_ID & 0xff) -// || cipherid[2] != 0 /* comprtype */ - ) { + if (len24 < 70) bad_record_die(tls, "'server hello'", len); - } dbg("<< SERVER_HELLO\n"); memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); - tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1]; + /* Set up encryption params based on selected cipher */ +#if 0 + 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ + 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ + 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA + // 0xC0,0x14, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - openssl s_server ... -cipher ECDHE-RSA-AES256-SHA: "No ciphers enabled for max supported SSL/TLS version" + 0xC0,0x23, // 4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ + // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0xC0,0x27, // 5 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 + // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0xC0,0x2B, // 6 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ + // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" + 0xC0,0x2F, // 7 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 + // 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" + //possibly these too: + // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet + 0x00,0x2F, // 8 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA + 0x00,0x35, // 9 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA + 0x00,0x3C, //10 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 + 0x00,0x3D, //11 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 + 0x00,0x9C, //12 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 + // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" + 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 +#endif + cipherid1 = cipherid[1]; + tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid1; dbg("server chose cipher %04x\n", cipher); - - if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA - || cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ) { - if (cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) - tls->flags |= NEED_EC_KEY; - tls->key_size = AES128_KEYSIZE; - tls->MAC_size = SHA1_OUTSIZE; - } - else - if (cipher == TLS_RSA_WITH_AES_256_CBC_SHA256) { - tls->key_size = AES256_KEYSIZE; - tls->MAC_size = SHA256_OUTSIZE; - } - else { /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */ - tls->flags |= NEED_EC_KEY | ENCRYPTION_AESGCM; - tls->key_size = AES128_KEYSIZE; - /* tls->MAC_size = 0; */ - tls->IV_size = 4; + tls->key_size = AES256_KEYSIZE; + tls->MAC_size = SHA256_OUTSIZE; + /*tls->IV_size = 0; - already is */ + if (cipherid[0] == 0xC0) { + /* All C0xx are ECDHE */ + tls->flags |= NEED_EC_KEY; + if (cipherid1 & 1) { + /* Odd numbered C0xx use AES128 (even ones use AES256) */ + tls->key_size = AES128_KEYSIZE; + } + if (cipherid1 <= 0x14) { + tls->MAC_size = SHA1_OUTSIZE; + } else + if (cipherid1 >= 0x2B && cipherid1 <= 0x30) { + /* C02B,2C,2F,30 are AES-GCM */ + tls->flags |= ENCRYPTION_AESGCM; + tls->MAC_size = 0; + tls->IV_size = 4; + } + } else { + /* All 00xx are RSA */ + if (cipherid1 == 0x2F + || cipherid1 == 0x3C + || cipherid1 == 0x9C + ) { + tls->key_size = AES128_KEYSIZE; + } + if (cipherid1 <= 0x35) { + tls->MAC_size = SHA1_OUTSIZE; + } else + if (cipherid1 == 0x9C || cipherid1 == 0x9D) { + /* 009C,9D are AES-GCM */ + tls->flags |= ENCRYPTION_AESGCM; + tls->MAC_size = 0; + tls->IV_size = 4; + } } + dbg("key_size:%u MAC_size:%u IV_size:%u\n", tls->key_size, tls->MAC_size, tls->IV_size); + /* Handshake hash eventually destined to FINISHED record * is sha256 regardless of cipher * (at least for all ciphers defined by RFC5246). @@ -2171,7 +2201,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) bad_record_die(tls, "switch to encrypted traffic", len); dbg("<< CHANGE_CIPHER_SPEC\n"); - if (CIPHER_ID1 == TLS_RSA_WITH_NULL_SHA256 + if (ALLOW_RSA_NULL_SHA256 && tls->cipher_id == TLS_RSA_WITH_NULL_SHA256 ) { tls->min_encrypted_len_on_read = tls->MAC_size; -- cgit v1.2.3-55-g6feb From d4681c7293da6aeb901101b5bc239229f4963926 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 10:33:23 +0100 Subject: tls: simplify hmac_begin() function old new delta hmac_begin 196 158 -38 Signed-off-by: Denys Vlasenko --- networking/tls.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index e76a78585..002983273 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -224,7 +224,7 @@ enum { OUTBUF_PFX = 8 + AES_BLOCK_SIZE, /* header + IV */ OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */ - // RFC 5246 + // RFC 5246: // | 6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext // | records carrying data in chunks of 2^14 bytes or less. Client @@ -405,7 +405,7 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer #endif } -// RFC 2104 +// RFC 2104: // HMAC(key, text) based on a hash H (say, sha256) is: // ipad = [0x36 x INSIZE] // opad = [0x5c x INSIZE] @@ -448,7 +448,7 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, { uint8_t key_xor_ipad[SHA_INSIZE]; uint8_t key_xor_opad[SHA_INSIZE]; - uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE]; +// uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE]; unsigned i; // "The authentication key can be of any length up to INSIZE, the @@ -456,10 +456,18 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, // than INSIZE bytes will first hash the key using H and then use the // resultant OUTSIZE byte string as the actual key to HMAC." if (key_size > SHA_INSIZE) { - md5sha_ctx_t ctx; - begin(&ctx); - md5sha_hash(&ctx, key, key_size); - key_size = sha_end(&ctx, tempkey); + bb_error_msg_and_die("HMAC key>64"); //does not happen (yet?) +// md5sha_ctx_t ctx; +// begin(&ctx); +// md5sha_hash(&ctx, key, key_size); +// key_size = sha_end(&ctx, tempkey); +// //key = tempkey; - right? RIGHT? why does it work without this? +// // because SHA_INSIZE is 64, but hmac() is always called with +// // key_size = tls->MAC_size = SHA1/256_OUTSIZE (20 or 32), +// // and prf_hmac_sha256() -> hmac_sha256() key sizes are: +// // - RSA_PREMASTER_SIZE is 48 +// // - CURVE25519_KEYSIZE is 32 +// // - master_secret[] is 48 } for (i = 0; i < key_size; i++) { @@ -519,8 +527,9 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un // document and in TLS documents published prior to this document when // TLS 1.2 is negotiated. // ^^^^^^^^^^^^^ IMPORTANT! -// PRF uses sha256 regardless of cipher (at least for all ciphers -// defined by RFC5246). It's not sha1 for AES_128_CBC_SHA! +// PRF uses sha256 regardless of cipher for all ciphers +// defined by RFC 5246. It's not sha1 for AES_128_CBC_SHA! +// However, for _SHA384 ciphers, it's sha384. See RFC 5288,5289. //... // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + // HMAC_hash(secret, A(2) + seed) + @@ -542,6 +551,12 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un // PRF(secret, label, seed) = P_(secret, label + seed) // // The label is an ASCII string. +// +// RFC 5288: +// For cipher suites ending with _SHA256, the PRF is the TLS PRF +// with SHA-256 as the hash function. +// For cipher suites ending with _SHA384, the PRF is the TLS PRF +// with SHA-384 as the hash function. static void prf_hmac_sha256(/*tls_state_t *tls,*/ uint8_t *outbuf, unsigned outbuf_size, uint8_t *secret, unsigned secret_size, @@ -675,7 +690,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un size += tls->MAC_size; - // RFC 5246 + // RFC 5246: // 6.2.3.1. Null or Standard Stream Cipher // // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) @@ -1467,6 +1482,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 0xC0,0x2B, // 6 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" +//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? 0xC0,0x2F, // 7 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 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" //possibly these too: @@ -1489,7 +1505,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0x00,0x0a, //extension_type: "supported_groups" 0x00,0x04, //ext len 0x00,0x02, //list len - 0x00,0x1d, //curve_x25519 (rfc7748) + 0x00,0x1d, //curve_x25519 (RFC 7748) //0x00,0x17, //curve_secp256r1 //0x00,0x18, //curve_secp384r1 //0x00,0x19, //curve_secp521r1 -- cgit v1.2.3-55-g6feb From f69f207490dd25b89380c21e816b1f6644a7529f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 13:00:28 +0100 Subject: libbb: add comment on sha384 Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 5 +++++ 1 file changed, 5 insertions(+) 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[] = { }; #endif /* NEED_SHA512 */ +// Note: SHA-384 is identical to SHA-512, except that initial hash values are +// 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, +// 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4, +// and the output is constructed by omitting last two 64-bit words of it. + /* Initialize structure containing state of computation. (FIPS 180-2:5.3.2) */ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) -- cgit v1.2.3-55-g6feb From d9f6c3b091cc1a2a824520e22764ea1538957f3d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 15:55:41 +0100 Subject: tls: speed up prf_hmac_sha256() function old new delta hmac_sha_precomputed - 58 +58 prf_hmac_sha256 181 222 +41 hmac_sha256 68 - -68 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 99/-68) Total: 31 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 79 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 002983273..6c87e12ff 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -420,29 +420,6 @@ typedef struct hmac_precomputed { md5sha_ctx_t hashed_key_xor_opad; } hmac_precomputed_t; -static unsigned hmac_sha_precomputed_v( - hmac_precomputed_t *pre, - uint8_t *out, - va_list va) -{ - uint8_t *text; - unsigned len; - - /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ - /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ - - /* calculate out = H((key XOR ipad) + text) */ - while ((text = va_arg(va, uint8_t*)) != NULL) { - unsigned text_size = va_arg(va, unsigned); - md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size); - } - len = sha_end(&pre->hashed_key_xor_ipad, out); - - /* out = H((key XOR opad) + out) */ - md5sha_hash(&pre->hashed_key_xor_opad, out, len); - return sha_end(&pre->hashed_key_xor_opad, out); -} - typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) { @@ -485,26 +462,43 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); } -static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) +static unsigned hmac_sha_precomputed_v( + hmac_precomputed_t *pre, + uint8_t *out, + va_list va) +{ + uint8_t *text; + unsigned len; + + /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ + /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ + + /* calculate out = H((key XOR ipad) + text) */ + while ((text = va_arg(va, uint8_t*)) != NULL) { + unsigned text_size = va_arg(va, unsigned); + md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size); + } + len = sha_end(&pre->hashed_key_xor_ipad, out); + + /* out = H((key XOR opad) + out) */ + md5sha_hash(&pre->hashed_key_xor_opad, out, len); + return sha_end(&pre->hashed_key_xor_opad, out); +} + +static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out, ...) { hmac_precomputed_t pre; va_list va; unsigned len; - va_start(va, key_size); - - hmac_begin(&pre, key, key_size, - (tls->MAC_size == SHA256_OUTSIZE) - ? sha256_begin - : sha1_begin - ); + va_start(va, out); + pre = *pre_init; /* struct copy */ len = hmac_sha_precomputed_v(&pre, out, va); - va_end(va); return len; } -static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, unsigned key_size, ...) +static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) { hmac_precomputed_t pre; va_list va; @@ -512,7 +506,11 @@ static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, un va_start(va, key_size); - hmac_begin(&pre, key, key_size, sha256_begin); + hmac_begin(&pre, key, key_size, + (tls->MAC_size == SHA256_OUTSIZE) + ? sha256_begin + : sha1_begin + ); len = hmac_sha_precomputed_v(&pre, out, va); va_end(va); @@ -563,6 +561,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ const char *label, uint8_t *seed, unsigned seed_size) { + hmac_precomputed_t pre; uint8_t a[TLS_MAX_MAC_SIZE]; uint8_t *out_p = outbuf; unsigned label_size = strlen(label); @@ -570,28 +569,28 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/ /* In P_hash() calculation, "seed" is "label + seed": */ #define SEED label, label_size, seed, seed_size -#define SECRET secret, secret_size #define A a, MAC_size + hmac_begin(&pre, secret, secret_size, sha256_begin); + /* A(1) = HMAC_hash(secret, seed) */ - hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL); -//TODO: convert hmac to precomputed + hmac_sha_precomputed(&pre, a, SEED, NULL); for (;;) { /* HMAC_hash(secret, A(1) + seed) */ if (outbuf_size <= MAC_size) { /* Last, possibly incomplete, block */ /* (use a[] as temp buffer) */ - hmac_sha256(/*tls,*/ a, SECRET, A, SEED, NULL); + hmac_sha_precomputed(&pre, a, A, SEED, NULL); memcpy(out_p, a, outbuf_size); return; } /* Not last block. Store directly to result buffer */ - hmac_sha256(/*tls,*/ out_p, SECRET, A, SEED, NULL); + hmac_sha_precomputed(&pre, out_p, A, SEED, NULL); out_p += MAC_size; outbuf_size -= MAC_size; /* A(2) = HMAC_hash(secret, A(1)) */ - hmac_sha256(/*tls,*/ a, SECRET, A, NULL); + hmac_sha_precomputed(&pre, a, A, NULL); } #undef A #undef SECRET -- cgit v1.2.3-55-g6feb From 60f784027e0e755a9338c548101eefb0bf7a1be6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 16:30:22 +0100 Subject: tls: cipher 009D is not yet supported, don't test for it function old new delta tls_handshake 2116 2108 -8 Signed-off-by: Denys Vlasenko --- networking/tls.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 6c87e12ff..750a152e8 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1629,7 +1629,6 @@ static void get_server_hello(tls_state_t *tls) struct server_hello *hp; uint8_t *cipherid; uint8_t cipherid1; - unsigned cipher; int len, len24; len = tls_xread_handshake_block(tls, 74 - 32); @@ -1696,8 +1695,7 @@ static void get_server_hello(tls_state_t *tls) 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 #endif cipherid1 = cipherid[1]; - tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid1; - dbg("server chose cipher %04x\n", cipher); + tls->cipher_id = 0x100 * cipherid[0] + cipherid1; tls->key_size = AES256_KEYSIZE; tls->MAC_size = SHA256_OUTSIZE; /*tls->IV_size = 0; - already is */ @@ -1728,13 +1726,14 @@ static void get_server_hello(tls_state_t *tls) if (cipherid1 <= 0x35) { tls->MAC_size = SHA1_OUTSIZE; } else - if (cipherid1 == 0x9C || cipherid1 == 0x9D) { + if (cipherid1 == 0x9C /*|| cipherid1 == 0x9D*/) { /* 009C,9D are AES-GCM */ tls->flags |= ENCRYPTION_AESGCM; tls->MAC_size = 0; tls->IV_size = 4; } } + dbg("server chose cipher %04x\n", tls->cipher_id); dbg("key_size:%u MAC_size:%u IV_size:%u\n", tls->key_size, tls->MAC_size, tls->IV_size); /* Handshake hash eventually destined to FINISHED record -- cgit v1.2.3-55-g6feb From 2eb04290f99101f93f082aa7c38e30268a2a885c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 16:39:19 +0100 Subject: tls: enable TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 cipher function old new delta static.ciphers 30 32 +2 Signed-off-by: Denys Vlasenko --- networking/tls.c | 58 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 750a152e8..1e42a39a4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -44,11 +44,11 @@ // does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) // getting alert 40 "handshake failure" at once // with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256 -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384 -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 -// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 -// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-SHA256 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-GCM-SHA384 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-GCM-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) //#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D // Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" @@ -1466,7 +1466,7 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { -#define NUM_CIPHERS (12 + ALLOW_RSA_NULL_SHA256) +#define NUM_CIPHERS (13 + ALLOW_RSA_NULL_SHA256) static const uint8_t ciphers[] = { 0x00,(1 + NUM_CIPHERS) * 2, //len16_be 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV @@ -1474,26 +1474,26 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA - // 0xC0,0x14, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - openssl s_server ... -cipher ECDHE-RSA-AES256-SHA: "No ciphers enabled for max supported SSL/TLS version" - 0xC0,0x23, // 4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ + 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) + 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0xC0,0x27, // 5 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 + 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0xC0,0x2B, // 6 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ + 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" //TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? - 0xC0,0x2F, // 7 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 + 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 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" //possibly these too: // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0x00,0x2F, // 8 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA - 0x00,0x35, // 9 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA - 0x00,0x3C, //10 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 - 0x00,0x3D, //11 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 - 0x00,0x9C, //12 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 + 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA + 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA + 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 + 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 + 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" #if ALLOW_RSA_NULL_SHA256 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 @@ -1672,25 +1672,25 @@ static void get_server_hello(tls_state_t *tls) 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA - // 0xC0,0x14, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - openssl s_server ... -cipher ECDHE-RSA-AES256-SHA: "No ciphers enabled for max supported SSL/TLS version" - 0xC0,0x23, // 4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ + 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) + 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0xC0,0x27, // 5 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 + 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0xC0,0x2B, // 6 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ + 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" - 0xC0,0x2F, // 7 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 + 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 // 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" //possibly these too: // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet - 0x00,0x2F, // 8 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA - 0x00,0x35, // 9 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA - 0x00,0x3C, //10 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 - 0x00,0x3D, //11 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 - 0x00,0x9C, //12 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 + 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA + 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA + 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 + 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 + 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 #endif @@ -2254,12 +2254,12 @@ static void tls_xwrite(tls_state_t *tls, int len) // To run a test server using openssl: // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' -// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 +// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 // // Unencryped SHA256 example: // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' -// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL -// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 +// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -cipher NULL +// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -cipher NULL-SHA256 void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags) { -- cgit v1.2.3-55-g6feb From 8a46c74f8dcb39ad1b3f7682a83ef3ed6d3697de Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Nov 2018 17:33:17 +0100 Subject: tls: add _anon_ cipher definitions Signed-off-by: Denys Vlasenko --- networking/tls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/networking/tls.c b/networking/tls.c index 1e42a39a4..6a004caf8 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -144,6 +144,8 @@ #define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F /*TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD */ +#define TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 /* RFC 5288 */ +#define TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 /* RFC 5288 */ #define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ #define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ @@ -155,6 +157,8 @@ #define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */ #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1 */ #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /*TLSv1 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1 */ +#define TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 /* RFC 4492 */ +#define TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 /* RFC 4492 */ #define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256 */ #define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384 */ #define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ -- cgit v1.2.3-55-g6feb From dffc8ff6a638a4ae865821eb2d0852124c096c11 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Nov 2018 10:35:10 +0100 Subject: tls: add ECDHE_PSK and remove ARIA cipher ids Signed-off-by: Denys Vlasenko --- networking/tls.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 6a004caf8..b0eb7b90c 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -176,17 +176,13 @@ #define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /*TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD */ #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ #define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /* From http://wiki.mozilla.org/Security/Server_Side_TLS */ /* and 'openssl ciphers -V -stdname' */ -#define TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ -#define TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /*TLSv1.2 Kx=RSA Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ -#define TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ -#define TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /*TLSv1.2 Kx=DH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ -#define TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(128) Mac=AEAD */ -#define TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /*TLSv1.2 Kx=ECDH Au=ECDSA Enc=ARIAGCM(256) Mac=AEAD */ -#define TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(128) Mac=AEAD */ -#define TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /*TLSv1.2 Kx=ECDH Au=RSA Enc=ARIAGCM(256) Mac=AEAD */ #define TLS_RSA_WITH_AES_128_CCM 0xC09C /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(128) Mac=AEAD */ #define TLS_RSA_WITH_AES_256_CCM 0xC09D /*TLSv1.2 Kx=RSA Au=RSA Enc=AESCCM(256) Mac=AEAD */ #define TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /*TLSv1.2 Kx=DH Au=RSA Enc=AESCCM(128) Mac=AEAD */ -- cgit v1.2.3-55-g6feb From 7b42f8fc76d78fe9c6b0cbe15e1425f2fd9fb5e8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 21 Nov 2018 10:11:01 +0000 Subject: Tweaks to build process for embedded scripts - Force a rebuild if a script in applets_sh is changed. - Move the dummy usage messages for custom applets to usage.h and change the name from 'dummy' to 'scripted'. - Hide an error from gen_build_files.sh if an embed directory exists but is empty. - Tidy up embedded_scripts script. v2: Remove a couple of unnecessary tests in embedded_scripts, as pointed out by Xabier Oneca. Drop the stripping of comments. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- Makefile | 2 +- include/applets.src.h | 6 ------ include/usage.src.h | 3 +++ scripts/embedded_scripts | 22 ++++++++-------------- scripts/gen_build_files.sh | 4 ++-- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 4b5a01df9..f0b4da234 100644 --- a/Makefile +++ b/Makefile @@ -853,7 +853,7 @@ quiet_cmd_split_autoconf = SPLIT include/autoconf.h -> include/config/* quiet_cmd_gen_embedded_scripts = GEN include/embedded_scripts.h cmd_gen_embedded_scripts = $(srctree)/scripts/embedded_scripts include/embedded_scripts.h $(srctree)/embed $(srctree)/applets_sh #bbox# piggybacked generation of few .h files -include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard $(srctree)/embed/*) $(srctree)/scripts/embedded_scripts +include/config/MARKER: scripts/basic/split-include include/autoconf.h $(wildcard $(srctree)/embed/*) $(wildcard $(srctree)/applets_sh/*) $(srctree)/scripts/embedded_scripts $(call cmd,split_autoconf) $(call cmd,gen_bbconfigopts) $(call cmd,gen_common_bufsiz) diff --git a/include/applets.src.h b/include/applets.src.h index a9db5d160..60968cec7 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -22,12 +22,6 @@ s - suid type: BB_SUID_REQUIRE or BB_SUID_MAYBE applet. */ -#define NOUSAGE_STR "\b" - -#define dummy_trivial_usage NOUSAGE_STR \ - -#define dummy_full_usage "" \ - #if defined(PROTOTYPES) # define APPLET(name,l,s) int name##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; # define APPLET_ODDNAME(name,main,l,s,help) int main##_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 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 @@ #define NOUSAGE_STR "\b" +#define scripted_trivial_usage NOUSAGE_STR +#define scripted_full_usage "" + #if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA # define CRYPT_METHODS_HELP_STR "des,md5,sha256/512" \ " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index c2e7c6961..86ad44d1d 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -81,21 +81,15 @@ exec >"$target.$$" if [ $n -ne 0 ] then printf '#ifdef DEFINE_SCRIPT_DATA\n' - if [ $n -ne 0 ] - then - printf 'const uint16_t applet_numbers[] = {\n' - for i in $custom_scripts $applet_scripts - do - # TODO support applets with names including invalid characters - printf '\tAPPLET_NO_%s,\n' $i - done - printf '};\n' - fi + printf 'const uint16_t applet_numbers[] = {\n' + for i in $custom_scripts $applet_scripts + do + # TODO support applets with names including invalid characters + printf '\tAPPLET_NO_%s,\n' $i + done + printf '};\n' printf '#else\n' - if [ $n -ne 0 ] - then - printf 'extern const uint16_t applet_numbers[];\n' - fi + printf 'extern const uint16_t applet_numbers[];\n' printf '#endif\n' fi diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 64e4bffa9..362632df3 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -23,9 +23,9 @@ custom_scripts() custom_loc="$1" if [ -d "$custom_loc" ] then - for i in $(cd "$custom_loc"; ls *) + for i in $(cd "$custom_loc"; ls * 2>/dev/null) do - printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, dummy)\n" $i; + printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted)\n" $i; done fi } -- cgit v1.2.3-55-g6feb From 2d217799e8f23514ad3be6a951aa928c265bc6a4 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 25 Nov 2018 11:46:39 +0000 Subject: build system: prevent duplicate applet names The embedded script feature makes it easier to create applets with duplicate names. Currently in such cases the build succeeds but the resulting executable doesn't work as the developer intended. Catch duplicate names when the applet tables are being generated and make the build fail. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- applets/applet_tables.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/applets/applet_tables.c b/applets/applet_tables.c index e3d10c83f..ce2037440 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c @@ -84,7 +84,15 @@ int main(int argc, char **argv) qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); - if (!argv[1]) + for (i = j = 0; i < NUM_APPLETS-1; ++i) { + if (cmp_name(applets+i, applets+i+1) == 0) { + fprintf(stderr, "%s: duplicate applet name '%s'\n", argv[0], + applets[i].name); + j = 1; + } + } + + if (j != 0 || !argv[1]) return 1; snprintf(tmp1, PATH_MAX, "%s.%u.new", argv[1], (int) getpid()); i = open(tmp1, O_WRONLY | O_TRUNC | O_CREAT, 0666); -- cgit v1.2.3-55-g6feb From f4fc303e3679e4ab0d45f60c31f9b687f27f7452 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Nov 2018 11:26:48 +0100 Subject: tar: fix too eager autodetection, closes 11531 function old new delta is_suffixed_with - 54 +54 tar_main 1006 1026 +20 open_transformer 92 79 -13 config_file_action 478 458 -20 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 74/-33) Total: 41 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 3 +-- archival/tar.c | 8 ++++++++ modutils/modprobe.c | 5 ++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index 9fefd4aad..4a4bf3916 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -278,8 +278,7 @@ static transformer_state_t *open_transformer(const char *fname, int fail_if_not_ if (ENABLE_FEATURE_SEAMLESS_LZMA) { /* .lzma has no header/signature, can only detect it by extension */ - char *sfx = strrchr(fname, '.'); - if (sfx && strcmp(sfx+1, "lzma") == 0) { + if (is_suffixed_with(fname, ".lzma")) { xstate = xzalloc(sizeof(*xstate)); xstate->src_fd = fd; xstate->xformer = unpack_lzma_stream; diff --git a/archival/tar.c b/archival/tar.c index 1c71f7f66..6950c271d 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -1162,8 +1162,16 @@ int tar_main(int argc UNUSED_PARAM, char **argv) tar_handle->seek = seek_by_read; } else if (ENABLE_FEATURE_TAR_AUTODETECT + && ENABLE_FEATURE_SEAMLESS_LZMA && flags == O_RDONLY && !(opt & OPT_ANY_COMPRESS) + && is_suffixed_with(tar_filename, ".lzma") + /* We do this only for .lzma files, they have no signature. + * All other compression formats are recognized in + * get_header_tar() when first tar block has invalid format. + * Doing it here for all filenames would falsely trigger + * on e.g. tarball with 1st file named "BZh5". + */ ) { tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0); if (tar_handle->src_fd < 0) 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, parser_t *p; struct module_entry *m; int rc = TRUE; - const char *base, *ext; + const char *base; /* Skip files that begin with a "." */ base = bb_basename(filename); @@ -266,8 +266,7 @@ static int FAST_FUNC config_file_action(const char *filename, * "include FILE_NOT_ENDING_IN_CONF" must work too. */ if (depth != 0) { - ext = strrchr(base, '.'); - if (ext == NULL || strcmp(ext + 1, "conf")) + if (!is_suffixed_with(base, ".conf")) goto error; } -- cgit v1.2.3-55-g6feb From e80d04b574456c2248bb38eee5a771dcd65b592c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Nov 2018 11:52:14 +0100 Subject: unlzma: fix too-eager corruption check function old new delta unpack_lzma_stream 2686 2674 -12 Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_unlzma.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) 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) if ((int32_t)pos < 0) { pos += header.dict_size; /* see unzip_bad_lzma_2.zip: */ - if (pos >= buffer_size) + if (pos >= buffer_size) { + dbg("%d pos:%d buffer_size:%d", __LINE__, pos, buffer_size); goto bad; + } } previous_byte = buffer[pos]; goto one_byte1; @@ -430,10 +432,9 @@ unpack_lzma_stream(transformer_state_t *xstate) for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--) rep0 = (rep0 << 1) | rc_direct_bit(rc); rep0 <<= LZMA_NUM_ALIGN_BITS; - if ((int32_t)rep0 < 0) { - dbg("%d rep0:%d", __LINE__, rep0); - goto bad; - } + // Note: (int32_t)rep0 may be < 0 here + // (I have linux-3.3.4.tar.lzma which has it). + // I moved the check after "++rep0 == 0" check below. prob3 = p + LZMA_ALIGN; } i2 = 1; @@ -444,8 +445,13 @@ unpack_lzma_stream(transformer_state_t *xstate) i2 <<= 1; } } - if (++rep0 == 0) - break; + rep0++; + if ((int32_t)rep0 <= 0) { + if (rep0 == 0) + break; + dbg("%d rep0:%d", __LINE__, rep0); + goto bad; + } } len += LZMA_MATCH_MIN_LEN; -- cgit v1.2.3-55-g6feb From 403d2574be8f8c41aa46f73dec5f998b2cbf2790 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Nov 2018 12:09:01 +0100 Subject: tar: skip 'V' headers (GNU volume label), closes 11526 function old new delta get_header_tar 1696 1690 -6 Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_tar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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) // case 'D': /* GNU dump dir */ // case 'M': /* Continuation of multi volume archive */ // case 'N': /* Old GNU for names > 100 characters */ -// case 'V': /* Volume header */ + case 'V': /* Volume header */ + ; /* Fall through to skip it */ #endif } skip_ext_hdr: -- cgit v1.2.3-55-g6feb From 31a04d91c24f6ee180de45e1508dc03dea9f9c11 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 27 Nov 2018 10:45:30 +0000 Subject: docs: add embedded-scripts.txt Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- docs/embedded-scripts.txt | 116 ++++++++++++++++++++++++++++++++++++++++++++++ util-linux/nologin.c | 2 +- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 docs/embedded-scripts.txt diff --git a/docs/embedded-scripts.txt b/docs/embedded-scripts.txt new file mode 100644 index 000000000..1b0c5b591 --- /dev/null +++ b/docs/embedded-scripts.txt @@ -0,0 +1,116 @@ +Embedded Shell Scripts in BusyBox +================================= + +BusyBox allows applets to be implemented as shell scripts. Since +this obviously requires a shell to interpret the scripts the feature +depends on having a shell (specifically, ash) built into the binary. +Support for embedded scripts also has to be enabled. + +To embed scripts in BusyBox you must enable these configuration options: + + ASH + ASH_EMBEDDED_SCRIPTS + +It's unlikely that your applet will be implemented as a pure shell +script: it will probably need some external commands. If these are +to be provided by BusyBox you'll need to ensure they're enabled too. + +There are two ways to include scripts in BusyBox: the quick-and-dirty +custom script and the full-featured scripted applet. + +Custom Scripts +-------------- + +When embedded script support is enabled the BusyBox build process +assumes that any files in the directory 'embed' at the top level of +the source tree are scripts to be embedded. + +The embed directory isn't present in the BusyBox source tree and +BusyBox itself will never put anything there: it's entirely for the +use of third parties. + +Adding a custom script is as simple as running the following sequence +of commands in the BusyBox source directory: + + mkdir embed + echo 'echo foo' >embed/foo + make defconfig + make + +The resulting binary includes the new applet foo! + +Custom scripts have limited opportunities for configuration: the only +control developers have is to put them in the embed directory, or not. +Everything else takes default values. For more control you need the +additional features provided by scripted applets. + +Scripted Applets +---------------- + +Suppose we want to make a shell script version of the sample applet +from the New Applet HOWTO. First we'd have to write a script (vaguely) +equivalent to the C code: + + return $(($RANDOM%256)) + +This should be placed in the file applets_sh/mu in the source tree. + +Next we need the configuration data. This is very similar to the example +code for the native applet: + +//config:config MU +//config: bool "MU" +//config: default y +//config: help +//config: Returns an indeterminate value. + +//applet:IF_MU(APPLET_SCRIPTED(mu, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, mu)) + +//usage:#define mu_trivial_usage +//usage: "[-abcde] FILE..." +//usage:#define mu_full_usage +//usage: "Returns an indeterminate value\n" +//usage: "\n -a First function" +//usage: "\n -b Second function" + +The only difference is that the applet is specified as being of type +APPLET_SCRIPTED. It would also be useful to include details of any +dependencies the script has. We can assume that ash is available. +No external commands are used by our mu script, but it does depend on +optional shell features. We can ensure these are selected by adding +this to the configuration: + +//config:config MU_DEPENDENCIES +//config: bool "Enable dependencies for mu" +//config: default y +//config: depends on MU +//config: select ASH_RANDOM_SUPPORT +//config: select FEATURE_SH_MATH +//config: help +//config: mu is implemented as a shell script. It requires ash +//config: support for $RANDOM and arithmetic. + +The configuration data should be placed in a C file in an appropriate +subdirectory. There isn't any C code, though! In this case the file +could be miscutils/mu.c. + +Scripted applets are just as configurable as applets written in C. +They can be enabled or disabled using the configuration menu; their +install directory can be specified and their usage messages are stored +along with those of all other applets. + +Additional Notes +---------------- + +The source for embedded scripts can be displayed by running: + + busybox --show SCRIPT + +This can be disabled by turning off FEATURE_SHOW_SCRIPT in the +configuration, though it won't prevent a determined user from +extracting the source code. + +It can be argued that embedded scripts are linked into the BusyBox +binary and are therefore not subject to the 'mere aggregation' +exception in the GPL. If this is the case embedded scripts should +have a licence compatible with BusyBox's GPL v2-only licence. diff --git a/util-linux/nologin.c b/util-linux/nologin.c index cc619bf8a..0982fff3d 100644 --- a/util-linux/nologin.c +++ b/util-linux/nologin.c @@ -6,7 +6,7 @@ //config: Politely refuse a login //config: //config:config NOLOGIN_DEPENDENCIES -//config: bool "Dependencies for nologin" +//config: bool "Enable dependencies for nologin" //config: default y //config: depends on NOLOGIN //config: select CAT -- cgit v1.2.3-55-g6feb From f4709d78cb0c4f54283046e8f86edb9ecd7e41ca Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Nov 2018 15:43:10 +0100 Subject: free: ensure there is a least one space between numbers Signed-off-by: Denys Vlasenko --- procps/free.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/procps/free.c b/procps/free.c index e41601e08..ee0cd981a 100644 --- a/procps/free.c +++ b/procps/free.c @@ -124,9 +124,9 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) cached += info.bufferram; cached_plus_free = cached + info.freeram; -#define FIELDS_6 "%12llu%12llu%12llu%12llu%12llu%12llu\n" -#define FIELDS_3 (FIELDS_6 + 3*6) -#define FIELDS_2 (FIELDS_6 + 4*6) +#define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" +#define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) +#define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) printf(FIELDS_6, scale(&G, info.totalram), //total -- cgit v1.2.3-55-g6feb From 71df2d3589e3e682cd6770f41f0b184841b78702 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 27 Nov 2018 14:34:25 +0000 Subject: hush: allow hush to run embedded scripts Embedded scripts require a shell to be present in the BusyBox binary. Allow either ash or hush to be used for this purpose. If both are enabled ash takes precedence. The size of the binary is unchanged in the default configuration: both ash and hush are present but support for embedded scripts isn't compiled into hush. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- archival/libarchive/Kbuild.src | 2 +- docs/embedded-scripts.txt | 21 ++++++++------------- include/libbb.h | 5 +++++ libbb/appletlib.c | 8 +++++++- scripts/embedded_scripts | 8 ++++++++ scripts/gen_build_files.sh | 2 +- shell/Config.src | 14 ++++++++++++++ shell/ash.c | 16 +--------------- shell/hush.c | 16 ++++++++++++++++ util-linux/nologin.c | 2 +- 10 files changed, 62 insertions(+), 32 deletions(-) diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 12e66a88b..d2f284b08 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -91,7 +91,7 @@ lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma. lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += open_transformer.o decompress_bunzip2.o lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += open_transformer.o decompress_bunzip2.o -lib-$(CONFIG_ASH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o +lib-$(CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS) += open_transformer.o decompress_bunzip2.o ifneq ($(lib-y),) lib-y += $(COMMON_FILES) diff --git a/docs/embedded-scripts.txt b/docs/embedded-scripts.txt index 1b0c5b591..7a273d698 100644 --- a/docs/embedded-scripts.txt +++ b/docs/embedded-scripts.txt @@ -3,13 +3,9 @@ Embedded Shell Scripts in BusyBox BusyBox allows applets to be implemented as shell scripts. Since this obviously requires a shell to interpret the scripts the feature -depends on having a shell (specifically, ash) built into the binary. -Support for embedded scripts also has to be enabled. - -To embed scripts in BusyBox you must enable these configuration options: - - ASH - ASH_EMBEDDED_SCRIPTS +depends on having a shell built into the binary. Either ash or hush +will do. If both are present ash will be used. Support for embedded +scripts also has to be enabled. It's unlikely that your applet will be implemented as a pure shell script: it will probably need some external commands. If these are @@ -75,10 +71,9 @@ code for the native applet: The only difference is that the applet is specified as being of type APPLET_SCRIPTED. It would also be useful to include details of any -dependencies the script has. We can assume that ash is available. -No external commands are used by our mu script, but it does depend on -optional shell features. We can ensure these are selected by adding -this to the configuration: +dependencies the script has. No external commands are used by our mu +script, but it does depend on optional shell features. We can ensure +these are selected by adding this to the configuration: //config:config MU_DEPENDENCIES //config: bool "Enable dependencies for mu" @@ -87,8 +82,8 @@ this to the configuration: //config: select ASH_RANDOM_SUPPORT //config: select FEATURE_SH_MATH //config: help -//config: mu is implemented as a shell script. It requires ash -//config: support for $RANDOM and arithmetic. +//config: mu is implemented as a shell script. It requires support +//config: for $RANDOM and arithmetic. The configuration data should be placed in a C file in an appropriate subdirectory. There isn't any C code, though! In this case the file diff --git a/include/libbb.h b/include/libbb.h index ebd090e18..b560cc2eb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1348,6 +1348,11 @@ int ash_main(int argc, char** argv) MAIN_EXTERNALLY_VISIBLE #endif ; +int hush_main(int argc, char** argv) +#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH + MAIN_EXTERNALLY_VISIBLE +#endif +; /* If shell needs them, they exist even if not enabled as applets */ int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a79a37efb..cd09b620c 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -50,7 +50,7 @@ #include "usage_compressed.h" -#if ENABLE_ASH_EMBEDDED_SCRIPTS +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS # define DEFINE_SCRIPT_DATA 1 # include "embedded_scripts.h" #else @@ -774,7 +774,13 @@ int scripted_main(int argc UNUSED_PARAM, char **argv) { int script = find_script_by_name(applet_name); if (script >= 0) +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH exit(ash_main(-script - 1, argv)); +#elif ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH + exit(hush_main(-script - 1, argv)); +#else + return 1; +#endif return 0; } diff --git a/scripts/embedded_scripts b/scripts/embedded_scripts index 86ad44d1d..aa7bf3e8a 100755 --- a/scripts/embedded_scripts +++ b/scripts/embedded_scripts @@ -1,5 +1,7 @@ #!/bin/sh +. ./.config || exit 1 + target="$1" custom_loc="$2" applet_loc="$3" @@ -8,6 +10,12 @@ test "$target" || exit 1 test "$SED" || SED=sed test "$DD" || DD=dd +if [ x"$CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS" != x"y" ] +then + printf '#define NUM_SCRIPTS 0\n' >"$target" + exit 0 +fi + # Some people were bitten by their system lacking a (proper) od od -v -b /dev/null if test $? != 0; then diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index 362632df3..92de681ac 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -25,7 +25,7 @@ custom_scripts() then for i in $(cd "$custom_loc"; ls * 2>/dev/null) do - printf "APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted)\n" $i; + printf "IF_FEATURE_SH_EMBEDDED_SCRIPTS(APPLET_SCRIPTED(%s, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, scripted))\n" $i; done fi } 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 to set shell history size. Note that its max value is capped by "History size" setting in library tuning section. +config FEATURE_SH_EMBEDDED_SCRIPTS + bool "Embed scripts in the binary" + default y + depends on ASH || HUSH || SH_IS_ASH || BASH_IS_ASH || SH_IS_HUSH || BASH_IS_HUSH + help + Allow scripts to be compressed and embedded in the busybox + binary. The scripts should be placed in the 'embed' directory + at build time. Like applets, scripts can be run as + 'busybox SCRIPT ...' or by linking their name to the binary. + + This also allows applets to be implemented as scripts: place + the script in 'applets_sh' and a stub C file containing + configuration in the appropriate subsystem directory. + endif # Options common to all shells endmenu diff --git a/shell/ash.c b/shell/ash.c index 04e4006c8..9ce1d1a76 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -148,20 +148,6 @@ //config: you to run the specified command or builtin, //config: even when there is a function with the same name. //config: -//config:config ASH_EMBEDDED_SCRIPTS -//config: bool "Embed scripts in the binary" -//config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Allow scripts to be compressed and embedded in the busybox -//config: binary. The scripts should be placed in the 'embed' directory -//config: at build time. Like applets, scripts can be run as -//config: 'busybox SCRIPT ...' or by linking their name to the binary. -//config: -//config: This also allows applets to be implemented as scripts: place -//config: the script in 'applets_sh' and a stub C file containing -//config: configuration in the appropriate subsystem directory. -//config: //config:endif # ash options //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) @@ -195,7 +181,7 @@ #include #include /* for setting $HOSTNAME */ #include "busybox.h" /* for applet_names */ -#if ENABLE_ASH_EMBEDDED_SCRIPTS +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS # include "embedded_scripts.h" #else # define NUM_SCRIPTS 0 diff --git a/shell/hush.c b/shell/hush.c index 431010f09..90191408d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -367,6 +367,11 @@ # define PIPE_BUF 4096 /* amount of buffering in a pipe */ #endif +#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) +# include "embedded_scripts.h" +#else +# define NUM_SCRIPTS 0 +#endif /* So far, all bash compat is controlled by one config option */ /* Separate defines document which part of code implements what */ @@ -9951,6 +9956,14 @@ int hush_main(int argc, char **argv) /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0; builtin_argc = 0; +#if NUM_SCRIPTS > 0 + if (argc < 0) { + optarg = get_script_content(-argc - 1); + optind = 0; + argc = string_array_len(argv); + goto run_script; + } +#endif while (1) { int opt = getopt(argc, argv, "+c:exinsl" #if !BB_MMU @@ -9974,6 +9987,9 @@ int hush_main(int argc, char **argv) * Note: the form without ARG0 never happens: * sh ... -c 'builtin' BARGV... "" */ +#if NUM_SCRIPTS > 0 + run_script: +#endif if (!G.root_pid) { G.root_pid = getpid(); G.root_ppid = getppid(); diff --git a/util-linux/nologin.c b/util-linux/nologin.c index 0982fff3d..5e5e42305 100644 --- a/util-linux/nologin.c +++ b/util-linux/nologin.c @@ -1,7 +1,7 @@ //config:config NOLOGIN //config: bool "nologin" //config: default y -//config: depends on ASH_EMBEDDED_SCRIPTS +//config: depends on FEATURE_SH_EMBEDDED_SCRIPTS //config: help //config: Politely refuse a login //config: -- cgit v1.2.3-55-g6feb From 572dfb8e78323b9837f7c5e3369ee233a440b8f2 Mon Sep 17 00:00:00 2001 From: Chen Qi Date: Wed, 21 Nov 2018 10:19:28 +0800 Subject: testsuite: check CONFIG_DESKTOP before using 'od -t' The '-t' option for od is enabled by CONFIG_DESKTOP. So check this config before using 'od -t' in test cases. Signed-off-by: Chen Qi Signed-off-by: Denys Vlasenko --- testsuite/echo/echo-prints-dash | 1 + testsuite/echo/echo-prints-non-opts | 1 + testsuite/echo/echo-prints-slash-zero | 2 +- testsuite/echo/echo-prints-slash_00041 | 2 +- testsuite/echo/echo-prints-slash_0041 | 2 +- testsuite/echo/echo-prints-slash_041 | 2 +- testsuite/echo/echo-prints-slash_41 | 2 +- 7 files changed, 7 insertions(+), 5 deletions(-) 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 @@ +# FEATURE: CONFIG_DESKTOP test "`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 @@ +# FEATURE: CONFIG_DESKTOP test "`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 @@ -# FEATURE: CONFIG_FEATURE_FANCY_ECHO +# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP test "`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 @@ -# FEATURE: CONFIG_FEATURE_FANCY_ECHO +# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP test "`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 @@ -# FEATURE: CONFIG_FEATURE_FANCY_ECHO +# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP test "`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 @@ -# FEATURE: CONFIG_FEATURE_FANCY_ECHO +# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP test "`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 @@ -# FEATURE: CONFIG_FEATURE_FANCY_ECHO +# FEATURE: CONFIG_FEATURE_FANCY_ECHO CONFIG_DESKTOP test "`busybox echo -ne '\41z' | od -t x1 | head -n 1`" = "0000000 21 7a" -- cgit v1.2.3-55-g6feb