aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/libarchive/bz/blocksort.c2
-rw-r--r--archival/libarchive/get_header_tar.c12
-rw-r--r--archival/libarchive/unxz/xz_dec_stream.c2
-rw-r--r--console-tools/resize.c14
-rw-r--r--coreutils/Config.src19
-rw-r--r--coreutils/df.c20
-rw-r--r--coreutils/mktemp.c16
-rw-r--r--coreutils/test.c5
-rw-r--r--editors/ed.c32
-rw-r--r--findutils/find.c147
-rw-r--r--include/libbb.h75
-rw-r--r--libbb/Config.src185
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/appletlib.c23
-rw-r--r--libbb/const_hack.c16
-rw-r--r--libbb/dump.c2
-rw-r--r--libbb/lineedit.c94
-rw-r--r--libbb/vfork_daemon_rexec.c16
-rw-r--r--libbb/xreadlink.c75
-rw-r--r--mailutils/Config.src4
-rw-r--r--miscutils/bc.c2
-rw-r--r--miscutils/less.c2
-rw-r--r--networking/Config.src26
-rw-r--r--networking/brctl.c2
-rw-r--r--networking/httpd.c9
-rw-r--r--networking/ifplugd.c2
-rw-r--r--networking/ip.c2
-rw-r--r--networking/libiproute/iplink.c35
-rw-r--r--networking/nslookup.c2
-rw-r--r--networking/ntpd.c4
-rw-r--r--networking/tls.c149
-rw-r--r--networking/tls.h5
-rw-r--r--networking/tls_fe.c54
-rw-r--r--networking/tls_pstm.h1
-rw-r--r--networking/tls_sp_c32.c1471
-rw-r--r--networking/tls_symmetric.h511
-rw-r--r--networking/wget.c26
-rw-r--r--procps/Config.src9
-rw-r--r--procps/powertop.c2
-rw-r--r--procps/ps.c32
-rw-r--r--shell/ash.c68
-rw-r--r--shell/ash_test/ash-arith/arith-postinc.right3
-rwxr-xr-xshell/ash_test/ash-arith/arith-postinc.tests4
-rw-r--r--shell/ash_test/ash-arith/arith.right78
-rwxr-xr-xshell/ash_test/ash-arith/arith.tests55
-rwxr-xr-xshell/ash_test/ash-arith/arith1.sub4
-rwxr-xr-xshell/ash_test/ash-arith/arith2.sub22
-rw-r--r--shell/ash_test/ash-comm/comm.right6
-rwxr-xr-xshell/ash_test/ash-comm/comm.tests20
-rw-r--r--shell/hush.c48
-rw-r--r--shell/hush_test/hush-arith/arith-postinc.right3
-rwxr-xr-xshell/hush_test/hush-arith/arith-postinc.tests4
-rw-r--r--shell/hush_test/hush-arith/arith.right37
-rwxr-xr-xshell/hush_test/hush-arith/arith.tests40
-rwxr-xr-xshell/hush_test/hush-arith/arith1.sub4
-rwxr-xr-xshell/hush_test/hush-arith/arith2.sub22
-rw-r--r--shell/hush_test/hush-comm/comm.right6
-rwxr-xr-xshell/hush_test/hush-comm/comm.tests20
-rw-r--r--shell/math.c71
-rwxr-xr-xtestsuite/realpath.tests45
-rwxr-xr-xtestsuite/xxd.tests6
-rw-r--r--util-linux/chrt.c2
-rw-r--r--util-linux/fbset.c2
-rw-r--r--util-linux/fdisk_sun.c2
-rw-r--r--util-linux/hexdump_xxd.c51
-rw-r--r--util-linux/mdev.c10
-rw-r--r--util-linux/mount.c21
67 files changed, 2156 insertions, 1604 deletions
diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c
index 062fd0f54..74f957544 100644
--- a/archival/libarchive/bz/blocksort.c
+++ b/archival/libarchive/bz/blocksort.c
@@ -107,7 +107,7 @@ void fallbackSimpleSort(uint32_t* fmap,
107#define FALLBACK_QSORT_SMALL_THRESH 10 107#define FALLBACK_QSORT_SMALL_THRESH 10
108#define FALLBACK_QSORT_STACK_SIZE 100 108#define FALLBACK_QSORT_STACK_SIZE 100
109 109
110static 110static NOINLINE
111void fallbackQSort3(uint32_t* fmap, 111void fallbackQSort3(uint32_t* fmap,
112 uint32_t* eclass, 112 uint32_t* eclass,
113 int32_t loSt, 113 int32_t loSt,
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index 2ab3c04b8..d26868bf8 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -147,6 +147,12 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g
147#endif 147#endif
148} 148}
149 149
150static void die_if_bad_fnamesize(off_t sz)
151{
152 if ((uoff_t)sz > 0xfff) /* more than 4k?! no funny business please */
153 bb_simple_error_msg_and_die("bad archive");
154}
155
150char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) 156char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
151{ 157{
152 file_header_t *file_header = archive_handle->file_header; 158 file_header_t *file_header = archive_handle->file_header;
@@ -331,8 +337,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
331 file_header->name = xstrdup(tar.name); 337 file_header->name = xstrdup(tar.name);
332 } 338 }
333 339
334 /* Set bits 12-15 of the files mode */
335 /* (typeflag was not trashed because chksum does not use getOctal) */
336 switch (tar_typeflag) { 340 switch (tar_typeflag) {
337 case '1': /* hardlink */ 341 case '1': /* hardlink */
338 /* we mark hardlinks as regular files with zero size and a link name */ 342 /* we mark hardlinks as regular files with zero size and a link name */
@@ -341,7 +345,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
341 * ... For tar archives written by pre POSIX.1-1988 345 * ... For tar archives written by pre POSIX.1-1988
342 * implementations, the size field usually contains the size of 346 * implementations, the size field usually contains the size of
343 * the file and needs to be ignored as no data may follow this 347 * the file and needs to be ignored as no data may follow this
344 * header type. For POSIX.1- 1988 compliant archives, the size 348 * header type. For POSIX.1-1988 compliant archives, the size
345 * field needs to be 0. For POSIX.1-2001 compliant archives, 349 * field needs to be 0. For POSIX.1-2001 compliant archives,
346 * the size field may be non zero, indicating that file data is 350 * the size field may be non zero, indicating that file data is
347 * included in the archive. 351 * included in the archive.
@@ -390,6 +394,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
390 /* free: paranoia: tar with several consecutive longnames */ 394 /* free: paranoia: tar with several consecutive longnames */
391 free(p_longname); 395 free(p_longname);
392 /* For paranoia reasons we allocate extra NUL char */ 396 /* For paranoia reasons we allocate extra NUL char */
397 die_if_bad_fnamesize(file_header->size);
393 p_longname = xzalloc(file_header->size + 1); 398 p_longname = xzalloc(file_header->size + 1);
394 /* We read ASCIZ string, including NUL */ 399 /* We read ASCIZ string, including NUL */
395 xread(archive_handle->src_fd, p_longname, file_header->size); 400 xread(archive_handle->src_fd, p_longname, file_header->size);
@@ -400,6 +405,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
400 goto again; 405 goto again;
401 case 'K': 406 case 'K':
402 free(p_linkname); 407 free(p_linkname);
408 die_if_bad_fnamesize(file_header->size);
403 p_linkname = xzalloc(file_header->size + 1); 409 p_linkname = xzalloc(file_header->size + 1);
404 xread(archive_handle->src_fd, p_linkname, file_header->size); 410 xread(archive_handle->src_fd, p_linkname, file_header->size);
405 archive_handle->offset += file_header->size; 411 archive_handle->offset += file_header->size;
diff --git a/archival/libarchive/unxz/xz_dec_stream.c b/archival/libarchive/unxz/xz_dec_stream.c
index bf791055b..31158b4e8 100644
--- a/archival/libarchive/unxz/xz_dec_stream.c
+++ b/archival/libarchive/unxz/xz_dec_stream.c
@@ -545,7 +545,7 @@ static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s)
545 return XZ_OK; 545 return XZ_OK;
546} 546}
547 547
548static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b) 548static NOINLINE enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
549{ 549{
550 enum xz_ret ret; 550 enum xz_ret ret;
551 551
diff --git a/console-tools/resize.c b/console-tools/resize.c
index 59d468d48..056e33750 100644
--- a/console-tools/resize.c
+++ b/console-tools/resize.c
@@ -74,7 +74,19 @@ int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
74 + (1 << SIGTERM) 74 + (1 << SIGTERM)
75 + (1 << SIGALRM) 75 + (1 << SIGALRM)
76 , onintr); 76 , onintr);
77 tcsetattr(STDERR_FILENO, TCSANOW, &new); 77 /* Users report:
78 * The resize command messes up the terminal.
79 * In my case it looks like it is hanging and
80 * I need to press ctrl-c to get a prompt.
81 * Actually the program does not hang but just
82 * the terminal is messed up.
83 * Replaced TCSANOW with TCSAFLUSH:
84 * "the change occurs after all output written to fd
85 * has been transmitted, and all input that has been
86 * received but not read will be discarded before
87 * the change is made.
88 */
89 tcsetattr(STDERR_FILENO, TCSAFLUSH, &new);
78 90
79 /* save_cursor_pos 7 91 /* save_cursor_pos 7
80 * scroll_whole_screen [r 92 * scroll_whole_screen [r
diff --git a/coreutils/Config.src b/coreutils/Config.src
index 1bded03a6..6c9e47551 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -5,10 +5,6 @@
5 5
6menu "Coreutils" 6menu "Coreutils"
7 7
8INSERT
9
10comment "Common options"
11
12config FEATURE_VERBOSE 8config FEATURE_VERBOSE
13 bool "Support verbose options (usually -v) for various applets" 9 bool "Support verbose options (usually -v) for various applets"
14 default y 10 default y
@@ -17,6 +13,19 @@ config FEATURE_VERBOSE
17 Also enables long option (--verbose) if it exists. 13 Also enables long option (--verbose) if it exists.
18 Without this option, -v is accepted but ignored. 14 Without this option, -v is accepted but ignored.
19 15
16comment "Common options for date and touch"
17
18config FEATURE_TIMEZONE
19 bool "Allow timezone in dates"
20 default y
21 depends on DESKTOP
22 help
23 Permit the use of timezones when parsing user-provided data
24 strings, e.g. '1996-04-09 12:45:00 -0500'.
25
26 This requires support for the '%z' extension to strptime() which
27 may not be available in all implementations.
28
20comment "Common options for cp and mv" 29comment "Common options for cp and mv"
21 depends on CP || MV 30 depends on CP || MV
22 31
@@ -37,4 +46,6 @@ config FEATURE_HUMAN_READABLE
37 help 46 help
38 Allow df, du, and ls to have human readable output. 47 Allow df, du, and ls to have human readable output.
39 48
49INSERT
50
40endmenu 51endmenu
diff --git a/coreutils/df.c b/coreutils/df.c
index 9f8b3a71e..176aa079f 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -32,6 +32,26 @@
32//config: -a Show all filesystems 32//config: -a Show all filesystems
33//config: -i Inodes 33//config: -i Inodes
34//config: -B <SIZE> Blocksize 34//config: -B <SIZE> Blocksize
35//config:
36//config:config FEATURE_SKIP_ROOTFS
37//config: bool "Skip rootfs in mount table"
38//config: default y
39//config: depends on DF
40//config: help
41//config: Ignore rootfs entry in mount table.
42//config:
43//config: In Linux, kernel has a special filesystem, rootfs, which is initially
44//config: mounted on /. It contains initramfs data, if kernel is configured
45//config: to have one. Usually, another file system is mounted over / early
46//config: in boot process, and therefore most tools which manipulate
47//config: mount table, such as df, will skip rootfs entry.
48//config:
49//config: However, some systems do not mount anything on /.
50//config: If you need to configure busybox for one of these systems,
51//config: you may find it useful to turn this option off to make df show
52//config: initramfs statistics.
53//config:
54//config: Otherwise, choose Y.
35 55
36//applet:IF_DF(APPLET_NOEXEC(df, df, BB_DIR_BIN, BB_SUID_DROP, df)) 56//applet:IF_DF(APPLET_NOEXEC(df, df, BB_DIR_BIN, BB_SUID_DROP, df))
37 57
diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c
index 5393320a5..33e2720de 100644
--- a/coreutils/mktemp.c
+++ b/coreutils/mktemp.c
@@ -72,13 +72,27 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
72 OPT_t = 1 << 2, 72 OPT_t = 1 << 2,
73 OPT_p = 1 << 3, 73 OPT_p = 1 << 3,
74 OPT_u = 1 << 4, 74 OPT_u = 1 << 4,
75 OPT_tmpdir = (1 << 5) * ENABLE_LONG_OPTS,
75 }; 76 };
76 77
77 path = getenv("TMPDIR"); 78 path = getenv("TMPDIR");
78 if (!path || path[0] == '\0') 79 if (!path || path[0] == '\0')
79 path = "/tmp"; 80 path = "/tmp";
80 81
82#if ENABLE_LONG_OPTS
83 opts = getopt32long(argv, "^"
84 "dqtp:u"
85 "\0"
86 "?1" /* 1 arg max */,
87 "directory\0" No_argument "d"
88 "quiet\0" No_argument "q"
89 "dry-run\0" No_argument "u"
90 "tmpdir\0" Optional_argument "\xff"
91 , &path, &path
92 );
93#else
81 opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path); 94 opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path);
95#endif
82 96
83 chp = argv[optind]; 97 chp = argv[optind];
84 if (!chp) { 98 if (!chp) {
@@ -95,7 +109,7 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
95 goto error; 109 goto error;
96 } 110 }
97#endif 111#endif
98 if (opts & (OPT_t|OPT_p)) 112 if (opts & (OPT_t|OPT_p|OPT_tmpdir))
99 chp = concat_path_file(path, chp); 113 chp = concat_path_file(path, chp);
100 114
101 if (opts & OPT_u) { 115 if (opts & OPT_u) {
diff --git a/coreutils/test.c b/coreutils/test.c
index 7c6574334..a914c7490 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -435,7 +435,7 @@ struct test_statics {
435}; 435};
436 436
437/* See test_ptr_hack.c */ 437/* See test_ptr_hack.c */
438extern struct test_statics *const test_ptr_to_statics; 438extern struct test_statics *BB_GLOBAL_CONST test_ptr_to_statics;
439 439
440#define S (*test_ptr_to_statics) 440#define S (*test_ptr_to_statics)
441#define args (S.args ) 441#define args (S.args )
@@ -446,8 +446,7 @@ extern struct test_statics *const test_ptr_to_statics;
446#define leaving (S.leaving ) 446#define leaving (S.leaving )
447 447
448#define INIT_S() do { \ 448#define INIT_S() do { \
449 (*(struct test_statics**)not_const_pp(&test_ptr_to_statics)) = xzalloc(sizeof(S)); \ 449 XZALLOC_CONST_PTR(&test_ptr_to_statics, sizeof(S)); \
450 barrier(); \
451} while (0) 450} while (0)
452#define DEINIT_S() do { \ 451#define DEINIT_S() do { \
453 free(group_array); \ 452 free(group_array); \
diff --git a/editors/ed.c b/editors/ed.c
index c50faeefa..14540e566 100644
--- a/editors/ed.c
+++ b/editors/ed.c
@@ -380,7 +380,8 @@ static void addLines(int num)
380static int readLines(const char *file, int num) 380static int readLines(const char *file, int num)
381{ 381{
382 int fd, cc; 382 int fd, cc;
383 int len, lineCount, charCount; 383 int len;
384 unsigned charCount;
384 char *cp; 385 char *cp;
385 386
386 if ((num < 1) || (num > lastNum + 1)) { 387 if ((num < 1) || (num > lastNum + 1)) {
@@ -396,7 +397,6 @@ static int readLines(const char *file, int num)
396 397
397 bufPtr = bufBase; 398 bufPtr = bufBase;
398 bufUsed = 0; 399 bufUsed = 0;
399 lineCount = 0;
400 charCount = 0; 400 charCount = 0;
401 cc = 0; 401 cc = 0;
402 402
@@ -415,7 +415,6 @@ static int readLines(const char *file, int num)
415 bufPtr += len; 415 bufPtr += len;
416 bufUsed -= len; 416 bufUsed -= len;
417 charCount += len; 417 charCount += len;
418 lineCount++;
419 num++; 418 num++;
420 continue; 419 continue;
421 } 420 }
@@ -449,15 +448,18 @@ static int readLines(const char *file, int num)
449 close(fd); 448 close(fd);
450 return -1; 449 return -1;
451 } 450 }
452 lineCount++;
453 charCount += bufUsed; 451 charCount += bufUsed;
454 } 452 }
455 453
456 close(fd); 454 close(fd);
457 455
458 printf("%d lines%s, %d chars\n", lineCount, 456 /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html
459 (bufUsed ? " (incomplete)" : ""), charCount); 457 * "Read Command"
460 458 * "...the number of bytes read shall be written to standard output
459 * in the following format:
460 * "%d\n", <number of bytes read>
461 */
462 printf("%u\n", charCount);
461 return TRUE; 463 return TRUE;
462} 464}
463 465
@@ -468,12 +470,12 @@ static int readLines(const char *file, int num)
468static int writeLines(const char *file, int num1, int num2) 470static int writeLines(const char *file, int num1, int num2)
469{ 471{
470 LINE *lp; 472 LINE *lp;
471 int fd, lineCount, charCount; 473 int fd;
474 unsigned charCount;
472 475
473 if (bad_nums(num1, num2, "write")) 476 if (bad_nums(num1, num2, "write"))
474 return FALSE; 477 return FALSE;
475 478
476 lineCount = 0;
477 charCount = 0; 479 charCount = 0;
478 480
479 fd = creat(file, 0666); 481 fd = creat(file, 0666);
@@ -482,9 +484,6 @@ static int writeLines(const char *file, int num1, int num2)
482 return FALSE; 484 return FALSE;
483 } 485 }
484 486
485 printf("\"%s\", ", file);
486 fflush_all();
487
488 lp = findLine(num1); 487 lp = findLine(num1);
489 if (lp == NULL) { 488 if (lp == NULL) {
490 close(fd); 489 close(fd);
@@ -498,7 +497,6 @@ static int writeLines(const char *file, int num1, int num2)
498 return FALSE; 497 return FALSE;
499 } 498 }
500 charCount += lp->len; 499 charCount += lp->len;
501 lineCount++;
502 lp = lp->next; 500 lp = lp->next;
503 } 501 }
504 502
@@ -507,7 +505,13 @@ static int writeLines(const char *file, int num1, int num2)
507 return FALSE; 505 return FALSE;
508 } 506 }
509 507
510 printf("%d lines, %d chars\n", lineCount, charCount); 508 /* https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ed.html
509 * "Write Command"
510 * "...the number of bytes written shall be written to standard output,
511 * unless the -s option was specified, in the following format:
512 * "%d\n", <number of bytes written>
513 */
514 printf("%u\n", charCount);
511 return TRUE; 515 return TRUE;
512} 516}
513 517
diff --git a/findutils/find.c b/findutils/find.c
index 188865e05..87f827b1f 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -67,21 +67,53 @@
67//config: interpreted by other programs. 67//config: interpreted by other programs.
68//config: 68//config:
69//config:config FEATURE_FIND_MTIME 69//config:config FEATURE_FIND_MTIME
70//config: bool "Enable -mtime: modified time matching" 70//config: bool "Enable -mtime: modification time matching"
71//config: default y 71//config: default y
72//config: depends on FIND 72//config: depends on FIND
73//config: help 73//config: help
74//config: Allow searching based on the modification time of 74//config: Allow searching based on the modification time of
75//config: files, in days. 75//config: files, in days.
76//config: 76//config:
77//config:config FEATURE_FIND_ATIME
78//config: bool "Enable -atime: access time matching"
79//config: default y
80//config: depends on FEATURE_FIND_MTIME
81//config: help
82//config: Allow searching based on the access time of
83//config: files, in days.
84//config:
85//config:config FEATURE_FIND_CTIME
86//config: bool "Enable -ctime: status change timestamp matching"
87//config: default y
88//config: depends on FEATURE_FIND_MTIME
89//config: help
90//config: Allow searching based on the status change timestamp of
91//config: files, in days.
92//config:
77//config:config FEATURE_FIND_MMIN 93//config:config FEATURE_FIND_MMIN
78//config: bool "Enable -mmin: modified time matching by minutes" 94//config: bool "Enable -mmin: modification time matching by minutes"
79//config: default y 95//config: default y
80//config: depends on FIND 96//config: depends on FIND
81//config: help 97//config: help
82//config: Allow searching based on the modification time of 98//config: Allow searching based on the modification time of
83//config: files, in minutes. 99//config: files, in minutes.
84//config: 100//config:
101//config:config FEATURE_FIND_AMIN
102//config: bool "Enable -amin: access time matching by minutes"
103//config: default y
104//config: depends on FEATURE_FIND_MMIN
105//config: help
106//config: Allow searching based on the access time of
107//config: files, in minutes.
108//config:
109//config:config FEATURE_FIND_CMIN
110//config: bool "Enable -cmin: status change timestamp matching by minutes"
111//config: default y
112//config: depends on FEATURE_FIND_MMIN
113//config: help
114//config: Allow searching based on the status change timestamp of
115//config: files, in minutes.
116//config:
85//config:config FEATURE_FIND_PERM 117//config:config FEATURE_FIND_PERM
86//config: bool "Enable -perm: permissions matching" 118//config: bool "Enable -perm: permissions matching"
87//config: default y 119//config: default y
@@ -296,10 +328,22 @@
296//usage: "\n -mtime DAYS mtime is greater than (+N), less than (-N)," 328//usage: "\n -mtime DAYS mtime is greater than (+N), less than (-N),"
297//usage: "\n or exactly N days in the past" 329//usage: "\n or exactly N days in the past"
298//usage: ) 330//usage: )
331//usage: IF_FEATURE_FIND_ATIME(
332//usage: "\n -atime DAYS atime +N/-N/N days in the past"
333//usage: )
334//usage: IF_FEATURE_FIND_CTIME(
335//usage: "\n -ctime DAYS ctime +N/-N/N days in the past"
336//usage: )
299//usage: IF_FEATURE_FIND_MMIN( 337//usage: IF_FEATURE_FIND_MMIN(
300//usage: "\n -mmin MINS mtime is greater than (+N), less than (-N)," 338//usage: "\n -mmin MINS mtime is greater than (+N), less than (-N),"
301//usage: "\n or exactly N minutes in the past" 339//usage: "\n or exactly N minutes in the past"
302//usage: ) 340//usage: )
341//usage: IF_FEATURE_FIND_AMIN(
342//usage: "\n -amin MINS atime +N/-N/N minutes in the past"
343//usage: )
344//usage: IF_FEATURE_FIND_CMIN(
345//usage: "\n -cmin MINS ctime +N/-N/N minutes in the past"
346//usage: )
303//usage: IF_FEATURE_FIND_NEWER( 347//usage: IF_FEATURE_FIND_NEWER(
304//usage: "\n -newer FILE mtime is more recent than FILE's" 348//usage: "\n -newer FILE mtime is more recent than FILE's"
305//usage: ) 349//usage: )
@@ -396,8 +440,8 @@ IF_FEATURE_FIND_PRINT0( ACTS(print0))
396IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;)) 440IF_FEATURE_FIND_TYPE( ACTS(type, int type_mask;))
397IF_FEATURE_FIND_EXECUTABLE(ACTS(executable)) 441IF_FEATURE_FIND_EXECUTABLE(ACTS(executable))
398IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;)) 442IF_FEATURE_FIND_PERM( ACTS(perm, char perm_char; mode_t perm_mask;))
399IF_FEATURE_FIND_MTIME( ACTS(mtime, char mtime_char; unsigned mtime_days;)) 443IF_FEATURE_FIND_MTIME( ACTS(mtime, unsigned char time_type; unsigned char mtime_char; unsigned mtime_days;))
400IF_FEATURE_FIND_MMIN( ACTS(mmin, char mmin_char; unsigned mmin_mins;)) 444IF_FEATURE_FIND_MMIN( ACTS(mmin, unsigned char time_type; unsigned char mmin_char; unsigned mmin_mins;))
401IF_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;)) 445IF_FEATURE_FIND_NEWER( ACTS(newer, time_t newer_mtime;))
402IF_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;)) 446IF_FEATURE_FIND_INUM( ACTS(inum, ino_t inode_num;))
403IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;)) 447IF_FEATURE_FIND_USER( ACTS(user, uid_t uid;))
@@ -618,30 +662,61 @@ ACTF(perm)
618 return (statbuf->st_mode & 07777) == ap->perm_mask; 662 return (statbuf->st_mode & 07777) == ap->perm_mask;
619} 663}
620#endif 664#endif
665
666#if 0 \
667 || ENABLE_FEATURE_FIND_AMIN \
668 || ENABLE_FEATURE_FIND_ATIME \
669 || ENABLE_FEATURE_FIND_CMIN \
670 || ENABLE_FEATURE_FIND_CTIME \
671 || ENABLE_FEATURE_FIND_MMIN \
672 || ENABLE_FEATURE_FIND_MTIME
673static int time_cmp(const struct stat *statbuf, unsigned type_and_char, time_t N_from_user, unsigned unit)
674{
675 time_t ftime, file_age;
676
677 ftime = statbuf->st_mtime;
678# if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME
679# if ENABLE_FEATURE_FIND_ATIME
680 if ((type_and_char >> 8) == 'a')
681 ftime = statbuf->st_atime;
682# endif
683# if ENABLE_FEATURE_FIND_CTIME
684 if ((type_and_char >> 8) == 'c')
685 ftime = statbuf->st_ctime;
686# endif
687 type_and_char &= 0xff;
688# endif
689 file_age = time(NULL) - ftime;
690 N_from_user *= unit;
691 switch (type_and_char) {
692 case '+': return file_age >= N_from_user + unit;
693 case '-': return file_age < N_from_user;
694 /* just numeric time */
695 default: return file_age >= N_from_user && file_age < N_from_user + unit;
696 }
697}
698#endif
699
621#if ENABLE_FEATURE_FIND_MTIME 700#if ENABLE_FEATURE_FIND_MTIME
622ACTF(mtime) 701ACTF(mtime)
623{ 702{
624 time_t file_age = time(NULL) - statbuf->st_mtime; 703 return time_cmp(statbuf,
625 time_t mtime_secs = ap->mtime_days * 24*60*60; 704# if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME
626 if (ap->mtime_char == '+') 705 (ap->time_type << 8) |
627 return file_age >= mtime_secs + 24*60*60; 706# endif
628 if (ap->mtime_char == '-') 707 ap->mtime_char,
629 return file_age < mtime_secs; 708 ap->mtime_days, 24*60*60);
630 /* just numeric mtime */
631 return file_age >= mtime_secs && file_age < (mtime_secs + 24*60*60);
632} 709}
633#endif 710#endif
634#if ENABLE_FEATURE_FIND_MMIN 711#if ENABLE_FEATURE_FIND_MMIN
635ACTF(mmin) 712ACTF(mmin)
636{ 713{
637 time_t file_age = time(NULL) - statbuf->st_mtime; 714 return time_cmp(statbuf,
638 time_t mmin_secs = ap->mmin_mins * 60; 715# if ENABLE_FEATURE_FIND_ATIME || ENABLE_FEATURE_FIND_CTIME
639 if (ap->mmin_char == '+') 716 (ap->time_type << 8) |
640 return file_age >= mmin_secs + 60; 717# endif
641 if (ap->mmin_char == '-') 718 ap->mmin_char,
642 return file_age < mmin_secs; 719 ap->mmin_mins, 60);
643 /* just numeric mmin */
644 return file_age >= mmin_secs && file_age < (mmin_secs + 60);
645} 720}
646#endif 721#endif
647#if ENABLE_FEATURE_FIND_NEWER 722#if ENABLE_FEATURE_FIND_NEWER
@@ -1043,7 +1118,11 @@ static action*** parse_params(char **argv)
1043 IF_FEATURE_FIND_TYPE( PARM_type ,) 1118 IF_FEATURE_FIND_TYPE( PARM_type ,)
1044 IF_FEATURE_FIND_PERM( PARM_perm ,) 1119 IF_FEATURE_FIND_PERM( PARM_perm ,)
1045 IF_FEATURE_FIND_MTIME( PARM_mtime ,) 1120 IF_FEATURE_FIND_MTIME( PARM_mtime ,)
1121 IF_FEATURE_FIND_ATIME( PARM_atime ,)
1122 IF_FEATURE_FIND_CTIME( PARM_ctime ,)
1046 IF_FEATURE_FIND_MMIN( PARM_mmin ,) 1123 IF_FEATURE_FIND_MMIN( PARM_mmin ,)
1124 IF_FEATURE_FIND_AMIN( PARM_amin ,)
1125 IF_FEATURE_FIND_CMIN( PARM_cmin ,)
1047 IF_FEATURE_FIND_NEWER( PARM_newer ,) 1126 IF_FEATURE_FIND_NEWER( PARM_newer ,)
1048 IF_FEATURE_FIND_INUM( PARM_inum ,) 1127 IF_FEATURE_FIND_INUM( PARM_inum ,)
1049 IF_FEATURE_FIND_USER( PARM_user ,) 1128 IF_FEATURE_FIND_USER( PARM_user ,)
@@ -1087,7 +1166,11 @@ static action*** parse_params(char **argv)
1087 IF_FEATURE_FIND_TYPE( "-type\0" ) 1166 IF_FEATURE_FIND_TYPE( "-type\0" )
1088 IF_FEATURE_FIND_PERM( "-perm\0" ) 1167 IF_FEATURE_FIND_PERM( "-perm\0" )
1089 IF_FEATURE_FIND_MTIME( "-mtime\0" ) 1168 IF_FEATURE_FIND_MTIME( "-mtime\0" )
1169 IF_FEATURE_FIND_ATIME( "-atime\0" )
1170 IF_FEATURE_FIND_CTIME( "-ctime\0" )
1090 IF_FEATURE_FIND_MMIN( "-mmin\0" ) 1171 IF_FEATURE_FIND_MMIN( "-mmin\0" )
1172 IF_FEATURE_FIND_AMIN( "-amin\0" )
1173 IF_FEATURE_FIND_CMIN( "-cmin\0" )
1091 IF_FEATURE_FIND_NEWER( "-newer\0" ) 1174 IF_FEATURE_FIND_NEWER( "-newer\0" )
1092 IF_FEATURE_FIND_INUM( "-inum\0" ) 1175 IF_FEATURE_FIND_INUM( "-inum\0" )
1093 IF_FEATURE_FIND_USER( "-user\0" ) 1176 IF_FEATURE_FIND_USER( "-user\0" )
@@ -1373,19 +1456,39 @@ static action*** parse_params(char **argv)
1373 } 1456 }
1374#endif 1457#endif
1375#if ENABLE_FEATURE_FIND_MTIME 1458#if ENABLE_FEATURE_FIND_MTIME
1376 else if (parm == PARM_mtime) { 1459 else if (parm == PARM_mtime
1460# if ENABLE_FEATURE_FIND_ATIME
1461 || parm == PARM_atime
1462# endif
1463# if ENABLE_FEATURE_FIND_CTIME
1464 || parm == PARM_ctime
1465# endif
1466 ) {
1377 action_mtime *ap; 1467 action_mtime *ap;
1378 dbg("%d", __LINE__); 1468 dbg("%d", __LINE__);
1379 ap = ALLOC_ACTION(mtime); 1469 ap = ALLOC_ACTION(mtime);
1470# if ENABLE_FEATURE_FIND_AMIN || ENABLE_FEATURE_FIND_CMIN
1471 ap->time_type = arg[1];
1472# endif
1380 ap->mtime_char = arg1[0]; 1473 ap->mtime_char = arg1[0];
1381 ap->mtime_days = xatoul(plus_minus_num(arg1)); 1474 ap->mtime_days = xatoul(plus_minus_num(arg1));
1382 } 1475 }
1383#endif 1476#endif
1384#if ENABLE_FEATURE_FIND_MMIN 1477#if ENABLE_FEATURE_FIND_MMIN
1385 else if (parm == PARM_mmin) { 1478 else if (parm == PARM_mmin
1479# if ENABLE_FEATURE_FIND_AMIN
1480 || parm == PARM_amin
1481# endif
1482# if ENABLE_FEATURE_FIND_CMIN
1483 || parm == PARM_cmin
1484# endif
1485 ) {
1386 action_mmin *ap; 1486 action_mmin *ap;
1387 dbg("%d", __LINE__); 1487 dbg("%d", __LINE__);
1388 ap = ALLOC_ACTION(mmin); 1488 ap = ALLOC_ACTION(mmin);
1489# if ENABLE_FEATURE_FIND_AMIN || ENABLE_FEATURE_FIND_CMIN
1490 ap->time_type = arg[1];
1491# endif
1389 ap->mmin_char = arg1[0]; 1492 ap->mmin_char = arg1[0];
1390 ap->mmin_mins = xatoul(plus_minus_num(arg1)); 1493 ap->mmin_mins = xatoul(plus_minus_num(arg1));
1391 } 1494 }
diff --git a/include/libbb.h b/include/libbb.h
index 3a958b555..098619305 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -324,9 +324,13 @@ typedef unsigned long long uoff_t;
324# endif 324# endif
325#else 325#else
326/* CONFIG_LFS is off */ 326/* CONFIG_LFS is off */
327# if UINT_MAX == 0xffffffff 327/* sizeof(off_t) == sizeof(long).
328/* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway. 328 * May or may not be == sizeof(int). If it is, use xatoi_positive()
329 * gcc will throw warnings on printf("%d", off_t). Crap... */ 329 * and bb_strtou() instead of xatoul_range() and bb_strtoul().
330 * Even if sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway.
331 * gcc will throw warnings on printf("%d", off_t)... Have to use %ld etc.
332 */
333# if UINT_MAX == ULONG_MAX
330typedef unsigned long uoff_t; 334typedef unsigned long uoff_t;
331# define XATOOFF(a) xatoi_positive(a) 335# define XATOOFF(a) xatoi_positive(a)
332# define BB_STRTOOFF bb_strtou 336# define BB_STRTOOFF bb_strtou
@@ -384,13 +388,27 @@ struct BUG_off_t_size_is_misdetected {
384#endif 388#endif
385#endif 389#endif
386 390
391/* We use a trick to have more optimized code (fewer pointer reloads
392 * and reduced binary size by a few kilobytes) like:
393 * ash.c: extern struct globals *const ash_ptr_to_globals;
394 * ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
395 * This way, compiler in ash.c knows the pointer can not change.
396 *
397 * However, this may break on weird arches or toolchains. In this case,
398 * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
399 * this optimization.
400 */
401#ifndef BB_GLOBAL_CONST
402# define BB_GLOBAL_CONST const
403#endif
404
387#if defined(errno) 405#if defined(errno)
388/* If errno is a define, assume it's "define errno (*__errno_location())" 406/* If errno is a define, assume it's "define errno (*__errno_location())"
389 * and we will cache it's result in this variable */ 407 * and we will cache it's result in this variable */
390extern int *const bb_errno; 408extern int *BB_GLOBAL_CONST bb_errno;
391#undef errno 409# undef errno
392#define errno (*bb_errno) 410# define errno (*bb_errno)
393#define bb_cached_errno_ptr 1 411# define bb_cached_errno_ptr 1
394#endif 412#endif
395 413
396#if !(ULONG_MAX > 0xffffffff) 414#if !(ULONG_MAX > 0xffffffff)
@@ -579,7 +597,7 @@ DIR *xopendir(const char *path) FAST_FUNC;
579DIR *warn_opendir(const char *path) FAST_FUNC; 597DIR *warn_opendir(const char *path) FAST_FUNC;
580 598
581char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC; 599char *xmalloc_realpath(const char *path) FAST_FUNC RETURNS_MALLOC;
582char *xmalloc_realpath_coreutils(const char *path) FAST_FUNC RETURNS_MALLOC; 600char *xmalloc_realpath_coreutils(char *path) FAST_FUNC RETURNS_MALLOC;
583char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC; 601char *xmalloc_readlink(const char *path) FAST_FUNC RETURNS_MALLOC;
584char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC; 602char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC RETURNS_MALLOC;
585/* !RETURNS_MALLOC: it's a realloc-like function */ 603/* !RETURNS_MALLOC: it's a realloc-like function */
@@ -1297,8 +1315,10 @@ void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_
1297#endif 1315#endif
1298void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; 1316void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC;
1299#if defined(__linux__) 1317#if defined(__linux__)
1318int re_execed_comm(void) FAST_FUNC;
1300void set_task_comm(const char *comm) FAST_FUNC; 1319void set_task_comm(const char *comm) FAST_FUNC;
1301#else 1320#else
1321# define re_execed_comm() 0
1302# define set_task_comm(name) ((void)0) 1322# define set_task_comm(name) ((void)0)
1303#endif 1323#endif
1304 1324
@@ -1526,16 +1546,8 @@ int scripted_main(int argc, char** argv) MAIN_EXTERNALLY_VISIBLE;
1526 1546
1527/* Applets which are useful from another applets */ 1547/* Applets which are useful from another applets */
1528int bb_cat(char** argv) FAST_FUNC; 1548int bb_cat(char** argv) FAST_FUNC;
1529int ash_main(int argc, char** argv) 1549int ash_main(int argc, char** argv) IF_SHELL_ASH(MAIN_EXTERNALLY_VISIBLE);
1530#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH 1550int hush_main(int argc, char** argv) IF_SHELL_HUSH(MAIN_EXTERNALLY_VISIBLE);
1531 MAIN_EXTERNALLY_VISIBLE
1532#endif
1533;
1534int hush_main(int argc, char** argv)
1535#if ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH
1536 MAIN_EXTERNALLY_VISIBLE
1537#endif
1538;
1539/* If shell needs them, they exist even if not enabled as applets */ 1551/* If shell needs them, they exist even if not enabled as applets */
1540int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE); 1552int echo_main(int argc, char** argv) IF_ECHO(MAIN_EXTERNALLY_VISIBLE);
1541int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE); 1553int printf_main(int argc, char **argv) IF_PRINTF(MAIN_EXTERNALLY_VISIBLE);
@@ -2331,6 +2343,7 @@ extern const char bb_PATH_root_path[] ALIGN1; /* BB_PATH_ROOT_PATH */
2331extern const int const_int_0; 2343extern const int const_int_0;
2332//extern const int const_int_1; 2344//extern const int const_int_1;
2333 2345
2346
2334/* This struct is deliberately not defined. */ 2347/* This struct is deliberately not defined. */
2335/* See docs/keep_data_small.txt */ 2348/* See docs/keep_data_small.txt */
2336struct globals; 2349struct globals;
@@ -2339,6 +2352,8 @@ struct globals;
2339 * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */ 2352 * If you want to assign a value, use SET_PTR_TO_GLOBALS(x) */
2340extern struct globals *const ptr_to_globals; 2353extern struct globals *const ptr_to_globals;
2341 2354
2355#define barrier() asm volatile ("":::"memory")
2356
2342#if defined(__clang_major__) && __clang_major__ >= 9 2357#if defined(__clang_major__) && __clang_major__ >= 9
2343/* Clang/llvm drops assignment to "constant" storage. Silently. 2358/* Clang/llvm drops assignment to "constant" storage. Silently.
2344 * Needs serious convincing to not eliminate the store. 2359 * Needs serious convincing to not eliminate the store.
@@ -2346,30 +2361,38 @@ extern struct globals *const ptr_to_globals;
2346static ALWAYS_INLINE void* not_const_pp(const void *p) 2361static ALWAYS_INLINE void* not_const_pp(const void *p)
2347{ 2362{
2348 void *pp; 2363 void *pp;
2349 __asm__ __volatile__( 2364 asm volatile (
2350 "# forget that p points to const" 2365 "# forget that p points to const"
2351 : /*outputs*/ "=r" (pp) 2366 : /*outputs*/ "=r" (pp)
2352 : /*inputs*/ "0" (p) 2367 : /*inputs*/ "0" (p)
2353 ); 2368 );
2354 return pp; 2369 return pp;
2355} 2370}
2371# define ASSIGN_CONST_PTR(pptr, v) do { \
2372 *(void**)not_const_pp(pptr) = (void*)(v); \
2373 barrier(); \
2374} while (0)
2375/* XZALLOC_CONST_PTR() is an out-of-line function to prevent
2376 * clang from reading pointer before it is assigned.
2377 */
2378void XZALLOC_CONST_PTR(const void *pptr, size_t size) FAST_FUNC;
2356#else 2379#else
2357static ALWAYS_INLINE void* not_const_pp(const void *p) { return (void*)p; } 2380# define ASSIGN_CONST_PTR(pptr, v) do { \
2358#endif 2381 *(void**)(pptr) = (void*)(v); \
2359 2382 /* At least gcc 3.4.6 on mipsel needs optimization barrier */ \
2360/* At least gcc 3.4.6 on mipsel system needs optimization barrier */
2361#define barrier() __asm__ __volatile__("":::"memory")
2362#define SET_PTR_TO_GLOBALS(x) do { \
2363 (*(struct globals**)not_const_pp(&ptr_to_globals)) = (void*)(x); \
2364 barrier(); \ 2383 barrier(); \
2365} while (0) 2384} while (0)
2385# define XZALLOC_CONST_PTR(pptr, size) ASSIGN_CONST_PTR(pptr, xzalloc(size))
2386#endif
2366 2387
2388#define SET_PTR_TO_GLOBALS(x) ASSIGN_CONST_PTR(&ptr_to_globals, x)
2367#define FREE_PTR_TO_GLOBALS() do { \ 2389#define FREE_PTR_TO_GLOBALS() do { \
2368 if (ENABLE_FEATURE_CLEAN_UP) { \ 2390 if (ENABLE_FEATURE_CLEAN_UP) { \
2369 free(ptr_to_globals); \ 2391 free(ptr_to_globals); \
2370 } \ 2392 } \
2371} while (0) 2393} while (0)
2372 2394
2395
2373/* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it, 2396/* You can change LIBBB_DEFAULT_LOGIN_SHELL, but don't use it,
2374 * use bb_default_login_shell and following defines. 2397 * use bb_default_login_shell and following defines.
2375 * If you change LIBBB_DEFAULT_LOGIN_SHELL, 2398 * If you change LIBBB_DEFAULT_LOGIN_SHELL,
diff --git a/libbb/Config.src b/libbb/Config.src
index 58c5fad50..24b31fad9 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -61,32 +61,73 @@ config SHA3_SMALL
61 64-bit x86: +270 bytes of code, 45% faster 61 64-bit x86: +270 bytes of code, 45% faster
62 32-bit x86: +450 bytes of code, 75% faster 62 32-bit x86: +450 bytes of code, 75% faster
63 63
64config FEATURE_FAST_TOP 64config FEATURE_NON_POSIX_CP
65 bool "Faster /proc scanning code (+100 bytes)" 65 bool "Non-POSIX, but safer, copying to special nodes"
66 default n # all "fast or small" options default to small 66 default y
67 help 67 help
68 This option makes top and ps ~20% faster (or 20% less CPU hungry), 68 With this option, "cp file symlink" will delete symlink
69 but code size is slightly bigger. 69 and create a regular file. This does not conform to POSIX,
70 but prevents a symlink attack.
71 Similarly, "cp file device" will not send file's data
72 to the device. (To do that, use "cat file >device")
70 73
71config FEATURE_ETC_NETWORKS 74config FEATURE_VERBOSE_CP_MESSAGE
72 bool "Support /etc/networks" 75 bool "Give more precise messages when copy fails (cp, mv etc)"
73 default n 76 default n
74 help 77 help
75 Enable support for network names in /etc/networks. This is 78 Error messages with this feature enabled:
76 a rarely used feature which allows you to use names
77 instead of IP/mask pairs in route command.
78 79
79config FEATURE_ETC_SERVICES 80 $ cp file /does_not_exist/file
80 bool "Consult /etc/services even for well-known ports" 81 cp: cannot create '/does_not_exist/file': Path does not exist
81 default n 82 $ cp file /vmlinuz/file
83 cp: cannot stat '/vmlinuz/file': Path has non-directory component
84
85 If this feature is not enabled, they will be, respectively:
86
87 cp: cannot create '/does_not_exist/file': No such file or directory
88 cp: cannot stat '/vmlinuz/file': Not a directory
89
90 This will cost you ~60 bytes.
91
92config FEATURE_USE_SENDFILE
93 bool "Use sendfile system call"
94 default y
95 help
96 When enabled, busybox will use the kernel sendfile() function
97 instead of read/write loops to copy data between file descriptors
98 (for example, cp command does this a lot).
99 If sendfile() doesn't work, copying code falls back to read/write
100 loop. sendfile() was originally implemented for faster I/O
101 from files to sockets, but since Linux 2.6.33 it was extended
102 to work for many more file types.
103
104config FEATURE_COPYBUF_KB
105 int "Copy buffer size, in kilobytes"
106 range 1 1024
107 default 4
108 help
109 Size of buffer used by cp, mv, install, wget etc.
110 Buffers which are 4 kb or less will be allocated on stack.
111 Bigger buffers will be allocated with mmap, with fallback to 4 kb
112 stack buffer if mmap fails.
113
114config MONOTONIC_SYSCALL
115 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
116 default y
117 help
118 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
119 time intervals (time, ping, traceroute etc need this).
120 Probably requires Linux 2.6+. If not selected, gettimeofday
121 will be used instead (which gives wrong results if date/time
122 is reset).
123
124config IOCTL_HEX2STR_ERROR
125 bool "Use ioctl names rather than hex values in error messages"
126 default y
82 help 127 help
83 Look up e.g. "telnet" and "http" in /etc/services file 128 Use ioctl names rather than hex values in error messages
84 instead of assuming ports 23 and 80. 129 (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
85 This is almost never necessary (everybody uses standard ports), 130 saves about 1400 bytes.
86 and it makes sense to avoid reading this file.
87 If you disable this option, in the cases where port is explicitly
88 specified as a service name (e.g. "telnet HOST PORTNAME"),
89 it will still be looked up in /etc/services.
90 131
91config FEATURE_EDITING 132config FEATURE_EDITING
92 bool "Command line editing" 133 bool "Command line editing"
@@ -302,107 +343,3 @@ config UNICODE_PRESERVE_BROKEN
302 For example, this means that entering 'l', 's', ' ', 0xff, [Enter] 343 For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
303 at shell prompt will list file named 0xff (single char name 344 at shell prompt will list file named 0xff (single char name
304 with char value 255), not file named '?'. 345 with char value 255), not file named '?'.
305
306config FEATURE_NON_POSIX_CP
307 bool "Non-POSIX, but safer, copying to special nodes"
308 default y
309 help
310 With this option, "cp file symlink" will delete symlink
311 and create a regular file. This does not conform to POSIX,
312 but prevents a symlink attack.
313 Similarly, "cp file device" will not send file's data
314 to the device. (To do that, use "cat file >device")
315
316config FEATURE_VERBOSE_CP_MESSAGE
317 bool "Give more precise messages when copy fails (cp, mv etc)"
318 default n
319 help
320 Error messages with this feature enabled:
321
322 $ cp file /does_not_exist/file
323 cp: cannot create '/does_not_exist/file': Path does not exist
324 $ cp file /vmlinuz/file
325 cp: cannot stat '/vmlinuz/file': Path has non-directory component
326
327 If this feature is not enabled, they will be, respectively:
328
329 cp: cannot create '/does_not_exist/file': No such file or directory
330 cp: cannot stat '/vmlinuz/file': Not a directory
331
332 This will cost you ~60 bytes.
333
334config FEATURE_USE_SENDFILE
335 bool "Use sendfile system call"
336 default y
337 help
338 When enabled, busybox will use the kernel sendfile() function
339 instead of read/write loops to copy data between file descriptors
340 (for example, cp command does this a lot).
341 If sendfile() doesn't work, copying code falls back to read/write
342 loop. sendfile() was originally implemented for faster I/O
343 from files to sockets, but since Linux 2.6.33 it was extended
344 to work for many more file types.
345
346config FEATURE_COPYBUF_KB
347 int "Copy buffer size, in kilobytes"
348 range 1 1024
349 default 4
350 help
351 Size of buffer used by cp, mv, install, wget etc.
352 Buffers which are 4 kb or less will be allocated on stack.
353 Bigger buffers will be allocated with mmap, with fallback to 4 kb
354 stack buffer if mmap fails.
355
356config FEATURE_SKIP_ROOTFS
357 bool "Skip rootfs in mount table"
358 default y
359 help
360 Ignore rootfs entry in mount table.
361
362 In Linux, kernel has a special filesystem, rootfs, which is initially
363 mounted on /. It contains initramfs data, if kernel is configured
364 to have one. Usually, another file system is mounted over / early
365 in boot process, and therefore most tools which manipulate
366 mount table, such as df, will skip rootfs entry.
367
368 However, some systems do not mount anything on /.
369 If you need to configure busybox for one of these systems,
370 you may find it useful to turn this option off to make df show
371 initramfs statistics.
372
373 Otherwise, choose Y.
374
375config MONOTONIC_SYSCALL
376 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
377 default y
378 help
379 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
380 time intervals (time, ping, traceroute etc need this).
381 Probably requires Linux 2.6+. If not selected, gettimeofday
382 will be used instead (which gives wrong results if date/time
383 is reset).
384
385config IOCTL_HEX2STR_ERROR
386 bool "Use ioctl names rather than hex values in error messages"
387 default y
388 help
389 Use ioctl names rather than hex values in error messages
390 (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
391 saves about 1400 bytes.
392
393config FEATURE_HWIB
394 bool "Support infiniband HW"
395 default y
396 help
397 Support for printing infiniband addresses in network applets.
398
399config FEATURE_TIMEZONE
400 bool "Allow timezone in dates"
401 default y
402 depends on DESKTOP
403 help
404 Permit the use of timezones when parsing user-provided data
405 strings, e.g. '1996-04-09 12:45:00 -0500'.
406
407 This requires support for the '%z' extension to strptime() which
408 may not be available in all implementations.
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 102e360af..60df3476f 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -21,6 +21,7 @@ lib-y += chomp.o
21lib-y += compare_string_array.o 21lib-y += compare_string_array.o
22lib-y += concat_path_file.o 22lib-y += concat_path_file.o
23lib-y += concat_subpath_file.o 23lib-y += concat_subpath_file.o
24lib-y += const_hack.o
24lib-y += copy_file.o 25lib-y += copy_file.o
25lib-y += copyfd.o 26lib-y += copyfd.o
26lib-y += crc32.o 27lib-y += crc32.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index e1f8bf432..6c0be4a83 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -262,8 +262,7 @@ void lbb_prepare(const char *applet
262 IF_FEATURE_INDIVIDUAL(, char **argv)) 262 IF_FEATURE_INDIVIDUAL(, char **argv))
263{ 263{
264#ifdef bb_cached_errno_ptr 264#ifdef bb_cached_errno_ptr
265 (*(int **)not_const_pp(&bb_errno)) = get_perrno(); 265 ASSIGN_CONST_PTR(&bb_errno, get_perrno());
266 barrier();
267#endif 266#endif
268 applet_name = applet; 267 applet_name = applet;
269 268
@@ -767,9 +766,9 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
767 int script = find_script_by_name(applet_name); 766 int script = find_script_by_name(applet_name);
768 if (script >= 0) 767 if (script >= 0)
769# if ENABLE_SHELL_ASH 768# if ENABLE_SHELL_ASH
770 exit(ash_main(-script - 1, argv)); 769 return ash_main(-script - 1, argv);
771# elif ENABLE_SHELL_HUSH 770# elif ENABLE_SHELL_HUSH
772 exit(hush_main(-script - 1, argv)); 771 return hush_main(-script - 1, argv);
773# else 772# else
774 return 1; 773 return 1;
775# endif 774# endif
@@ -1161,10 +1160,10 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
1161{ 1160{
1162# if ENABLE_SHELL_ASH 1161# if ENABLE_SHELL_ASH
1163 int script = 0; 1162 int script = 0;
1164 exit(ash_main(-script - 1, argv)); 1163 return ash_main(-script - 1, argv);
1165# elif ENABLE_SHELL_HUSH 1164# elif ENABLE_SHELL_HUSH
1166 int script = 0; 1165 int script = 0;
1167 exit(hush_main(-script - 1, argv)); 1166 return hush_main(-script - 1, argv);
1168# else 1167# else
1169 return 1; 1168 return 1;
1170# endif 1169# endif
@@ -1282,7 +1281,7 @@ int main(int argc UNUSED_PARAM, char **argv)
1282 1281
1283 full_write2_str(bb_basename(argv[0])); 1282 full_write2_str(bb_basename(argv[0]));
1284 full_write2_str(": no applets enabled\n"); 1283 full_write2_str(": no applets enabled\n");
1285 exit(127); 1284 return 127;
1286 1285
1287#else 1286#else
1288 1287
@@ -1314,8 +1313,14 @@ int main(int argc UNUSED_PARAM, char **argv)
1314 || ENABLE_FEATURE_PREFER_APPLETS 1313 || ENABLE_FEATURE_PREFER_APPLETS
1315 || !BB_MMU 1314 || !BB_MMU
1316 ) { 1315 ) {
1317 if (NUM_APPLETS > 1) 1316 if (NUM_APPLETS > 1) {
1318 set_task_comm(applet_name); 1317 /* Careful, do not trash comm of "SCRIPT.sh" -
1318 * the case when started from e.g. #!/bin/ash script.
1319 * (not limited to shells - #!/bin/awk scripts also exist)
1320 */
1321 if (re_execed_comm())
1322 set_task_comm(applet_name);
1323 }
1319 } 1324 }
1320 1325
1321 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 1326 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
diff --git a/libbb/const_hack.c b/libbb/const_hack.c
new file mode 100644
index 000000000..9575e6d67
--- /dev/null
+++ b/libbb/const_hack.c
@@ -0,0 +1,16 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Trick to assign a const ptr with barrier for clang
4 *
5 * Copyright (C) 2021 by YU Jincheng <shana@zju.edu.cn>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9#include "libbb.h"
10
11#if defined(__clang_major__) && __clang_major__ >= 9
12void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size)
13{
14 ASSIGN_CONST_PTR(pptr, xzalloc(size));
15}
16#endif
diff --git a/libbb/dump.c b/libbb/dump.c
index ffae04786..d24057325 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -568,7 +568,7 @@ static void conv_u(PR *pr, unsigned char *p)
568 } 568 }
569} 569}
570 570
571static void display(priv_dumper_t* dumper) 571static NOINLINE void display(priv_dumper_t* dumper)
572{ 572{
573 unsigned char *bp; 573 unsigned char *bp;
574 unsigned char savech = '\0'; 574 unsigned char savech = '\0';
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 7c46fa5db..8abc87976 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -135,10 +135,6 @@ enum {
135 : 0x7ff0 135 : 0x7ff0
136}; 136};
137 137
138#if ENABLE_USERNAME_OR_HOMEDIR
139static const char null_str[] ALIGN1 = "";
140#endif
141
142/* We try to minimize both static and stack usage. */ 138/* We try to minimize both static and stack usage. */
143struct lineedit_statics { 139struct lineedit_statics {
144 line_input_t *state; 140 line_input_t *state;
@@ -161,12 +157,13 @@ struct lineedit_statics {
161 157
162#if ENABLE_USERNAME_OR_HOMEDIR 158#if ENABLE_USERNAME_OR_HOMEDIR
163 char *user_buf; 159 char *user_buf;
164 char *home_pwd_buf; /* = (char*)null_str; */ 160 char *home_pwd_buf;
161 smallint got_user_strings;
165#endif 162#endif
166 163
167#if ENABLE_FEATURE_TAB_COMPLETION 164#if ENABLE_FEATURE_TAB_COMPLETION
168 char **matches;
169 unsigned num_matches; 165 unsigned num_matches;
166 char **matches;
170#endif 167#endif
171 168
172#if ENABLE_FEATURE_EDITING_WINCH 169#if ENABLE_FEATURE_EDITING_WINCH
@@ -192,7 +189,7 @@ struct lineedit_statics {
192}; 189};
193 190
194/* See lineedit_ptr_hack.c */ 191/* See lineedit_ptr_hack.c */
195extern struct lineedit_statics *const lineedit_ptr_to_statics; 192extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics;
196 193
197#define S (*lineedit_ptr_to_statics) 194#define S (*lineedit_ptr_to_statics)
198#define state (S.state ) 195#define state (S.state )
@@ -207,15 +204,15 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
207#define prompt_last_line (S.prompt_last_line) 204#define prompt_last_line (S.prompt_last_line)
208#define user_buf (S.user_buf ) 205#define user_buf (S.user_buf )
209#define home_pwd_buf (S.home_pwd_buf ) 206#define home_pwd_buf (S.home_pwd_buf )
210#define matches (S.matches ) 207#define got_user_strings (S.got_user_strings)
211#define num_matches (S.num_matches ) 208#define num_matches (S.num_matches )
209#define matches (S.matches )
212#define delptr (S.delptr ) 210#define delptr (S.delptr )
213#define newdelflag (S.newdelflag ) 211#define newdelflag (S.newdelflag )
214#define delbuf (S.delbuf ) 212#define delbuf (S.delbuf )
215 213
216#define INIT_S() do { \ 214#define INIT_S() do { \
217 (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ 215 XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \
218 barrier(); \
219} while (0) 216} while (0)
220 217
221static void deinit_S(void) 218static void deinit_S(void)
@@ -227,14 +224,47 @@ static void deinit_S(void)
227#endif 224#endif
228#if ENABLE_USERNAME_OR_HOMEDIR 225#if ENABLE_USERNAME_OR_HOMEDIR
229 free(user_buf); 226 free(user_buf);
230 if (home_pwd_buf != null_str) 227 free(home_pwd_buf);
231 free(home_pwd_buf);
232#endif 228#endif
233 free(lineedit_ptr_to_statics); 229 free(lineedit_ptr_to_statics);
234} 230}
235#define DEINIT_S() deinit_S() 231#define DEINIT_S() deinit_S()
236 232
237 233
234#if ENABLE_USERNAME_OR_HOMEDIR
235/* Call getpwuid() only if necessary.
236 * E.g. if PS1=':', no user database reading is needed to generate prompt.
237 * (Unfortunately, default PS1='\w \$' needs it, \w abbreviates homedir
238 * as ~/... - for that it needs to *know* the homedir...)
239 */
240static void get_user_strings(void)
241{
242 struct passwd *entry;
243
244 got_user_strings = 1;
245 entry = getpwuid(geteuid());
246 if (entry) {
247 user_buf = xstrdup(entry->pw_name);
248 home_pwd_buf = xstrdup(entry->pw_dir);
249 }
250}
251
252static const char *get_username_str(void)
253{
254 if (!got_user_strings)
255 get_user_strings();
256 return user_buf ? user_buf : "";
257 /* btw, bash uses "I have no name!" string if uid has no entry */
258}
259
260static NOINLINE const char *get_homedir_or_NULL(void)
261{
262 if (!got_user_strings)
263 get_user_strings();
264 return home_pwd_buf;
265}
266#endif
267
238#if ENABLE_UNICODE_SUPPORT 268#if ENABLE_UNICODE_SUPPORT
239static size_t load_string(const char *src) 269static size_t load_string(const char *src)
240{ 270{
@@ -748,11 +778,11 @@ static char *username_path_completion(char *ud)
748 struct passwd *entry; 778 struct passwd *entry;
749#endif 779#endif
750 char *tilde_name = ud; 780 char *tilde_name = ud;
751 char *home = NULL; 781 const char *home = NULL;
752 782
753 ud++; /* skip ~ */ 783 ud++; /* skip ~ */
754 if (*ud == '/') { /* "~/..." */ 784 if (*ud == '/') { /* "~/..." */
755 home = home_pwd_buf; 785 home = get_homedir_or_NULL();
756# if !ENABLE_PLATFORM_MINGW32 786# if !ENABLE_PLATFORM_MINGW32
757 } else { 787 } else {
758 /* "~user/..." */ 788 /* "~user/..." */
@@ -1881,7 +1911,7 @@ vi_back_motion(void)
1881 input_backward(1); 1911 input_backward(1);
1882 } 1912 }
1883} 1913}
1884#endif 1914#endif /* ENABLE_FEATURE_EDITING_VI */
1885 1915
1886/* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ 1916/* Modelled after bash 4.0 behavior of Ctrl-<arrow> */
1887static void ctrl_left(void) 1917static void ctrl_left(void)
@@ -1982,7 +2012,7 @@ static void ask_terminal(void)
1982 } 2012 }
1983} 2013}
1984#else 2014#else
1985#define ask_terminal() ((void)0) 2015# define ask_terminal() ((void)0)
1986#endif 2016#endif
1987 2017
1988/* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: 2018/* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing:
@@ -2091,7 +2121,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2091 2121
2092 switch (c) { 2122 switch (c) {
2093 case 'u': 2123 case 'u':
2094 pbuf = user_buf ? user_buf : (char*)""; 2124 pbuf = (char*)get_username_str();
2095 break; 2125 break;
2096 case 'H': 2126 case 'H':
2097 case 'h': 2127 case 'h':
@@ -2113,14 +2143,15 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2113 case 'w': /* current dir */ 2143 case 'w': /* current dir */
2114 case 'W': /* basename of cur dir */ 2144 case 'W': /* basename of cur dir */
2115 if (!cwd_buf) { 2145 if (!cwd_buf) {
2146 const char *home;
2116 cwd_buf = xrealloc_getcwd_or_warn(NULL); 2147 cwd_buf = xrealloc_getcwd_or_warn(NULL);
2117 if (!cwd_buf) 2148 if (!cwd_buf)
2118 cwd_buf = (char *)bb_msg_unknown; 2149 cwd_buf = (char *)bb_msg_unknown;
2119 else if (home_pwd_buf[0]) { 2150 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) {
2120 char *after_home_user; 2151 char *after_home_user;
2121 2152
2122 /* /home/user[/something] -> ~[/something] */ 2153 /* /home/user[/something] -> ~[/something] */
2123 after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); 2154 after_home_user = is_prefixed_with(cwd_buf, home);
2124 if (after_home_user 2155 if (after_home_user
2125 && (*after_home_user == '/' || *after_home_user == '\0') 2156 && (*after_home_user == '/' || *after_home_user == '\0')
2126 ) { 2157 ) {
@@ -2176,7 +2207,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2176 if (c == '\n') 2207 if (c == '\n')
2177 cmdedit_prmt_len = 0; 2208 cmdedit_prmt_len = 0;
2178 else if (flg_not_length != ']') { 2209 else if (flg_not_length != ']') {
2179#if ENABLE_UNICODE_SUPPORT 2210# if ENABLE_UNICODE_SUPPORT
2180 if (n == 1) { 2211 if (n == 1) {
2181 /* Only count single-byte characters and the first of multi-byte characters */ 2212 /* Only count single-byte characters and the first of multi-byte characters */
2182 if ((unsigned char)*pbuf < 0x80 /* single byte character */ 2213 if ((unsigned char)*pbuf < 0x80 /* single byte character */
@@ -2187,9 +2218,9 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2187 } else { 2218 } else {
2188 cmdedit_prmt_len += unicode_strwidth(pbuf); 2219 cmdedit_prmt_len += unicode_strwidth(pbuf);
2189 } 2220 }
2190#else 2221# else
2191 cmdedit_prmt_len += n; 2222 cmdedit_prmt_len += n;
2192#endif 2223# endif
2193 } 2224 }
2194 } 2225 }
2195 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); 2226 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf);
@@ -2416,7 +2447,7 @@ static int32_t reverse_i_search(int timeout)
2416 } 2447 }
2417 2448
2418 /* Append this char */ 2449 /* Append this char */
2419#if ENABLE_UNICODE_SUPPORT 2450# if ENABLE_UNICODE_SUPPORT
2420 if (unicode_status == UNICODE_ON) { 2451 if (unicode_status == UNICODE_ON) {
2421 mbstate_t mbstate = { 0 }; 2452 mbstate_t mbstate = { 0 };
2422 char buf[MB_CUR_MAX + 1]; 2453 char buf[MB_CUR_MAX + 1];
@@ -2427,7 +2458,7 @@ static int32_t reverse_i_search(int timeout)
2427 strcpy(match_buf + match_buf_len, buf); 2458 strcpy(match_buf + match_buf_len, buf);
2428 } 2459 }
2429 } else 2460 } else
2430#endif 2461# endif
2431 if (match_buf_len < sizeof(match_buf) - 1) { 2462 if (match_buf_len < sizeof(match_buf) - 1) {
2432 match_buf[match_buf_len] = ic; 2463 match_buf[match_buf_len] = ic;
2433 match_buf[match_buf_len + 1] = '\0'; 2464 match_buf[match_buf_len + 1] = '\0';
@@ -2479,7 +2510,7 @@ static int32_t reverse_i_search(int timeout)
2479 2510
2480 return ic; 2511 return ic;
2481} 2512}
2482#endif 2513#endif /* ENABLE_FEATURE_REVERSE_SEARCH */
2483 2514
2484#if ENABLE_FEATURE_EDITING_WINCH 2515#if ENABLE_FEATURE_EDITING_WINCH
2485static void sigaction2(int sig, struct sigaction *act) 2516static void sigaction2(int sig, struct sigaction *act)
@@ -2521,7 +2552,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2521 //command_len = 0; - done by INIT_S() 2552 //command_len = 0; - done by INIT_S()
2522 //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ 2553 //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
2523 cmdedit_termw = 80; 2554 cmdedit_termw = 80;
2524 IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;)
2525 IF_FEATURE_EDITING_VI(delptr = delbuf;) 2555 IF_FEATURE_EDITING_VI(delptr = delbuf;)
2526 2556
2527#if !ENABLE_PLATFORM_MINGW32 2557#if !ENABLE_PLATFORM_MINGW32
@@ -2589,18 +2619,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2589 tcsetattr_stdin_TCSANOW(&new_settings); 2619 tcsetattr_stdin_TCSANOW(&new_settings);
2590#endif 2620#endif
2591 2621
2592#if ENABLE_USERNAME_OR_HOMEDIR
2593 {
2594 struct passwd *entry;
2595
2596 entry = getpwuid(geteuid());
2597 if (entry) {
2598 user_buf = xstrdup(entry->pw_name);
2599 home_pwd_buf = xstrdup(entry->pw_dir);
2600 }
2601 }
2602#endif
2603
2604#if 0 2622#if 0
2605 for (i = 0; i <= state->max_history; i++) 2623 for (i = 0; i <= state->max_history; i++)
2606 bb_error_msg("history[%d]:'%s'", i, state->history[i]); 2624 bb_error_msg("history[%d]:'%s'", i, state->history[i]);
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 885c19f1a..151739ae2 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -28,6 +28,22 @@
28# ifndef PR_GET_NAME 28# ifndef PR_GET_NAME
29# define PR_GET_NAME 16 29# define PR_GET_NAME 16
30# endif 30# endif
31# if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS || !BB_MMU
32int FAST_FUNC re_execed_comm(void)
33{
34 const char *e, *expected_comm;
35 char comm[16];
36
37 BUILD_BUG_ON(CONFIG_BUSYBOX_EXEC_PATH[0] != '/');
38 e = CONFIG_BUSYBOX_EXEC_PATH;
39 /* Hopefully (strrchr(e) - e) evaluates to constant at compile time: */
40 expected_comm = bb_busybox_exec_path + (strrchr(e, '/') - e) + 1;
41
42 prctl(PR_GET_NAME, (long)comm, 0, 0, 0);
43 //bb_error_msg("comm:'%.*s' expected:'%s'", 16, comm, expected_comm);
44 return strcmp(comm, expected_comm) == 0;
45}
46# endif
31void FAST_FUNC set_task_comm(const char *comm) 47void FAST_FUNC set_task_comm(const char *comm)
32{ 48{
33 /* okay if too long (truncates) */ 49 /* okay if too long (truncates) */
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 31680810b..024ee9047 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -130,7 +130,7 @@ char* FAST_FUNC xmalloc_realpath(const char *path)
130#endif 130#endif
131} 131}
132 132
133char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) 133char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
134{ 134{
135 char *buf; 135 char *buf;
136 136
@@ -144,32 +144,19 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
144 * (the directory must exist). 144 * (the directory must exist).
145 */ 145 */
146 if (!buf && errno == ENOENT) { 146 if (!buf && errno == ENOENT) {
147 char *last_slash = strrchr(path, '/'); 147 char *target, c, *last_slash;
148 if (last_slash) { 148 size_t i;
149 *last_slash++ = '\0'; 149
150 buf = xmalloc_realpath(path); 150 target = xmalloc_readlink(path);
151 if (buf) { 151 if (target) {
152 unsigned len = strlen(buf); 152 /*
153 buf = xrealloc(buf, len + strlen(last_slash) + 2); 153 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
154 buf[len++] = '/'; 154 * $ readlink -f symlink
155 strcpy(buf + len, last_slash); 155 * /usr/bin/qwe
156 } 156 * $ realpath symlink
157 } else { 157 * /usr/bin/qwe
158 char *target = xmalloc_readlink(path); 158 */
159 if (target) { 159 if (target[0] != '/') {
160 char *cwd;
161 if (target[0] == '/') {
162 /*
163 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
164 * $ readlink -f symlink
165 * /usr/bin/qwe/target_does_not_exist
166 * $ realpath symlink
167 * /usr/bin/qwe/target_does_not_exist
168 */
169 buf = xmalloc_realpath_coreutils(target);
170 free(target);
171 return buf;
172 }
173 /* 160 /*
174 * $ ln -s target_does_not_exist symlink 161 * $ ln -s target_does_not_exist symlink
175 * $ readlink -f symlink 162 * $ readlink -f symlink
@@ -177,13 +164,41 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
177 * $ realpath symlink 164 * $ realpath symlink
178 * /CURDIR/target_does_not_exist 165 * /CURDIR/target_does_not_exist
179 */ 166 */
180 cwd = xrealloc_getcwd_or_warn(NULL); 167 char *cwd = xrealloc_getcwd_or_warn(NULL);
181 buf = concat_path_file(cwd, target); 168 char *tmp = concat_path_file(cwd, target);
182 free(cwd); 169 free(cwd);
183 free(target); 170 free(target);
184 return buf; 171 target = tmp;
172 }
173 buf = xmalloc_realpath_coreutils(target);
174 free(target);
175 return buf;
176 }
177
178 /* ignore leading and trailing slashes */
179 while (path[0] == '/' && path[1] == '/')
180 ++path;
181 i = strlen(path) - 1;
182 while (i > 0 && path[i] == '/')
183 i--;
184 c = path[i + 1];
185 path[i + 1] = '\0';
186
187 last_slash = strrchr(path, '/');
188 if (last_slash == path)
189 buf = xstrdup(path);
190 else if (last_slash) {
191 *last_slash = '\0';
192 buf = xmalloc_realpath(path);
193 *last_slash++ = '/';
194 if (buf) {
195 unsigned len = strlen(buf);
196 buf = xrealloc(buf, len + strlen(last_slash) + 2);
197 buf[len++] = '/';
198 strcpy(buf + len, last_slash);
185 } 199 }
186 } 200 }
201 path[i + 1] = c;
187 } 202 }
188 203
189 return buf; 204 return buf;
diff --git a/mailutils/Config.src b/mailutils/Config.src
index 6d47163e4..b3a3e506d 100644
--- a/mailutils/Config.src
+++ b/mailutils/Config.src
@@ -1,7 +1,5 @@
1menu "Mail Utilities" 1menu "Mail Utilities"
2 2
3INSERT
4
5config FEATURE_MIME_CHARSET 3config FEATURE_MIME_CHARSET
6 string "Default charset" 4 string "Default charset"
7 default "us-ascii" 5 default "us-ascii"
@@ -9,4 +7,6 @@ config FEATURE_MIME_CHARSET
9 help 7 help
10 Default charset of the message. 8 Default charset of the message.
11 9
10INSERT
11
12endmenu 12endmenu
diff --git a/miscutils/bc.c b/miscutils/bc.c
index f931be5cc..e3f7573c9 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -2261,7 +2261,7 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size
2261} 2261}
2262#define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS) 2262#define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS)
2263 2263
2264static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale) 2264static NOINLINE BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2265{ 2265{
2266 BcStatus s; 2266 BcStatus s;
2267 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp; 2267 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
diff --git a/miscutils/less.c b/miscutils/less.c
index a5ce14c91..063c4d378 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -1904,7 +1904,7 @@ int less_main(int argc, char **argv)
1904 getopt32(argv, "EMmN~IF" 1904 getopt32(argv, "EMmN~IF"
1905 IF_FEATURE_LESS_TRUNCATE("S") 1905 IF_FEATURE_LESS_TRUNCATE("S")
1906 IF_FEATURE_LESS_RAW("R") 1906 IF_FEATURE_LESS_RAW("R")
1907 /*ignored:*/"s" 1907 /*ignored:*/"sX"
1908 ); 1908 );
1909 argv += optind; 1909 argv += optind;
1910 num_files = argc - optind; 1910 num_files = argc - optind;
diff --git a/networking/Config.src b/networking/Config.src
index 04d644bc9..0942645c3 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -46,6 +46,32 @@ config VERBOSE_RESOLUTION_ERRORS
46 "can't resolve 'hostname.com'" and want to know more. 46 "can't resolve 'hostname.com'" and want to know more.
47 This may increase size of your executable a bit. 47 This may increase size of your executable a bit.
48 48
49config FEATURE_ETC_NETWORKS
50 bool "Support /etc/networks"
51 default n
52 help
53 Enable support for network names in /etc/networks. This is
54 a rarely used feature which allows you to use names
55 instead of IP/mask pairs in route command.
56
57config FEATURE_ETC_SERVICES
58 bool "Consult /etc/services even for well-known ports"
59 default n
60 help
61 Look up e.g. "telnet" and "http" in /etc/services file
62 instead of assuming ports 23 and 80.
63 This is almost never necessary (everybody uses standard ports),
64 and it makes sense to avoid reading this file.
65 If you disable this option, in the cases where port is explicitly
66 specified as a service name (e.g. "telnet HOST PORTNAME"),
67 it will still be looked up in /etc/services.
68
69config FEATURE_HWIB
70 bool "Support infiniband HW"
71 default y
72 help
73 Support for printing infiniband addresses in network applets.
74
49config FEATURE_TLS_SHA1 75config FEATURE_TLS_SHA1
50 bool "In TLS code, support ciphers which use deprecated SHA1" 76 bool "In TLS code, support ciphers which use deprecated SHA1"
51 depends on TLS 77 depends on TLS
diff --git a/networking/brctl.c b/networking/brctl.c
index c83aac6e0..956bd91f3 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -318,7 +318,7 @@ static void printf_xstrtou(const char *fmt)
318 printf(fmt, xstrtou(filedata, 0)); 318 printf(fmt, xstrtou(filedata, 0));
319} 319}
320 320
321static void show_bridge_port(const char *name) 321static NOINLINE void show_bridge_port(const char *name)
322{ 322{
323 char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8]; 323 char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 8];
324 char *sfx; 324 char *sfx;
diff --git a/networking/httpd.c b/networking/httpd.c
index 71e3a723f..6cc189272 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -281,7 +281,7 @@
281//usage: IF_NOT_PLATFORM_MINGW32( 281//usage: IF_NOT_PLATFORM_MINGW32(
282//usage: "\n -i Inetd mode" 282//usage: "\n -i Inetd mode"
283//usage: ) 283//usage: )
284//usage: "\n -f Don't daemonize" 284//usage: "\n -f Run in foreground"
285//usage: "\n -v[v] Verbose" 285//usage: "\n -v[v] Verbose"
286//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")" 286//usage: "\n -p [IP:]PORT Bind to IP:PORT (default *:"STR(CONFIG_FEATURE_HTTPD_PORT_DEFAULT)")"
287//usage: IF_FEATURE_HTTPD_SETUID( 287//usage: IF_FEATURE_HTTPD_SETUID(
@@ -1918,14 +1918,17 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
1918 send_headers(HTTP_OK); 1918 send_headers(HTTP_OK);
1919#if ENABLE_FEATURE_USE_SENDFILE 1919#if ENABLE_FEATURE_USE_SENDFILE
1920 { 1920 {
1921 off_t offset = (range_start < 0) ? 0 : range_start; 1921 off_t offset;
1922 if (range_start < 0)
1923 range_start = 0;
1924 offset = range_start;
1922 while (1) { 1925 while (1) {
1923 /* sz is rounded down to 64k */ 1926 /* sz is rounded down to 64k */
1924 ssize_t sz = MAXINT(ssize_t) - 0xffff; 1927 ssize_t sz = MAXINT(ssize_t) - 0xffff;
1925 IF_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;) 1928 IF_FEATURE_HTTPD_RANGES(if (sz > range_len) sz = range_len;)
1926 count = sendfile(STDOUT_FILENO, fd, &offset, sz); 1929 count = sendfile(STDOUT_FILENO, fd, &offset, sz);
1927 if (count < 0) { 1930 if (count < 0) {
1928 if (offset == range_start) 1931 if (offset == range_start) /* was it the very 1st sendfile? */
1929 break; /* fall back to read/write loop */ 1932 break; /* fall back to read/write loop */
1930 goto fin; 1933 goto fin;
1931 } 1934 }
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 18dcaff96..c4b6b9584 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -20,7 +20,7 @@
20//usage: "[OPTIONS]" 20//usage: "[OPTIONS]"
21//usage:#define ifplugd_full_usage "\n\n" 21//usage:#define ifplugd_full_usage "\n\n"
22//usage: "Network interface plug detection daemon\n" 22//usage: "Network interface plug detection daemon\n"
23//usage: "\n -n Don't daemonize" 23//usage: "\n -n Run in foreground"
24//usage: "\n -s Don't log to syslog" 24//usage: "\n -s Don't log to syslog"
25//usage: "\n -i IFACE Interface" 25//usage: "\n -i IFACE Interface"
26//usage: "\n -f/-F Treat link detection error as link down/link up" 26//usage: "\n -f/-F Treat link detection error as link down/link up"
diff --git a/networking/ip.c b/networking/ip.c
index 85b1ba080..7c3208699 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -152,7 +152,7 @@
152//usage:#define iplink_trivial_usage 152//usage:#define iplink_trivial_usage
153//usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n" 153//usage: /*Usage:iplink*/"set IFACE [up|down] [arp on|off] [multicast on|off]\n"
154//usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n" 154//usage: " [promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]\n"
155//usage: " [master IFACE | nomaster]" 155//usage: " [master IFACE | nomaster] [netns PID]"
156// * short help shows only "set" command, long help continues (with just one "\n") 156// * short help shows only "set" command, long help continues (with just one "\n")
157// * and shows all other commands: 157// * and shows all other commands:
158//usage:#define iplink_full_usage "\n" 158//usage:#define iplink_full_usage "\n"
diff --git a/networking/libiproute/iplink.c b/networking/libiproute/iplink.c
index 1a1064bdc..68d199044 100644
--- a/networking/libiproute/iplink.c
+++ b/networking/libiproute/iplink.c
@@ -153,6 +153,30 @@ static void set_master(char *dev, int master)
153} 153}
154 154
155/* Exits on error */ 155/* Exits on error */
156static void set_netns(char *dev, int netns)
157{
158 struct rtnl_handle rth;
159 struct {
160 struct nlmsghdr n;
161 struct ifinfomsg i;
162 char buf[1024];
163 } req;
164
165 memset(&req, 0, sizeof(req));
166 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
167 req.n.nlmsg_flags = NLM_F_REQUEST;
168 req.n.nlmsg_type = RTM_NEWLINK;
169 req.i.ifi_family = preferred_family;
170
171 xrtnl_open(&rth);
172 req.i.ifi_index = xll_name_to_index(dev);
173 //printf("netns %i for %i\n", netns, req.i.ifi_index);
174 addattr_l(&req.n, sizeof(req), IFLA_NET_NS_PID, &netns, 4);
175 if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
176 xfunc_die();
177}
178
179/* Exits on error */
156static int get_address(char *dev, int *htype) 180static int get_address(char *dev, int *htype)
157{ 181{
158 struct ifreq ifr; 182 struct ifreq ifr;
@@ -226,6 +250,7 @@ static int do_set(char **argv)
226 int qlen = -1; 250 int qlen = -1;
227 int mtu = -1; 251 int mtu = -1;
228 int master = -1; 252 int master = -1;
253 int netns = -1;
229 char *newaddr = NULL; 254 char *newaddr = NULL;
230 char *newbrd = NULL; 255 char *newbrd = NULL;
231 struct ifreq ifr0, ifr1; 256 struct ifreq ifr0, ifr1;
@@ -234,11 +259,11 @@ static int do_set(char **argv)
234 /* If you add stuff here, update iplink_full_usage */ 259 /* If you add stuff here, update iplink_full_usage */
235 static const char keywords[] ALIGN1 = 260 static const char keywords[] ALIGN1 =
236 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0" 261 "up\0""down\0""name\0""mtu\0""qlen\0""multicast\0"
237 "arp\0""promisc\0""address\0" 262 "arp\0""promisc\0""address\0""netns\0"
238 "master\0""nomaster\0" 263 "master\0""nomaster\0"
239 "dev\0" /* must be last */; 264 "dev\0" /* must be last */;
240 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast, 265 enum { ARG_up = 0, ARG_down, ARG_name, ARG_mtu, ARG_qlen, ARG_multicast,
241 ARG_arp, ARG_promisc, ARG_addr, 266 ARG_arp, ARG_promisc, ARG_addr, ARG_netns,
242 ARG_master, ARG_nomaster, 267 ARG_master, ARG_nomaster,
243 ARG_dev }; 268 ARG_dev };
244 enum { PARM_on = 0, PARM_off }; 269 enum { PARM_on = 0, PARM_off };
@@ -276,6 +301,9 @@ static int do_set(char **argv)
276 master = xll_name_to_index(*argv); 301 master = xll_name_to_index(*argv);
277 } else if (key == ARG_nomaster) { 302 } else if (key == ARG_nomaster) {
278 master = 0; 303 master = 0;
304 } else if (key == ARG_netns) {
305 NEXT_ARG();
306 netns = get_unsigned(*argv, "netns");
279 } else if (key >= ARG_dev) { 307 } else if (key >= ARG_dev) {
280 /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */ 308 /* ^^^^^^ ">=" here results in "dev IFACE" treated as default */
281 if (key == ARG_dev) { 309 if (key == ARG_dev) {
@@ -463,6 +491,9 @@ static int do_set(char **argv)
463 if (master != -1) { 491 if (master != -1) {
464 set_master(dev, master); 492 set_master(dev, master);
465 } 493 }
494 if (netns != -1) {
495 set_netns(dev, netns);
496 }
466 if (mask) 497 if (mask)
467 do_chflags(dev, flags, mask); 498 do_chflags(dev, flags, mask);
468 return 0; 499 return 0;
diff --git a/networking/nslookup.c b/networking/nslookup.c
index de7b5c0e7..6da97baf4 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -335,7 +335,7 @@ enum {
335 OPT_debug = (1 << 0), 335 OPT_debug = (1 << 0),
336}; 336};
337 337
338static int parse_reply(const unsigned char *msg, size_t len) 338static NOINLINE int parse_reply(const unsigned char *msg, size_t len)
339{ 339{
340 HEADER *header; 340 HEADER *header;
341 341
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 6bf6c4e07..204e1d7c2 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -78,7 +78,7 @@
78//usage:#define ntpd_full_usage "\n\n" 78//usage:#define ntpd_full_usage "\n\n"
79//usage: "NTP client/server\n" 79//usage: "NTP client/server\n"
80//usage: "\n -d[d] Verbose" 80//usage: "\n -d[d] Verbose"
81//usage: "\n -n Do not daemonize" 81//usage: "\n -n Run in foreground"
82//usage: "\n -q Quit after clock is set" 82//usage: "\n -q Quit after clock is set"
83//usage: "\n -N Run at high priority" 83//usage: "\n -N Run at high priority"
84//usage: "\n -w Do not set time (only query peers), implies -n" 84//usage: "\n -w Do not set time (only query peers), implies -n"
@@ -1152,7 +1152,7 @@ fit(peer_t *p, double rd)
1152// return 0; 1152// return 0;
1153 return 1; 1153 return 1;
1154} 1154}
1155static peer_t* 1155static NOINLINE peer_t*
1156select_and_cluster(void) 1156select_and_cluster(void)
1157{ 1157{
1158 peer_t *p; 1158 peer_t *p;
diff --git a/networking/tls.c b/networking/tls.c
index a1b12f9ed..36f83212b 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -22,47 +22,23 @@
22 22
23#include "tls.h" 23#include "tls.h"
24 24
25// Usually enabled. You can disable some of them to force only
26// specific ciphers to be advertized to server.
27// (this would not exclude code to handle disabled ciphers, no code size win)
28#define ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 1
29#define ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256 1
30#define ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 1
31#define ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256 1
32#define ALLOW_RSA_WITH_AES_128_CBC_SHA256 1
33#define ALLOW_RSA_WITH_AES_256_CBC_SHA256 1
34#define ALLOW_RSA_WITH_AES_128_GCM_SHA256 1
35#define ALLOW_CURVE_P256 1
36#define ALLOW_CURVE_X25519 1
37
38// For testing (does everything except encrypting).
25// works against "openssl s_server -cipher NULL" 39// works against "openssl s_server -cipher NULL"
26// and against wolfssl-3.9.10-stable/examples/server/server.c: 40// and against wolfssl-3.9.10-stable/examples/server/server.c:
27#define ALLOW_RSA_NULL_SHA256 0 // for testing (does everything except encrypting) 41#define ALLOW_RSA_NULL_SHA256 0
28
29//Tested against kernel.org:
30//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box
31//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE
32//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE
33//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it)
34//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE
35//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
36//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE
37//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
38//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
39//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
40//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
41//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
42//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE
43//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE
44
45// works against wolfssl-3.9.10-stable/examples/server/server.c
46// works for kernel.org
47// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page)
48// getting alert 40 "handshake failure" at once
49// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher
50// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-SHA256
51// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES256-GCM-SHA384
52// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA256
53// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-GCM-SHA256
54// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -cipher AES128-SHA
55// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported)
56//#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 //0x003D
57// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz"
58//#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA //0x002F
59
60// bug #11456:
61// ftp.openbsd.org only supports ECDHE-RSA-AESnnn-GCM-SHAnnn or ECDHE-RSA-CHACHA20-POLY1305
62//#define CIPHER_ID3 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //0xC02F
63// host is.gd accepts only ECDHE-ECDSA-foo (the simplest which works: ECDHE-ECDSA-AES128-SHA 0xC009)
64//#define CIPHER_ID4 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA //0xC009
65
66 42
67#define TLS_DEBUG 0 43#define TLS_DEBUG 0
68#define TLS_DEBUG_HASH 0 44#define TLS_DEBUG_HASH 0
@@ -1488,9 +1464,20 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un
1488 1464
1489static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 1465static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1490{ 1466{
1491#define NUM_CIPHERS (7 + 6 * ENABLE_FEATURE_TLS_SHA1 + ALLOW_RSA_NULL_SHA256) 1467#define NUM_CIPHERS (0 \
1468 + 4 * ENABLE_FEATURE_TLS_SHA1 \
1469 + ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 \
1470 + ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256 \
1471 + ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 \
1472 + ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256 \
1473 + 2 * ENABLE_FEATURE_TLS_SHA1 \
1474 + ALLOW_RSA_WITH_AES_128_CBC_SHA256 \
1475 + ALLOW_RSA_WITH_AES_256_CBC_SHA256 \
1476 + ALLOW_RSA_WITH_AES_128_GCM_SHA256 \
1477 + ALLOW_RSA_NULL_SHA256 \
1478 )
1492 static const uint8_t ciphers[] = { 1479 static const uint8_t ciphers[] = {
1493 0x00,2 + NUM_CIPHERS*2, //len16_be 1480 0x00,2 * (1 + NUM_CIPHERS), //len16_be
1494 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV 1481 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV
1495 /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ 1482 /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1496#if ENABLE_FEATURE_TLS_SHA1 1483#if ENABLE_FEATURE_TLS_SHA1
@@ -1501,14 +1488,22 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1501 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA 1488 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
1502 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA 1489 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
1503#endif 1490#endif
1491#if ALLOW_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
1504 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ 1492 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1493#endif
1505 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1494 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1495#if ALLOW_ECDHE_RSA_WITH_AES_128_CBC_SHA256
1506 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 1496 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
1497#endif
1507 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1498 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1499#if ALLOW_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
1508 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ 1500 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/
1501#endif
1509 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" 1502 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC"
1510//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF? 1503//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF?
1504#if ALLOW_ECDHE_RSA_WITH_AES_128_GCM_SHA256
1511 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 1505 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1506#endif
1512 // 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" 1507 // 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"
1513 //possibly these too: 1508 //possibly these too:
1514#if ENABLE_FEATURE_TLS_SHA1 1509#if ENABLE_FEATURE_TLS_SHA1
@@ -1521,9 +1516,15 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1521 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 1516 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1522 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA 1517 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1523#endif 1518#endif
1519#if ALLOW_RSA_WITH_AES_128_CBC_SHA256
1524 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 1520 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1521#endif
1522#if ALLOW_RSA_WITH_AES_256_CBC_SHA256
1525 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 1523 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1524#endif
1525#if ALLOW_RSA_WITH_AES_128_GCM_SHA256
1526 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 1526 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
1527#endif
1527 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" 1528 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac"
1528#if ALLOW_RSA_NULL_SHA256 1529#if ALLOW_RSA_NULL_SHA256
1529 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 1530 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256
@@ -1532,12 +1533,16 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1532 }; 1533 };
1533 static const uint8_t supported_groups[] = { 1534 static const uint8_t supported_groups[] = {
1534 0x00,0x0a, //extension_type: "supported_groups" 1535 0x00,0x0a, //extension_type: "supported_groups"
1535 0x00,0x06, //ext len 1536 0x00,2 * (1 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //ext len
1536 0x00,0x04, //list len 1537 0x00,2 * (0 + ALLOW_CURVE_P256 + ALLOW_CURVE_X25519), //list len
1537 0x00,0x17, //curve_secp256r1 (aka P256) 1538#if ALLOW_CURVE_P256
1539 0x00,0x17, //curve_secp256r1 (aka P256, aka prime256v1)
1540#endif
1538 //0x00,0x18, //curve_secp384r1 1541 //0x00,0x18, //curve_secp384r1
1539 //0x00,0x19, //curve_secp521r1 1542 //0x00,0x19, //curve_secp521r1
1543#if ALLOW_CURVE_X25519
1540 0x00,0x1d, //curve_x25519 (RFC 7748) 1544 0x00,0x1d, //curve_x25519 (RFC 7748)
1545#endif
1541 //0x00,0x1e, //curve_x448 (RFC 7748) 1546 //0x00,0x1e, //curve_x448 (RFC 7748)
1542 }; 1547 };
1543 //static const uint8_t signature_algorithms[] = { 1548 //static const uint8_t signature_algorithms[] = {
@@ -1555,7 +1560,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1555 uint8_t session_id_len; 1560 uint8_t session_id_len;
1556 /* uint8_t session_id[]; */ 1561 /* uint8_t session_id[]; */
1557 uint8_t cipherid_len16_hi, cipherid_len16_lo; 1562 uint8_t cipherid_len16_hi, cipherid_len16_lo;
1558 uint8_t cipherid[2 + NUM_CIPHERS*2]; /* actually variable */ 1563 uint8_t cipherid[2 * (1 + NUM_CIPHERS)]; /* actually variable */
1559 uint8_t comprtypes_len; 1564 uint8_t comprtypes_len;
1560 uint8_t comprtypes[1]; /* actually variable */ 1565 uint8_t comprtypes[1]; /* actually variable */
1561 /* Extensions (SNI shown): 1566 /* Extensions (SNI shown):
@@ -1603,7 +1608,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1603 memset(record->rand32, 0x11, sizeof(record->rand32)); 1608 memset(record->rand32, 0x11, sizeof(record->rand32));
1604 /* record->session_id_len = 0; - already is */ 1609 /* record->session_id_len = 0; - already is */
1605 1610
1606 BUILD_BUG_ON(sizeof(ciphers) != 2 + 2 + NUM_CIPHERS*2 + 2); 1611 BUILD_BUG_ON(sizeof(ciphers) != 2 * (1 + 1 + NUM_CIPHERS + 1));
1607 memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); 1612 memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers));
1608 1613
1609 ptr = (void*)(record + 1); 1614 ptr = (void*)(record + 1);
@@ -1700,42 +1705,33 @@ static void get_server_hello(tls_state_t *tls)
1700 1705
1701 /* Set up encryption params based on selected cipher */ 1706 /* Set up encryption params based on selected cipher */
1702#if 0 1707#if 0
1703#if ENABLE_FEATURE_TLS_SHA1
1704 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 1708 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/
1705 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 1709 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/
1706 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 1710 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA
1707 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) 1711 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)
1708 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA 1712 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
1709 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA 1713 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
1710#endif
1711 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ 1714 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1712 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1715 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1713 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 1716 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
1714 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1717 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1715 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ 1718 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/
1716 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" 1719 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC"
1717//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF?
1718 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 1720 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1719 // 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" 1721 // 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"
1720 //possibly these too: 1722 //possibly these too:
1721#if ENABLE_FEATURE_TLS_SHA1
1722 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 1723 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
1723 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 1724 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
1724#endif
1725 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 1725 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
1726 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1726 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1727#if ENABLE_FEATURE_TLS_SHA1
1728 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 1727 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1729 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA 1728 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1730#endif
1731 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 1729 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1732 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 1730 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1733 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 1731 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
1734 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" 1732 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac"
1735#if ALLOW_RSA_NULL_SHA256
1736 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 1733 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256
1737#endif 1734#endif
1738#endif
1739 cipherid1 = cipherid[1]; 1735 cipherid1 = cipherid[1];
1740 tls->cipher_id = 0x100 * cipherid[0] + cipherid1; 1736 tls->cipher_id = 0x100 * cipherid[0] + cipherid1;
1741 tls->key_size = AES256_KEYSIZE; 1737 tls->key_size = AES256_KEYSIZE;
@@ -1944,7 +1940,7 @@ static void send_client_key_exchange(tls_state_t *tls)
1944 if (!(tls->flags & NEED_EC_KEY)) { 1940 if (!(tls->flags & NEED_EC_KEY)) {
1945 /* RSA */ 1941 /* RSA */
1946 if (!(tls->flags & GOT_CERT_RSA_KEY_ALG)) 1942 if (!(tls->flags & GOT_CERT_RSA_KEY_ALG))
1947 bb_simple_error_msg("server cert is not RSA"); 1943 bb_simple_error_msg_and_die("server cert is not RSA");
1948 1944
1949 tls_get_random(premaster, RSA_PREMASTER_SIZE); 1945 tls_get_random(premaster, RSA_PREMASTER_SIZE);
1950 if (TLS_DEBUG_FIXED_SECRETS) 1946 if (TLS_DEBUG_FIXED_SECRETS)
@@ -2330,6 +2326,47 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls, unsigned flags)
2330 const int INBUF_STEP = 4 * 1024; 2326 const int INBUF_STEP = 4 * 1024;
2331 struct pollfd pfds[2]; 2327 struct pollfd pfds[2];
2332 2328
2329#if 0
2330// Debug aid for comparing P256 implementations.
2331// Enable this, set SP_DEBUG and FIXED_SECRET to 1,
2332// and add
2333// tls_run_copy_loop(NULL, 0);
2334// e.g. at the very beginning of wget_main()
2335//
2336{
2337 uint8_t ecc_pub_key32[2 * 32];
2338 uint8_t pubkey2x32[2 * 32];
2339 uint8_t premaster32[32];
2340
2341//Fixed input key:
2342// memset(ecc_pub_key32, 0xee, sizeof(ecc_pub_key32));
2343//Fixed 000000000000000000000000000000000000ab000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2344// memset(ecc_pub_key32, 0x00, sizeof(ecc_pub_key32));
2345// ecc_pub_key32[18] = 0xab;
2346//Random key:
2347// tls_get_random(ecc_pub_key32, sizeof(ecc_pub_key32));
2348//Biased random (almost all zeros or almost all ones):
2349 srand(time(NULL) ^ getpid());
2350 if (rand() & 1)
2351 memset(ecc_pub_key32, 0x00, sizeof(ecc_pub_key32));
2352 else
2353 memset(ecc_pub_key32, 0xff, sizeof(ecc_pub_key32));
2354 ecc_pub_key32[rand() & 0x3f] = rand();
2355
2356 xmove_fd(xopen("p256.OLD", O_WRONLY | O_CREAT | O_TRUNC), 2);
2357 curve_P256_compute_pubkey_and_premaster(
2358 pubkey2x32, premaster32,
2359 /*point:*/ ecc_pub_key32
2360 );
2361 xmove_fd(xopen("p256.NEW", O_WRONLY | O_CREAT | O_TRUNC), 2);
2362 curve_P256_compute_pubkey_and_premaster_NEW(
2363 pubkey2x32, premaster32,
2364 /*point:*/ ecc_pub_key32
2365 );
2366 exit(1);
2367}
2368#endif
2369
2333 pfds[0].fd = STDIN_FILENO; 2370 pfds[0].fd = STDIN_FILENO;
2334 pfds[0].events = POLLIN; 2371 pfds[0].events = POLLIN;
2335 pfds[1].fd = tls->ifd; 2372 pfds[1].fd = tls->ifd;
diff --git a/networking/tls.h b/networking/tls.h
index 215e92b02..0173b87b2 100644
--- a/networking/tls.h
+++ b/networking/tls.h
@@ -101,7 +101,6 @@ void xorbuf_aligned_AES_BLOCK_SIZE(void* buf, const void* mask) FAST_FUNC;
101 101
102 102
103#include "tls_pstm.h" 103#include "tls_pstm.h"
104#include "tls_symmetric.h"
105#include "tls_aes.h" 104#include "tls_aes.h"
106#include "tls_aesgcm.h" 105#include "tls_aesgcm.h"
107#include "tls_rsa.h" 106#include "tls_rsa.h"
@@ -117,3 +116,7 @@ void curve_x25519_compute_pubkey_and_premaster(
117void curve_P256_compute_pubkey_and_premaster( 116void curve_P256_compute_pubkey_and_premaster(
118 uint8_t *pubkey2x32, uint8_t *premaster32, 117 uint8_t *pubkey2x32, uint8_t *premaster32,
119 const uint8_t *peerkey2x32) FAST_FUNC; 118 const uint8_t *peerkey2x32) FAST_FUNC;
119
120void curve_P256_compute_pubkey_and_premaster_NEW(
121 uint8_t *pubkey2x32, uint8_t *premaster32,
122 const uint8_t *peerkey2x32) FAST_FUNC;
diff --git a/networking/tls_fe.c b/networking/tls_fe.c
index ecb410281..3a0a6776f 100644
--- a/networking/tls_fe.c
+++ b/networking/tls_fe.c
@@ -63,16 +63,22 @@ static void fprime_select(byte *dst, const byte *zero, const byte *one, byte con
63} 63}
64#endif 64#endif
65 65
66#if 0 /* constant-time */
66static void fe_select(byte *dst, 67static void fe_select(byte *dst,
67 const byte *zero, const byte *one, 68 const byte *src,
68 byte condition) 69 byte condition)
69{ 70{
70 const byte mask = -condition; 71 const byte mask = -condition;
71 int i; 72 int i;
72 73
73 for (i = 0; i < F25519_SIZE; i++) 74 for (i = 0; i < F25519_SIZE; i++)
74 dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); 75 dst[i] = dst[i] ^ (mask & (src[i] ^ dst[i]));
75} 76}
77#else
78# define fe_select(dst, src, condition) do { \
79 if (condition) lm_copy(dst, src); \
80} while (0)
81#endif
76 82
77#if 0 //UNUSED 83#if 0 //UNUSED
78static void raw_add(byte *x, const byte *p) 84static void raw_add(byte *x, const byte *p)
@@ -225,7 +231,7 @@ static void fe_normalize(byte *x)
225 minusp[31] = (byte)c; 231 minusp[31] = (byte)c;
226 232
227 /* Load x-p if no underflow */ 233 /* Load x-p if no underflow */
228 fe_select(x, minusp, x, (c >> 15) & 1); 234 fe_select(x, minusp, !(c & (1<<15)));
229} 235}
230 236
231static void lm_add(byte* r, const byte* a, const byte* b) 237static void lm_add(byte* r, const byte* a, const byte* b)
@@ -548,26 +554,32 @@ static void curve25519(byte *result, const byte *e, const byte *q)
548{ 554{
549 int i; 555 int i;
550 556
551 struct { 557 struct Z {
552 /* for bbox's special case of q == NULL meaning "use basepoint" */ 558 /* for bbox's special case of q == NULL meaning "use basepoint" */
553 /*static const*/ uint8_t basepoint9[CURVE25519_KEYSIZE]; // = {9}; 559 /*static const*/ uint8_t basepoint9[CURVE25519_KEYSIZE]; // = {9};
554 560
555 /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */ 561 /* from wolfssl-3.15.3/wolfssl/wolfcrypt/fe_operations.h */
556 /*static const*/ byte f25519_one[F25519_SIZE]; // = {1}; 562 /*static const*/ byte f25519_one[F25519_SIZE]; // = {1};
557 563
558 /* Current point: P_m */
559 byte xm[F25519_SIZE];
560 byte zm[F25519_SIZE]; // = {1};
561 /* Predecessor: P_(m-1) */ 564 /* Predecessor: P_(m-1) */
562 byte xm1[F25519_SIZE]; // = {1}; 565 byte xm1[F25519_SIZE]; // = {1};
563 byte zm1[F25519_SIZE]; // = {0}; 566 byte zm1[F25519_SIZE]; // = {0};
567 /* Current point: P_m */
568 byte xm[F25519_SIZE];
569 byte zm[F25519_SIZE]; // = {1};
570 /* Temporaries */
571 byte xms[F25519_SIZE];
572 byte zms[F25519_SIZE];
564 } z; 573 } z;
574 uint8_t *XM1 = (uint8_t*)&z + offsetof(struct Z,xm1); // gcc 11.0.0 workaround
565#define basepoint9 z.basepoint9 575#define basepoint9 z.basepoint9
566#define f25519_one z.f25519_one 576#define f25519_one z.f25519_one
567#define xm z.xm
568#define zm z.zm
569#define xm1 z.xm1 577#define xm1 z.xm1
570#define zm1 z.zm1 578#define zm1 z.zm1
579#define xm z.xm
580#define zm z.zm
581#define xms z.xms
582#define zms z.zms
571 memset(&z, 0, sizeof(z)); 583 memset(&z, 0, sizeof(z));
572 f25519_one[0] = 1; 584 f25519_one[0] = 1;
573 zm[0] = 1; 585 zm[0] = 1;
@@ -583,8 +595,8 @@ static void curve25519(byte *result, const byte *e, const byte *q)
583 595
584 for (i = 253; i >= 0; i--) { 596 for (i = 253; i >= 0; i--) {
585 const int bit = (e[i >> 3] >> (i & 7)) & 1; 597 const int bit = (e[i >> 3] >> (i & 7)) & 1;
586 byte xms[F25519_SIZE]; 598// byte xms[F25519_SIZE];
587 byte zms[F25519_SIZE]; 599// byte zms[F25519_SIZE];
588 600
589 /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ 601 /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */
590 xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); 602 xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1);
@@ -597,10 +609,22 @@ static void curve25519(byte *result, const byte *e, const byte *q)
597 * bit = 1 --> (P_(2m+1), P_(2m)) 609 * bit = 1 --> (P_(2m+1), P_(2m))
598 * bit = 0 --> (P_(2m), P_(2m-1)) 610 * bit = 0 --> (P_(2m), P_(2m-1))
599 */ 611 */
600 fe_select(xm1, xm1, xm, bit); 612#if 0
601 fe_select(zm1, zm1, zm, bit); 613 fe_select(xm1, xm, bit);
602 fe_select(xm, xm, xms, bit); 614 fe_select(zm1, zm, bit);
603 fe_select(zm, zm, zms, bit); 615 fe_select(xm, xms, bit);
616 fe_select(zm, zms, bit);
617#else
618// same as above in about 50 bytes smaller code, but
619// requires that in-memory order is exactly xm1,zm1,xm,zm,xms,zms
620 if (bit) {
621 //memcpy(xm1, xm, 4 * F25519_SIZE);
622 //^^^ gcc 11.0.0 warns of overlapping memcpy
623 //memmove(xm1, xm, 4 * F25519_SIZE);
624 //^^^ gcc 11.0.0 warns of out-of-bounds access to xm1[]
625 memmove(XM1, XM1 + 2 * F25519_SIZE, 4 * F25519_SIZE);
626 }
627#endif
604 } 628 }
605 629
606 /* Freeze out of projective coordinates */ 630 /* Freeze out of projective coordinates */
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h
index bc7a0119a..56c6bb879 100644
--- a/networking/tls_pstm.h
+++ b/networking/tls_pstm.h
@@ -283,4 +283,3 @@ extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b,
283 typedef int32 pstm_int; 283 typedef int32 pstm_int;
284#endif /* !DISABLE_PSTM */ 284#endif /* !DISABLE_PSTM */
285#endif /* _h_PSTMATH */ 285#endif /* _h_PSTMATH */
286
diff --git a/networking/tls_sp_c32.c b/networking/tls_sp_c32.c
index 5a84852a5..4d4ecdd74 100644
--- a/networking/tls_sp_c32.c
+++ b/networking/tls_sp_c32.c
@@ -9,6 +9,8 @@
9#define FIXED_SECRET 0 9#define FIXED_SECRET 0
10#define FIXED_PEER_PUBKEY 0 10#define FIXED_PEER_PUBKEY 0
11 11
12#define ALLOW_ASM 1
13
12#if SP_DEBUG 14#if SP_DEBUG
13# define dbg(...) fprintf(stderr, __VA_ARGS__) 15# define dbg(...) fprintf(stderr, __VA_ARGS__)
14static void dump_hex(const char *fmt, const void *vp, int len) 16static void dump_hex(const char *fmt, const void *vp, int len)
@@ -24,127 +26,98 @@ static void dump_hex(const char *fmt, const void *vp, int len)
24# define dump_hex(...) ((void)0) 26# define dump_hex(...) ((void)0)
25#endif 27#endif
26 28
27#undef DIGIT_BIT 29typedef uint32_t sp_digit;
28#define DIGIT_BIT 32 30typedef int32_t signed_sp_digit;
29typedef int32_t sp_digit;
30 31
31/* The code below is taken from parts of 32/* The code below is taken from parts of
32 * wolfssl-3.15.3/wolfcrypt/src/sp_c32.c 33 * wolfssl-3.15.3/wolfcrypt/src/sp_c32.c
33 * and heavily modified. 34 * and heavily modified.
34 * Header comment is kept intact:
35 */ 35 */
36 36
37/* sp.c
38 *
39 * Copyright (C) 2006-2018 wolfSSL Inc.
40 *
41 * This file is part of wolfSSL.
42 *
43 * wolfSSL is free software; you can redistribute it and/or modify
44 * it under the terms of the GNU General Public License as published by
45 * the Free Software Foundation; either version 2 of the License, or
46 * (at your option) any later version.
47 *
48 * wolfSSL is distributed in the hope that it will be useful,
49 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 * GNU General Public License for more details.
52 *
53 * You should have received a copy of the GNU General Public License
54 * along with this program; if not, write to the Free Software
55 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
56 */
57
58/* Implementation by Sean Parkinson. */
59
60typedef struct sp_point { 37typedef struct sp_point {
61 sp_digit x[2 * 10]; 38 sp_digit x[2 * 8];
62 sp_digit y[2 * 10]; 39 sp_digit y[2 * 8];
63 sp_digit z[2 * 10]; 40 sp_digit z[2 * 8];
64 int infinity; 41 int infinity;
65} sp_point; 42} sp_point;
66 43
67/* The modulus (prime) of the curve P256. */ 44/* The modulus (prime) of the curve P256. */
68static const sp_digit p256_mod[10] = { 45static const sp_digit p256_mod[8] = {
69 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000, 46 0xffffffff,0xffffffff,0xffffffff,0x00000000,
70 0x0000000,0x0000000,0x0000400,0x3ff0000,0x03fffff, 47 0x00000000,0x00000000,0x00000001,0xffffffff,
71}; 48};
72 49
73#define p256_mp_mod ((sp_digit)0x000001) 50#define p256_mp_mod ((sp_digit)0x000001)
74 51
75/* Write r as big endian to byte aray. 52/* Normalize the values in each word to 32 bits - NOP */
53#define sp_256_norm_8(a) ((void)0)
54
55/* Write r as big endian to byte array.
76 * Fixed length number of bytes written: 32 56 * Fixed length number of bytes written: 32
77 * 57 *
78 * r A single precision integer. 58 * r A single precision integer.
79 * a Byte array. 59 * a Byte array.
80 */ 60 */
81static void sp_256_to_bin(sp_digit* r, uint8_t* a) 61static void sp_256_to_bin_8(const sp_digit* r, uint8_t* a)
82{ 62{
83 int i, j, s = 0, b; 63 int i;
84 64
85 for (i = 0; i < 9; i++) { 65 sp_256_norm_8(r);
86 r[i+1] += r[i] >> 26; 66
87 r[i] &= 0x3ffffff; 67 r += 8;
88 } 68 for (i = 0; i < 8; i++) {
89 j = 256 / 8 - 1; 69 r--;
90 a[j] = 0; 70 move_to_unaligned32(a, SWAP_BE32(*r));
91 for (i = 0; i < 10 && j >= 0; i++) { 71 a += 4;
92 b = 0;
93 a[j--] |= r[i] << s; b += 8 - s;
94 if (j < 0)
95 break;
96 while (b < 26) {
97 a[j--] = r[i] >> b; b += 8;
98 if (j < 0)
99 break;
100 }
101 s = 8 - (b - 26);
102 if (j >= 0)
103 a[j] = 0;
104 if (s != 0)
105 j++;
106 } 72 }
107} 73}
108 74
109/* Read big endian unsigned byte aray into r. 75/* Read big endian unsigned byte array into r.
110 * 76 *
111 * r A single precision integer. 77 * r A single precision integer.
112 * a Byte array. 78 * a Byte array.
113 * n Number of bytes in array to read. 79 * n Number of bytes in array to read.
114 */ 80 */
115static void sp_256_from_bin(sp_digit* r, int max, const uint8_t* a, int n) 81static void sp_256_from_bin_8(sp_digit* r, const uint8_t* a)
116{ 82{
117 int i, j = 0, s = 0; 83 int i;
118 84
119 r[0] = 0; 85 r += 8;
120 for (i = n-1; i >= 0; i--) { 86 for (i = 0; i < 8; i++) {
121 r[j] |= ((sp_digit)a[i]) << s; 87 sp_digit v;
122 if (s >= 18) { 88 move_from_unaligned32(v, a);
123 r[j] &= 0x3ffffff; 89 *--r = SWAP_BE32(v);
124 s = 26 - s; 90 a += 4;
125 if (j + 1 >= max)
126 break;
127 r[++j] = a[i] >> s;
128 s = 8 - s;
129 }
130 else
131 s += 8;
132 } 91 }
92}
133 93
134 for (j++; j < max; j++) 94#if SP_DEBUG
135 r[j] = 0; 95static void dump_256(const char *fmt, const sp_digit* r)
96{
97 uint8_t b32[32];
98 sp_256_to_bin_8(r, b32);
99 dump_hex(fmt, b32, 32);
100}
101static void dump_512(const char *fmt, const sp_digit* r)
102{
103 uint8_t b64[64];
104 sp_256_to_bin_8(r, b64 + 32);
105 sp_256_to_bin_8(r+8, b64);
106 dump_hex(fmt, b64, 64);
136} 107}
108#else
109# define dump_256(...) ((void)0)
110# define dump_512(...) ((void)0)
111#endif
137 112
138/* Convert a point of big-endian 32-byte x,y pair to type sp_point. */ 113/* Convert a point of big-endian 32-byte x,y pair to type sp_point. */
139static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32) 114static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32)
140{ 115{
141 memset(p, 0, sizeof(*p)); 116 memset(p, 0, sizeof(*p));
142 /*p->infinity = 0;*/ 117 /*p->infinity = 0;*/
143 sp_256_from_bin(p->x, 2 * 10, bin2x32, 32); 118 sp_256_from_bin_8(p->x, bin2x32);
144 sp_256_from_bin(p->y, 2 * 10, bin2x32 + 32, 32); 119 sp_256_from_bin_8(p->y, bin2x32 + 32);
145 //static const uint8_t one[1] = { 1 }; 120 p->z[0] = 1; /* p->z = 1 */
146 //sp_256_from_bin(p->z, 2 * 10, one, 1);
147 p->z[0] = 1;
148} 121}
149 122
150/* Compare a with b. 123/* Compare a with b.
@@ -152,201 +125,650 @@ static void sp_256_point_from_bin2x32(sp_point* p, const uint8_t *bin2x32)
152 * return -ve, 0 or +ve if a is less than, equal to or greater than b 125 * return -ve, 0 or +ve if a is less than, equal to or greater than b
153 * respectively. 126 * respectively.
154 */ 127 */
155static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b) 128static signed_sp_digit sp_256_cmp_8(const sp_digit* a, const sp_digit* b)
156{ 129{
157 sp_digit r;
158 int i; 130 int i;
159 for (i = 9; i >= 0; i--) { 131 for (i = 7; i >= 0; i--) {
160 r = a[i] - b[i]; 132/* signed_sp_digit r = a[i] - b[i];
161 if (r != 0) 133 * if (r != 0)
162 break; 134 * return r;
135 * does not work: think about a[i]=0, b[i]=0xffffffff
136 */
137 if (a[i] == b[i])
138 continue;
139 return (a[i] > b[i]) * 2 - 1;
163 } 140 }
164 return r; 141 return 0;
165} 142}
166 143
167/* Compare two numbers to determine if they are equal. 144/* Compare two numbers to determine if they are equal.
168 * 145 *
169 * return 1 when equal and 0 otherwise. 146 * return 1 when equal and 0 otherwise.
170 */ 147 */
171static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) 148static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b)
172{ 149{
173 return sp_256_cmp_10(a, b) == 0; 150 return sp_256_cmp_8(a, b) == 0;
174} 151}
175 152
176/* Normalize the values in each word to 26 bits. */ 153/* Add b to a into r. (r = a + b). Return !0 on overflow */
177static void sp_256_norm_10(sp_digit* a) 154static int sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
178{ 155{
156#if ALLOW_ASM && defined(__GNUC__) && defined(__i386__)
157 sp_digit reg;
158 asm volatile (
159"\n movl (%0), %3"
160"\n addl (%1), %3"
161"\n movl %3, (%2)"
162"\n"
163"\n movl 1*4(%0), %3"
164"\n adcl 1*4(%1), %3"
165"\n movl %3, 1*4(%2)"
166"\n"
167"\n movl 2*4(%0), %3"
168"\n adcl 2*4(%1), %3"
169"\n movl %3, 2*4(%2)"
170"\n"
171"\n movl 3*4(%0), %3"
172"\n adcl 3*4(%1), %3"
173"\n movl %3, 3*4(%2)"
174"\n"
175"\n movl 4*4(%0), %3"
176"\n adcl 4*4(%1), %3"
177"\n movl %3, 4*4(%2)"
178"\n"
179"\n movl 5*4(%0), %3"
180"\n adcl 5*4(%1), %3"
181"\n movl %3, 5*4(%2)"
182"\n"
183"\n movl 6*4(%0), %3"
184"\n adcl 6*4(%1), %3"
185"\n movl %3, 6*4(%2)"
186"\n"
187"\n movl 7*4(%0), %3"
188"\n adcl 7*4(%1), %3"
189"\n movl %3, 7*4(%2)"
190"\n"
191"\n sbbl %3, %3"
192"\n"
193 : "=r" (a), "=r" (b), "=r" (r), "=r" (reg)
194 : "0" (a), "1" (b), "2" (r)
195 : "memory"
196 );
197 return reg;
198#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
199 /* x86_64 has no alignment restrictions, and is little-endian,
200 * so 64-bit and 32-bit representations are identical */
201 uint64_t reg;
202 asm volatile (
203"\n movq (%0), %3"
204"\n addq (%1), %3"
205"\n movq %3, (%2)"
206"\n"
207"\n movq 1*8(%0), %3"
208"\n adcq 1*8(%1), %3"
209"\n movq %3, 1*8(%2)"
210"\n"
211"\n movq 2*8(%0), %3"
212"\n adcq 2*8(%1), %3"
213"\n movq %3, 2*8(%2)"
214"\n"
215"\n movq 3*8(%0), %3"
216"\n adcq 3*8(%1), %3"
217"\n movq %3, 3*8(%2)"
218"\n"
219"\n sbbq %3, %3"
220"\n"
221 : "=r" (a), "=r" (b), "=r" (r), "=r" (reg)
222 : "0" (a), "1" (b), "2" (r)
223 : "memory"
224 );
225 return reg;
226#else
179 int i; 227 int i;
180 for (i = 0; i < 9; i++) { 228 sp_digit carry;
181 a[i+1] += a[i] >> 26; 229
182 a[i] &= 0x3ffffff; 230 carry = 0;
231 for (i = 0; i < 8; i++) {
232 sp_digit w, v;
233 w = b[i] + carry;
234 v = a[i];
235 if (w != 0) {
236 v = a[i] + w;
237 carry = (v < a[i]);
238 /* hope compiler detects above as "carry flag set" */
239 }
240 /* else: b + carry == 0, two cases:
241 * b:ffffffff, carry:1
242 * b:00000000, carry:0
243 * in either case, r[i] = a[i] and carry remains unchanged
244 */
245 r[i] = v;
183 } 246 }
247 return carry;
248#endif
184} 249}
185 250
186/* Add b to a into r. (r = a + b) */ 251/* Sub b from a into r. (r = a - b). Return !0 on underflow */
187static void sp_256_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b) 252static int sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
188{ 253{
254#if ALLOW_ASM && defined(__GNUC__) && defined(__i386__)
255 sp_digit reg;
256 asm volatile (
257"\n movl (%0), %3"
258"\n subl (%1), %3"
259"\n movl %3, (%2)"
260"\n"
261"\n movl 1*4(%0), %3"
262"\n sbbl 1*4(%1), %3"
263"\n movl %3, 1*4(%2)"
264"\n"
265"\n movl 2*4(%0), %3"
266"\n sbbl 2*4(%1), %3"
267"\n movl %3, 2*4(%2)"
268"\n"
269"\n movl 3*4(%0), %3"
270"\n sbbl 3*4(%1), %3"
271"\n movl %3, 3*4(%2)"
272"\n"
273"\n movl 4*4(%0), %3"
274"\n sbbl 4*4(%1), %3"
275"\n movl %3, 4*4(%2)"
276"\n"
277"\n movl 5*4(%0), %3"
278"\n sbbl 5*4(%1), %3"
279"\n movl %3, 5*4(%2)"
280"\n"
281"\n movl 6*4(%0), %3"
282"\n sbbl 6*4(%1), %3"
283"\n movl %3, 6*4(%2)"
284"\n"
285"\n movl 7*4(%0), %3"
286"\n sbbl 7*4(%1), %3"
287"\n movl %3, 7*4(%2)"
288"\n"
289"\n sbbl %3, %3"
290"\n"
291 : "=r" (a), "=r" (b), "=r" (r), "=r" (reg)
292 : "0" (a), "1" (b), "2" (r)
293 : "memory"
294 );
295 return reg;
296#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
297 /* x86_64 has no alignment restrictions, and is little-endian,
298 * so 64-bit and 32-bit representations are identical */
299 uint64_t reg;
300 asm volatile (
301"\n movq (%0), %3"
302"\n subq (%1), %3"
303"\n movq %3, (%2)"
304"\n"
305"\n movq 1*8(%0), %3"
306"\n sbbq 1*8(%1), %3"
307"\n movq %3, 1*8(%2)"
308"\n"
309"\n movq 2*8(%0), %3"
310"\n sbbq 2*8(%1), %3"
311"\n movq %3, 2*8(%2)"
312"\n"
313"\n movq 3*8(%0), %3"
314"\n sbbq 3*8(%1), %3"
315"\n movq %3, 3*8(%2)"
316"\n"
317"\n sbbq %3, %3"
318"\n"
319 : "=r" (a), "=r" (b), "=r" (r), "=r" (reg)
320 : "0" (a), "1" (b), "2" (r)
321 : "memory"
322 );
323 return reg;
324#else
189 int i; 325 int i;
190 for (i = 0; i < 10; i++) 326 sp_digit borrow;
191 r[i] = a[i] + b[i]; 327
328 borrow = 0;
329 for (i = 0; i < 8; i++) {
330 sp_digit w, v;
331 w = b[i] + borrow;
332 v = a[i];
333 if (w != 0) {
334 v = a[i] - w;
335 borrow = (v > a[i]);
336 /* hope compiler detects above as "carry flag set" */
337 }
338 /* else: b + borrow == 0, two cases:
339 * b:ffffffff, borrow:1
340 * b:00000000, borrow:0
341 * in either case, r[i] = a[i] and borrow remains unchanged
342 */
343 r[i] = v;
344 }
345 return borrow;
346#endif
192} 347}
193 348
194/* Sub b from a into r. (r = a - b) */ 349/* Sub p256_mod from r. (r = r - p256_mod). */
195static void sp_256_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b) 350#if ALLOW_ASM && defined(__GNUC__) && defined(__i386__)
351static void sp_256_sub_8_p256_mod(sp_digit* r)
196{ 352{
197 int i; 353//p256_mod[7..0] = ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
198 for (i = 0; i < 10; i++) 354 asm volatile (
199 r[i] = a[i] - b[i]; 355"\n subl $0xffffffff, (%0)"
356"\n sbbl $0xffffffff, 1*4(%0)"
357"\n sbbl $0xffffffff, 2*4(%0)"
358"\n sbbl $0, 3*4(%0)"
359"\n sbbl $0, 4*4(%0)"
360"\n sbbl $0, 5*4(%0)"
361"\n sbbl $1, 6*4(%0)"
362"\n sbbl $0xffffffff, 7*4(%0)"
363"\n"
364 : "=r" (r)
365 : "0" (r)
366 : "memory"
367 );
200} 368}
201 369#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
202/* Shift number left one bit. Bottom bit is lost. */ 370static void sp_256_sub_8_p256_mod(sp_digit* r)
203static void sp_256_rshift1_10(sp_digit* r, sp_digit* a)
204{ 371{
205 int i; 372 uint64_t reg;
206 for (i = 0; i < 9; i++) 373 uint64_t ooff;
207 r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff; 374//p256_mod[3..0] = ffffffff00000001 0000000000000000 00000000ffffffff ffffffffffffffff
208 r[9] = a[9] >> 1; 375 asm volatile (
376"\n addq $1, (%0)" // adding 1 is the same as subtracting ffffffffffffffff
377"\n cmc" // only carry bit needs inverting
378"\n"
379"\n sbbq %1, 1*8(%0)" // %1 holds 00000000ffffffff
380"\n"
381"\n sbbq $0, 2*8(%0)"
382"\n"
383"\n movq 3*8(%0), %2"
384"\n sbbq $0, %2" // adding 00000000ffffffff (in %1)
385"\n addq %1, %2" // is the same as subtracting ffffffff00000001
386"\n movq %2, 3*8(%0)"
387"\n"
388 : "=r" (r), "=r" (ooff), "=r" (reg)
389 : "0" (r), "1" (0x00000000ffffffff)
390 : "memory"
391 );
209} 392}
210 393#else
211/* Mul a by scalar b and add into r. (r += a * b) */ 394static void sp_256_sub_8_p256_mod(sp_digit* r)
212static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a, sp_digit b)
213{ 395{
214 int64_t tb = b; 396 sp_256_sub_8(r, r, p256_mod);
215 int64_t t = 0;
216 int i;
217
218 for (i = 0; i < 10; i++) {
219 t += (tb * a[i]) + r[i];
220 r[i] = t & 0x3ffffff;
221 t >>= 26;
222 }
223 r[10] += t;
224} 397}
398#endif
225 399
226/* Multiply a and b into r. (r = a * b) */ 400/* Multiply a and b into r. (r = a * b) */
227static void sp_256_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b) 401static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b)
228{ 402{
403#if ALLOW_ASM && defined(__GNUC__) && defined(__i386__)
404 sp_digit rr[15]; /* in case r coincides with a or b */
405 int k;
406 uint32_t accl;
407 uint32_t acch;
408
409 acch = accl = 0;
410 for (k = 0; k < 15; k++) {
411 int i, j;
412 uint32_t acc_hi;
413 i = k - 7;
414 if (i < 0)
415 i = 0;
416 j = k - i;
417 acc_hi = 0;
418 do {
419////////////////////////
420// uint64_t m = ((uint64_t)a[i]) * b[j];
421// acc_hi:acch:accl += m;
422 asm volatile (
423 // a[i] is already loaded in %%eax
424"\n mull %7"
425"\n addl %%eax, %0"
426"\n adcl %%edx, %1"
427"\n adcl $0, %2"
428 : "=rm" (accl), "=rm" (acch), "=rm" (acc_hi)
429 : "0" (accl), "1" (acch), "2" (acc_hi), "a" (a[i]), "m" (b[j])
430 : "cc", "dx"
431 );
432////////////////////////
433 j--;
434 i++;
435 } while (i != 8 && i <= k);
436 rr[k] = accl;
437 accl = acch;
438 acch = acc_hi;
439 }
440 r[15] = accl;
441 memcpy(r, rr, sizeof(rr));
442#elif ALLOW_ASM && defined(__GNUC__) && defined(__x86_64__)
443 /* x86_64 has no alignment restrictions, and is little-endian,
444 * so 64-bit and 32-bit representations are identical */
445 const uint64_t* aa = (const void*)a;
446 const uint64_t* bb = (const void*)b;
447 uint64_t rr[8];
448 int k;
449 uint64_t accl;
450 uint64_t acch;
451
452 acch = accl = 0;
453 for (k = 0; k < 7; k++) {
454 int i, j;
455 uint64_t acc_hi;
456 i = k - 3;
457 if (i < 0)
458 i = 0;
459 j = k - i;
460 acc_hi = 0;
461 do {
462////////////////////////
463// uint128_t m = ((uint128_t)a[i]) * b[j];
464// acc_hi:acch:accl += m;
465 asm volatile (
466 // aa[i] is already loaded in %%rax
467"\n mulq %7"
468"\n addq %%rax, %0"
469"\n adcq %%rdx, %1"
470"\n adcq $0, %2"
471 : "=rm" (accl), "=rm" (acch), "=rm" (acc_hi)
472 : "0" (accl), "1" (acch), "2" (acc_hi), "a" (aa[i]), "m" (bb[j])
473 : "cc", "dx"
474 );
475////////////////////////
476 j--;
477 i++;
478 } while (i != 4 && i <= k);
479 rr[k] = accl;
480 accl = acch;
481 acch = acc_hi;
482 }
483 rr[7] = accl;
484 memcpy(r, rr, sizeof(rr));
485#elif 0
486 //TODO: arm assembly (untested)
487 sp_digit tmp[16];
488
489 asm volatile (
490"\n mov r5, #0"
491"\n mov r6, #0"
492"\n mov r7, #0"
493"\n mov r8, #0"
494"\n 1:"
495"\n subs r3, r5, #28"
496"\n movcc r3, #0"
497"\n sub r4, r5, r3"
498"\n 2:"
499"\n ldr r14, [%[a], r3]"
500"\n ldr r12, [%[b], r4]"
501"\n umull r9, r10, r14, r12"
502"\n adds r6, r6, r9"
503"\n adcs r7, r7, r10"
504"\n adc r8, r8, #0"
505"\n add r3, r3, #4"
506"\n sub r4, r4, #4"
507"\n cmp r3, #32"
508"\n beq 3f"
509"\n cmp r3, r5"
510"\n ble 2b"
511"\n 3:"
512"\n str r6, [%[r], r5]"
513"\n mov r6, r7"
514"\n mov r7, r8"
515"\n mov r8, #0"
516"\n add r5, r5, #4"
517"\n cmp r5, #56"
518"\n ble 1b"
519"\n str r6, [%[r], r5]"
520 : [r] "r" (tmp), [a] "r" (a), [b] "r" (b)
521 : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
522 );
523 memcpy(r, tmp, sizeof(tmp));
524#else
525 sp_digit rr[15]; /* in case r coincides with a or b */
229 int i, j, k; 526 int i, j, k;
230 int64_t c; 527 uint64_t acc;
231 528
232 c = ((int64_t)a[9]) * b[9]; 529 acc = 0;
233 r[19] = (sp_digit)(c >> 26); 530 for (k = 0; k < 15; k++) {
234 c = (c & 0x3ffffff) << 26; 531 uint32_t acc_hi;
235 for (k = 17; k >= 0; k--) { 532 i = k - 7;
236 for (i = 9; i >= 0; i--) { 533 if (i < 0)
237 j = k - i; 534 i = 0;
238 if (j >= 10) 535 j = k - i;
239 break; 536 acc_hi = 0;
240 if (j < 0) 537 do {
241 continue; 538 uint64_t m = ((uint64_t)a[i]) * b[j];
242 c += ((int64_t)a[i]) * b[j]; 539 acc += m;
243 } 540 if (acc < m)
244 r[k + 2] += c >> 52; 541 acc_hi++;
245 r[k + 1] = (c >> 26) & 0x3ffffff; 542 j--;
246 c = (c & 0x3ffffff) << 26; 543 i++;
544 } while (i != 8 && i <= k);
545 rr[k] = acc;
546 acc = (acc >> 32) | ((uint64_t)acc_hi << 32);
247 } 547 }
248 r[0] = (sp_digit)(c >> 26); 548 r[15] = acc;
549 memcpy(r, rr, sizeof(rr));
550#endif
249} 551}
250 552
251/* Square a and put result in r. (r = a * a) */ 553/* Shift number right one bit. Bottom bit is lost. */
252static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) 554static void sp_256_rshift1_8(sp_digit* r, sp_digit* a, sp_digit carry)
253{ 555{
254 int i, j, k; 556 int i;
255 int64_t c; 557
256 558 carry = (!!carry << 31);
257 c = ((int64_t)a[9]) * a[9]; 559 for (i = 7; i >= 0; i--) {
258 r[19] = (sp_digit)(c >> 26); 560 sp_digit c = a[i] << 31;
259 c = (c & 0x3ffffff) << 26; 561 r[i] = (a[i] >> 1) | carry;
260 for (k = 17; k >= 0; k--) { 562 carry = c;
261 for (i = 9; i >= 0; i--) {
262 j = k - i;
263 if (j >= 10 || i <= j)
264 break;
265 if (j < 0)
266 continue;
267 c += ((int64_t)a[i]) * a[j] * 2;
268 }
269 if (i == j)
270 c += ((int64_t)a[i]) * a[i];
271 r[k + 2] += c >> 52;
272 r[k + 1] = (c >> 26) & 0x3ffffff;
273 c = (c & 0x3ffffff) << 26;
274 } 563 }
275 r[0] = (sp_digit)(c >> 26);
276} 564}
277 565
278/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) */ 566/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) */
279static void sp_256_div2_10(sp_digit* r, const sp_digit* a, const sp_digit* m) 567static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m)
280{ 568{
569 int carry = 0;
281 if (a[0] & 1) 570 if (a[0] & 1)
282 sp_256_add_10(r, a, m); 571 carry = sp_256_add_8(r, a, m);
283 sp_256_norm_10(r); 572 sp_256_norm_8(r);
284 sp_256_rshift1_10(r, r); 573 sp_256_rshift1_8(r, r, carry);
285} 574}
286 575
287/* Add two Montgomery form numbers (r = a + b % m) */ 576/* Add two Montgomery form numbers (r = a + b % m) */
288static void sp_256_mont_add_10(sp_digit* r, const sp_digit* a, const sp_digit* b, 577static void sp_256_mont_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b
289 const sp_digit* m) 578 /*, const sp_digit* m*/)
290{ 579{
291 sp_256_add_10(r, a, b); 580// const sp_digit* m = p256_mod;
292 sp_256_norm_10(r); 581
293 if ((r[9] >> 22) > 0) 582 int carry = sp_256_add_8(r, a, b);
294 sp_256_sub_10(r, r, m); 583 sp_256_norm_8(r);
295 sp_256_norm_10(r); 584 if (carry) {
585 sp_256_sub_8_p256_mod(r);
586 sp_256_norm_8(r);
587 }
296} 588}
297 589
298/* Subtract two Montgomery form numbers (r = a - b % m) */ 590/* Subtract two Montgomery form numbers (r = a - b % m) */
299static void sp_256_mont_sub_10(sp_digit* r, const sp_digit* a, const sp_digit* b, 591static void sp_256_mont_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b
300 const sp_digit* m) 592 /*, const sp_digit* m*/)
301{ 593{
302 sp_256_sub_10(r, a, b); 594 const sp_digit* m = p256_mod;
303 if (r[9] >> 22) 595
304 sp_256_add_10(r, r, m); 596 int borrow;
305 sp_256_norm_10(r); 597 borrow = sp_256_sub_8(r, a, b);
598 sp_256_norm_8(r);
599 if (borrow) {
600 sp_256_add_8(r, r, m);
601 sp_256_norm_8(r);
602 }
306} 603}
307 604
308/* Double a Montgomery form number (r = a + a % m) */ 605/* Double a Montgomery form number (r = a + a % m) */
309static void sp_256_mont_dbl_10(sp_digit* r, const sp_digit* a, const sp_digit* m) 606static void sp_256_mont_dbl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* m*/)
310{ 607{
311 sp_256_add_10(r, a, a); 608// const sp_digit* m = p256_mod;
312 sp_256_norm_10(r); 609
313 if ((r[9] >> 22) > 0) 610 int carry = sp_256_add_8(r, a, a);
314 sp_256_sub_10(r, r, m); 611 sp_256_norm_8(r);
315 sp_256_norm_10(r); 612 if (carry)
613 sp_256_sub_8_p256_mod(r);
614 sp_256_norm_8(r);
316} 615}
317 616
318/* Triple a Montgomery form number (r = a + a + a % m) */ 617/* Triple a Montgomery form number (r = a + a + a % m) */
319static void sp_256_mont_tpl_10(sp_digit* r, const sp_digit* a, const sp_digit* m) 618static void sp_256_mont_tpl_8(sp_digit* r, const sp_digit* a /*, const sp_digit* m*/)
320{ 619{
321 sp_256_add_10(r, a, a); 620// const sp_digit* m = p256_mod;
322 sp_256_norm_10(r); 621
323 if ((r[9] >> 22) > 0) 622 int carry = sp_256_add_8(r, a, a);
324 sp_256_sub_10(r, r, m); 623 sp_256_norm_8(r);
325 sp_256_norm_10(r); 624 if (carry) {
326 sp_256_add_10(r, r, a); 625 sp_256_sub_8_p256_mod(r);
327 sp_256_norm_10(r); 626 sp_256_norm_8(r);
328 if ((r[9] >> 22) > 0) 627 }
329 sp_256_sub_10(r, r, m); 628 carry = sp_256_add_8(r, r, a);
330 sp_256_norm_10(r); 629 sp_256_norm_8(r);
630 if (carry) {
631 sp_256_sub_8_p256_mod(r);
632 sp_256_norm_8(r);
633 }
331} 634}
332 635
333/* Shift the result in the high 256 bits down to the bottom. */ 636/* Shift the result in the high 256 bits down to the bottom. */
334static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) 637static void sp_256_mont_shift_8(sp_digit* r, const sp_digit* a)
335{ 638{
336 int i; 639 int i;
337 sp_digit n, s; 640
338 641 for (i = 0; i < 8; i++) {
339 s = a[10]; 642 r[i] = a[i+8];
340 n = a[9] >> 22; 643 r[i+8] = 0;
341 for (i = 0; i < 9; i++) {
342 n += (s & 0x3ffffff) << 4;
343 r[i] = n & 0x3ffffff;
344 n >>= 26;
345 s = a[11 + i] + (s >> 26);
346 } 644 }
347 n += s << 4; 645}
348 r[9] = n; 646
349 memset(&r[10], 0, sizeof(*r) * 10); 647/* Mul a by scalar b and add into r. (r += a * b) */
648static int sp_256_mul_add_8(sp_digit* r /*, const sp_digit* a, sp_digit b*/)
649{
650// const sp_digit* a = p256_mod;
651//a[7..0] = ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
652 sp_digit b = r[0];
653
654 uint64_t t;
655
656// t = 0;
657// for (i = 0; i < 8; i++) {
658// uint32_t t_hi;
659// uint64_t m = ((uint64_t)b * a[i]) + r[i];
660// t += m;
661// t_hi = (t < m);
662// r[i] = (sp_digit)t;
663// t = (t >> 32) | ((uint64_t)t_hi << 32);
664// }
665// r[8] += (sp_digit)t;
666
667 // Unroll, then optimize the above loop:
668 //uint32_t t_hi;
669 uint64_t m;
670 uint32_t t32;
671
672 //m = ((uint64_t)b * a[0]) + r[0];
673 // Since b is r[0] and a[0] is ffffffff, the above optimizes to:
674 // m = r[0] * ffffffff + r[0] = (r[0] * 100000000 - r[0]) + r[0] = r[0] << 32;
675 //t += m;
676 // t = r[0] << 32 = b << 32;
677 //t_hi = (t < m);
678 // t_hi = 0;
679 //r[0] = (sp_digit)t;
680 r[0] = 0;
681 //t = (t >> 32) | ((uint64_t)t_hi << 32);
682 // t = b;
683
684 //m = ((uint64_t)b * a[1]) + r[1];
685 // Since a[1] is ffffffff, the above optimizes to:
686 // m = b * ffffffff + r[1] = (b * 100000000 - b) + r[1] = (b << 32) - b + r[1];
687 //t += m;
688 // t = b + (b << 32) - b + r[1] = (b << 32) + r[1];
689 //t_hi = (t < m);
690 // t_hi = 0;
691 //r[1] = (sp_digit)t;
692 // r[1] = r[1];
693 //t = (t >> 32) | ((uint64_t)t_hi << 32);
694 // t = b;
695
696 //m = ((uint64_t)b * a[2]) + r[2];
697 // Since a[2] is ffffffff, the above optimizes to:
698 // m = b * ffffffff + r[2] = (b * 100000000 - b) + r[2] = (b << 32) - b + r[2];
699 //t += m;
700 // t = b + (b << 32) - b + r[2] = (b << 32) + r[2]
701 //t_hi = (t < m);
702 // t_hi = 0;
703 //r[2] = (sp_digit)t;
704 // r[2] = r[2];
705 //t = (t >> 32) | ((uint64_t)t_hi << 32);
706 // t = b;
707
708 //m = ((uint64_t)b * a[3]) + r[3];
709 // Since a[3] is 00000000, the above optimizes to:
710 // m = b * 0 + r[3] = r[3];
711 //t += m;
712 // t = b + r[3];
713 //t_hi = (t < m);
714 // t_hi = 0;
715 //r[3] = (sp_digit)t;
716 r[3] = r[3] + b;
717 //t = (t >> 32) | ((uint64_t)t_hi << 32);
718 t32 = (r[3] < b); // 0 or 1
719
720 //m = ((uint64_t)b * a[4]) + r[4];
721 // Since a[4] is 00000000, the above optimizes to:
722 // m = b * 0 + r[4] = r[4];
723 //t += m;
724 // t = t32 + r[4];
725 //t_hi = (t < m);
726 // t_hi = 0;
727 //r[4] = (sp_digit)t;
728 //t = (t >> 32) | ((uint64_t)t_hi << 32);
729 if (t32 != 0) {
730 r[4]++;
731 t32 = (r[4] == 0); // 0 or 1
732
733 //m = ((uint64_t)b * a[5]) + r[5];
734 // Since a[5] is 00000000, the above optimizes to:
735 // m = b * 0 + r[5] = r[5];
736 //t += m;
737 // t = t32 + r[5]; (t32 is 0 or 1)
738 //t_hi = (t < m);
739 // t_hi = 0;
740 //r[5] = (sp_digit)t;
741 //t = (t >> 32) | ((uint64_t)t_hi << 32);
742 if (t32 != 0) {
743 r[5]++;
744 t32 = (r[5] == 0); // 0 or 1
745 }
746 }
747
748 //m = ((uint64_t)b * a[6]) + r[6];
749 // Since a[6] is 00000001, the above optimizes to:
750 // m = (uint64_t)b + r[6]; // 33 bits at most
751 //t += m;
752 t = t32 + (uint64_t)b + r[6];
753 //t_hi = (t < m);
754 // t_hi = 0;
755 r[6] = (sp_digit)t;
756 //t = (t >> 32) | ((uint64_t)t_hi << 32);
757 t = (t >> 32);
758
759 //m = ((uint64_t)b * a[7]) + r[7];
760 // Since a[7] is ffffffff, the above optimizes to:
761 // m = b * ffffffff + r[7] = (b * 100000000 - b) + r[7]
762 m = ((uint64_t)b << 32) - b + r[7];
763 t += m;
764 //t_hi = (t < m);
765 // t_hi in fact is always 0 here (256bit * 32bit can't have more than 32 bits of overflow)
766 r[7] = (sp_digit)t;
767 //t = (t >> 32) | ((uint64_t)t_hi << 32);
768 t = (t >> 32);
769
770 r[8] += (sp_digit)t;
771 return (r[8] < (sp_digit)t); /* 1 if addition overflowed */
350} 772}
351 773
352/* Reduce the number back to 256 bits using Montgomery reduction. 774/* Reduce the number back to 256 bits using Montgomery reduction.
@@ -355,39 +777,159 @@ static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a)
355 * m The single precision number representing the modulus. 777 * m The single precision number representing the modulus.
356 * mp The digit representing the negative inverse of m mod 2^n. 778 * mp The digit representing the negative inverse of m mod 2^n.
357 */ 779 */
358static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp) 780static void sp_256_mont_reduce_8(sp_digit* a/*, const sp_digit* m, sp_digit mp*/)
359{ 781{
782// const sp_digit* m = p256_mod;
783 sp_digit mp = p256_mp_mod;
784
360 int i; 785 int i;
361 sp_digit mu; 786// sp_digit mu;
362 787
363 if (mp != 1) { 788 if (mp != 1) {
364 for (i = 0; i < 9; i++) { 789 sp_digit word16th = 0;
365 mu = (a[i] * mp) & 0x3ffffff; 790 for (i = 0; i < 8; i++) {
366 sp_256_mul_add_10(a+i, m, mu); 791// mu = (sp_digit)(a[i] * mp);
367 a[i+1] += a[i] >> 26; 792 if (sp_256_mul_add_8(a+i /*, m, mu*/)) {
793 int j = i + 8;
794 inc_next_word0:
795 if (++j > 15) { /* a[16] array has no more words? */
796 word16th++;
797 continue;
798 }
799 if (++a[j] == 0) /* did this overflow too? */
800 goto inc_next_word0;
801 }
368 } 802 }
369 mu = (a[i] * mp) & 0x3fffffl; 803 sp_256_mont_shift_8(a, a);
370 sp_256_mul_add_10(a+i, m, mu); 804 if (word16th != 0)
371 a[i+1] += a[i] >> 26; 805 sp_256_sub_8_p256_mod(a);
372 a[i] &= 0x3ffffff; 806 sp_256_norm_8(a);
373 } 807 }
374 else { 808 else { /* Same code for explicit mp == 1 (which is always the case for P256) */
375 for (i = 0; i < 9; i++) { 809 sp_digit word16th = 0;
376 mu = a[i] & 0x3ffffff; 810 for (i = 0; i < 8; i++) {
377 sp_256_mul_add_10(a+i, p256_mod, mu); 811 /*mu = a[i];*/
378 a[i+1] += a[i] >> 26; 812 if (sp_256_mul_add_8(a+i /*, m, mu*/)) {
813 int j = i + 8;
814 inc_next_word:
815 if (++j > 15) { /* a[16] array has no more words? */
816 word16th++;
817 continue;
818 }
819 if (++a[j] == 0) /* did this overflow too? */
820 goto inc_next_word;
821 }
379 } 822 }
380 mu = a[i] & 0x3fffffl; 823 sp_256_mont_shift_8(a, a);
381 sp_256_mul_add_10(a+i, p256_mod, mu); 824 if (word16th != 0)
382 a[i+1] += a[i] >> 26; 825 sp_256_sub_8_p256_mod(a);
383 a[i] &= 0x3ffffff; 826 sp_256_norm_8(a);
384 } 827 }
385
386 sp_256_mont_shift_10(a, a);
387 if ((a[9] >> 22) > 0)
388 sp_256_sub_10(a, a, m);
389 sp_256_norm_10(a);
390} 828}
829#if 0
830//TODO: arm32 asm (also adapt for x86?)
831static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m, sp_digit mp)
832{
833 sp_digit ca = 0;
834
835 asm volatile (
836 # i = 0
837 mov r12, #0
838 ldr r10, [%[a], #0]
839 ldr r14, [%[a], #4]
8401:
841 # mu = a[i] * mp
842 mul r8, %[mp], r10
843 # a[i+0] += m[0] * mu
844 ldr r7, [%[m], #0]
845 ldr r9, [%[a], #0]
846 umull r6, r7, r8, r7
847 adds r10, r10, r6
848 adc r5, r7, #0
849 # a[i+1] += m[1] * mu
850 ldr r7, [%[m], #4]
851 ldr r9, [%[a], #4]
852 umull r6, r7, r8, r7
853 adds r10, r14, r6
854 adc r4, r7, #0
855 adds r10, r10, r5
856 adc r4, r4, #0
857 # a[i+2] += m[2] * mu
858 ldr r7, [%[m], #8]
859 ldr r14, [%[a], #8]
860 umull r6, r7, r8, r7
861 adds r14, r14, r6
862 adc r5, r7, #0
863 adds r14, r14, r4
864 adc r5, r5, #0
865 # a[i+3] += m[3] * mu
866 ldr r7, [%[m], #12]
867 ldr r9, [%[a], #12]
868 umull r6, r7, r8, r7
869 adds r9, r9, r6
870 adc r4, r7, #0
871 adds r9, r9, r5
872 str r9, [%[a], #12]
873 adc r4, r4, #0
874 # a[i+4] += m[4] * mu
875 ldr r7, [%[m], #16]
876 ldr r9, [%[a], #16]
877 umull r6, r7, r8, r7
878 adds r9, r9, r6
879 adc r5, r7, #0
880 adds r9, r9, r4
881 str r9, [%[a], #16]
882 adc r5, r5, #0
883 # a[i+5] += m[5] * mu
884 ldr r7, [%[m], #20]
885 ldr r9, [%[a], #20]
886 umull r6, r7, r8, r7
887 adds r9, r9, r6
888 adc r4, r7, #0
889 adds r9, r9, r5
890 str r9, [%[a], #20]
891 adc r4, r4, #0
892 # a[i+6] += m[6] * mu
893 ldr r7, [%[m], #24]
894 ldr r9, [%[a], #24]
895 umull r6, r7, r8, r7
896 adds r9, r9, r6
897 adc r5, r7, #0
898 adds r9, r9, r4
899 str r9, [%[a], #24]
900 adc r5, r5, #0
901 # a[i+7] += m[7] * mu
902 ldr r7, [%[m], #28]
903 ldr r9, [%[a], #28]
904 umull r6, r7, r8, r7
905 adds r5, r5, r6
906 adcs r7, r7, %[ca]
907 mov %[ca], #0
908 adc %[ca], %[ca], %[ca]
909 adds r9, r9, r5
910 str r9, [%[a], #28]
911 ldr r9, [%[a], #32]
912 adcs r9, r9, r7
913 str r9, [%[a], #32]
914 adc %[ca], %[ca], #0
915 # i += 1
916 add %[a], %[a], #4
917 add r12, r12, #4
918 cmp r12, #32
919 blt 1b
920
921 str r10, [%[a], #0]
922 str r14, [%[a], #4]
923 : [ca] "+r" (ca), [a] "+r" (a)
924 : [m] "r" (m), [mp] "r" (mp)
925 : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14"
926 );
927
928 memcpy(a, a + 8, 32);
929 if (ca)
930 a -= m;
931}
932#endif
391 933
392/* Multiply two Montogmery form numbers mod the modulus (prime). 934/* Multiply two Montogmery form numbers mod the modulus (prime).
393 * (r = a * b mod m) 935 * (r = a * b mod m)
@@ -398,11 +940,13 @@ static void sp_256_mont_reduce_10(sp_digit* a, const sp_digit* m, sp_digit mp)
398 * m Modulus (prime). 940 * m Modulus (prime).
399 * mp Montogmery mulitplier. 941 * mp Montogmery mulitplier.
400 */ 942 */
401static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b, 943static void sp_256_mont_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b
402 const sp_digit* m, sp_digit mp) 944 /*, const sp_digit* m, sp_digit mp*/)
403{ 945{
404 sp_256_mul_10(r, a, b); 946 //const sp_digit* m = p256_mod;
405 sp_256_mont_reduce_10(r, m, mp); 947 //sp_digit mp = p256_mp_mod;
948 sp_256_mul_8(r, a, b);
949 sp_256_mont_reduce_8(r /*, m, mp*/);
406} 950}
407 951
408/* Square the Montgomery form number. (r = a * a mod m) 952/* Square the Montgomery form number. (r = a * a mod m)
@@ -412,11 +956,12 @@ static void sp_256_mont_mul_10(sp_digit* r, const sp_digit* a, const sp_digit* b
412 * m Modulus (prime). 956 * m Modulus (prime).
413 * mp Montogmery mulitplier. 957 * mp Montogmery mulitplier.
414 */ 958 */
415static void sp_256_mont_sqr_10(sp_digit* r, const sp_digit* a, const sp_digit* m, 959static void sp_256_mont_sqr_8(sp_digit* r, const sp_digit* a
416 sp_digit mp) 960 /*, const sp_digit* m, sp_digit mp*/)
417{ 961{
418 sp_256_sqr_10(r, a); 962 //const sp_digit* m = p256_mod;
419 sp_256_mont_reduce_10(r, m, mp); 963 //sp_digit mp = p256_mp_mod;
964 sp_256_mont_mul_8(r, a, a /*, m, mp*/);
420} 965}
421 966
422/* Invert the number, in Montgomery form, modulo the modulus (prime) of the 967/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
@@ -437,19 +982,19 @@ static const uint32_t p256_mod_2[8] = {
437//543210987654321098765432109876543210987654321098765432109876543210...09876543210...09876543210 982//543210987654321098765432109876543210987654321098765432109876543210...09876543210...09876543210
438//111111111111111111111111111111110000000000000000000000000000000100...00000111111...11111111101 983//111111111111111111111111111111110000000000000000000000000000000100...00000111111...11111111101
439#endif 984#endif
440static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a) 985static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a)
441{ 986{
442 sp_digit t[2*10]; //can be just [10]? 987 sp_digit t[2*8]; //can be just [8]?
443 int i; 988 int i;
444 989
445 memcpy(t, a, sizeof(sp_digit) * 10); 990 memcpy(t, a, sizeof(sp_digit) * 8);
446 for (i = 254; i >= 0; i--) { 991 for (i = 254; i >= 0; i--) {
447 sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod); 992 sp_256_mont_sqr_8(t, t /*, p256_mod, p256_mp_mod*/);
448 /*if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))*/ 993 /*if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32)))*/
449 if (i >= 224 || i == 192 || (i <= 95 && i != 1)) 994 if (i >= 224 || i == 192 || (i <= 95 && i != 1))
450 sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); 995 sp_256_mont_mul_8(t, t, a /*, p256_mod, p256_mp_mod*/);
451 } 996 }
452 memcpy(r, t, sizeof(sp_digit) * 10); 997 memcpy(r, t, sizeof(sp_digit) * 8);
453} 998}
454 999
455/* Multiply a number by Montogmery normalizer mod modulus (prime). 1000/* Multiply a number by Montogmery normalizer mod modulus (prime).
@@ -457,93 +1002,29 @@ static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a)
457 * r The resulting Montgomery form number. 1002 * r The resulting Montgomery form number.
458 * a The number to convert. 1003 * a The number to convert.
459 */ 1004 */
460static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a) 1005static void sp_256_mod_mul_norm_8(sp_digit* r, const sp_digit* a)
461{ 1006{
462 int64_t t[8]; 1007 int64_t t[8];
463 int64_t o; 1008 int32_t o;
464 uint32_t a32;
465 1009
1010#define A(n) ((uint64_t)a[n])
466 /* 1 1 0 -1 -1 -1 -1 0 */ 1011 /* 1 1 0 -1 -1 -1 -1 0 */
1012 t[0] = 0 + A(0) + A(1) - A(3) - A(4) - A(5) - A(6);
467 /* 0 1 1 0 -1 -1 -1 -1 */ 1013 /* 0 1 1 0 -1 -1 -1 -1 */
1014 t[1] = 0 + A(1) + A(2) - A(4) - A(5) - A(6) - A(7);
468 /* 0 0 1 1 0 -1 -1 -1 */ 1015 /* 0 0 1 1 0 -1 -1 -1 */
1016 t[2] = 0 + A(2) + A(3) - A(5) - A(6) - A(7);
469 /* -1 -1 0 2 2 1 0 -1 */ 1017 /* -1 -1 0 2 2 1 0 -1 */
1018 t[3] = 0 - A(0) - A(1) + 2 * A(3) + 2 * A(4) + A(5) - A(7);
470 /* 0 -1 -1 0 2 2 1 0 */ 1019 /* 0 -1 -1 0 2 2 1 0 */
1020 t[4] = 0 - A(1) - A(2) + 2 * A(4) + 2 * A(5) + A(6);
471 /* 0 0 -1 -1 0 2 2 1 */ 1021 /* 0 0 -1 -1 0 2 2 1 */
1022 t[5] = 0 - A(2) - A(3) + 2 * A(5) + 2 * A(6) + A(7);
472 /* -1 -1 0 0 0 1 3 2 */ 1023 /* -1 -1 0 0 0 1 3 2 */
1024 t[6] = 0 - A(0) - A(1) + A(5) + 3 * A(6) + 2 * A(7);
473 /* 1 0 -1 -1 -1 -1 0 3 */ 1025 /* 1 0 -1 -1 -1 -1 0 3 */
474 // t[] should be calculated from "a" (converted from 26-bit to 32-bit vector a32[8]) 1026 t[7] = 0 + A(0) - A(2) - A(3) - A(4) - A(5) + 3 * A(7);
475 // according to the above matrix: 1027#undef A
476 //t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6] ;
477 //t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7] ;
478 //t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7] ;
479 //t[3] = 0 - a32[0] - a32[1] + 2*a32[3] + 2*a32[4] + a32[5] - a32[7] ;
480 //t[4] = 0 - a32[1] - a32[2] + 2*a32[4] + 2*a32[5] + a32[6] ;
481 //t[5] = 0 - a32[2] - a32[3] + 2*a32[5] + 2*a32[6] + a32[7] ;
482 //t[6] = 0 - a32[0] - a32[1] + a32[5] + 3*a32[6] + 2*a32[7];
483 //t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3*a32[7];
484 // We can do it "piecemeal" after each a32[i] is known, no need to store entire a32[8] vector:
485
486#define A32 (int64_t)a32
487 a32 = a[0] | (a[1] << 26);
488 t[0] = 0 + A32;
489 t[3] = 0 - A32;
490 t[6] = 0 - A32;
491 t[7] = 0 + A32;
492
493 a32 = (a[1] >> 6) | (a[2] << 20);
494 t[0] += A32 ;
495 t[1] = 0 + A32;
496 t[3] -= A32 ;
497 t[4] = 0 - A32;
498 t[6] -= A32 ;
499
500 a32 = (a[2] >> 12) | (a[3] << 14);
501 t[1] += A32 ;
502 t[2] = 0 + A32;
503 t[4] -= A32 ;
504 t[5] = 0 - A32;
505 t[7] -= A32 ;
506
507 a32 = (a[3] >> 18) | (a[4] << 8);
508 t[0] -= A32 ;
509 t[2] += A32 ;
510 t[3] += 2*A32;
511 t[5] -= A32 ;
512 t[7] -= A32 ;
513
514 a32 = (a[4] >> 24) | (a[5] << 2) | (a[6] << 28);
515 t[0] -= A32 ;
516 t[1] -= A32 ;
517 t[3] += 2*A32;
518 t[4] += 2*A32;
519 t[7] -= A32 ;
520
521 a32 = (a[6] >> 4) | (a[7] << 22);
522 t[0] -= A32 ;
523 t[1] -= A32 ;
524 t[2] -= A32 ;
525 t[3] += A32 ;
526 t[4] += 2*A32;
527 t[5] += 2*A32;
528 t[6] += A32 ;
529 t[7] -= A32 ;
530
531 a32 = (a[7] >> 10) | (a[8] << 16);
532 t[0] -= A32 ;
533 t[1] -= A32 ;
534 t[2] -= A32 ;
535 t[4] += A32 ;
536 t[5] += 2*A32;
537 t[6] += 3*A32;
538
539 a32 = (a[8] >> 16) | (a[9] << 10);
540 t[1] -= A32 ;
541 t[2] -= A32 ;
542 t[3] -= A32 ;
543 t[5] += A32 ;
544 t[6] += 2*A32;
545 t[7] += 3*A32;
546#undef A32
547 1028
548 t[1] += t[0] >> 32; t[0] &= 0xffffffff; 1029 t[1] += t[0] >> 32; t[0] &= 0xffffffff;
549 t[2] += t[1] >> 32; t[1] &= 0xffffffff; 1030 t[2] += t[1] >> 32; t[1] &= 0xffffffff;
@@ -552,29 +1033,27 @@ static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a)
552 t[5] += t[4] >> 32; t[4] &= 0xffffffff; 1033 t[5] += t[4] >> 32; t[4] &= 0xffffffff;
553 t[6] += t[5] >> 32; t[5] &= 0xffffffff; 1034 t[6] += t[5] >> 32; t[5] &= 0xffffffff;
554 t[7] += t[6] >> 32; t[6] &= 0xffffffff; 1035 t[7] += t[6] >> 32; t[6] &= 0xffffffff;
555 o = t[7] >> 32; t[7] &= 0xffffffff; 1036 o = t[7] >> 32; //t[7] &= 0xffffffff;
556 t[0] += o; 1037 t[0] += o;
557 t[3] -= o; 1038 t[3] -= o;
558 t[6] -= o; 1039 t[6] -= o;
559 t[7] += o; 1040 t[7] += o;
560 t[1] += t[0] >> 32; //t[0] &= 0xffffffff; 1041 r[0] = (sp_digit)t[0];
561 t[2] += t[1] >> 32; //t[1] &= 0xffffffff; 1042 t[1] += t[0] >> 32;
562 t[3] += t[2] >> 32; //t[2] &= 0xffffffff; 1043 r[1] = (sp_digit)t[1];
563 t[4] += t[3] >> 32; //t[3] &= 0xffffffff; 1044 t[2] += t[1] >> 32;
564 t[5] += t[4] >> 32; //t[4] &= 0xffffffff; 1045 r[2] = (sp_digit)t[2];
565 t[6] += t[5] >> 32; //t[5] &= 0xffffffff; 1046 t[3] += t[2] >> 32;
566 t[7] += t[6] >> 32; //t[6] &= 0xffffffff; - (uint32_t)t[i] casts below accomplish masking 1047 r[3] = (sp_digit)t[3];
567 1048 t[4] += t[3] >> 32;
568 r[0] = 0x3ffffff & ((sp_digit)((uint32_t)t[0])); 1049 r[4] = (sp_digit)t[4];
569 r[1] = 0x3ffffff & ((sp_digit)((uint32_t)t[0] >> 26) | ((sp_digit)t[1] << 6)); 1050 t[5] += t[4] >> 32;
570 r[2] = 0x3ffffff & ((sp_digit)((uint32_t)t[1] >> 20) | ((sp_digit)t[2] << 12)); 1051 r[5] = (sp_digit)t[5];
571 r[3] = 0x3ffffff & ((sp_digit)((uint32_t)t[2] >> 14) | ((sp_digit)t[3] << 18)); 1052 t[6] += t[5] >> 32;
572 r[4] = 0x3ffffff & ((sp_digit)((uint32_t)t[3] >> 8) | ((sp_digit)t[4] << 24)); 1053 r[6] = (sp_digit)t[6];
573 r[5] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 2)); 1054// t[7] += t[6] >> 32;
574 r[6] = 0x3ffffff & ((sp_digit)((uint32_t)t[4] >> 28) | ((sp_digit)t[5] << 4)); 1055// r[7] = (sp_digit)t[7];
575 r[7] = 0x3ffffff & ((sp_digit)((uint32_t)t[5] >> 22) | ((sp_digit)t[6] << 10)); 1056 r[7] = (sp_digit)t[7] + (sp_digit)(t[6] >> 32);
576 r[8] = 0x3ffffff & ((sp_digit)((uint32_t)t[6] >> 16) | ((sp_digit)t[7] << 16));
577 r[9] = ((sp_digit)((uint32_t)t[7] >> 10));
578} 1057}
579 1058
580/* Map the Montgomery form projective co-ordinate point to an affine point. 1059/* Map the Montgomery form projective co-ordinate point to an affine point.
@@ -582,33 +1061,33 @@ static void sp_256_mod_mul_norm_10(sp_digit* r, const sp_digit* a)
582 * r Resulting affine co-ordinate point. 1061 * r Resulting affine co-ordinate point.
583 * p Montgomery form projective co-ordinate point. 1062 * p Montgomery form projective co-ordinate point.
584 */ 1063 */
585static void sp_256_map_10(sp_point* r, sp_point* p) 1064static void sp_256_map_8(sp_point* r, sp_point* p)
586{ 1065{
587 sp_digit t1[2*10]; 1066 sp_digit t1[2*8];
588 sp_digit t2[2*10]; 1067 sp_digit t2[2*8];
589 1068
590 sp_256_mont_inv_10(t1, p->z); 1069 sp_256_mont_inv_8(t1, p->z);
591 1070
592 sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); 1071 sp_256_mont_sqr_8(t2, t1 /*, p256_mod, p256_mp_mod*/);
593 sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); 1072 sp_256_mont_mul_8(t1, t2, t1 /*, p256_mod, p256_mp_mod*/);
594 1073
595 /* x /= z^2 */ 1074 /* x /= z^2 */
596 sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod); 1075 sp_256_mont_mul_8(r->x, p->x, t2 /*, p256_mod, p256_mp_mod*/);
597 memset(r->x + 10, 0, sizeof(r->x) / 2); 1076 memset(r->x + 8, 0, sizeof(r->x) / 2);
598 sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod); 1077 sp_256_mont_reduce_8(r->x /*, p256_mod, p256_mp_mod*/);
599 /* Reduce x to less than modulus */ 1078 /* Reduce x to less than modulus */
600 if (sp_256_cmp_10(r->x, p256_mod) >= 0) 1079 if (sp_256_cmp_8(r->x, p256_mod) >= 0)
601 sp_256_sub_10(r->x, r->x, p256_mod); 1080 sp_256_sub_8_p256_mod(r->x);
602 sp_256_norm_10(r->x); 1081 sp_256_norm_8(r->x);
603 1082
604 /* y /= z^3 */ 1083 /* y /= z^3 */
605 sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod); 1084 sp_256_mont_mul_8(r->y, p->y, t1 /*, p256_mod, p256_mp_mod*/);
606 memset(r->y + 10, 0, sizeof(r->y) / 2); 1085 memset(r->y + 8, 0, sizeof(r->y) / 2);
607 sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod); 1086 sp_256_mont_reduce_8(r->y /*, p256_mod, p256_mp_mod*/);
608 /* Reduce y to less than modulus */ 1087 /* Reduce y to less than modulus */
609 if (sp_256_cmp_10(r->y, p256_mod) >= 0) 1088 if (sp_256_cmp_8(r->y, p256_mod) >= 0)
610 sp_256_sub_10(r->y, r->y, p256_mod); 1089 sp_256_sub_8_p256_mod(r->y);
611 sp_256_norm_10(r->y); 1090 sp_256_norm_8(r->y);
612 1091
613 memset(r->z, 0, sizeof(r->z)); 1092 memset(r->z, 0, sizeof(r->z));
614 r->z[0] = 1; 1093 r->z[0] = 1;
@@ -619,56 +1098,62 @@ static void sp_256_map_10(sp_point* r, sp_point* p)
619 * r Result of doubling point. 1098 * r Result of doubling point.
620 * p Point to double. 1099 * p Point to double.
621 */ 1100 */
622static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p) 1101static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p)
623{ 1102{
624 sp_point tp; 1103 sp_digit t1[2*8];
625 sp_digit t1[2*10]; 1104 sp_digit t2[2*8];
626 sp_digit t2[2*10];
627 1105
628 /* Put point to double into result */ 1106 /* Put point to double into result */
629 if (r != p) 1107 if (r != p)
630 *r = *p; /* struct copy */ 1108 *r = *p; /* struct copy */
631 1109
632 if (r->infinity) { 1110 if (r->infinity)
633 /* If infinity, don't double (work on dummy value) */ 1111 return;
634 r = &tp; 1112
1113 if (SP_DEBUG) {
1114 /* unused part of t2, may result in spurios
1115 * differences in debug output. Clear it.
1116 */
1117 memset(t2, 0, sizeof(t2));
635 } 1118 }
1119
636 /* T1 = Z * Z */ 1120 /* T1 = Z * Z */
637 sp_256_mont_sqr_10(t1, r->z, p256_mod, p256_mp_mod); 1121 sp_256_mont_sqr_8(t1, r->z /*, p256_mod, p256_mp_mod*/);
638 /* Z = Y * Z */ 1122 /* Z = Y * Z */
639 sp_256_mont_mul_10(r->z, r->y, r->z, p256_mod, p256_mp_mod); 1123 sp_256_mont_mul_8(r->z, r->y, r->z /*, p256_mod, p256_mp_mod*/);
640 /* Z = 2Z */ 1124 /* Z = 2Z */
641 sp_256_mont_dbl_10(r->z, r->z, p256_mod); 1125 sp_256_mont_dbl_8(r->z, r->z /*, p256_mod*/);
642 /* T2 = X - T1 */ 1126 /* T2 = X - T1 */
643 sp_256_mont_sub_10(t2, r->x, t1, p256_mod); 1127 sp_256_mont_sub_8(t2, r->x, t1 /*, p256_mod*/);
644 /* T1 = X + T1 */ 1128 /* T1 = X + T1 */
645 sp_256_mont_add_10(t1, r->x, t1, p256_mod); 1129 sp_256_mont_add_8(t1, r->x, t1 /*, p256_mod*/);
646 /* T2 = T1 * T2 */ 1130 /* T2 = T1 * T2 */
647 sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod); 1131 sp_256_mont_mul_8(t2, t1, t2 /*, p256_mod, p256_mp_mod*/);
648 /* T1 = 3T2 */ 1132 /* T1 = 3T2 */
649 sp_256_mont_tpl_10(t1, t2, p256_mod); 1133 sp_256_mont_tpl_8(t1, t2 /*, p256_mod*/);
650 /* Y = 2Y */ 1134 /* Y = 2Y */
651 sp_256_mont_dbl_10(r->y, r->y, p256_mod); 1135 sp_256_mont_dbl_8(r->y, r->y /*, p256_mod*/);
652 /* Y = Y * Y */ 1136 /* Y = Y * Y */
653 sp_256_mont_sqr_10(r->y, r->y, p256_mod, p256_mp_mod); 1137 sp_256_mont_sqr_8(r->y, r->y /*, p256_mod, p256_mp_mod*/);
654 /* T2 = Y * Y */ 1138 /* T2 = Y * Y */
655 sp_256_mont_sqr_10(t2, r->y, p256_mod, p256_mp_mod); 1139 sp_256_mont_sqr_8(t2, r->y /*, p256_mod, p256_mp_mod*/);
656 /* T2 = T2/2 */ 1140 /* T2 = T2/2 */
657 sp_256_div2_10(t2, t2, p256_mod); 1141 sp_256_div2_8(t2, t2, p256_mod);
658 /* Y = Y * X */ 1142 /* Y = Y * X */
659 sp_256_mont_mul_10(r->y, r->y, r->x, p256_mod, p256_mp_mod); 1143 sp_256_mont_mul_8(r->y, r->y, r->x /*, p256_mod, p256_mp_mod*/);
660 /* X = T1 * T1 */ 1144 /* X = T1 * T1 */
661 sp_256_mont_mul_10(r->x, t1, t1, p256_mod, p256_mp_mod); 1145 sp_256_mont_mul_8(r->x, t1, t1 /*, p256_mod, p256_mp_mod*/);
662 /* X = X - Y */ 1146 /* X = X - Y */
663 sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod); 1147 sp_256_mont_sub_8(r->x, r->x, r->y /*, p256_mod*/);
664 /* X = X - Y */ 1148 /* X = X - Y */
665 sp_256_mont_sub_10(r->x, r->x, r->y, p256_mod); 1149 sp_256_mont_sub_8(r->x, r->x, r->y /*, p256_mod*/);
666 /* Y = Y - X */ 1150 /* Y = Y - X */
667 sp_256_mont_sub_10(r->y, r->y, r->x, p256_mod); 1151 sp_256_mont_sub_8(r->y, r->y, r->x /*, p256_mod*/);
668 /* Y = Y * T1 */ 1152 /* Y = Y * T1 */
669 sp_256_mont_mul_10(r->y, r->y, t1, p256_mod, p256_mp_mod); 1153 sp_256_mont_mul_8(r->y, r->y, t1 /*, p256_mod, p256_mp_mod*/);
670 /* Y = Y - T2 */ 1154 /* Y = Y - T2 */
671 sp_256_mont_sub_10(r->y, r->y, t2, p256_mod); 1155 sp_256_mont_sub_8(r->y, r->y, t2 /*, p256_mod*/);
1156 dump_512("y2 %s\n", r->y);
672} 1157}
673 1158
674/* Add two Montgomery form projective points. 1159/* Add two Montgomery form projective points.
@@ -677,13 +1162,13 @@ static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p)
677 * p Frist point to add. 1162 * p Frist point to add.
678 * q Second point to add. 1163 * q Second point to add.
679 */ 1164 */
680static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q) 1165static NOINLINE void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q)
681{ 1166{
682 sp_digit t1[2*10]; 1167 sp_digit t1[2*8];
683 sp_digit t2[2*10]; 1168 sp_digit t2[2*8];
684 sp_digit t3[2*10]; 1169 sp_digit t3[2*8];
685 sp_digit t4[2*10]; 1170 sp_digit t4[2*8];
686 sp_digit t5[2*10]; 1171 sp_digit t5[2*8];
687 1172
688 /* Ensure only the first point is the same as the result. */ 1173 /* Ensure only the first point is the same as the result. */
689 if (q == r) { 1174 if (q == r) {
@@ -693,13 +1178,13 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q)
693 } 1178 }
694 1179
695 /* Check double */ 1180 /* Check double */
696 sp_256_sub_10(t1, p256_mod, q->y); 1181 sp_256_sub_8(t1, p256_mod, q->y);
697 sp_256_norm_10(t1); 1182 sp_256_norm_8(t1);
698 if (sp_256_cmp_equal_10(p->x, q->x) 1183 if (sp_256_cmp_equal_8(p->x, q->x)
699 && sp_256_cmp_equal_10(p->z, q->z) 1184 && sp_256_cmp_equal_8(p->z, q->z)
700 && (sp_256_cmp_equal_10(p->y, q->y) || sp_256_cmp_equal_10(p->y, t1)) 1185 && (sp_256_cmp_equal_8(p->y, q->y) || sp_256_cmp_equal_8(p->y, t1))
701 ) { 1186 ) {
702 sp_256_proj_point_dbl_10(r, p); 1187 sp_256_proj_point_dbl_8(r, p);
703 } 1188 }
704 else { 1189 else {
705 sp_point tp; 1190 sp_point tp;
@@ -714,37 +1199,37 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q)
714 *r = p->infinity ? *q : *p; /* struct copy */ 1199 *r = p->infinity ? *q : *p; /* struct copy */
715 1200
716 /* U1 = X1*Z2^2 */ 1201 /* U1 = X1*Z2^2 */
717 sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod); 1202 sp_256_mont_sqr_8(t1, q->z /*, p256_mod, p256_mp_mod*/);
718 sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod); 1203 sp_256_mont_mul_8(t3, t1, q->z /*, p256_mod, p256_mp_mod*/);
719 sp_256_mont_mul_10(t1, t1, v->x, p256_mod, p256_mp_mod); 1204 sp_256_mont_mul_8(t1, t1, v->x /*, p256_mod, p256_mp_mod*/);
720 /* U2 = X2*Z1^2 */ 1205 /* U2 = X2*Z1^2 */
721 sp_256_mont_sqr_10(t2, v->z, p256_mod, p256_mp_mod); 1206 sp_256_mont_sqr_8(t2, v->z /*, p256_mod, p256_mp_mod*/);
722 sp_256_mont_mul_10(t4, t2, v->z, p256_mod, p256_mp_mod); 1207 sp_256_mont_mul_8(t4, t2, v->z /*, p256_mod, p256_mp_mod*/);
723 sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); 1208 sp_256_mont_mul_8(t2, t2, q->x /*, p256_mod, p256_mp_mod*/);
724 /* S1 = Y1*Z2^3 */ 1209 /* S1 = Y1*Z2^3 */
725 sp_256_mont_mul_10(t3, t3, v->y, p256_mod, p256_mp_mod); 1210 sp_256_mont_mul_8(t3, t3, v->y /*, p256_mod, p256_mp_mod*/);
726 /* S2 = Y2*Z1^3 */ 1211 /* S2 = Y2*Z1^3 */
727 sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); 1212 sp_256_mont_mul_8(t4, t4, q->y /*, p256_mod, p256_mp_mod*/);
728 /* H = U2 - U1 */ 1213 /* H = U2 - U1 */
729 sp_256_mont_sub_10(t2, t2, t1, p256_mod); 1214 sp_256_mont_sub_8(t2, t2, t1 /*, p256_mod*/);
730 /* R = S2 - S1 */ 1215 /* R = S2 - S1 */
731 sp_256_mont_sub_10(t4, t4, t3, p256_mod); 1216 sp_256_mont_sub_8(t4, t4, t3 /*, p256_mod*/);
732 /* Z3 = H*Z1*Z2 */ 1217 /* Z3 = H*Z1*Z2 */
733 sp_256_mont_mul_10(v->z, v->z, q->z, p256_mod, p256_mp_mod); 1218 sp_256_mont_mul_8(v->z, v->z, q->z /*, p256_mod, p256_mp_mod*/);
734 sp_256_mont_mul_10(v->z, v->z, t2, p256_mod, p256_mp_mod); 1219 sp_256_mont_mul_8(v->z, v->z, t2 /*, p256_mod, p256_mp_mod*/);
735 /* X3 = R^2 - H^3 - 2*U1*H^2 */ 1220 /* X3 = R^2 - H^3 - 2*U1*H^2 */
736 sp_256_mont_sqr_10(v->x, t4, p256_mod, p256_mp_mod); 1221 sp_256_mont_sqr_8(v->x, t4 /*, p256_mod, p256_mp_mod*/);
737 sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); 1222 sp_256_mont_sqr_8(t5, t2 /*, p256_mod, p256_mp_mod*/);
738 sp_256_mont_mul_10(v->y, t1, t5, p256_mod, p256_mp_mod); 1223 sp_256_mont_mul_8(v->y, t1, t5 /*, p256_mod, p256_mp_mod*/);
739 sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); 1224 sp_256_mont_mul_8(t5, t5, t2 /*, p256_mod, p256_mp_mod*/);
740 sp_256_mont_sub_10(v->x, v->x, t5, p256_mod); 1225 sp_256_mont_sub_8(v->x, v->x, t5 /*, p256_mod*/);
741 sp_256_mont_dbl_10(t1, v->y, p256_mod); 1226 sp_256_mont_dbl_8(t1, v->y /*, p256_mod*/);
742 sp_256_mont_sub_10(v->x, v->x, t1, p256_mod); 1227 sp_256_mont_sub_8(v->x, v->x, t1 /*, p256_mod*/);
743 /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ 1228 /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
744 sp_256_mont_sub_10(v->y, v->y, v->x, p256_mod); 1229 sp_256_mont_sub_8(v->y, v->y, v->x /*, p256_mod*/);
745 sp_256_mont_mul_10(v->y, v->y, t4, p256_mod, p256_mp_mod); 1230 sp_256_mont_mul_8(v->y, v->y, t4 /*, p256_mod, p256_mp_mod*/);
746 sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod); 1231 sp_256_mont_mul_8(t5, t5, t3 /*, p256_mod, p256_mp_mod*/);
747 sp_256_mont_sub_10(v->y, v->y, t5, p256_mod); 1232 sp_256_mont_sub_8(v->y, v->y, t5 /*, p256_mod*/);
748 } 1233 }
749} 1234}
750 1235
@@ -756,12 +1241,11 @@ static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q)
756 * k Scalar to multiply by. 1241 * k Scalar to multiply by.
757 * map Indicates whether to convert result to affine. 1242 * map Indicates whether to convert result to affine.
758 */ 1243 */
759static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit* k /*, int map*/) 1244static void sp_256_ecc_mulmod_8(sp_point* r, const sp_point* g, const sp_digit* k /*, int map*/)
760{ 1245{
761 enum { map = 1 }; /* we always convert result to affine coordinates */ 1246 enum { map = 1 }; /* we always convert result to affine coordinates */
762 sp_point t[3]; 1247 sp_point t[3];
763 sp_digit n; 1248 sp_digit n = n; /* for compiler */
764 int i;
765 int c, y; 1249 int c, y;
766 1250
767 memset(t, 0, sizeof(t)); 1251 memset(t, 0, sizeof(t));
@@ -769,33 +1253,44 @@ static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit*
769 /* t[0] = {0, 0, 1} * norm */ 1253 /* t[0] = {0, 0, 1} * norm */
770 t[0].infinity = 1; 1254 t[0].infinity = 1;
771 /* t[1] = {g->x, g->y, g->z} * norm */ 1255 /* t[1] = {g->x, g->y, g->z} * norm */
772 sp_256_mod_mul_norm_10(t[1].x, g->x); 1256 sp_256_mod_mul_norm_8(t[1].x, g->x);
773 sp_256_mod_mul_norm_10(t[1].y, g->y); 1257 sp_256_mod_mul_norm_8(t[1].y, g->y);
774 sp_256_mod_mul_norm_10(t[1].z, g->z); 1258 sp_256_mod_mul_norm_8(t[1].z, g->z);
775
776 i = 9;
777 c = 22;
778 n = k[i--] << (26 - c);
779 for (; ; c--) {
780 if (c == 0) {
781 if (i == -1)
782 break;
783 1259
784 n = k[i--]; 1260 /* For every bit, starting from most significant... */
785 c = 26; 1261 k += 7;
1262 c = 256;
1263 for (;;) {
1264 if ((c & 0x1f) == 0) {
1265 if (c == 0)
1266 break;
1267 n = *k--;
786 } 1268 }
787 1269
788 y = (n >> 25) & 1; 1270 y = (n >> 31);
789 n <<= 1; 1271 dbg("y:%d t[%d] = t[0]+t[1]\n", y, y^1);
790 1272 sp_256_proj_point_add_8(&t[y^1], &t[0], &t[1]);
791 sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1]); 1273 dump_512("t[0].x %s\n", t[0].x);
1274 dump_512("t[0].y %s\n", t[0].y);
1275 dump_512("t[0].z %s\n", t[0].z);
1276 dump_512("t[1].x %s\n", t[1].x);
1277 dump_512("t[1].y %s\n", t[1].y);
1278 dump_512("t[1].z %s\n", t[1].z);
1279 dbg("t[2] = t[%d]\n", y);
792 memcpy(&t[2], &t[y], sizeof(sp_point)); 1280 memcpy(&t[2], &t[y], sizeof(sp_point));
793 sp_256_proj_point_dbl_10(&t[2], &t[2]); 1281 dbg("t[2] *= 2\n");
1282 sp_256_proj_point_dbl_8(&t[2], &t[2]);
1283 dump_512("t[2].x %s\n", t[2].x);
1284 dump_512("t[2].y %s\n", t[2].y);
1285 dump_512("t[2].z %s\n", t[2].z);
794 memcpy(&t[y], &t[2], sizeof(sp_point)); 1286 memcpy(&t[y], &t[2], sizeof(sp_point));
1287
1288 n <<= 1;
1289 c--;
795 } 1290 }
796 1291
797 if (map) 1292 if (map)
798 sp_256_map_10(r, &t[0]); 1293 sp_256_map_8(r, &t[0]);
799 else 1294 else
800 memcpy(r, &t[0], sizeof(sp_point)); 1295 memcpy(r, &t[0], sizeof(sp_point));
801 1296
@@ -809,7 +1304,7 @@ static void sp_256_ecc_mulmod_10(sp_point* r, const sp_point* g, const sp_digit*
809 * k Scalar to multiply by. 1304 * k Scalar to multiply by.
810 * map Indicates whether to convert result to affine. 1305 * map Indicates whether to convert result to affine.
811 */ 1306 */
812static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/) 1307static void sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k /*, int map*/)
813{ 1308{
814 /* Since this function is called only once, save space: 1309 /* Since this function is called only once, save space:
815 * don't have "static const sp_point p256_base = {...}", 1310 * don't have "static const sp_point p256_base = {...}",
@@ -826,7 +1321,7 @@ static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/)
826 1321
827 sp_256_point_from_bin2x32(&p256_base, p256_base_bin); 1322 sp_256_point_from_bin2x32(&p256_base, p256_base_bin);
828 1323
829 sp_256_ecc_mulmod_10(r, &p256_base, k /*, map*/); 1324 sp_256_ecc_mulmod_8(r, &p256_base, k /*, map*/);
830} 1325}
831 1326
832/* Multiply the point by the scalar and serialize the X ordinate. 1327/* Multiply the point by the scalar and serialize the X ordinate.
@@ -836,7 +1331,7 @@ static void sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k /*, int map*/)
836 * pub2x32 Point to multiply. 1331 * pub2x32 Point to multiply.
837 * out32 Buffer to hold X ordinate. 1332 * out32 Buffer to hold X ordinate.
838 */ 1333 */
839static void sp_ecc_secret_gen_256(const sp_digit priv[10], const uint8_t *pub2x32, uint8_t* out32) 1334static void sp_ecc_secret_gen_256(const sp_digit priv[8], const uint8_t *pub2x32, uint8_t* out32)
840{ 1335{
841 sp_point point[1]; 1336 sp_point point[1];
842 1337
@@ -847,66 +1342,51 @@ static void sp_ecc_secret_gen_256(const sp_digit priv[10], const uint8_t *pub2x3
847 dump_hex(" %s\n", pub2x32 + 32, 32); 1342 dump_hex(" %s\n", pub2x32 + 32, 32);
848 1343
849 sp_256_point_from_bin2x32(point, pub2x32); 1344 sp_256_point_from_bin2x32(point, pub2x32);
850 dump_hex("point->x %s\n", point->x, sizeof(point->x)); 1345 dump_512("point->x %s\n", point->x);
851 dump_hex("point->y %s\n", point->y, sizeof(point->y)); 1346 dump_512("point->y %s\n", point->y);
852 1347
853 sp_256_ecc_mulmod_10(point, point, priv); 1348 sp_256_ecc_mulmod_8(point, point, priv);
854 1349
855 sp_256_to_bin(point->x, out32); 1350 sp_256_to_bin_8(point->x, out32);
856 dump_hex("out32: %s\n", out32, 32); 1351 dump_hex("out32: %s\n", out32, 32);
857} 1352}
858 1353
859/* Generates a scalar that is in the range 1..order-1. */ 1354/* Generates a random scalar in [1..order-1] range. */
860#define SIMPLIFY 1 1355static void sp_256_ecc_gen_k_8(sp_digit k[8])
861/* Add 1 to a. (a = a + 1) */
862static void sp_256_add_one_10(sp_digit* a)
863{ 1356{
864 a[0]++; 1357 /* Since 32-bit words are "dense", no need to use
865 sp_256_norm_10(a); 1358 * sp_256_from_bin_8(k, buf) to convert random stream
866} 1359 * to sp_digit array - just store random bits there directly.
867static void sp_256_ecc_gen_k_10(sp_digit k[10]) 1360 */
868{ 1361 tls_get_random(k, 8 * sizeof(k[0]));
869#if !SIMPLIFY
870 /* The order of the curve P256 minus 2. */
871 static const sp_digit p256_order2[10] = {
872 0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,
873 0x3ffffff,0x3ffffff,0x00003ff,0x3ff0000,0x03fffff,
874 };
875#endif
876 uint8_t buf[32];
877
878 for (;;) {
879 tls_get_random(buf, sizeof(buf));
880#if FIXED_SECRET 1362#if FIXED_SECRET
881 memset(buf, 0x77, sizeof(buf)); 1363 memset(k, 0x77, 8 * sizeof(k[0]));
882#endif
883 sp_256_from_bin(k, 10, buf, sizeof(buf));
884#if !SIMPLIFY
885 if (sp_256_cmp_10(k, p256_order2) < 0)
886 break;
887#else
888 /* non-loopy version (and not needing p256_order2[]):
889 * if most-significant word seems that k can be larger
890 * than p256_order2, fix it up:
891 */
892 if (k[9] >= 0x03fffff)
893 k[9] = 0x03ffffe;
894 break;
895#endif 1364#endif
896 } 1365
897 sp_256_add_one_10(k); 1366// If scalar is too large, try again (pseudo-code)
898#undef SIMPLIFY 1367// if (k >= 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - 1) // order of P256
1368// goto pick_another_random;
1369// k++; // ensure non-zero
1370 /* Simpler alternative, at the cost of not choosing some valid
1371 * random values, and slightly non-uniform distribution */
1372 if (k[0] == 0)
1373 k[0] = 1;
1374 if (k[7] >= 0xffffffff)
1375 k[7] = 0xfffffffe;
899} 1376}
900 1377
901/* Makes a random EC key pair. */ 1378/* Makes a random EC key pair. */
902static void sp_ecc_make_key_256(sp_digit privkey[10], uint8_t *pubkey) 1379static void sp_ecc_make_key_256(sp_digit privkey[8], uint8_t *pubkey)
903{ 1380{
904 sp_point point[1]; 1381 sp_point point[1];
905 1382
906 sp_256_ecc_gen_k_10(privkey); 1383 sp_256_ecc_gen_k_8(privkey);
907 sp_256_ecc_mulmod_base_10(point, privkey); 1384 dump_256("privkey %s\n", privkey);
908 sp_256_to_bin(point->x, pubkey); 1385 sp_256_ecc_mulmod_base_8(point, privkey);
909 sp_256_to_bin(point->y, pubkey + 32); 1386 dump_512("point->x %s\n", point->x);
1387 dump_512("point->y %s\n", point->y);
1388 sp_256_to_bin_8(point->x, pubkey);
1389 sp_256_to_bin_8(point->y, pubkey + 32);
910 1390
911 memset(point, 0, sizeof(point)); //paranoia 1391 memset(point, 0, sizeof(point)); //paranoia
912} 1392}
@@ -915,8 +1395,9 @@ void FAST_FUNC curve_P256_compute_pubkey_and_premaster(
915 uint8_t *pubkey2x32, uint8_t *premaster32, 1395 uint8_t *pubkey2x32, uint8_t *premaster32,
916 const uint8_t *peerkey2x32) 1396 const uint8_t *peerkey2x32)
917{ 1397{
918 sp_digit privkey[10]; 1398 sp_digit privkey[8];
919 1399
1400 dump_hex("peerkey2x32: %s\n", peerkey2x32, 64);
920 sp_ecc_make_key_256(privkey, pubkey2x32); 1401 sp_ecc_make_key_256(privkey, pubkey2x32);
921 dump_hex("pubkey: %s\n", pubkey2x32, 32); 1402 dump_hex("pubkey: %s\n", pubkey2x32, 32);
922 dump_hex(" %s\n", pubkey2x32 + 32, 32); 1403 dump_hex(" %s\n", pubkey2x32 + 32, 32);
diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h
deleted file mode 100644
index 5e0e4b6d8..000000000
--- a/networking/tls_symmetric.h
+++ /dev/null
@@ -1,511 +0,0 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7
8/* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h
9 * Changes are flagged with //bbox
10 */
11
12/******************************************************************************/
13/* 32-bit Rotates */
14/******************************************************************************/
15#if defined(_MSC_VER)
16/******************************************************************************/
17
18/* instrinsic rotate */
19#include <stdlib.h>
20#pragma intrinsic(_lrotr,_lrotl)
21#define ROR(x,n) _lrotr(x,n)
22#define ROL(x,n) _lrotl(x,n)
23
24/******************************************************************************/
25#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \
26 !defined(INTEL_CC) && !defined(PS_NO_ASM)
27
28static ALWAYS_INLINE unsigned ROL(unsigned word, int i)
29{
30 if (__builtin_constant_p(i)) { //box
31 // Rotates by constant use fewer registers,
32 // and on many Intel CPUs rotates by %cl take 2 cycles, not 1.
33 asm ("roll %2,%0"
34 :"=r" (word)
35 :"0" (word),"i" (i));
36 return word;
37 } //box
38 asm ("roll %%cl,%0"
39 :"=r" (word)
40 :"0" (word),"c" (i));
41 return word;
42}
43
44static ALWAYS_INLINE unsigned ROR(unsigned word, int i)
45{
46 if (__builtin_constant_p(i)) { //box
47 asm ("rorl %2,%0"
48 :"=r" (word)
49 :"0" (word),"i" (i));
50 return word;
51 } //box
52 asm ("rorl %%cl,%0"
53 :"=r" (word)
54 :"0" (word),"c" (i));
55 return word;
56}
57
58/******************************************************************************/
59#else
60
61/* rotates the hard way */
62#define ROL(x, y) \
63 ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \
64 (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \
65 0xFFFFFFFFUL)
66#define ROR(x, y) \
67 ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
68 ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
69
70#endif /* 32-bit Rotates */
71/******************************************************************************/
72
73#ifdef HAVE_NATIVE_INT64
74#ifdef _MSC_VER
75 #define CONST64(n) n ## ui64
76#else
77 #define CONST64(n) n ## ULL
78#endif
79#endif
80
81/******************************************************************************/
82/*
83 Endian helper macros
84 */
85#if defined (ENDIAN_NEUTRAL)
86#define STORE32L(x, y) { \
87(y)[3] = (unsigned char)(((x)>>24)&255); \
88(y)[2] = (unsigned char)(((x)>>16)&255); \
89(y)[1] = (unsigned char)(((x)>>8)&255); \
90(y)[0] = (unsigned char)((x)&255); \
91}
92
93#define LOAD32L(x, y) { \
94x = ((unsigned long)((y)[3] & 255)<<24) | \
95((unsigned long)((y)[2] & 255)<<16) | \
96((unsigned long)((y)[1] & 255)<<8) | \
97((unsigned long)((y)[0] & 255)); \
98}
99
100#define STORE64L(x, y) { \
101(y)[7] = (unsigned char)(((x)>>56)&255); \
102(y)[6] = (unsigned char)(((x)>>48)&255); \
103(y)[5] = (unsigned char)(((x)>>40)&255); \
104(y)[4] = (unsigned char)(((x)>>32)&255); \
105(y)[3] = (unsigned char)(((x)>>24)&255); \
106(y)[2] = (unsigned char)(((x)>>16)&255); \
107(y)[1] = (unsigned char)(((x)>>8)&255); \
108(y)[0] = (unsigned char)((x)&255); \
109}
110
111#define LOAD64L(x, y) { \
112x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
113(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
114(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
115(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
116}
117
118#define STORE32H(x, y) { \
119(y)[0] = (unsigned char)(((x)>>24)&255); \
120(y)[1] = (unsigned char)(((x)>>16)&255); \
121(y)[2] = (unsigned char)(((x)>>8)&255); \
122(y)[3] = (unsigned char)((x)&255); \
123}
124
125#define LOAD32H(x, y) { \
126x = ((unsigned long)((y)[0] & 255)<<24) | \
127((unsigned long)((y)[1] & 255)<<16) | \
128((unsigned long)((y)[2] & 255)<<8) | \
129((unsigned long)((y)[3] & 255)); \
130}
131
132#define STORE64H(x, y) { \
133(y)[0] = (unsigned char)(((x)>>56)&255); \
134(y)[1] = (unsigned char)(((x)>>48)&255); \
135(y)[2] = (unsigned char)(((x)>>40)&255); \
136(y)[3] = (unsigned char)(((x)>>32)&255); \
137(y)[4] = (unsigned char)(((x)>>24)&255); \
138(y)[5] = (unsigned char)(((x)>>16)&255); \
139(y)[6] = (unsigned char)(((x)>>8)&255); \
140(y)[7] = (unsigned char)((x)&255); \
141}
142
143#define LOAD64H(x, y) { \
144x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
145(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
146(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
147(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \
148}
149
150#endif /* ENDIAN_NEUTRAL */
151
152#ifdef ENDIAN_LITTLE
153#define STORE32H(x, y) { \
154(y)[0] = (unsigned char)(((x)>>24)&255); \
155(y)[1] = (unsigned char)(((x)>>16)&255); \
156(y)[2] = (unsigned char)(((x)>>8)&255); \
157(y)[3] = (unsigned char)((x)&255); \
158}
159
160#define LOAD32H(x, y) { \
161x = ((unsigned long)((y)[0] & 255)<<24) | \
162((unsigned long)((y)[1] & 255)<<16) | \
163((unsigned long)((y)[2] & 255)<<8) | \
164((unsigned long)((y)[3] & 255)); \
165}
166
167#define STORE64H(x, y) { \
168(y)[0] = (unsigned char)(((x)>>56)&255); \
169(y)[1] = (unsigned char)(((x)>>48)&255); \
170(y)[2] = (unsigned char)(((x)>>40)&255); \
171(y)[3] = (unsigned char)(((x)>>32)&255); \
172(y)[4] = (unsigned char)(((x)>>24)&255); \
173(y)[5] = (unsigned char)(((x)>>16)&255); \
174(y)[6] = (unsigned char)(((x)>>8)&255); \
175(y)[7] = (unsigned char)((x)&255); \
176}
177
178#define LOAD64H(x, y) { \
179x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
180(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
181(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
182(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); }
183
184#ifdef ENDIAN_32BITWORD
185#define STORE32L(x, y) { \
186unsigned long __t = (x); memcpy(y, &__t, 4); \
187}
188
189#define LOAD32L(x, y) memcpy(&(x), y, 4);
190
191#define STORE64L(x, y) { \
192(y)[7] = (unsigned char)(((x)>>56)&255); \
193(y)[6] = (unsigned char)(((x)>>48)&255); \
194(y)[5] = (unsigned char)(((x)>>40)&255); \
195(y)[4] = (unsigned char)(((x)>>32)&255); \
196(y)[3] = (unsigned char)(((x)>>24)&255); \
197(y)[2] = (unsigned char)(((x)>>16)&255); \
198(y)[1] = (unsigned char)(((x)>>8)&255); \
199(y)[0] = (unsigned char)((x)&255); \
200}
201
202#define LOAD64L(x, y) { \
203x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
204(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
205(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
206(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
207}
208
209#else /* 64-bit words then */
210#define STORE32L(x, y) \
211{ unsigned long __t = (x); memcpy(y, &__t, 4); }
212
213#define LOAD32L(x, y) \
214{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
215
216#define STORE64L(x, y) \
217{ uint64 __t = (x); memcpy(y, &__t, 8); }
218
219#define LOAD64L(x, y) \
220{ memcpy(&(x), y, 8); }
221
222#endif /* ENDIAN_64BITWORD */
223#endif /* ENDIAN_LITTLE */
224
225#ifdef ENDIAN_BIG
226#define STORE32L(x, y) { \
227(y)[3] = (unsigned char)(((x)>>24)&255); \
228(y)[2] = (unsigned char)(((x)>>16)&255); \
229(y)[1] = (unsigned char)(((x)>>8)&255); \
230(y)[0] = (unsigned char)((x)&255); \
231}
232
233#define LOAD32L(x, y) { \
234x = ((unsigned long)((y)[3] & 255)<<24) | \
235((unsigned long)((y)[2] & 255)<<16) | \
236((unsigned long)((y)[1] & 255)<<8) | \
237((unsigned long)((y)[0] & 255)); \
238}
239
240#define STORE64L(x, y) { \
241(y)[7] = (unsigned char)(((x)>>56)&255); \
242(y)[6] = (unsigned char)(((x)>>48)&255); \
243(y)[5] = (unsigned char)(((x)>>40)&255); \
244(y)[4] = (unsigned char)(((x)>>32)&255); \
245(y)[3] = (unsigned char)(((x)>>24)&255); \
246(y)[2] = (unsigned char)(((x)>>16)&255); \
247(y)[1] = (unsigned char)(((x)>>8)&255); \
248(y)[0] = (unsigned char)((x)&255); \
249}
250
251#define LOAD64L(x, y) { \
252x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \
253(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \
254(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \
255(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
256}
257
258#ifdef ENDIAN_32BITWORD
259#define STORE32H(x, y) \
260{ unsigned int __t = (x); memcpy(y, &__t, 4); }
261
262#define LOAD32H(x, y) memcpy(&(x), y, 4);
263
264#define STORE64H(x, y) { \
265(y)[0] = (unsigned char)(((x)>>56)&255); \
266(y)[1] = (unsigned char)(((x)>>48)&255); \
267(y)[2] = (unsigned char)(((x)>>40)&255); \
268(y)[3] = (unsigned char)(((x)>>32)&255); \
269(y)[4] = (unsigned char)(((x)>>24)&255); \
270(y)[5] = (unsigned char)(((x)>>16)&255); \
271(y)[6] = (unsigned char)(((x)>>8)&255); \
272(y)[7] = (unsigned char)((x)&255); \
273}
274
275#define LOAD64H(x, y) { \
276x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \
277(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \
278(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \
279(((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \
280}
281
282#else /* 64-bit words then */
283
284#define STORE32H(x, y) \
285{ unsigned long __t = (x); memcpy(y, &__t, 4); }
286
287#define LOAD32H(x, y) \
288{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
289
290#define STORE64H(x, y) \
291{ uint64 __t = (x); memcpy(y, &__t, 8); }
292
293#define LOAD64H(x, y) \
294{ memcpy(&(x), y, 8); }
295
296#endif /* ENDIAN_64BITWORD */
297#endif /* ENDIAN_BIG */
298
299#ifdef HAVE_NATIVE_INT64
300#define ROL64c(x, y) \
301( (((x)<<((uint64)(y)&63)) | \
302(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
303
304#define ROR64c(x, y) \
305( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \
306((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
307#endif /* HAVE_NATIVE_INT64 */
308/******************************************************************************/
309
310
311
312/* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/.
313 * Changes are flagged with //bbox
314 */
315
316/**
317 * @file symmetric.h
318 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
319 *
320 * Header for internal symmetric key cryptography support.
321 */
322/*
323 * Copyright (c) 2013-2015 INSIDE Secure Corporation
324 * Copyright (c) PeerSec Networks, 2002-2011
325 * All Rights Reserved
326 *
327 * The latest version of this code is available at http://www.matrixssl.org
328 *
329 * This software is open source; you can redistribute it and/or modify
330 * it under the terms of the GNU General Public License as published by
331 * the Free Software Foundation; either version 2 of the License, or
332 * (at your option) any later version.
333 *
334 * This General Public License does NOT permit incorporating this software
335 * into proprietary programs. If you are unable to comply with the GPL, a
336 * commercial license for this software may be purchased from INSIDE at
337 * http://www.insidesecure.com/eng/Company/Locations
338 *
339 * This program is distributed in WITHOUT ANY WARRANTY; without even the
340 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
341 * See the GNU General Public License for more details.
342 *
343 * You should have received a copy of the GNU General Public License
344 * along with this program; if not, write to the Free Software
345 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
346 * http://www.gnu.org/copyleft/gpl.html
347 */
348/******************************************************************************/
349
350#ifndef _h_PS_SYMMETRIC
351#define _h_PS_SYMMETRIC
352
353/******************************************************************************/
354#ifdef USE_AES
355/******************************************************************************/
356
357
358#ifndef USE_AES_CBC_EXTERNAL
359typedef struct {
360 uint32 eK[64], dK[64];
361 int32 Nr;
362} psAesKey_t;
363
364typedef struct {
365 int32 blocklen;
366 unsigned char IV[16];
367 psAesKey_t key;
368#if defined(USE_AES_GCM) || defined(USE_AES_CCM)
369 unsigned char EncCtr[16];
370 unsigned char CtrBlock[16];
371#endif
372#ifdef USE_AES_GCM
373 unsigned char gInit[16];
374 uint32 TagTemp[4];
375 unsigned char Hash_SubKey[16];
376 uint32 ProcessedBitCount[4];
377 uint32 InputBufferCount;
378 uint32 OutputBufferCount;
379 union
380 {
381 unsigned char Buffer[128];
382 uint32 BufferAlignment;
383 } Input;
384#endif /* USE_AES_GCM */
385#ifdef USE_AES_CCM
386 uint32_t ccmTagTemp[16 / sizeof(uint32_t)]; /* 32 */
387 union
388 {
389 /* Used for formatting IV. */
390 uint8_t Temporary[16];
391 /* Used for processing Mac. */
392 uint8_t Y0[16];
393 } u; /* 48 */
394#endif /* USE_AES_CCM */
395} psAesCipher_t;
396#endif /* USE_AES_CBC_EXTERNAL */
397
398#endif /* USE_AES */
399
400#ifdef USE_IDEA
401#define SSL_IDEA_KEY_LEN 16
402#define SSL_IDEA_IV_LEN 8
403#define SSL_IDEA_BLOCK_LEN 8
404
405typedef struct {
406 uint16 key_schedule[52];
407} psIdeaKey_t;
408
409typedef struct {
410 psIdeaKey_t key;
411 uint32 IV[2];
412 short for_encryption;
413 short inverted;
414} idea_CBC;
415#endif
416/******************************************************************************/
417
418/******************************************************************************/
419#ifdef USE_SEED
420/******************************************************************************/
421#define SSL_SEED_KEY_LEN 16
422#define SSL_SEED_IV_LEN 16
423
424
425typedef struct {
426 uint32 K[32], dK[32];
427} psSeedKey_t;
428
429typedef struct {
430 int32 blocklen;
431 unsigned char IV[16];
432 psSeedKey_t key;
433} seed_CBC;
434
435#endif /* USE_SEED */
436/******************************************************************************/
437
438/******************************************************************************/
439#if defined(USE_3DES) || defined(USE_DES)
440/******************************************************************************/
441#define DES3_KEY_LEN 24
442#define DES3_IV_LEN 8
443#define DES_KEY_LEN 8
444
445typedef struct {
446 uint32 ek[3][32], dk[3][32];
447} psDes3Key_t;
448
449/*
450 A block cipher CBC structure
451 */
452typedef struct {
453 int32 blocklen;
454 unsigned char IV[8];
455 psDes3Key_t key;
456} des3_CBC;
457
458#endif /* USE_3DES || USE_DES */
459/******************************************************************************/
460
461/******************************************************************************/
462#ifdef USE_ARC4
463typedef struct {
464 unsigned char state[256];
465 uint32 byteCount;
466 unsigned char x;
467 unsigned char y;
468} psRc4Key_t;
469#endif /* USE_ARC4 */
470/******************************************************************************/
471#ifdef USE_RC2
472typedef struct {
473 unsigned xkey[64];
474} psRc2Key_t;
475
476typedef struct {
477 int32 blocklen;
478 unsigned char IV[8];
479 psRc2Key_t key;
480} rc2_CBC;
481#endif /* USE_RC2 */
482/******************************************************************************/
483/* Universal types and defines */
484/******************************************************************************/
485#define MAXBLOCKSIZE 24
486
487typedef union {
488#ifdef USE_RC2
489 rc2_CBC rc2;
490#endif
491#ifdef USE_ARC4
492 psRc4Key_t arc4;
493#endif
494#ifdef USE_3DES
495 des3_CBC des3;
496#endif
497#ifdef USE_AES
498 psAesCipher_t aes;
499#endif
500#ifdef USE_SEED
501 seed_CBC seed;
502#endif
503#ifdef USE_IDEA
504 idea_CBC idea;
505#endif
506} psCipherContext_t;
507
508#define byte(x, n) (((x) >> (8 * (n))) & 255)
509
510#endif /* _h_PS_SYMMETRIC */
511/******************************************************************************/
diff --git a/networking/wget.c b/networking/wget.c
index a5369be22..85a04eaba 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -135,7 +135,8 @@
135 135
136//usage:#define wget_trivial_usage 136//usage:#define wget_trivial_usage
137//usage: IF_FEATURE_WGET_LONG_OPTIONS( 137//usage: IF_FEATURE_WGET_LONG_OPTIONS(
138//usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header 'HEADER: VALUE'] [-Y on/off]\n" 138//usage: "[-cqS] [--spider] [-O FILE] [-o LOGFILE] [--header STR]\n"
139//usage: " [--post-data STR | --post-file FILE] [-Y on/off]\n"
139/* Since we ignore these opts, we don't show them in --help */ 140/* Since we ignore these opts, we don't show them in --help */
140/* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */ 141/* //usage: " [--no-cache] [--passive-ftp] [-t TRIES]" */
141/* //usage: " [-nv] [-nc] [-nH] [-np]" */ 142/* //usage: " [-nv] [-nc] [-nH] [-np]" */
@@ -148,6 +149,9 @@
148//usage: "Retrieve files via HTTP or FTP\n" 149//usage: "Retrieve files via HTTP or FTP\n"
149//usage: IF_FEATURE_WGET_LONG_OPTIONS( 150//usage: IF_FEATURE_WGET_LONG_OPTIONS(
150//usage: "\n --spider Only check URL existence: $? is 0 if exists" 151//usage: "\n --spider Only check URL existence: $? is 0 if exists"
152//usage: "\n --header STR Add STR (of form 'header: value') to headers"
153//usage: "\n --post-data STR Send STR using POST method"
154//usage: "\n --post-file FILE Send FILE using POST method"
151//usage: IF_FEATURE_WGET_OPENSSL( 155//usage: IF_FEATURE_WGET_OPENSSL(
152//usage: "\n --no-check-certificate Don't validate the server's certificate" 156//usage: "\n --no-check-certificate Don't validate the server's certificate"
153//usage: ) 157//usage: )
@@ -244,6 +248,7 @@ struct globals {
244 char *dir_prefix; 248 char *dir_prefix;
245#if ENABLE_FEATURE_WGET_LONG_OPTIONS 249#if ENABLE_FEATURE_WGET_LONG_OPTIONS
246 char *post_data; 250 char *post_data;
251 char *post_file;
247 char *extra_headers; 252 char *extra_headers;
248 unsigned char user_headers; /* Headers mentioned by the user */ 253 unsigned char user_headers; /* Headers mentioned by the user */
249#endif 254#endif
@@ -292,10 +297,13 @@ enum {
292 WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 297 WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
293 WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 298 WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
294 WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 299 WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
300 WGET_OPT_POST_FILE = (1 << 15) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
295 /* hijack this bit for other than opts purposes: */ 301 /* hijack this bit for other than opts purposes: */
296 WGET_NO_FTRUNCATE = (1 << 31) 302 WGET_NO_FTRUNCATE = (1 << 31)
297}; 303};
298 304
305#define WGET_OPT_POST (WGET_OPT_POST_DATA | WGET_OPT_POST_FILE)
306
299enum { 307enum {
300 PROGRESS_START = -1, 308 PROGRESS_START = -1,
301 PROGRESS_END = 0, 309 PROGRESS_END = 0,
@@ -1246,7 +1254,7 @@ static void download_one_url(const char *url)
1246 target.path); 1254 target.path);
1247 } else { 1255 } else {
1248 SENDFMT(sfp, "%s /%s HTTP/1.1\r\n", 1256 SENDFMT(sfp, "%s /%s HTTP/1.1\r\n",
1249 (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET", 1257 (option_mask32 & WGET_OPT_POST) ? "POST" : "GET",
1250 target.path); 1258 target.path);
1251 } 1259 }
1252 if (!USR_HEADER_HOST) 1260 if (!USR_HEADER_HOST)
@@ -1279,7 +1287,13 @@ static void download_one_url(const char *url)
1279 fputs(G.extra_headers, sfp); 1287 fputs(G.extra_headers, sfp);
1280 } 1288 }
1281 1289
1282 if (option_mask32 & WGET_OPT_POST_DATA) { 1290 if (option_mask32 & WGET_OPT_POST_FILE) {
1291 int fd = xopen_stdin(G.post_file);
1292 G.post_data = xmalloc_read(fd, NULL);
1293 close(fd);
1294 }
1295
1296 if (G.post_data) {
1283 SENDFMT(sfp, 1297 SENDFMT(sfp,
1284 "Content-Type: application/x-www-form-urlencoded\r\n" 1298 "Content-Type: application/x-www-form-urlencoded\r\n"
1285 "Content-Length: %u\r\n" 1299 "Content-Length: %u\r\n"
@@ -1522,6 +1536,7 @@ IF_DESKTOP( "tries\0" Required_argument "t")
1522 "post-data\0" Required_argument "\xfe" 1536 "post-data\0" Required_argument "\xfe"
1523 "spider\0" No_argument "\xfd" 1537 "spider\0" No_argument "\xfd"
1524 "no-check-certificate\0" No_argument "\xfc" 1538 "no-check-certificate\0" No_argument "\xfc"
1539 "post-file\0" Required_argument "\xfb"
1525 /* Ignored (we always use PASV): */ 1540 /* Ignored (we always use PASV): */
1526IF_DESKTOP( "passive-ftp\0" No_argument "\xf0") 1541IF_DESKTOP( "passive-ftp\0" No_argument "\xf0")
1527 /* Ignored (we don't support caching) */ 1542 /* Ignored (we don't support caching) */
@@ -1565,6 +1580,9 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1565 */ 1580 */
1566 "\0" 1581 "\0"
1567 "-1" /* at least one URL */ 1582 "-1" /* at least one URL */
1583 IF_FEATURE_WGET_LONG_OPTIONS(":\xfe--\xfb")
1584 IF_FEATURE_WGET_LONG_OPTIONS(":\xfe--\xfe")
1585 IF_FEATURE_WGET_LONG_OPTIONS(":\xfb--\xfb")
1568 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */ 1586 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */
1569 LONGOPTS 1587 LONGOPTS
1570 , &G.fname_out, &G.fname_log, &G.dir_prefix, 1588 , &G.fname_out, &G.fname_log, &G.dir_prefix,
@@ -1574,6 +1592,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1574 NULL /* -n[ARG] */ 1592 NULL /* -n[ARG] */
1575 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist) 1593 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
1576 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data) 1594 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
1595 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_file)
1577 ); 1596 );
1578#if 0 /* option bits debug */ 1597#if 0 /* option bits debug */
1579 if (option_mask32 & WGET_OPT_RETRIES) bb_error_msg("-t NUM"); 1598 if (option_mask32 & WGET_OPT_RETRIES) bb_error_msg("-t NUM");
@@ -1582,6 +1601,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1582 if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data"); 1601 if (option_mask32 & WGET_OPT_POST_DATA) bb_error_msg("--post-data");
1583 if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider"); 1602 if (option_mask32 & WGET_OPT_SPIDER) bb_error_msg("--spider");
1584 if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate"); 1603 if (option_mask32 & WGET_OPT_NO_CHECK_CERT) bb_error_msg("--no-check-certificate");
1604 if (option_mask32 & WGET_OPT_POST_FILE) bb_error_msg("--post-file");
1585 exit(0); 1605 exit(0);
1586#endif 1606#endif
1587 argv += optind; 1607 argv += optind;
diff --git a/procps/Config.src b/procps/Config.src
index 2b1b8ab11..7fcce98c5 100644
--- a/procps/Config.src
+++ b/procps/Config.src
@@ -5,7 +5,12 @@
5 5
6menu "Process Utilities" 6menu "Process Utilities"
7 7
8INSERT 8config FEATURE_FAST_TOP
9 bool "Faster /proc scanning code (+100 bytes)"
10 default n # all "fast or small" options default to small
11 help
12 This option makes top and ps ~20% faster (or 20% less CPU hungry),
13 but code size is slightly bigger.
9 14
10config FEATURE_SHOW_THREADS 15config FEATURE_SHOW_THREADS
11 bool "Support thread display in ps/pstree/top" 16 bool "Support thread display in ps/pstree/top"
@@ -15,4 +20,6 @@ config FEATURE_SHOW_THREADS
15 Enables the ps -T option, showing of threads in pstree, 20 Enables the ps -T option, showing of threads in pstree,
16 and 'h' command in top. 21 and 'h' command in top.
17 22
23INSERT
24
18endmenu 25endmenu
diff --git a/procps/powertop.c b/procps/powertop.c
index fc6018b7a..24c2b320f 100644
--- a/procps/powertop.c
+++ b/procps/powertop.c
@@ -505,7 +505,7 @@ static void cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
505 unsigned int *edx) 505 unsigned int *edx)
506{ 506{
507 /* EAX value specifies what information to return */ 507 /* EAX value specifies what information to return */
508 __asm__( 508 asm (
509 " pushl %%ebx\n" /* Save EBX */ 509 " pushl %%ebx\n" /* Save EBX */
510 " cpuid\n" 510 " cpuid\n"
511 " movl %%ebx, %1\n" /* Save content of EBX */ 511 " movl %%ebx, %1\n" /* Save content of EBX */
diff --git a/procps/ps.c b/procps/ps.c
index 801a6fdf3..4c6e07e8b 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -451,17 +451,19 @@ static void parse_o(char* opt)
451 opt = comma + 1; 451 opt = comma + 1;
452 continue; 452 continue;
453 } 453 }
454 break; 454 // opt points to last spec in comma separated list.
455 } 455 // This one can have =HEADER part.
456 // opt points to last spec in comma separated list. 456 new = new_out_t();
457 // This one can have =HEADER part. 457 if (equal)
458 new = new_out_t(); 458 *equal = '\0';
459 if (equal) 459 *new = *find_out_spec(opt);
460 *equal = '\0'; 460 if (!equal)
461 *new = *find_out_spec(opt); 461 break;
462 if (equal) { 462 *equal++ = '=';
463 *equal = '='; 463 new->header = equal;
464 new->header = equal + 1; 464 comma = strchr(equal, ',');
465 if (comma)
466 *comma = '\0';
465 // POSIX: the field widths shall be ... at least as wide as 467 // POSIX: the field widths shall be ... at least as wide as
466 // the header text (default or overridden value). 468 // the header text (default or overridden value).
467 // If the header text is null, such as -o user=, 469 // If the header text is null, such as -o user=,
@@ -469,10 +471,12 @@ static void parse_o(char* opt)
469 // default header text 471 // default header text
470 if (new->header[0]) { 472 if (new->header[0]) {
471 new->width = strlen(new->header); 473 new->width = strlen(new->header);
472 print_header = 1;
473 } 474 }
474 } else 475 if (!comma)
475 print_header = 1; 476 break;
477 //*comma = ','; /* no, new->header should stay NUL-terminated */
478 opt = comma + 1;
479 }
476} 480}
477 481
478static void alloc_line_buffer(void) 482static void alloc_line_buffer(void)
diff --git a/shell/ash.c b/shell/ash.c
index 9214982c1..98da20f8a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -351,19 +351,6 @@ typedef long arith_t;
351# error "Do not even bother, ash will not run on NOMMU machine" 351# error "Do not even bother, ash will not run on NOMMU machine"
352#endif 352#endif
353 353
354/* We use a trick to have more optimized code (fewer pointer reloads):
355 * ash.c: extern struct globals *const ash_ptr_to_globals;
356 * ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
357 * This way, compiler in ash.c knows the pointer can not change.
358 *
359 * However, this may break on weird arches or toolchains. In this case,
360 * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
361 * this optimization.
362 */
363#ifndef BB_GLOBAL_CONST
364# define BB_GLOBAL_CONST const
365#endif
366
367#if ENABLE_PLATFORM_MINGW32 354#if ENABLE_PLATFORM_MINGW32
368# define FORKSHELL_DEBUG 0 355# define FORKSHELL_DEBUG 0
369 356
@@ -693,8 +680,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
693#endif 680#endif
694 681
695#define INIT_G_misc() do { \ 682#define INIT_G_misc() do { \
696 (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ 683 XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \
697 barrier(); \
698 savestatus = -1; \ 684 savestatus = -1; \
699 curdir = nullstr; \ 685 curdir = nullstr; \
700 physdir = nullstr; \ 686 physdir = nullstr; \
@@ -1783,8 +1769,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1783#define g_stacknleft (G_memstack.g_stacknleft) 1769#define g_stacknleft (G_memstack.g_stacknleft)
1784#define stackbase (G_memstack.stackbase ) 1770#define stackbase (G_memstack.stackbase )
1785#define INIT_G_memstack() do { \ 1771#define INIT_G_memstack() do { \
1786 (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ 1772 XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \
1787 barrier(); \
1788 g_stackp = &stackbase; \ 1773 g_stackp = &stackbase; \
1789 g_stacknxt = stackbase.space; \ 1774 g_stacknxt = stackbase.space; \
1790 g_stacknleft = MINSIZE; \ 1775 g_stacknleft = MINSIZE; \
@@ -2445,8 +2430,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2445#endif 2430#endif
2446#define INIT_G_var() do { \ 2431#define INIT_G_var() do { \
2447 unsigned i; \ 2432 unsigned i; \
2448 (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ 2433 XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \
2449 barrier(); \
2450 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ 2434 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2451 varinit[i].flags = varinit_data[i].flags; \ 2435 varinit[i].flags = varinit_data[i].flags; \
2452 varinit[i].var_text = varinit_data[i].var_text; \ 2436 varinit[i].var_text = varinit_data[i].var_text; \
@@ -7840,14 +7824,19 @@ subevalvar(char *start, char *str, int strloc,
7840 if ((unsigned)len > (orig_len - pos)) 7824 if ((unsigned)len > (orig_len - pos))
7841 len = orig_len - pos; 7825 len = orig_len - pos;
7842 7826
7843 for (vstr = startp; pos; vstr++, pos--) { 7827 if (!quotes) {
7844 if (quotes && (unsigned char)*vstr == CTLESC) 7828 loc = mempcpy(startp, startp + pos, len);
7829 } else {
7830 for (vstr = startp; pos != 0; pos--) {
7831 if ((unsigned char)*vstr == CTLESC)
7832 vstr++;
7845 vstr++; 7833 vstr++;
7846 } 7834 }
7847 for (loc = startp; len; len--) { 7835 for (loc = startp; len != 0; len--) {
7848 if (quotes && (unsigned char)*vstr == CTLESC) 7836 if ((unsigned char)*vstr == CTLESC)
7837 *loc++ = *vstr++;
7849 *loc++ = *vstr++; 7838 *loc++ = *vstr++;
7850 *loc++ = *vstr++; 7839 }
7851 } 7840 }
7852 *loc = '\0'; 7841 *loc = '\0';
7853 goto out; 7842 goto out;
@@ -7901,7 +7890,7 @@ subevalvar(char *start, char *str, int strloc,
7901#if BASH_PATTERN_SUBST 7890#if BASH_PATTERN_SUBST
7902 workloc = expdest - (char *)stackblock(); 7891 workloc = expdest - (char *)stackblock();
7903 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 7892 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7904 size_t no_meta_len; 7893 size_t no_meta_len, first_escaped;
7905 int len; 7894 int len;
7906 char *idx, *end; 7895 char *idx, *end;
7907 7896
@@ -7919,28 +7908,34 @@ subevalvar(char *start, char *str, int strloc,
7919 if (str[0] == '\0') 7908 if (str[0] == '\0')
7920 goto out1; 7909 goto out1;
7921 7910
7922 no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); 7911 first_escaped = (str[0] == '\\' && str[1]);
7912 /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
7913 * as literal too (as it is semi-common, and easy to accomodate
7914 * by just using str + 1).
7915 */
7916 no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str);
7923 len = 0; 7917 len = 0;
7924 idx = startp; 7918 idx = startp;
7925 end = str - 1; 7919 end = str - 1;
7926 while (idx <= end) { 7920 while (idx <= end) {
7927 try_to_match: 7921 try_to_match:
7928 if (no_meta_len == 0) { 7922 if (no_meta_len == 0) {
7929 /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ 7923 /* pattern has meta chars, have to glob */
7930 loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); 7924 loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
7931 } else { 7925 } else {
7932 /* Testcase for very slow replace (performs about 22k replaces): 7926 /* Testcase for very slow replace (performs about 22k replaces):
7933 * x=:::::::::::::::::::::: 7927 * x=::::::::::::::::::::::
7934 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} 7928 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
7935 * echo "${x//:/|}" 7929 * echo "${x//:/|}"
7930 * To test "first_escaped" logic, replace : with *.
7936 */ 7931 */
7937 if (strncmp(rmesc, str, no_meta_len) != 0) 7932 if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0)
7938 goto no_match; 7933 goto no_match;
7939 loc = idx; 7934 loc = idx;
7940 if (!quotes) { 7935 if (!quotes) {
7941 loc += no_meta_len; 7936 loc += no_meta_len - first_escaped;
7942 } else { 7937 } else {
7943 size_t n = no_meta_len; 7938 size_t n = no_meta_len - first_escaped;
7944 do { 7939 do {
7945 if ((unsigned char)*loc == CTLESC) 7940 if ((unsigned char)*loc == CTLESC)
7946 loc++; 7941 loc++;
@@ -11811,14 +11806,14 @@ static void freestrings(struct strpush *sp)
11811 INT_OFF; 11806 INT_OFF;
11812 do { 11807 do {
11813 struct strpush *psp; 11808 struct strpush *psp;
11814 11809#if ENABLE_ASH_ALIAS
11815 if (sp->ap) { 11810 if (sp->ap) {
11816 sp->ap->flag &= ~ALIASINUSE; 11811 sp->ap->flag &= ~ALIASINUSE;
11817 if (sp->ap->flag & ALIASDEAD) { 11812 if (sp->ap->flag & ALIASDEAD) {
11818 unalias(sp->ap->name); 11813 unalias(sp->ap->name);
11819 } 11814 }
11820 } 11815 }
11821 11816#endif
11822 psp = sp; 11817 psp = sp;
11823 sp = sp->spfree; 11818 sp = sp->spfree;
11824 11819
@@ -15497,7 +15492,7 @@ init(void)
15497 15492
15498 15493
15499//usage:#define ash_trivial_usage 15494//usage:#define ash_trivial_usage
15500//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" 15495//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
15501//////// comes from ^^^^^^^^^^optletters 15496//////// comes from ^^^^^^^^^^optletters
15502//usage:#define ash_full_usage "\n\n" 15497//usage:#define ash_full_usage "\n\n"
15503//usage: "Unix shell interpreter" 15498//usage: "Unix shell interpreter"
@@ -15764,13 +15759,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
15764 } 15759 }
15765 state2: 15760 state2:
15766 state = 3; 15761 state = 3;
15767 if ( 15762 if (iflag
15768#if ENABLE_PLATFORM_POSIX 15763#if ENABLE_PLATFORM_POSIX
15769#ifndef linux 15764#ifndef linux
15770 getuid() == geteuid() && getgid() == getegid() && 15765 && getuid() == geteuid() && getgid() == getegid()
15771#endif 15766#endif
15772#endif 15767#endif
15773 iflag
15774 ) { 15768 ) {
15775 const char *shinit = lookupvar("ENV"); 15769 const char *shinit = lookupvar("ENV");
15776 if (shinit != NULL && *shinit != '\0') 15770 if (shinit != NULL && *shinit != '\0')
diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right
index c95ce02bf..5cd4ba6b4 100644
--- a/shell/ash_test/ash-arith/arith-postinc.right
+++ b/shell/ash_test/ash-arith/arith-postinc.right
@@ -2,4 +2,7 @@
21 1 21 1
31 1 31 1
41 1 41 1
56 6
67 7
77 7
5Ok:0 8Ok:0
diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests
index 3fd9bfed5..f2ae778df 100755
--- a/shell/ash_test/ash-arith/arith-postinc.tests
+++ b/shell/ash_test/ash-arith/arith-postinc.tests
@@ -2,4 +2,8 @@ echo 1 $((0++1))
2echo 1 $((0--1)) 2echo 1 $((0--1))
3x=-1; echo 1 $((0-$x)) 3x=-1; echo 1 $((0-$x))
4x=+1; echo 1 $((0+$x)) 4x=+1; echo 1 $((0+$x))
5a=3
6echo 6 $((a+++3)) # a++ + 3
7echo 7 $(((a)+++3)) # a + + + 3
8echo 7 $(((a)+++3)) # a + + + 3
5echo Ok:$? 9echo Ok:$?
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right
index 6936f1269..61fcab55e 100644
--- a/shell/ash_test/ash-arith/arith.right
+++ b/shell/ash_test/ash-arith/arith.right
@@ -43,40 +43,60 @@ Format: 'expected actual'
434 4 434 4
4429 29 4429 29
455 5 455 5
46unary plus, minus
46-4 -4 47-4 -4
474 4 484 4
49conditional expressions
481 1 501 1
4932 32 5132 32
5032 32 5232 32
511 1 531 1
521 1 541 1
5332 32 5532 32
56check that the unevaluated part of the ternary operator does not do evaluation or assignment
5420 20 5720 20
5530 30 5830 30
5620 20 5920 20
5730 30 6030 30
58./arith.tests: line 117: arithmetic syntax error 61check precedence of assignment vs. conditional operator
62./arith.tests: line 116: arithmetic syntax error
63check precedence of assignment vs. conditional operator
64associativity of assignment-operator operator
596 6 656 6
606,5,3 6,5,3 666,5,3 6,5,3
67octal, hex
61263 263 68263 263
62255 255 69255 255
6340 40 7040 40
64./arith.tests: line 163: arithmetic syntax error 71other bases
65./arith.tests: line 165: divide by zero 7210 10
66./arith.tests: let: line 166: arithmetic syntax error 7310 10
67./arith.tests: line 167: arithmetic syntax error 7410 10
68./arith.tests: let: line 168: arithmetic syntax error 7510 10
7610 10
7710 10
7836 36
7936 36
8062 62
8163 63
82missing number after base
830 0
84./arith.tests: line 162: arithmetic syntax error
85./arith.tests: line 164: divide by zero
86./arith.tests: let: line 165: arithmetic syntax error
87./arith.tests: line 166: arithmetic syntax error
88./arith.tests: let: line 167: arithmetic syntax error
69abc 89abc
70def 90def
71ghi 91ghi
72./arith.tests: line 191: arithmetic syntax error 92./arith.tests: line 190: arithmetic syntax error
7316 16 9316 16
74./arith.tests: line 196: arithmetic syntax error 94./arith.tests: line 195: arithmetic syntax error
75./arith.tests: line 197: malformed ?: operator 95./arith.tests: line 196: malformed ?: operator
76./arith.tests: line 198: arithmetic syntax error 96./arith.tests: line 197: arithmetic syntax error
779 9 979 9
78./arith.tests: line 205: arithmetic syntax error 98./arith.tests: line 204: arithmetic syntax error
79./arith.tests: line 208: arithmetic syntax error 99./arith.tests: line 207: arithmetic syntax error
809 9 1009 9
819 9 1019 9
829 9 1029 9
@@ -97,14 +117,17 @@ ghi
973 3 1173 3
984 4 1184 4
994 4 1194 4
100./arith.tests: line 257: arithmetic syntax error 1207 7
121./arith.tests: line 256: arithmetic syntax error
122./arith.tests: line 258: arithmetic syntax error
101./arith.tests: line 259: arithmetic syntax error 123./arith.tests: line 259: arithmetic syntax error
102./arith.tests: line 260: arithmetic syntax error 124./arith.tests: line 261: arithmetic syntax error
103./arith.tests: line 262: arithmetic syntax error 125./arith.tests: line 262: arithmetic syntax error
104./arith.tests: line 263: arithmetic syntax error
1054 4 1264 4
1067 7 1277 7
107-7 -7 128-7 -7
1297
1307
108./arith1.sub: line 2: arithmetic syntax error 131./arith1.sub: line 2: arithmetic syntax error
109./arith1.sub: line 3: arithmetic syntax error 132./arith1.sub: line 3: arithmetic syntax error
110./arith1.sub: line 4: arithmetic syntax error 133./arith1.sub: line 4: arithmetic syntax error
@@ -119,11 +142,12 @@ ghi
1192 2 1422 2
120-2 -2 143-2 -2
1211 1 1441 1
122./arith1.sub: line 37: arithmetic syntax error 1457
123./arith2.sub: line 2: arithmetic syntax error 1467
124./arith2.sub: line 3: arithmetic syntax error 1477
125./arith2.sub: line 4: arithmetic syntax error 1487
126./arith2.sub: line 5: arithmetic syntax error 1497
1507
1275 5 1515 5
1281 1 1521 1
1296 6 1536 6
@@ -132,11 +156,17 @@ ghi
1321 1 1561 1
1334 4 1574 4
1340 0 1580 0
135./arith2.sub: line 42: arithmetic syntax error 159-7
136./arith2.sub: line 47: arithmetic syntax error 160-7
1617
1627
163-7 -7
164-7 -7
1657 7
1667 7
1378 12 1678 12
138./arith.tests: line 290: arithmetic syntax error 168./arith.tests: line 289: arithmetic syntax error
13942 16942
14042 17042
14142 17142
142./arith.tests: line 302: a[b[c]d]=e: not found 172./arith.tests: line 301: a[b[c]d]=e: not found
diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests
index d65758e7d..b9cb8ba4c 100755
--- a/shell/ash_test/ash-arith/arith.tests
+++ b/shell/ash_test/ash-arith/arith.tests
@@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 ))
75echo 29 $(( iv += (jv + 9))) 75echo 29 $(( iv += (jv + 9)))
76echo 5 $(( (iv + 4) % 7 )) 76echo 5 $(( (iv + 4) % 7 ))
77 77
78# unary plus, minus 78echo unary plus, minus
79echo -4 $(( +4 - 8 )) 79echo -4 $(( +4 - 8 ))
80echo 4 $(( -4 + 8 )) 80echo 4 $(( -4 + 8 ))
81 81
82# conditional expressions 82echo conditional expressions
83echo 1 $(( 4<5 ? 1 : 32)) 83echo 1 $(( 4<5 ? 1 : 32))
84echo 32 $(( 4>5 ? 1 : 32)) 84echo 32 $(( 4>5 ? 1 : 32))
85echo 32 $(( 4>(2+3) ? 1 : 32)) 85echo 32 $(( 4>(2+3) ? 1 : 32))
@@ -87,8 +87,7 @@ echo 1 $(( 4<(2+3) ? 1 : 32))
87echo 1 $(( (2+2)<(2+3) ? 1 : 32)) 87echo 1 $(( (2+2)<(2+3) ? 1 : 32))
88echo 32 $(( (2+2)>(2+3) ? 1 : 32)) 88echo 32 $(( (2+2)>(2+3) ? 1 : 32))
89 89
90# check that the unevaluated part of the ternary operator does not do 90echo check that the unevaluated part of the ternary operator does not do evaluation or assignment
91# evaluation or assignment
92x=i+=2 91x=i+=2
93y=j+=2 92y=j+=2
94#ash# declare -i i=1 j=1 93#ash# declare -i i=1 j=1
@@ -109,20 +108,20 @@ echo 20 $((1 ? 20 : (x+=2)))
109echo 30 $((0 ? (y+=2) : 30)) 108echo 30 $((0 ? (y+=2) : 30))
110#ash# echo $i,$y # ash mishandles this 109#ash# echo $i,$y # ash mishandles this
111 110
112# check precedence of assignment vs. conditional operator 111echo check precedence of assignment vs. conditional operator
113# should be an error 112# should be an error
114#ash# declare -i x=2 113#ash# declare -i x=2
115 x=2 114 x=2
116#ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: 115#ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash:
117( y=$((1 ? 20 : x+=2)) ) 116( y=$((1 ? 20 : x+=2)) )
118 117
119# check precedence of assignment vs. conditional operator 118echo check precedence of assignment vs. conditional operator
120#ash# declare -i x=2 119#ash# declare -i x=2
121 x=2 120 x=2
122# ash says "line NNN: syntax error: 0 ? x+=2 : 20" 121# ash says "line NNN: syntax error: 0 ? x+=2 : 20"
123#ash# echo 20 $((0 ? x+=2 : 20)) 122#ash# echo 20 $((0 ? x+=2 : 20))
124 123
125# associativity of assignment-operator operator 124echo associativity of assignment-operator operator
126#ash# declare -i i=1 j=2 k=3 125#ash# declare -i i=1 j=2 k=3
127i=1 126i=1
128j=2 127j=2
@@ -130,7 +129,7 @@ k=3
130echo 6 $((i += j += k)) 129echo 6 $((i += j += k))
131echo 6,5,3 $i,$j,$k 130echo 6,5,3 $i,$j,$k
132 131
133# octal, hex 132echo octal, hex
134echo 263 $(( 0x100 | 007 )) 133echo 263 $(( 0x100 | 007 ))
135echo 255 $(( 0xff )) 134echo 255 $(( 0xff ))
136#ash# echo 255 $(( 16#ff )) 135#ash# echo 255 $(( 16#ff ))
@@ -139,25 +138,25 @@ echo 255 $(( 0xff ))
139 138
140echo 40 $(( 8 ^ 32 )) 139echo 40 $(( 8 ^ 32 ))
141 140
142#ash# # other bases 141echo other bases
143#ash# echo 10 $(( 16#a )) 142echo 10 $(( 16#a ))
144#ash# echo 10 $(( 32#a )) 143echo 10 $(( 32#a ))
145#ash# echo 10 $(( 56#a )) 144echo 10 $(( 56#a ))
146#ash# echo 10 $(( 64#a )) 145echo 10 $(( 64#a ))
147#ash# 146
148#ash# echo 10 $(( 16#A )) 147echo 10 $(( 16#A ))
149#ash# echo 10 $(( 32#A )) 148echo 10 $(( 32#A ))
150#ash# echo 36 $(( 56#A )) 149echo 36 $(( 56#A ))
151#ash# echo 36 $(( 64#A )) 150echo 36 $(( 64#A ))
152#ash# 151
153#ash# echo 62 $(( 64#@ )) 152echo 62 $(( 64#@ ))
154#ash# echo 63 $(( 64#_ )) 153echo 63 $(( 64#_ ))
155 154
156#ash# # weird bases (error) 155#ash# # weird bases (error)
157#ash# echo $(( 3425#56 )) 156#ash# echo $(( 3425#56 ))
158 157
159#ash# # missing number after base 158echo missing number after base
160#ash# echo 0 $(( 2# )) 159echo 0 $(( 2# ))
161 160
162# these should generate errors 161# these should generate errors
163( echo $(( 7 = 43 )) ) 162( echo $(( 7 = 43 )) )
@@ -252,8 +251,8 @@ echo 3 $x
252echo 4 $(( ++x )) 251echo 4 $(( ++x ))
253echo 4 $x 252echo 4 $x
254 253
255# bash 3.2 apparently thinks that ++7 is 7 254# ++ is not a inc operator on non-variable, it is the + + sequence
256#ash# echo 7 $(( ++7 )) 255echo 7 $(( ++7 ))
257( echo $(( 7-- )) ) 256( echo $(( 7-- )) )
258 257
259( echo $(( --x=7 )) ) 258( echo $(( --x=7 )) )
@@ -267,9 +266,9 @@ echo 4 $x
267echo 7 $(( +7 )) 266echo 7 $(( +7 ))
268echo -7 $(( -7 )) 267echo -7 $(( -7 ))
269 268
270# bash 3.2 apparently thinks that ++7 is 7 269# ++ is not a inc operator on non-variable, it is the + + sequence
271#ash# echo $(( ++7 )) 270echo $(( ++7 ))
272#ash# echo $(( --7 )) 271echo $(( --7 ))
273 272
274${THIS_SH} ./arith1.sub 273${THIS_SH} ./arith1.sub
275${THIS_SH} ./arith2.sub 274${THIS_SH} ./arith2.sub
diff --git a/shell/ash_test/ash-arith/arith1.sub b/shell/ash_test/ash-arith/arith1.sub
index 80aa99922..a36785c67 100755
--- a/shell/ash_test/ash-arith/arith1.sub
+++ b/shell/ash_test/ash-arith/arith1.sub
@@ -35,6 +35,6 @@ echo 1 $a
35 35
36#ash# (( ++ )) 36#ash# (( ++ ))
37( echo $(( +++7 )) ) 37( echo $(( +++7 )) )
38# bash 3.2 apparently thinks that ++ +7 is 7 38# ++ is not a inc operator on non-variable, it is the + + sequence
39#ash# echo $(( ++ + 7 )) 39echo $(( ++ + 7 ))
40#ash# (( -- )) 40#ash# (( -- ))
diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub
index 9105059db..8d7918114 100755
--- a/shell/ash_test/ash-arith/arith2.sub
+++ b/shell/ash_test/ash-arith/arith2.sub
@@ -1,4 +1,4 @@
1# bash 3.2 apparently thinks that ++7 is 7 etc 1# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences
2( echo $(( --7 )) ) 2( echo $(( --7 )) )
3( echo $(( ++7 )) ) 3( echo $(( ++7 )) )
4( echo $(( -- 7 )) ) 4( echo $(( -- 7 )) )
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a ))
37echo 0 $a 37echo 0 $a
38 38
39#ash# (( -- )) 39#ash# (( -- ))
40# bash 3.2 apparently thinks that ---7 is -7 40# -- is not a dec operator on non-variable, it is the - - sequence
41#ash# echo $(( ---7 )) 41echo $(( ---7 ))
42( echo $(( -- - 7 )) ) 42( echo $(( -- - 7 )) )
43 43
44#ash# (( ++ )) 44#ash# (( ++ ))
45# bash 3.2: 7 45# ++ is not a inc operator on non-variable, it is the + + sequence
46#ash# echo 7 $(( ++7 )) 46echo $(( ++7 ))
47( echo $(( ++ + 7 )) ) 47( echo $(( ++ + 7 )) )
48 48
49# bash 3.2: -7 49echo -7 $(( ++-7 ))
50#ash# echo -7 $(( ++-7 )) 50echo -7 $(( ++ - 7 ))
51# bash 3.2: -7
52#ash# echo -7 $(( ++ - 7 ))
53 51
54# bash 3.2: 7 52echo 7 $(( +--7 ))
55#ash# echo 7 $(( +--7 )) 53echo 7 $(( -- + 7 ))
56# bash 3.2: 7
57#ash# echo 7 $(( -- + 7 ))
diff --git a/shell/ash_test/ash-comm/comm.right b/shell/ash_test/ash-comm/comm.right
new file mode 100644
index 000000000..1d836656f
--- /dev/null
+++ b/shell/ash_test/ash-comm/comm.right
@@ -0,0 +1,6 @@
1./SCRIPT.sh:
2 /proc/N/comm: SCRIPT.sh
3exec ./SCRIPT.sh:
4 /proc/N/comm: SCRIPT.sh
5sh ./SCRIPT.sh:
6 /proc/N/comm: ash
diff --git a/shell/ash_test/ash-comm/comm.tests b/shell/ash_test/ash-comm/comm.tests
new file mode 100755
index 000000000..671bfc176
--- /dev/null
+++ b/shell/ash_test/ash-comm/comm.tests
@@ -0,0 +1,20 @@
1{
2echo "#!$THIS_SH"
3echo 'procdir=/proc/$$'
4#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"'
5echo 'echo " /proc/N/comm: $(cat $procdir/comm)"'
6} >SCRIPT.sh
7chmod 755 SCRIPT.sh
8
9# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
10echo './SCRIPT.sh:'
11./SCRIPT.sh
12
13# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
14echo 'exec ./SCRIPT.sh:'
15(exec ./SCRIPT.sh)
16
17echo 'sh ./SCRIPT.sh:'
18$THIS_SH ./SCRIPT.sh
19
20rm SCRIPT.sh
diff --git a/shell/hush.c b/shell/hush.c
index 6d472337f..6a27b1634 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -339,7 +339,7 @@
339 * therefore we don't show them either. 339 * therefore we don't show them either.
340 */ 340 */
341//usage:#define hush_trivial_usage 341//usage:#define hush_trivial_usage
342//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" 342//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
343//usage:#define hush_full_usage "\n\n" 343//usage:#define hush_full_usage "\n\n"
344//usage: "Unix shell interpreter" 344//usage: "Unix shell interpreter"
345 345
@@ -373,7 +373,7 @@
373# define F_DUPFD_CLOEXEC F_DUPFD 373# define F_DUPFD_CLOEXEC F_DUPFD
374#endif 374#endif
375 375
376#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) 376#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH
377# include "embedded_scripts.h" 377# include "embedded_scripts.h"
378#else 378#else
379# define NUM_SCRIPTS 0 379# define NUM_SCRIPTS 0
@@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n)
3360 * NEXT points past the terminator of the first element, and REST 3360 * NEXT points past the terminator of the first element, and REST
3361 * points past the final }. We will accumulate result names from 3361 * points past the final }. We will accumulate result names from
3362 * recursive runs for each brace alternative in the buffer using 3362 * recursive runs for each brace alternative in the buffer using
3363 * GLOB_APPEND. */ 3363 * GLOB_APPEND. */
3364 3364
3365 p = begin + 1; 3365 p = begin + 1;
3366 while (1) { 3366 while (1) {
@@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int
6311 6311
6312/* Expanding ARG in ${var+ARG}, ${var-ARG} 6312/* Expanding ARG in ${var+ARG}, ${var-ARG}
6313 */ 6313 */
6314static int encode_then_append_var_plusminus(o_string *output, int n, 6314static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n,
6315 char *str, int dquoted) 6315 char *str, int dquoted)
6316{ 6316{
6317 struct in_str input; 6317 struct in_str input;
@@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
6472/* ${var/[/]pattern[/repl]} helpers */ 6472/* ${var/[/]pattern[/repl]} helpers */
6473static char *strstr_pattern(char *val, const char *pattern, int *size) 6473static char *strstr_pattern(char *val, const char *pattern, int *size)
6474{ 6474{
6475 int sz = strcspn(pattern, "*?[\\"); 6475 int first_escaped = (pattern[0] == '\\' && pattern[1]);
6476 if (pattern[sz] == '\0') { 6476 /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
6477 * as literal too (as it is semi-common, and easy to accomodate
6478 * by just using str + 1).
6479 */
6480 int sz = strcspn(pattern + first_escaped * 2, "*?[\\");
6481 if ((pattern + first_escaped * 2)[sz] == '\0') {
6477 /* Optimization for trivial patterns. 6482 /* Optimization for trivial patterns.
6478 * Testcase for very slow replace (performs about 22k replaces): 6483 * Testcase for very slow replace (performs about 22k replaces):
6479 * x=:::::::::::::::::::::: 6484 * x=::::::::::::::::::::::
6480 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} 6485 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
6481 * echo "${x//:/|}" 6486 * echo "${x//:/|}"
6482 */ 6487 */
6483 *size = sz; 6488 *size = sz + first_escaped;
6484 return strstr(val, pattern); 6489 return strstr(val, pattern + first_escaped);
6485 } 6490 }
6486 6491
6487 while (1) { 6492 while (1) {
@@ -10220,7 +10225,7 @@ int hush_main(int argc, char **argv)
10220 10225
10221 cached_getpid = getpid(); /* for tcsetpgrp() during init */ 10226 cached_getpid = getpid(); /* for tcsetpgrp() during init */
10222 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ 10227 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */
10223 G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ 10228 G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */
10224 10229
10225 /* Deal with HUSH_VERSION */ 10230 /* Deal with HUSH_VERSION */
10226 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); 10231 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
@@ -10351,6 +10356,29 @@ int hush_main(int argc, char **argv)
10351 /* Well, we cannot just declare interactiveness, 10356 /* Well, we cannot just declare interactiveness,
10352 * we have to have some stuff (ctty, etc) */ 10357 * we have to have some stuff (ctty, etc) */
10353 /* G_interactive_fd++; */ 10358 /* G_interactive_fd++; */
10359//There are a few cases where bash -i -c 'SCRIPT'
10360//has visible effect (differs from bash -c 'SCRIPT'):
10361//it ignores TERM:
10362// bash -i -c 'kill $$; echo ALIVE'
10363// ALIVE
10364//it resets SIG_INGed HUP to SIG_DFL:
10365// trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE'
10366// Hangup [the message is not printed by bash, it's the shell which started it]
10367//is talkative about jobs and exiting:
10368// bash -i -c 'sleep 1 & exit'
10369// [1] 16170
10370// exit
10371//includes $ENV file (only if run as "sh"):
10372// echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE'
10373// last: cannot open /var/log/wtmp: No such file or directory
10374// HERE
10375//(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i).
10376//
10377//ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting
10378//(this may be a bug, bash does not do this).
10379//(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed)
10380//
10381//None of the above feel like useful features people would rely on.
10354 break; 10382 break;
10355 case 's': 10383 case 's':
10356 G.opt_s = 1; 10384 G.opt_s = 1;
@@ -11727,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv)
11727 /* TODO: bash prints a string representation 11755 /* TODO: bash prints a string representation
11728 * of job being foregrounded (like "sleep 1 | cat") */ 11756 * of job being foregrounded (like "sleep 1 | cat") */
11729 if (argv[0][0] == 'f' && G_saved_tty_pgrp) { 11757 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
11730 /* Put the job into the foreground. */ 11758 /* Put the job into the foreground. */
11731 tcsetpgrp(G_interactive_fd, pi->pgrp); 11759 tcsetpgrp(G_interactive_fd, pi->pgrp);
11732 } 11760 }
11733 11761
diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right
index c95ce02bf..5cd4ba6b4 100644
--- a/shell/hush_test/hush-arith/arith-postinc.right
+++ b/shell/hush_test/hush-arith/arith-postinc.right
@@ -2,4 +2,7 @@
21 1 21 1
31 1 31 1
41 1 41 1
56 6
67 7
77 7
5Ok:0 8Ok:0
diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests
index 3fd9bfed5..f2ae778df 100755
--- a/shell/hush_test/hush-arith/arith-postinc.tests
+++ b/shell/hush_test/hush-arith/arith-postinc.tests
@@ -2,4 +2,8 @@ echo 1 $((0++1))
2echo 1 $((0--1)) 2echo 1 $((0--1))
3x=-1; echo 1 $((0-$x)) 3x=-1; echo 1 $((0-$x))
4x=+1; echo 1 $((0+$x)) 4x=+1; echo 1 $((0+$x))
5a=3
6echo 6 $((a+++3)) # a++ + 3
7echo 7 $(((a)+++3)) # a + + + 3
8echo 7 $(((a)+++3)) # a + + + 3
5echo Ok:$? 9echo Ok:$?
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right
index c48e468a5..a8612295e 100644
--- a/shell/hush_test/hush-arith/arith.right
+++ b/shell/hush_test/hush-arith/arith.right
@@ -70,6 +70,19 @@ octal, hex
70263 263 70263 263
71255 255 71255 255
7240 40 7240 40
73other bases
7410 10
7510 10
7610 10
7710 10
7810 10
7910 10
8036 36
8136 36
8262 62
8363 63
84missing number after base
850 0
73hush: arithmetic syntax error 86hush: arithmetic syntax error
74hush: divide by zero 87hush: divide by zero
75hush: can't execute 'let': No such file or directory 88hush: can't execute 'let': No such file or directory
@@ -106,6 +119,7 @@ hush: arithmetic syntax error
1063 3 1193 3
1074 4 1204 4
1084 4 1214 4
1227 7
109hush: arithmetic syntax error 123hush: arithmetic syntax error
110hush: arithmetic syntax error 124hush: arithmetic syntax error
111hush: arithmetic syntax error 125hush: arithmetic syntax error
@@ -114,6 +128,8 @@ hush: arithmetic syntax error
1144 4 1284 4
1157 7 1297 7
116-7 -7 130-7 -7
1317
1327
117hush: arithmetic syntax error 133hush: arithmetic syntax error
118hush: arithmetic syntax error 134hush: arithmetic syntax error
119hush: arithmetic syntax error 135hush: arithmetic syntax error
@@ -128,11 +144,12 @@ hush: arithmetic syntax error
1282 2 1442 2
129-2 -2 145-2 -2
1301 1 1461 1
131hush: arithmetic syntax error 1477
132hush: arithmetic syntax error 1487
133hush: arithmetic syntax error 1497
134hush: arithmetic syntax error 1507
135hush: arithmetic syntax error 1517
1527
1365 5 1535 5
1371 1 1541 1
1386 6 1556 6
@@ -141,8 +158,14 @@ hush: arithmetic syntax error
1411 1 1581 1
1424 4 1594 4
1430 0 1600 0
144hush: arithmetic syntax error 161-7
145hush: arithmetic syntax error 162-7
1637
1647
165-7 -7
166-7 -7
1677 7
1687 7
1468 12 1698 12
147hush: arithmetic syntax error 170hush: arithmetic syntax error
14842 17142
diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests
index bc6b341d1..6b707486c 100755
--- a/shell/hush_test/hush-arith/arith.tests
+++ b/shell/hush_test/hush-arith/arith.tests
@@ -142,25 +142,25 @@ echo 255 $(( 0xff ))
142 142
143echo 40 $(( 8 ^ 32 )) 143echo 40 $(( 8 ^ 32 ))
144 144
145#ash# # other bases 145echo other bases
146#ash# echo 10 $(( 16#a )) 146echo 10 $(( 16#a ))
147#ash# echo 10 $(( 32#a )) 147echo 10 $(( 32#a ))
148#ash# echo 10 $(( 56#a )) 148echo 10 $(( 56#a ))
149#ash# echo 10 $(( 64#a )) 149echo 10 $(( 64#a ))
150#ash# 150
151#ash# echo 10 $(( 16#A )) 151echo 10 $(( 16#A ))
152#ash# echo 10 $(( 32#A )) 152echo 10 $(( 32#A ))
153#ash# echo 36 $(( 56#A )) 153echo 36 $(( 56#A ))
154#ash# echo 36 $(( 64#A )) 154echo 36 $(( 64#A ))
155#ash# 155
156#ash# echo 62 $(( 64#@ )) 156echo 62 $(( 64#@ ))
157#ash# echo 63 $(( 64#_ )) 157echo 63 $(( 64#_ ))
158 158
159#ash# # weird bases (error) 159#ash# # weird bases (error)
160#ash# echo $(( 3425#56 )) 160#ash# echo $(( 3425#56 ))
161 161
162#ash# # missing number after base 162echo missing number after base
163#ash# echo 0 $(( 2# )) 163echo 0 $(( 2# ))
164 164
165# these should generate errors 165# these should generate errors
166( echo $(( 7 = 43 )) ) 166( echo $(( 7 = 43 )) )
@@ -255,8 +255,8 @@ echo 3 $x
255echo 4 $(( ++x )) 255echo 4 $(( ++x ))
256echo 4 $x 256echo 4 $x
257 257
258# bash 3.2 apparently thinks that ++7 is 7 258# ++ is not a inc operator on non-variable, it is the + + sequence
259#ash# echo 7 $(( ++7 )) 259echo 7 $(( ++7 ))
260( echo $(( 7-- )) ) 260( echo $(( 7-- )) )
261 261
262( echo $(( --x=7 )) ) 262( echo $(( --x=7 )) )
@@ -270,9 +270,9 @@ echo 4 $x
270echo 7 $(( +7 )) 270echo 7 $(( +7 ))
271echo -7 $(( -7 )) 271echo -7 $(( -7 ))
272 272
273# bash 3.2 apparently thinks that ++7 is 7 273# ++ is not a inc operator on non-variable, it is the + + sequence
274#ash# echo $(( ++7 )) 274echo $(( ++7 ))
275#ash# echo $(( --7 )) 275echo $(( --7 ))
276 276
277${THIS_SH} ./arith1.sub 277${THIS_SH} ./arith1.sub
278${THIS_SH} ./arith2.sub 278${THIS_SH} ./arith2.sub
diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub
index 80aa99922..a36785c67 100755
--- a/shell/hush_test/hush-arith/arith1.sub
+++ b/shell/hush_test/hush-arith/arith1.sub
@@ -35,6 +35,6 @@ echo 1 $a
35 35
36#ash# (( ++ )) 36#ash# (( ++ ))
37( echo $(( +++7 )) ) 37( echo $(( +++7 )) )
38# bash 3.2 apparently thinks that ++ +7 is 7 38# ++ is not a inc operator on non-variable, it is the + + sequence
39#ash# echo $(( ++ + 7 )) 39echo $(( ++ + 7 ))
40#ash# (( -- )) 40#ash# (( -- ))
diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub
index 9105059db..8d7918114 100755
--- a/shell/hush_test/hush-arith/arith2.sub
+++ b/shell/hush_test/hush-arith/arith2.sub
@@ -1,4 +1,4 @@
1# bash 3.2 apparently thinks that ++7 is 7 etc 1# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences
2( echo $(( --7 )) ) 2( echo $(( --7 )) )
3( echo $(( ++7 )) ) 3( echo $(( ++7 )) )
4( echo $(( -- 7 )) ) 4( echo $(( -- 7 )) )
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a ))
37echo 0 $a 37echo 0 $a
38 38
39#ash# (( -- )) 39#ash# (( -- ))
40# bash 3.2 apparently thinks that ---7 is -7 40# -- is not a dec operator on non-variable, it is the - - sequence
41#ash# echo $(( ---7 )) 41echo $(( ---7 ))
42( echo $(( -- - 7 )) ) 42( echo $(( -- - 7 )) )
43 43
44#ash# (( ++ )) 44#ash# (( ++ ))
45# bash 3.2: 7 45# ++ is not a inc operator on non-variable, it is the + + sequence
46#ash# echo 7 $(( ++7 )) 46echo $(( ++7 ))
47( echo $(( ++ + 7 )) ) 47( echo $(( ++ + 7 )) )
48 48
49# bash 3.2: -7 49echo -7 $(( ++-7 ))
50#ash# echo -7 $(( ++-7 )) 50echo -7 $(( ++ - 7 ))
51# bash 3.2: -7
52#ash# echo -7 $(( ++ - 7 ))
53 51
54# bash 3.2: 7 52echo 7 $(( +--7 ))
55#ash# echo 7 $(( +--7 )) 53echo 7 $(( -- + 7 ))
56# bash 3.2: 7
57#ash# echo 7 $(( -- + 7 ))
diff --git a/shell/hush_test/hush-comm/comm.right b/shell/hush_test/hush-comm/comm.right
new file mode 100644
index 000000000..1b62b617e
--- /dev/null
+++ b/shell/hush_test/hush-comm/comm.right
@@ -0,0 +1,6 @@
1./SCRIPT.sh:
2 /proc/N/comm: SCRIPT.sh
3exec ./SCRIPT.sh:
4 /proc/N/comm: SCRIPT.sh
5sh ./SCRIPT.sh:
6 /proc/N/comm: hush
diff --git a/shell/hush_test/hush-comm/comm.tests b/shell/hush_test/hush-comm/comm.tests
new file mode 100755
index 000000000..671bfc176
--- /dev/null
+++ b/shell/hush_test/hush-comm/comm.tests
@@ -0,0 +1,20 @@
1{
2echo "#!$THIS_SH"
3echo 'procdir=/proc/$$'
4#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"'
5echo 'echo " /proc/N/comm: $(cat $procdir/comm)"'
6} >SCRIPT.sh
7chmod 755 SCRIPT.sh
8
9# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
10echo './SCRIPT.sh:'
11./SCRIPT.sh
12
13# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
14echo 'exec ./SCRIPT.sh:'
15(exec ./SCRIPT.sh)
16
17echo 'sh ./SCRIPT.sh:'
18$THIS_SH ./SCRIPT.sh
19
20rm SCRIPT.sh
diff --git a/shell/math.c b/shell/math.c
index 2942cdd26..76d22c9bd 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -116,10 +116,6 @@
116#include "libbb.h" 116#include "libbb.h"
117#include "math.h" 117#include "math.h"
118 118
119#define lookupvar (math_state->lookupvar)
120#define setvar (math_state->setvar )
121//#define endofname (math_state->endofname)
122
123typedef unsigned char operator; 119typedef unsigned char operator;
124 120
125/* An operator's token id is a bit of a bitfield. The lower 5 bits are the 121/* An operator's token id is a bit of a bitfield. The lower 5 bits are the
@@ -258,7 +254,7 @@ static const char*
258arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) 254arith_lookup_val(arith_state_t *math_state, var_or_num_t *t)
259{ 255{
260 if (t->var) { 256 if (t->var) {
261 const char *p = lookupvar(t->var); 257 const char *p = math_state->lookupvar(t->var);
262 if (p) { 258 if (p) {
263 remembered_name *cur; 259 remembered_name *cur;
264 remembered_name cur_save; 260 remembered_name cur_save;
@@ -445,16 +441,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
445 441
446 if (top_of_stack->var == NULL) { 442 if (top_of_stack->var == NULL) {
447 /* Hmm, 1=2 ? */ 443 /* Hmm, 1=2 ? */
448//TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8
449 goto err; 444 goto err;
450 } 445 }
451 /* Save to shell variable */ 446 /* Save to shell variable */
452 sprintf(buf, ARITH_FMT, rez); 447 sprintf(buf, ARITH_FMT, rez);
453 setvar(top_of_stack->var, buf); 448 math_state->setvar(top_of_stack->var, buf);
454 /* After saving, make previous value for v++ or v-- */ 449 /* After saving, make previous value for v++ or v-- */
455 if (op == TOK_POST_INC) 450 if (op == TOK_POST_INC)
456 rez--; 451 rez--;
457 else if (op == TOK_POST_DEC) 452 if (op == TOK_POST_DEC)
458 rez++; 453 rez++;
459 } 454 }
460 455
@@ -607,11 +602,9 @@ evaluate_string(arith_state_t *math_state, const char *expr)
607 const char *p; 602 const char *p;
608 operator op; 603 operator op;
609 operator prec; 604 operator prec;
610 char arithval;
611 605
612 expr = skip_whitespace(expr); 606 expr = skip_whitespace(expr);
613 arithval = *expr; 607 if (*expr == '\0') {
614 if (arithval == '\0') {
615 if (expr == start_expr) { 608 if (expr == start_expr) {
616 /* Null expression */ 609 /* Null expression */
617 numstack->val = 0; 610 numstack->val = 0;
@@ -628,6 +621,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
628 * append a closing right paren 621 * append a closing right paren
629 * and let the loop process it */ 622 * and let the loop process it */
630 expr = ptr_to_rparen; 623 expr = ptr_to_rparen;
624//bb_error_msg("expr=')'");
631 continue; 625 continue;
632 } 626 }
633 /* At this point, we're done with the expression */ 627 /* At this point, we're done with the expression */
@@ -635,19 +629,16 @@ evaluate_string(arith_state_t *math_state, const char *expr)
635 /* ...but if there isn't, it's bad */ 629 /* ...but if there isn't, it's bad */
636 goto err; 630 goto err;
637 } 631 }
638 if (numstack->var) {
639 /* expression is $((var)) only, lookup now */
640 errmsg = arith_lookup_val(math_state, numstack);
641 }
642 goto ret; 632 goto ret;
643 } 633 }
644 634
645 p = endofname(expr); 635 p = endofname(expr);
646 if (p != expr) { 636 if (p != expr) {
647 /* Name */ 637 /* Name */
648 size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ 638 size_t var_name_size = (p - expr) + 1; /* +1 for NUL */
649 numstackptr->var = alloca(var_name_size); 639 numstackptr->var = alloca(var_name_size);
650 safe_strncpy(numstackptr->var, expr, var_name_size); 640 safe_strncpy(numstackptr->var, expr, var_name_size);
641//bb_error_msg("var:'%s'", numstackptr->var);
651 expr = p; 642 expr = p;
652 num: 643 num:
653 numstackptr->second_val_present = 0; 644 numstackptr->second_val_present = 0;
@@ -656,11 +647,12 @@ evaluate_string(arith_state_t *math_state, const char *expr)
656 continue; 647 continue;
657 } 648 }
658 649
659 if (isdigit(arithval)) { 650 if (isdigit(*expr)) {
660 /* Number */ 651 /* Number */
661 numstackptr->var = NULL; 652 numstackptr->var = NULL;
662 errno = 0; 653 errno = 0;
663 numstackptr->val = strto_arith_t(expr, (char**) &expr); 654 numstackptr->val = strto_arith_t(expr, (char**) &expr);
655//bb_error_msg("val:%lld", numstackptr->val);
664 if (errno) 656 if (errno)
665 numstackptr->val = 0; /* bash compat */ 657 numstackptr->val = 0; /* bash compat */
666 goto num; 658 goto num;
@@ -668,19 +660,26 @@ evaluate_string(arith_state_t *math_state, const char *expr)
668 660
669 /* Should be an operator */ 661 /* Should be an operator */
670 662
671 /* Special case: NUM-- and NUM++ are not recognized if NUM 663 /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized
672 * is a literal number, not a variable. IOW: 664 * only if XYZ is a variable name, not a number or EXPR. IOW:
673 * "a+++v" is a++ + v. 665 * "a+++v" is a++ + v.
666 * "(a)+++7" is ( a ) + + + 7.
674 * "7+++v" is 7 + ++v, not 7++ + v. 667 * "7+++v" is 7 + ++v, not 7++ + v.
668 * "--7" is - - 7, not --7.
669 * "++++a" is + + ++a, not ++ ++a.
675 */ 670 */
676 if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ 671 if ((expr[0] == '+' || expr[0] == '-')
677 && (expr[0] == '+' || expr[0] == '-')
678 && (expr[1] == expr[0]) 672 && (expr[1] == expr[0])
679 ) { 673 ) {
680 //bb_error_msg("special %c%c", expr[0], expr[0]); 674 if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */
681 op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); 675 char next = skip_whitespace(expr + 2)[0];
682 expr += 1; 676 if (!(isalpha(next) || next == '_')) { /* not a ++VAR */
683 goto tok_found1; 677 //bb_error_msg("special %c%c", expr[0], expr[0]);
678 op = (expr[0] == '+' ? TOK_ADD : TOK_SUB);
679 expr++;
680 goto tok_found1;
681 }
682 }
684 } 683 }
685 684
686 p = op_tokens; 685 p = op_tokens;
@@ -749,26 +748,40 @@ evaluate_string(arith_state_t *math_state, const char *expr)
749 * "applied" in this way. 748 * "applied" in this way.
750 */ 749 */
751 prec = PREC(op); 750 prec = PREC(op);
751//bb_error_msg("prec:%02x", prec);
752 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { 752 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
753 /* not left paren or unary */ 753 /* not left paren or unary */
754 if (lasttok != TOK_NUM) { 754 if (lasttok != TOK_NUM) {
755 /* binary op must be preceded by a num */ 755 /* binary op must be preceded by a num */
756 goto err; 756 goto err;
757 } 757 }
758 /* The algorithm employed here is simple: while we don't
759 * hit an open paren nor the bottom of the stack, pop
760 * tokens and apply them */
758 while (stackptr != stack) { 761 while (stackptr != stack) {
759 operator prev_op = *--stackptr; 762 operator prev_op = *--stackptr;
760 if (op == TOK_RPAREN) { 763 if (op == TOK_RPAREN) {
761 /* The algorithm employed here is simple: while we don't 764//bb_error_msg("op == TOK_RPAREN");
762 * hit an open paren nor the bottom of the stack, pop
763 * tokens and apply them */
764 if (prev_op == TOK_LPAREN) { 765 if (prev_op == TOK_LPAREN) {
766//bb_error_msg("prev_op == TOK_LPAREN");
767//bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var);
768 if (numstackptr[-1].var) {
769 /* Expression is (var), lookup now */
770 errmsg = arith_lookup_val(math_state, &numstackptr[-1]);
771 if (errmsg)
772 goto err_with_custom_msg;
773 /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */
774 numstackptr[-1].var = NULL;
775 }
765 /* Any operator directly after a 776 /* Any operator directly after a
766 * close paren should consider itself binary */ 777 * close paren should consider itself binary */
767 lasttok = TOK_NUM; 778 lasttok = TOK_NUM;
768 goto next; 779 goto next;
769 } 780 }
781//bb_error_msg("prev_op != TOK_LPAREN");
770 } else { 782 } else {
771 operator prev_prec = PREC(prev_op); 783 operator prev_prec = PREC(prev_op);
784//bb_error_msg("op != TOK_RPAREN");
772 fix_assignment_prec(prec); 785 fix_assignment_prec(prec);
773 fix_assignment_prec(prev_prec); 786 fix_assignment_prec(prev_prec);
774 if (prev_prec < prec 787 if (prev_prec < prec
@@ -778,6 +791,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
778 break; 791 break;
779 } 792 }
780 } 793 }
794//bb_error_msg("arith_apply(prev_op:%02x)", prev_op);
781 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); 795 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
782 if (errmsg) 796 if (errmsg)
783 goto err_with_custom_msg; 797 goto err_with_custom_msg;
@@ -787,6 +801,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
787 } 801 }
788 802
789 /* Push this operator to the stack and remember it */ 803 /* Push this operator to the stack and remember it */
804//bb_error_msg("push op:%02x", op);
790 *stackptr++ = lasttok = op; 805 *stackptr++ = lasttok = op;
791 next: ; 806 next: ;
792 } /* while (1) */ 807 } /* while (1) */
diff --git a/testsuite/realpath.tests b/testsuite/realpath.tests
new file mode 100755
index 000000000..0e68e0279
--- /dev/null
+++ b/testsuite/realpath.tests
@@ -0,0 +1,45 @@
1#!/bin/sh
2
3# Realpath tests.
4# Copyright 2006 by Natanael Copa <n@tanael.org>
5# Copyright 2021 by Ron Yorston <rmy@pobox.com>
6# Licensed under GPLv2, see file LICENSE in this source tree.
7
8. ./testing.sh
9
10unset LC_ALL
11unset LC_MESSAGES
12unset LANG
13unset LANGUAGE
14
15TESTDIR=realpath_testdir
16TESTLINK1="link1"
17TESTLINK2="link2"
18
19# create the dir and test files
20mkdir -p "./$TESTDIR"
21ln -s "./$TESTDIR/not_file" "./$TESTLINK1"
22ln -s "./$TESTDIR/not_file/not_dir" "./$TESTLINK2"
23
24# shell's $PWD may leave symlinks unresolved.
25# "pwd" may be a built-in and have the same problem.
26# External pwd _can't_ have that problem (current dir on Unix is physical).
27pwd=`which pwd`
28pwd=`$pwd`
29testing "realpath on non-existent absolute path 1" "realpath /not_file" "/not_file\n" "" ""
30testing "realpath on non-existent absolute path 2" "realpath /not_file/" "/not_file\n" "" ""
31testing "realpath on non-existent absolute path 3" "realpath //not_file" "/not_file\n" "" ""
32testing "realpath on non-existent absolute path 4" "realpath /not_dir/not_file 2>&1" "realpath: /not_dir/not_file: No such file or directory\n" "" ""
33
34testing "realpath on non-existent local file 1" "realpath $TESTDIR/not_file" "$pwd/$TESTDIR/not_file\n" "" ""
35testing "realpath on non-existent local file 2" "realpath $TESTDIR/not_dir/not_file 2>&1" "realpath: $TESTDIR/not_dir/not_file: No such file or directory\n" "" ""
36
37testing "realpath on link to non-existent file 1" "realpath $TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" ""
38testing "realpath on link to non-existent file 2" "realpath $TESTLINK2 2>&1" "realpath: $TESTLINK2: No such file or directory\n" "" ""
39testing "realpath on link to non-existent file 3" "realpath ./$TESTLINK1" "$pwd/$TESTDIR/not_file\n" "" ""
40testing "realpath on link to non-existent file 4" "realpath ./$TESTLINK2 2>&1" "realpath: ./$TESTLINK2: No such file or directory\n" "" ""
41
42# clean up
43rm -r "$TESTLINK1" "$TESTLINK2" "$TESTDIR"
44
45exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255))
diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests
index 2e80be5fe..76fa96af9 100755
--- a/testsuite/xxd.tests
+++ b/testsuite/xxd.tests
@@ -31,4 +31,10 @@ testing 'xxd -p with 31 NULs' \
31 '' \ 31 '' \
32 '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' 32 '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
33 33
34testing 'xxd -p -r' \
35 'xxd -p -r' \
36 '01234567765432100123456776543210' \
37 '' \
38 '30313233343536373736353433323130 30313233343536373736353433323130'
39
34exit $FAILCOUNT 40exit $FAILCOUNT
diff --git a/util-linux/chrt.c b/util-linux/chrt.c
index a8701b55f..6799abb2d 100644
--- a/util-linux/chrt.c
+++ b/util-linux/chrt.c
@@ -93,7 +93,7 @@ int chrt_main(int argc UNUSED_PARAM, char **argv)
93 unsigned opt; 93 unsigned opt;
94 struct sched_param sp; 94 struct sched_param sp;
95 char *pid_str; 95 char *pid_str;
96 char *priority = priority; /* for compiler */ 96 char *priority = NULL;
97 const char *current_new; 97 const char *current_new;
98 int policy = SCHED_RR; 98 int policy = SCHED_RR;
99 int ret; 99 int ret;
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index cc5413b40..41cc29f37 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -267,7 +267,7 @@ static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what)
267 * vsync high 267 * vsync high
268 * endmode 268 * endmode
269 */ 269 */
270static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, 270static NOINLINE int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
271 const char *mode) 271 const char *mode)
272{ 272{
273 char *token[2], *p, *s; 273 char *token[2], *p, *s;
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c
index 66e434833..5b7760e8c 100644
--- a/util-linux/fdisk_sun.c
+++ b/util-linux/fdisk_sun.c
@@ -403,7 +403,7 @@ verify_sun_cmp(int *a, int *b)
403 return -1; 403 return -1;
404} 404}
405 405
406static void 406static NOINLINE void
407verify_sun(void) 407verify_sun(void)
408{ 408{
409 unsigned starts[8], lens[8], start, stop; 409 unsigned starts[8], lens[8], start, stop;
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index fe78f6242..76dada983 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -69,7 +69,7 @@
69#define OPT_c (1 << 7) 69#define OPT_c (1 << 7)
70#define OPT_o (1 << 8) 70#define OPT_o (1 << 8)
71 71
72static void reverse(unsigned opt, unsigned cols, const char *filename) 72static void reverse(unsigned opt, const char *filename)
73{ 73{
74 FILE *fp; 74 FILE *fp;
75 char *buf; 75 char *buf;
@@ -77,9 +77,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
77 fp = filename ? xfopen_for_read(filename) : stdin; 77 fp = filename ? xfopen_for_read(filename) : stdin;
78 78
79 while ((buf = xmalloc_fgetline(fp)) != NULL) { 79 while ((buf = xmalloc_fgetline(fp)) != NULL) {
80 char *p = buf; 80 char *p;
81 unsigned cnt = cols;
82 81
82 p = buf;
83 if (!(opt & OPT_p)) { 83 if (!(opt & OPT_p)) {
84 /* skip address */ 84 /* skip address */
85 while (isxdigit(*p)) p++; 85 while (isxdigit(*p)) p++;
@@ -92,9 +92,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
92 } 92 }
93 93
94 /* Process hex bytes optionally separated by whitespace */ 94 /* Process hex bytes optionally separated by whitespace */
95 do { 95 for (;;) {
96 uint8_t val, c; 96 uint8_t val, c;
97 97 nibble1:
98 p = skip_whitespace(p); 98 p = skip_whitespace(p);
99 99
100 c = *p++; 100 c = *p++;
@@ -102,8 +102,19 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
102 val = c - '0'; 102 val = c - '0';
103 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 103 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
104 val = (c|0x20) - ('a' - 10); 104 val = (c|0x20) - ('a' - 10);
105 else 105 else {
106 /* xxd V1.10 is inconsistent here.
107 * echo -e "31 !3 0a 0a" | xxd -r -p
108 * is "10<a0>" (no <cr>) - "!" is ignored,
109 * but
110 * echo -e "31 !!343434\n30 0a" | xxd -r -p
111 * is "10<cr>" - "!!" drops rest of the line.
112 * We will ignore all invalid chars:
113 */
114 if (c != '\0')
115 goto nibble1;
106 break; 116 break;
117 }
107 val <<= 4; 118 val <<= 4;
108 119
109 /* Works the same with xxd V1.10: 120 /* Works the same with xxd V1.10:
@@ -111,6 +122,7 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
111 * echo "31 0 9 32 0a" | xxd -r -p 122 * echo "31 0 9 32 0a" | xxd -r -p
112 * thus allow whitespace even within the byte: 123 * thus allow whitespace even within the byte:
113 */ 124 */
125 nibble2:
114 p = skip_whitespace(p); 126 p = skip_whitespace(p);
115 127
116 c = *p++; 128 c = *p++;
@@ -118,10 +130,23 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
118 val |= c - '0'; 130 val |= c - '0';
119 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 131 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
120 val |= (c|0x20) - ('a' - 10); 132 val |= (c|0x20) - ('a' - 10);
121 else 133 else {
122 break; 134 if (c != '\0') {
135 /* "...3<not_hex_char>..." ignores both chars */
136 goto nibble1;
137 }
138 /* Nibbles can join even through newline:
139 * echo -e "31 3\n2 0a" | xxd -r -p
140 * is "12<cr>".
141 */
142 free(buf);
143 p = buf = xmalloc_fgetline(fp);
144 if (!buf)
145 break;
146 goto nibble2;
147 }
123 putchar(val); 148 putchar(val);
124 } while (!(opt & OPT_p) || --cnt != 0); 149 }
125 free(buf); 150 free(buf);
126 } 151 }
127 //fclose(fp); 152 //fclose(fp);
@@ -174,6 +199,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
174 //BUGGY for /proc/version (unseekable?) 199 //BUGGY for /proc/version (unseekable?)
175 } 200 }
176 201
202 if (opt & OPT_r) {
203 reverse(opt, argv[0]);
204 }
205
177 if (opt & OPT_o) { 206 if (opt & OPT_o) {
178 /* -o accepts negative numbers too */ 207 /* -o accepts negative numbers too */
179 dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); 208 dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0);
@@ -194,10 +223,6 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
194 bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " 223 bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
195 } 224 }
196 225
197 if (opt & OPT_r) {
198 reverse(opt, cols, argv[0]);
199 }
200
201 if (bytes < 1 || bytes >= cols) { 226 if (bytes < 1 || bytes >= cols) {
202 sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" 227 sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX"
203 bb_dump_add(dumper, buf); 228 bb_dump_add(dumper, buf);
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index dbbcbc655..ebdc0c254 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -82,12 +82,12 @@
82//usage:#define mdev_trivial_usage 82//usage:#define mdev_trivial_usage
83//usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }") 83//usage: "[-vS] " IF_FEATURE_MDEV_DAEMON("{ ") "[-s]" IF_FEATURE_MDEV_DAEMON(" | [-df] }")
84//usage:#define mdev_full_usage "\n\n" 84//usage:#define mdev_full_usage "\n\n"
85//usage: " -v verbose\n" 85//usage: " -v Verbose\n"
86//usage: " -S log to syslog too\n" 86//usage: " -S Log to syslog too\n"
87//usage: " -s scan /sys and populate /dev\n" 87//usage: " -s Scan /sys and populate /dev\n"
88//usage: IF_FEATURE_MDEV_DAEMON( 88//usage: IF_FEATURE_MDEV_DAEMON(
89//usage: " -d daemon, listen on netlink\n" 89//usage: " -d Daemon, listen on netlink\n"
90//usage: " -f stay in foreground\n" 90//usage: " -f Run in foreground\n"
91//usage: ) 91//usage: )
92//usage: "\n" 92//usage: "\n"
93//usage: "Bare mdev is a kernel hotplug helper. To activate it:\n" 93//usage: "Bare mdev is a kernel hotplug helper. To activate it:\n"
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 44afdbcff..4e65b6b46 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -589,7 +589,7 @@ static void append_mount_options(char **oldopts, const char *newopts)
589 589
590// Use the mount_options list to parse options into flags. 590// Use the mount_options list to parse options into flags.
591// Also update list of unrecognized options if unrecognized != NULL 591// Also update list of unrecognized options if unrecognized != NULL
592static unsigned long parse_mount_options(char *options, char **unrecognized) 592static unsigned long parse_mount_options(char *options, char **unrecognized, uint32_t *opt)
593{ 593{
594 unsigned long flags = MS_SILENT; 594 unsigned long flags = MS_SILENT;
595 595
@@ -617,6 +617,11 @@ static unsigned long parse_mount_options(char *options, char **unrecognized)
617 flags &= fl; 617 flags &= fl;
618 else 618 else
619 flags |= fl; 619 flags |= fl;
620 /* If we see "-o rw" on command line, it's the same as -w:
621 * "do not try to fall back to RO mounts"
622 */
623 if (fl == ~MS_RDONLY && opt)
624 (*opt) |= OPT_w;
620 goto found; 625 goto found;
621 } 626 }
622 option_str += opt_len + 1; 627 option_str += opt_len + 1;
@@ -1973,7 +1978,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
1973 1978
1974 errno = 0; 1979 errno = 0;
1975 1980
1976 vfsflags = parse_mount_options(mp->mnt_opts, &filteropts); 1981 vfsflags = parse_mount_options(mp->mnt_opts, &filteropts, NULL);
1977 1982
1978 // Treat fstype "auto" as unspecified 1983 // Treat fstype "auto" as unspecified
1979 if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0) 1984 if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0)
@@ -2047,7 +2052,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2047 len, share, 2052 len, share,
2048 share + len + 1 /* "dir1/dir2" */ 2053 share + len + 1 /* "dir1/dir2" */
2049 ); 2054 );
2050 parse_mount_options(unc, &filteropts); 2055 parse_mount_options(unc, &filteropts, NULL);
2051 if (ENABLE_FEATURE_CLEAN_UP) free(unc); 2056 if (ENABLE_FEATURE_CLEAN_UP) free(unc);
2052 } 2057 }
2053 2058
@@ -2073,7 +2078,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
2073// (instead of _numeric_ iface_id) with glibc. 2078// (instead of _numeric_ iface_id) with glibc.
2074// This probably should be fixed in glibc, not here. 2079// This probably should be fixed in glibc, not here.
2075// The workaround is to manually specify correct "ip=ADDR%n" option. 2080// The workaround is to manually specify correct "ip=ADDR%n" option.
2076 parse_mount_options(ip, &filteropts); 2081 parse_mount_options(ip, &filteropts, NULL);
2077 if (ENABLE_FEATURE_CLEAN_UP) free(ip); 2082 if (ENABLE_FEATURE_CLEAN_UP) free(ip);
2078 } 2083 }
2079 2084
@@ -2355,7 +2360,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2355 // Past this point, we are handling either "mount -a [opts]" 2360 // Past this point, we are handling either "mount -a [opts]"
2356 // or "mount [opts] single_param" 2361 // or "mount [opts] single_param"
2357 2362
2358 cmdopt_flags = parse_mount_options(cmdopts, NULL); 2363 cmdopt_flags = parse_mount_options(cmdopts, NULL, &option_mask32);
2359 if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags 2364 if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags
2360 bb_simple_error_msg_and_die(bb_msg_you_must_be_root); 2365 bb_simple_error_msg_and_die(bb_msg_you_must_be_root);
2361 2366
@@ -2429,7 +2434,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2429 continue; 2434 continue;
2430 2435
2431 // Skip noauto and swap anyway 2436 // Skip noauto and swap anyway
2432 if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP)) 2437 if ((parse_mount_options(mtcur->mnt_opts, NULL, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP))
2433 // swap is bogus "fstype", parse_mount_options can't check fstypes 2438 // swap is bogus "fstype", parse_mount_options can't check fstypes
2434 || strcasecmp(mtcur->mnt_type, "swap") == 0 2439 || strcasecmp(mtcur->mnt_type, "swap") == 0
2435 ) { 2440 ) {
@@ -2490,7 +2495,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2490 // exit_group(32) = ? 2495 // exit_group(32) = ?
2491#if 0 2496#if 0
2492 // In case we want to simply skip swap partitions: 2497 // In case we want to simply skip swap partitions:
2493 l = parse_mount_options(mtcur->mnt_opts, NULL); 2498 l = parse_mount_options(mtcur->mnt_opts, NULL, NULL);
2494 if ((l & MOUNT_SWAP) 2499 if ((l & MOUNT_SWAP)
2495 // swap is bogus "fstype", parse_mount_options can't check fstypes 2500 // swap is bogus "fstype", parse_mount_options can't check fstypes
2496 || strcasecmp(mtcur->mnt_type, "swap") == 0 2501 || strcasecmp(mtcur->mnt_type, "swap") == 0
@@ -2500,7 +2505,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
2500#endif 2505#endif
2501 if (nonroot) { 2506 if (nonroot) {
2502 // fstab must have "users" or "user" 2507 // fstab must have "users" or "user"
2503 l = parse_mount_options(mtcur->mnt_opts, NULL); 2508 l = parse_mount_options(mtcur->mnt_opts, NULL, NULL);
2504 if (!(l & MOUNT_USERS)) 2509 if (!(l & MOUNT_USERS))
2505 bb_simple_error_msg_and_die(bb_msg_you_must_be_root); 2510 bb_simple_error_msg_and_die(bb_msg_you_must_be_root);
2506 } 2511 }