From 0ffac1cc22e3e864e64c1e0357ffd127fd1c1b23 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 14:14:19 +0100 Subject: unzip: do not use CDF.extra_len, read local file header. Closes 9536 While at it, shorten many field and variable names. function old new delta unzip_main 2334 2376 +42 Signed-off-by: Denys Vlasenko --- archival/unzip.c | 236 ++++++++++++++++++++++++++------------------------ testsuite/unzip.tests | 4 +- 2 files changed, 125 insertions(+), 115 deletions(-) diff --git a/archival/unzip.c b/archival/unzip.c index 98a71c09d..921493591 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -62,8 +62,8 @@ enum { #if BB_BIG_ENDIAN ZIP_FILEHEADER_MAGIC = 0x504b0304, - ZIP_CDF_MAGIC = 0x504b0102, /* central directory's file header */ - ZIP_CDE_MAGIC = 0x504b0506, /* "end of central directory" record */ + ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ + ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ ZIP_DD_MAGIC = 0x504b0708, #else ZIP_FILEHEADER_MAGIC = 0x04034b50, @@ -91,16 +91,16 @@ typedef union { /* filename follows (not NUL terminated) */ /* extra field follows */ /* data follows */ - } formatted PACKED; + } fmt PACKED; } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ -#define FIX_ENDIANNESS_ZIP(zip_header) \ +#define FIX_ENDIANNESS_ZIP(zip) \ do { if (BB_BIG_ENDIAN) { \ - (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ - (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ - (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ - (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ - (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ + (zip).fmt.crc32 = SWAP_LE32((zip).fmt.crc32 ); \ + (zip).fmt.cmpsize = SWAP_LE32((zip).fmt.cmpsize ); \ + (zip).fmt.ucmpsize = SWAP_LE32((zip).fmt.ucmpsize ); \ + (zip).fmt.filename_len = SWAP_LE16((zip).fmt.filename_len); \ + (zip).fmt.extra_len = SWAP_LE16((zip).fmt.extra_len ); \ }} while (0) #define CDF_HEADER_LEN 42 @@ -118,39 +118,39 @@ typedef union { uint32_t crc32; /* 12-15 */ uint32_t cmpsize; /* 16-19 */ uint32_t ucmpsize; /* 20-23 */ - uint16_t file_name_length; /* 24-25 */ - uint16_t extra_field_length; /* 26-27 */ + uint16_t filename_len; /* 24-25 */ + uint16_t extra_len; /* 26-27 */ uint16_t file_comment_length; /* 28-29 */ uint16_t disk_number_start; /* 30-31 */ - uint16_t internal_file_attributes; /* 32-33 */ - uint32_t external_file_attributes PACKED; /* 34-37 */ + uint16_t internal_attributes; /* 32-33 */ + uint32_t external_attributes PACKED; /* 34-37 */ uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ /* filename follows (not NUL terminated) */ /* extra field follows */ - /* comment follows */ - } formatted PACKED; + /* file comment follows */ + } fmt PACKED; } cdf_header_t; -#define FIX_ENDIANNESS_CDF(cdf_header) \ +#define FIX_ENDIANNESS_CDF(cdf) \ do { if (BB_BIG_ENDIAN) { \ - (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ - (cdf_header).formatted.version_needed = SWAP_LE16((cdf_header).formatted.version_needed); \ - (cdf_header).formatted.method = SWAP_LE16((cdf_header).formatted.method ); \ - (cdf_header).formatted.modtime = SWAP_LE16((cdf_header).formatted.modtime ); \ - (cdf_header).formatted.moddate = SWAP_LE16((cdf_header).formatted.moddate ); \ - (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ - (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ - (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ - (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ - (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ - (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ - (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ + (cdf).fmt.version_made_by = SWAP_LE16((cdf).fmt.version_made_by); \ + (cdf).fmt.version_needed = SWAP_LE16((cdf).fmt.version_needed); \ + (cdf).fmt.method = SWAP_LE16((cdf).fmt.method ); \ + (cdf).fmt.modtime = SWAP_LE16((cdf).fmt.modtime ); \ + (cdf).fmt.moddate = SWAP_LE16((cdf).fmt.moddate ); \ + (cdf).fmt.crc32 = SWAP_LE32((cdf).fmt.crc32 ); \ + (cdf).fmt.cmpsize = SWAP_LE32((cdf).fmt.cmpsize ); \ + (cdf).fmt.ucmpsize = SWAP_LE32((cdf).fmt.ucmpsize ); \ + (cdf).fmt.filename_len = SWAP_LE16((cdf).fmt.filename_len); \ + (cdf).fmt.extra_len = SWAP_LE16((cdf).fmt.extra_len ); \ + (cdf).fmt.file_comment_length = SWAP_LE16((cdf).fmt.file_comment_length); \ + (cdf).fmt.external_attributes = SWAP_LE32((cdf).fmt.external_attributes); \ }} while (0) -#define CDE_HEADER_LEN 16 +#define CDE_LEN 16 typedef union { - uint8_t raw[CDE_HEADER_LEN]; + uint8_t raw[CDE_LEN]; struct { /* uint32_t signature; 50 4b 05 06 */ uint16_t this_disk_no; @@ -159,14 +159,14 @@ typedef union { uint16_t cdf_entries_total; uint32_t cdf_size; uint32_t cdf_offset; - /* uint16_t file_comment_length; */ - /* .ZIP file comment (variable size) */ - } formatted PACKED; -} cde_header_t; + /* uint16_t archive_comment_length; */ + /* archive comment follows */ + } fmt PACKED; +} cde_t; -#define FIX_ENDIANNESS_CDE(cde_header) \ +#define FIX_ENDIANNESS_CDE(cde) \ do { if (BB_BIG_ENDIAN) { \ - (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ + (cde).fmt.cdf_offset = SWAP_LE32((cde).fmt.cdf_offset); \ }} while (0) struct BUG { @@ -175,13 +175,13 @@ struct BUG { * even though the elements are all in the right place. */ char BUG_zip_header_must_be_26_bytes[ - offsetof(zip_header_t, formatted.extra_len) + 2 + offsetof(zip_header_t, fmt.extra_len) + 2 == ZIP_HEADER_LEN ? 1 : -1]; char BUG_cdf_header_must_be_42_bytes[ - offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 + offsetof(cdf_header_t, fmt.relative_offset_of_local_header) + 4 == CDF_HEADER_LEN ? 1 : -1]; - char BUG_cde_header_must_be_16_bytes[ - sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; + char BUG_cde_must_be_16_bytes[ + sizeof(cde_t) == CDE_LEN ? 1 : -1]; }; @@ -207,7 +207,7 @@ enum { zip_fd = 3 }; /* NB: does not preserve file position! */ static uint32_t find_cdf_offset(void) { - cde_header_t cde_header; + cde_t cde; unsigned char *buf; unsigned char *p; off_t end; @@ -228,7 +228,7 @@ static uint32_t find_cdf_offset(void) found = BAD_CDF_OFFSET; p = buf; - while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { + while (p <= buf + PEEK_FROM_END - CDE_LEN - 4) { if (*p != 'P') { p++; continue; @@ -240,19 +240,19 @@ static uint32_t find_cdf_offset(void) if (*++p != 6) continue; /* we found CDE! */ - memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); - FIX_ENDIANNESS_CDE(cde_header); + memcpy(cde.raw, p + 1, CDE_LEN); + FIX_ENDIANNESS_CDE(cde); /* * I've seen .ZIP files with seemingly valid CDEs * where cdf_offset points past EOF - ?? * This check ignores such CDEs: */ - if (cde_header.formatted.cdf_offset < end + (p - buf)) { - found = cde_header.formatted.cdf_offset; + if (cde.fmt.cdf_offset < end + (p - buf)) { + found = cde.fmt.cdf_offset; dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x", (unsigned)found, end + (p-3 - buf)); dbg(" cdf_offset+cdf_size:0x%x", - (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size))); + (unsigned)(found + SWAP_LE32(cde.fmt.cdf_size))); /* * We do not "break" here because only the last CDE is valid. * I've seen a .zip archive which contained a .zip file, @@ -266,7 +266,7 @@ static uint32_t find_cdf_offset(void) return found; }; -static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) +static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf) { uint32_t magic; @@ -276,23 +276,25 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) dbg("Reading CDF at 0x%x", (unsigned)cdf_offset); xlseek(zip_fd, cdf_offset, SEEK_SET); xread(zip_fd, &magic, 4); - /* Central Directory End? */ + /* Central Directory End? Assume CDF has ended. + * (more correct method is to use cde.cdf_entries_total counter) + */ if (magic == ZIP_CDE_MAGIC) { dbg("got ZIP_CDE_MAGIC"); return 0; /* EOF */ } - xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); + xread(zip_fd, cdf->raw, CDF_HEADER_LEN); - FIX_ENDIANNESS_CDF(*cdf_ptr); - dbg(" file_name_length:%u extra_field_length:%u file_comment_length:%u", - (unsigned)cdf_ptr->formatted.file_name_length, - (unsigned)cdf_ptr->formatted.extra_field_length, - (unsigned)cdf_ptr->formatted.file_comment_length + FIX_ENDIANNESS_CDF(*cdf); + dbg(" filename_len:%u extra_len:%u file_comment_length:%u", + (unsigned)cdf->fmt.filename_len, + (unsigned)cdf->fmt.extra_len, + (unsigned)cdf->fmt.file_comment_length ); cdf_offset += 4 + CDF_HEADER_LEN - + cdf_ptr->formatted.file_name_length - + cdf_ptr->formatted.extra_field_length - + cdf_ptr->formatted.file_comment_length; + + cdf->fmt.filename_len + + cdf->fmt.extra_len + + cdf->fmt.file_comment_length; return cdf_offset; }; @@ -315,28 +317,28 @@ static void unzip_create_leading_dirs(const char *fn) free(name); } -static void unzip_extract(zip_header_t *zip_header, int dst_fd) +static void unzip_extract(zip_header_t *zip, int dst_fd) { - if (zip_header->formatted.method == 0) { + if (zip->fmt.method == 0) { /* Method 0 - stored (not compressed) */ - off_t size = zip_header->formatted.ucmpsize; + off_t size = zip->fmt.ucmpsize; if (size) bb_copyfd_exact_size(zip_fd, dst_fd, size); } else { /* Method 8 - inflate */ transformer_state_t xstate; init_transformer_state(&xstate); - xstate.bytes_in = zip_header->formatted.cmpsize; + xstate.bytes_in = zip->fmt.cmpsize; xstate.src_fd = zip_fd; xstate.dst_fd = dst_fd; if (inflate_unzip(&xstate) < 0) bb_error_msg_and_die("inflate error"); /* Validate decompression - crc */ - if (zip_header->formatted.crc32 != (xstate.crc32 ^ 0xffffffffL)) { + if (zip->fmt.crc32 != (xstate.crc32 ^ 0xffffffffL)) { bb_error_msg_and_die("crc error"); } /* Validate decompression - size */ - if (zip_header->formatted.ucmpsize != xstate.bytes_out) { + if (zip->fmt.ucmpsize != xstate.bytes_out) { /* Don't die. Who knows, maybe len calculation * was botched somewhere. After all, crc matched! */ bb_error_msg("bad length"); @@ -563,7 +565,7 @@ int unzip_main(int argc, char **argv) total_entries = 0; cdf_offset = find_cdf_offset(); /* try to seek to the end, find CDE and CDF start */ while (1) { - zip_header_t zip_header; + zip_header_t zip; mode_t dir_mode = 0777; #if ENABLE_FEATURE_UNZIP_CDF mode_t file_mode = 0666; @@ -589,7 +591,7 @@ int unzip_main(int argc, char **argv) /* Check magic number */ xread(zip_fd, &magic, 4); - /* Central directory? It's at the end, so exit */ + /* CDF item? Assume there are no more files, exit */ if (magic == ZIP_CDF_MAGIC) { dbg("got ZIP_CDF_MAGIC"); break; @@ -605,71 +607,74 @@ int unzip_main(int argc, char **argv) bb_error_msg_and_die("invalid zip magic %08X", (int)magic); dbg("got ZIP_FILEHEADER_MAGIC"); - xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); - FIX_ENDIANNESS_ZIP(zip_header); - if ((zip_header.formatted.method != 0) - && (zip_header.formatted.method != 8) + xread(zip_fd, zip.raw, ZIP_HEADER_LEN); + FIX_ENDIANNESS_ZIP(zip); + if ((zip.fmt.method != 0) + && (zip.fmt.method != 8) ) { /* TODO? method 12: bzip2, method 14: LZMA */ - bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); + bb_error_msg_and_die("unsupported method %d", zip.fmt.method); } - if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { + if (zip.fmt.zip_flags & SWAP_LE16(0x0009)) { bb_error_msg_and_die("zip flags 1 and 8 are not supported"); } } #if ENABLE_FEATURE_UNZIP_CDF else { /* cdf_offset is valid (and we know the file is seekable) */ - cdf_header_t cdf_header; - cdf_offset = read_next_cdf(cdf_offset, &cdf_header); + cdf_header_t cdf; + cdf_offset = read_next_cdf(cdf_offset, &cdf); if (cdf_offset == 0) /* EOF? */ break; -# if 0 +# if 1 xlseek(zip_fd, - SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4, + SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4, SEEK_SET); - xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); - FIX_ENDIANNESS_ZIP(zip_header); - if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { + xread(zip_fd, zip.raw, ZIP_HEADER_LEN); + FIX_ENDIANNESS_ZIP(zip); + if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) { /* 0x0008 - streaming. [u]cmpsize can be reliably gotten * only from Central Directory. */ - zip_header.formatted.crc32 = cdf_header.formatted.crc32; - zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; - zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; + zip.fmt.crc32 = cdf.fmt.crc32; + zip.fmt.cmpsize = cdf.fmt.cmpsize; + zip.fmt.ucmpsize = cdf.fmt.ucmpsize; } # else - /* CDF has the same data as local header, no need to read the latter */ - memcpy(&zip_header.formatted.version, - &cdf_header.formatted.version_needed, ZIP_HEADER_LEN); + /* CDF has the same data as local header, no need to read the latter... + * ...not really. An archive was seen with cdf.extra_len == 6 but + * zip.extra_len == 0. + */ + memcpy(&zip.fmt.version, + &cdf.fmt.version_needed, ZIP_HEADER_LEN); xlseek(zip_fd, - SWAP_LE32(cdf_header.formatted.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, + SWAP_LE32(cdf.fmt.relative_offset_of_local_header) + 4 + ZIP_HEADER_LEN, SEEK_SET); # endif - if ((cdf_header.formatted.version_made_by >> 8) == 3) { + if ((cdf.fmt.version_made_by >> 8) == 3) { /* This archive is created on Unix */ - dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); + dir_mode = file_mode = (cdf.fmt.external_attributes >> 16); } } #endif - if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { + if (zip.fmt.zip_flags & SWAP_LE16(0x0001)) { /* 0x0001 - encrypted */ bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); } dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", - (unsigned)zip_header.formatted.cmpsize, - (unsigned)zip_header.formatted.extra_len, - (unsigned)zip_header.formatted.ucmpsize + (unsigned)zip.fmt.cmpsize, + (unsigned)zip.fmt.extra_len, + (unsigned)zip.fmt.ucmpsize ); /* Read filename */ free(dst_fn); - dst_fn = xzalloc(zip_header.formatted.filename_len + 1); - xread(zip_fd, dst_fn, zip_header.formatted.filename_len); + dst_fn = xzalloc(zip.fmt.filename_len + 1); + xread(zip_fd, dst_fn, zip.fmt.filename_len); /* Skip extra header bytes */ - unzip_skip(zip_header.formatted.extra_len); + unzip_skip(zip.fmt.extra_len); /* Guard against "/abspath", "/../" and similar attacks */ overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); @@ -684,32 +689,32 @@ int unzip_main(int argc, char **argv) /* List entry */ char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", - (zip_header.formatted.moddate >> 5) & 0xf, // mm: 0x01e0 - (zip_header.formatted.moddate) & 0x1f, // dd: 0x001f - (zip_header.formatted.moddate >> 9) + 1980, // yy: 0xfe00 - (zip_header.formatted.modtime >> 11), // hh: 0xf800 - (zip_header.formatted.modtime >> 5) & 0x3f // mm: 0x07e0 - // seconds/2 are not shown, encoded in ----------- 0x001f + (zip.fmt.moddate >> 5) & 0xf, // mm: 0x01e0 + (zip.fmt.moddate) & 0x1f, // dd: 0x001f + (zip.fmt.moddate >> 9) + 1980, // yy: 0xfe00 + (zip.fmt.modtime >> 11), // hh: 0xf800 + (zip.fmt.modtime >> 5) & 0x3f // mm: 0x07e0 + // seconds/2 not shown, encoded in -- 0x001f ); if (!verbose) { // " Length Date Time Name\n" // "--------- ---------- ----- ----" printf( "%9u " "%s " "%s\n", - (unsigned)zip_header.formatted.ucmpsize, + (unsigned)zip.fmt.ucmpsize, dtbuf, dst_fn); } else { - unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; + unsigned long percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; if ((int32_t)percents < 0) percents = 0; /* happens if ucmpsize < cmpsize */ percents = percents * 100; - if (zip_header.formatted.ucmpsize) - percents /= zip_header.formatted.ucmpsize; + if (zip.fmt.ucmpsize) + percents /= zip.fmt.ucmpsize; // " Length Method Size Cmpr Date Time CRC-32 Name\n" // "-------- ------ ------- ---- ---------- ----- -------- ----" printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", - (unsigned)zip_header.formatted.ucmpsize, - zip_header.formatted.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ + (unsigned)zip.fmt.ucmpsize, + zip.fmt.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ /* TODO: show other methods? * 1 - Shrunk * 2 - Reduced with compression factor 1 @@ -722,15 +727,16 @@ int unzip_main(int argc, char **argv) * 10 - PKWARE Data Compression Library Imploding * 11 - Reserved by PKWARE * 12 - BZIP2 + * 14 - LZMA */ - (unsigned)zip_header.formatted.cmpsize, + (unsigned)zip.fmt.cmpsize, (unsigned)percents, dtbuf, - zip_header.formatted.crc32, + zip.fmt.crc32, dst_fn); - total_size += zip_header.formatted.cmpsize; + total_size += zip.fmt.cmpsize; } - total_usize += zip_header.formatted.ucmpsize; + total_usize += zip.fmt.ucmpsize; i = 'n'; } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */ @@ -798,9 +804,11 @@ int unzip_main(int argc, char **argv) #endif case -1: /* Unzip */ if (!quiet) { - printf(" inflating: %s\n", dst_fn); + printf(/* zip.fmt.method == 0 + ? " extracting: %s\n" + : */ " inflating: %s\n", dst_fn); } - unzip_extract(&zip_header, dst_fd); + unzip_extract(&zip, dst_fd); if (dst_fd != STDOUT_FILENO) { /* closing STDOUT is potentially bad for future business */ close(dst_fd); @@ -811,7 +819,7 @@ int unzip_main(int argc, char **argv) overwrite = O_NEVER; case 'n': /* Skip entry data */ - unzip_skip(zip_header.formatted.cmpsize); + unzip_skip(zip.fmt.cmpsize); break; case 'r': diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests index d9c45242c..2e4becdb8 100755 --- a/testsuite/unzip.tests +++ b/testsuite/unzip.tests @@ -34,7 +34,9 @@ rm foo.zip optional FEATURE_UNZIP_CDF testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ "Archive: bad.zip -unzip: short read + inflating: ]3j½r«IK-%Ix +unzip: corrupted data +unzip: inflate error 1 " \ "" "\ -- cgit v1.2.3-55-g6feb From a474728e82510aa98995f02ac53ca7207b0baf76 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Sun, 8 Jan 2017 14:27:34 +0100 Subject: ash: fix "kill %1" not working if CONFIG_ASH is disabled ix ash "kill %1" not working if CONFIG_ASH is disabled but ash is launched by 'sh' or 'bash' name Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- procps/kill.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/procps/kill.c b/procps/kill.c index 57a33bcaa..36cd22f37 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -285,7 +285,8 @@ int kill_main(int argc UNUSED_PARAM, char **argv) /* Looks like they want to do a kill. Do that */ while (arg) { -#if ENABLE_ASH || ENABLE_HUSH +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ + || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH /* * We need to support shell's "hack formats" of * " -PRGP_ID" (yes, with a leading space) -- cgit v1.2.3-55-g6feb From d5e7ff02921854e28a9859d443f96900e041ca03 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Sun, 8 Jan 2017 14:31:06 +0100 Subject: bunzip2: fix code bloat caused by zcat's seamless magic This example single-applet configuration would trigger the bloat: CONFIG_FEATURE_SEAMLESS_XZ=y CONFIG_FEATURE_SEAMLESS_LZMA=y CONFIG_FEATURE_SEAMLESS_BZ2=y CONFIG_FEATURE_SEAMLESS_GZ=y CONFIG_BUNZIP2=y # CONFIG_ZCAT is not set # All other applets disabled Here, the resulting "busybox-bunzip2" binary would contain unpack_gz_stream, unpack_lzma_stream and unpack_xz_stream functions code. In other words, the gzip, lzma and xz decompressors' code are linked into the binary unnecessarily. This happens because SEAMLESS_MAGIC != 0 and compiler is unable to figure out that SEAMLESS_MAGIC bit is never set. Fix this by disabling SEAMLESS_MAGIC option flag (setting its value to 0) when zcat is disabled. This will help the compiler optimize out bbunpack() and no longer generate open_zipped() function call. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 60a837e22..0eff58713 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -25,7 +25,7 @@ enum { OPT_QUIET = 1 << 3, OPT_DECOMPRESS = 1 << 4, OPT_TEST = 1 << 5, - SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION, + SEAMLESS_MAGIC = (1 << 31) * ENABLE_ZCAT * SEAMLESS_COMPRESSION, }; static -- cgit v1.2.3-55-g6feb From 4d06b314532f7f52a9d8a5d6b7dcafaf00ff1334 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Sat, 7 Jan 2017 15:16:46 +0800 Subject: build system: no longer prompt for PLATFORM_LINUX option With the new "select PLATFORM_LINUX" mechanism (commit e3b1a1fd28558f7a1b3c0ec33313bedb675be8a1), the PLATFORM_LINUX option alone no longer has any purpose of changing program behavior or affecting compiled code. So there is no longer need to prompt user of this config question. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- Config.in | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Config.in b/Config.in index 924a197da..66f7787d2 100644 --- a/Config.in +++ b/Config.in @@ -50,17 +50,6 @@ config USE_PORTABLE_CODE compiler other than gcc. If you do use gcc, this option may needlessly increase code size. -config PLATFORM_LINUX - bool "Enable Linux-specific applets and features" - default y - help - For the most part, busybox requires only POSIX compatibility - from the target system, but some applets and features use - Linux-specific interfaces. - - Answering 'N' here will disable such applets and hide the - corresponding configuration options. - config SHOW_USAGE bool "Show applet usage messages" default y @@ -338,6 +327,17 @@ config FEATURE_HAVE_RPC # This is automatically selected if any of enabled applets need it. # You do not need to select it manually. +config PLATFORM_LINUX + bool #No description makes it a hidden option + default n + #help + # For the most part, busybox requires only POSIX compatibility + # from the target system, but some applets and features use + # Linux-specific interfaces. + # + # This is automatically selected if any applet or feature requires + # Linux-specific interfaces. You do not need to select it manually. + comment 'Build Options' config STATIC -- cgit v1.2.3-55-g6feb From 0ef478f01bb3d42f6776f58fb5891e1430af8799 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Fri, 6 Jan 2017 22:03:08 +0100 Subject: httpd: fix address family for reverse proxy client socket When httpd proxies a request to another server, it first creates an AF_INET socket, then resolves the server name to a sockaddr, then connects to it. This fails if the server name resolves to an IPv6 address. This patch ensures that the socket is created with the correct address family (AF_INET6 if the server resolves to an IPv6 address and AF_INET otherwise). Signed-off-by: Laurent Bercot Signed-off-by: Denys Vlasenko --- networking/httpd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index d301d598d..cfcd2a06e 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2396,12 +2396,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) int proxy_fd; len_and_sockaddr *lsa; - proxy_fd = socket(AF_INET, SOCK_STREAM, 0); - if (proxy_fd < 0) - send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); lsa = host2sockaddr(proxy_entry->host_port, 80); if (lsa == NULL) send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); + proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); + if (proxy_fd < 0) + send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n", -- cgit v1.2.3-55-g6feb From d5b5c2fa151d318fa96778d5871e23ede312e5fa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 15:46:04 +0100 Subject: hush: support %%, %+ and % jobspec (meaning "current job") function old new delta parse_jobspec 83 133 +50 builtin_wait 278 283 +5 Signed-off-by: Denys Vlasenko --- shell/hush.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index a56d3b280..58132ef17 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -347,7 +347,7 @@ #define ERR_PTR ((void*)(long)1) -#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" +#define JOB_STATUS_FORMAT "[%u] %-22s %.40s\n" #define _SPECIAL_VARS_STR "_*@$!?#" #define SPECIAL_VARS_STR ("_*@$!?#" + 1) @@ -563,7 +563,7 @@ struct pipe { int alive_cmds; /* number of commands running (not exited) */ int stopped_cmds; /* number of commands alive, but stopped */ #if ENABLE_HUSH_JOB - int jobid; /* job number */ + unsigned jobid; /* job number */ pid_t pgrp; /* process group ID for the job */ char *cmdtext; /* name of job */ #endif @@ -740,7 +740,7 @@ struct globals { #endif #if ENABLE_HUSH_JOB int run_list_level; - int last_jobid; + unsigned last_jobid; pid_t saved_tty_pgrp; struct pipe *job_list; # define G_saved_tty_pgrp (G.saved_tty_pgrp) @@ -7043,7 +7043,7 @@ static void insert_bg_job(struct pipe *pi) job->cmdtext = xstrdup(get_cmdtext(pi)); if (G_interactive_fd) - printf("[%d] %d %s\n", job->jobid, job->cmds[0].pid, job->cmdtext); + printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext); G.last_jobid = job->jobid; } @@ -9264,11 +9264,21 @@ static int FAST_FUNC builtin_type(char **argv) static struct pipe *parse_jobspec(const char *str) { struct pipe *pi; - int jobnum; + unsigned jobnum; - if (sscanf(str, "%%%d", &jobnum) != 1) { - bb_error_msg("bad argument '%s'", str); - return NULL; + if (sscanf(str, "%%%u", &jobnum) != 1) { + if (str[0] != '%' + || (str[1] != '%' && str[1] != '+' && str[1] != '\0') + ) { + bb_error_msg("bad argument '%s'", str); + return NULL; + } + /* It is "%%", "%+" or "%" - current job */ + jobnum = G.last_jobid; + if (jobnum == 0) { + bb_error_msg("no current job"); + return NULL; + } } for (pi = G.job_list; pi; pi = pi->next) { if (pi->jobid == jobnum) { @@ -9622,13 +9632,15 @@ static int FAST_FUNC builtin_wait(char **argv) #if ENABLE_HUSH_JOB if (argv[0][0] == '%') { struct pipe *wait_pipe; + ret = 127; /* bash compat for bad jobspecs */ wait_pipe = parse_jobspec(*argv); if (wait_pipe) { ret = job_exited_or_stopped(wait_pipe); if (ret < 0) ret = wait_for_child_or_signal(wait_pipe, 0); - continue; } + /* else: parse_jobspec() already emitted error msg */ + continue; } #endif /* mimic bash message */ -- cgit v1.2.3-55-g6feb From 1125d7d6801940a5218b74c8fd46f1eaa2e4de39 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 17:19:38 +0100 Subject: hush: kill builtin and kill %jobspec support Also made it and printf, type and wait builtins optional. function old new delta builtin_kill - 323 +323 bltins1 336 348 +12 builtin_type 114 116 +2 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 2/0 up/down: 337/0) Total: 337 bytes Signed-off-by: Denys Vlasenko --- coreutils/Kbuild.src | 5 +- procps/Kbuild.src | 2 + procps/kill.c | 4 +- shell/hush.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 138 insertions(+), 7 deletions(-) diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src index d9a448781..9ac6b9e78 100644 --- a/coreutils/Kbuild.src +++ b/coreutils/Kbuild.src @@ -15,11 +15,14 @@ lib-$(CONFIG_LESS) += cat.o # less too lib-$(CONFIG_CRONTAB) += cat.o # crontab -l lib-$(CONFIG_ADDUSER) += chown.o # used by adduser lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser +lib-$(CONFIG_FTPD) += ls.o # used by ftpd + lib-$(CONFIG_ASH) += echo.o # used by ash lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash lib-$(CONFIG_HUSH) += echo.o # used by hush lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush -lib-$(CONFIG_FTPD) += ls.o # used by ftpd + lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o +lib-$(CONFIG_HUSH_PRINTF) += printf.o diff --git a/procps/Kbuild.src b/procps/Kbuild.src index e7adc7340..82f37f0df 100644 --- a/procps/Kbuild.src +++ b/procps/Kbuild.src @@ -11,3 +11,5 @@ INSERT lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash + +lib-$(CONFIG_HUSH_KILL) += kill.o # used for built-in kill by hush diff --git a/procps/kill.c b/procps/kill.c index 36cd22f37..579c8e53c 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -285,8 +285,8 @@ int kill_main(int argc UNUSED_PARAM, char **argv) /* Looks like they want to do a kill. Do that */ while (arg) { -#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ - || ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH +#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ + || ENABLE_HUSH_KILL /* * We need to support shell's "hack formats" of * " -PRGP_ID" (yes, with a leading space) diff --git a/shell/hush.c b/shell/hush.c index 58132ef17..9aafb4d25 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -44,12 +44,12 @@ * special variables (done: PWD, PPID, RANDOM) * tilde expansion * aliases - * kill %jobspec * follow IFS rules more precisely, including update semantics * builtins mandated by standards we don't support: * [un]alias, command, fc, getopts, newgrp, readonly, times * make complex ${var%...} constructs support optional * make here documents optional + * make trap, read, ulimit builtins optional * * Bash compat TODO: * redirection of stdout+stderr: &> and >& @@ -117,6 +117,34 @@ //config: help //config: Enable help builtin in hush. Code size + ~1 kbyte. //config: +//config:config HUSH_PRINTF +//config: bool "printf builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable printf builtin in hush. +//config: +//config:config HUSH_KILL +//config: bool "kill builtin (for kill %jobspec)" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable kill builtin in hush. +//config: +//config:config HUSH_WAIT +//config: bool "wait builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable wait builtin in hush. +//config: +//config:config HUSH_TYPE +//config: bool "type builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable type builtin in hush. +//config: //config:config HUSH_INTERACTIVE //config: bool "Interactive mode" //config: default y @@ -860,7 +888,7 @@ static int builtin_local(char **argv) FAST_FUNC; #if HUSH_DEBUG static int builtin_memleak(char **argv) FAST_FUNC; #endif -#if ENABLE_PRINTF +#if ENABLE_HUSH_PRINTF static int builtin_printf(char **argv) FAST_FUNC; #endif static int builtin_pwd(char **argv) FAST_FUNC; @@ -870,11 +898,18 @@ static int builtin_shift(char **argv) FAST_FUNC; static int builtin_source(char **argv) FAST_FUNC; static int builtin_test(char **argv) FAST_FUNC; static int builtin_trap(char **argv) FAST_FUNC; +#if ENABLE_HUSH_TYPE static int builtin_type(char **argv) FAST_FUNC; +#endif static int builtin_true(char **argv) FAST_FUNC; static int builtin_umask(char **argv) FAST_FUNC; static int builtin_unset(char **argv) FAST_FUNC; +#if ENABLE_HUSH_KILL +static int builtin_kill(char **argv) FAST_FUNC; +#endif +#if ENABLE_HUSH_WAIT static int builtin_wait(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_LOOPS static int builtin_break(char **argv) FAST_FUNC; static int builtin_continue(char **argv) FAST_FUNC; @@ -929,6 +964,9 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_JOB BLTIN("jobs" , builtin_jobs , "List jobs"), #endif +#if ENABLE_HUSH_KILL + BLTIN("kill" , builtin_kill , "Send signals to processes"), +#endif #if ENABLE_HUSH_LOCAL BLTIN("local" , builtin_local , "Set local variables"), #endif @@ -946,18 +984,22 @@ static const struct built_in_command bltins1[] = { #endif BLTIN("trap" , builtin_trap , "Trap signals"), BLTIN("true" , builtin_true , NULL), +#if ENABLE_HUSH_TYPE BLTIN("type" , builtin_type , "Show command type"), +#endif BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), BLTIN("umask" , builtin_umask , "Set file creation mask"), BLTIN("unset" , builtin_unset , "Unset variables"), +#if ENABLE_HUSH_WAIT BLTIN("wait" , builtin_wait , "Wait for process"), +#endif }; /* For now, echo and test are unconditionally enabled. * Maybe make it configurable? */ static const struct built_in_command bltins2[] = { BLTIN("[" , builtin_test , NULL), BLTIN("echo" , builtin_echo , NULL), -#if ENABLE_PRINTF +#if ENABLE_HUSH_PRINTF BLTIN("printf" , builtin_printf , NULL), #endif BLTIN("pwd" , builtin_pwd , NULL), @@ -8689,7 +8731,7 @@ static int FAST_FUNC builtin_echo(char **argv) return run_applet_main(argv, echo_main); } -#if ENABLE_PRINTF +#if ENABLE_HUSH_PRINTF static int FAST_FUNC builtin_printf(char **argv) { return run_applet_main(argv, printf_main); @@ -9227,6 +9269,7 @@ static int FAST_FUNC builtin_trap(char **argv) goto process_sig_list; } +#if ENABLE_HUSH_TYPE /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ static int FAST_FUNC builtin_type(char **argv) { @@ -9259,6 +9302,7 @@ static int FAST_FUNC builtin_type(char **argv) return ret; } +#endif #if ENABLE_HUSH_JOB static struct pipe *parse_jobspec(const char *str) @@ -9526,6 +9570,87 @@ static int FAST_FUNC builtin_umask(char **argv) return !rc; /* rc != 0 - success */ } +#if ENABLE_HUSH_KILL +static int FAST_FUNC builtin_kill(char **argv) +{ + int ret = 0; + + argv = skip_dash_dash(argv); + if (argv[0] && strcmp(argv[0], "-l") != 0) { + int i = 0; + + do { + struct pipe *pi; + char *dst; + int j, n; + + if (argv[i][0] != '%') + continue; + /* + * "kill %N" - job kill + * Converting to pgrp / pid kill + */ + pi = parse_jobspec(argv[i]); + if (!pi) { + /* Eat bad jobspec */ + j = i; + do { + j++; + argv[j - 1] = argv[j]; + } while (argv[j]); + ret = 1; + i--; + continue; + } + /* + * In jobs started under job control, we signal + * entire process group by kill -PGRP_ID. + * This happens, f.e., in interactive shell. + * + * Otherwise, we signal each child via + * kill PID1 PID2 PID3. + * Testcases: + * sh -c 'sleep 1|sleep 1 & kill %1' + * sh -c 'true|sleep 2 & sleep 1; kill %1' + * sh -c 'true|sleep 1 & sleep 2; kill %1' + */ + n = pi->num_cmds; + if (ENABLE_HUSH_JOB && G_interactive_fd) + n = 1; + dst = alloca(n * sizeof(int)*4); + argv[i] = dst; +#if ENABLE_HUSH_JOB + if (G_interactive_fd) + dst += sprintf(dst, " -%u", (int)pi->pgrp); + else +#endif + for (j = 0; j < n; j++) { + struct command *cmd = &pi->cmds[j]; + /* Skip exited members of the job */ + if (cmd->pid == 0) + continue; + /* + * kill_main has matching code to expect + * leading space. Needed to not confuse + * negative pids with "kill -SIGNAL_NO" syntax + */ + dst += sprintf(dst, " %u", (int)cmd->pid); + } + *dst = '\0'; + } while (argv[++i]); + } + + if (argv[0] || ret == 0) { + argv--; + argv[0] = (char*)"kill"; /* why? think about "kill -- PID" */ + /* kill_main also handles "killall" etc, so it does look at argv[0]! */ + ret = run_applet_main(argv, kill_main); + } + return ret; +} +#endif + +#if ENABLE_HUSH_WAIT /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ #if !ENABLE_HUSH_JOB # define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid) @@ -9686,6 +9811,7 @@ static int FAST_FUNC builtin_wait(char **argv) return ret; } +#endif #if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min) -- cgit v1.2.3-55-g6feb From 7a85c60e7e370d0bc171bd10043c1eb7c20ab913 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 17:40:18 +0100 Subject: hush: make read and trap builtins optional Signed-off-by: Denys Vlasenko --- shell/hush.c | 189 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 71 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 9aafb4d25..e6e8c1baf 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -49,7 +49,6 @@ * [un]alias, command, fc, getopts, newgrp, readonly, times * make complex ${var%...} constructs support optional * make here documents optional - * make trap, read, ulimit builtins optional * * Bash compat TODO: * redirection of stdout+stderr: &> and >& @@ -110,41 +109,6 @@ //config: help //config: Enable {abc,def} extension. //config: -//config:config HUSH_HELP -//config: bool "help builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable help builtin in hush. Code size + ~1 kbyte. -//config: -//config:config HUSH_PRINTF -//config: bool "printf builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable printf builtin in hush. -//config: -//config:config HUSH_KILL -//config: bool "kill builtin (for kill %jobspec)" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable kill builtin in hush. -//config: -//config:config HUSH_WAIT -//config: bool "wait builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable wait builtin in hush. -//config: -//config:config HUSH_TYPE -//config: bool "type builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable type builtin in hush. -//config: //config:config HUSH_INTERACTIVE //config: bool "Interactive mode" //config: default y @@ -209,7 +173,7 @@ //config: Enable support for shell functions in hush. +800 bytes. //config: //config:config HUSH_LOCAL -//config: bool "Support local builtin" +//config: bool "local builtin" //config: default y //config: depends on HUSH_FUNCTIONS //config: help @@ -238,6 +202,62 @@ //config: This instructs hush to print commands before execution. //config: Adds ~300 bytes. //config: +//config:config HUSH_HELP +//config: bool "help builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable help builtin in hush. Code size + ~1 kbyte. +//config: +//config:config HUSH_PRINTF +//config: bool "printf builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable printf builtin in hush. +//config: +//config:config HUSH_KILL +//config: bool "kill builtin (for kill %jobspec)" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable kill builtin in hush. +//config: +//config:config HUSH_WAIT +//config: bool "wait builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable wait builtin in hush. +//config: +//config:config HUSH_TRAP +//config: bool "trap builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable trap builtin in hush. +//config: +//config:config HUSH_ULIMIT +//config: bool "ulimit builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable ulimit builtin in hush. +//config: +//config:config HUSH_TYPE +//config: bool "type builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable type builtin in hush. +//config: +//config:config HUSH_READ +//config: bool "read builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable read builtin in hush. +//config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" //config: default n @@ -842,7 +862,12 @@ struct globals { #else # define G_fatal_sig_mask 0 #endif +#if ENABLE_HUSH_TRAP char **traps; /* char *traps[NSIG] */ +# define G_traps G.traps +#else +# define G_traps ((char**)NULL) +#endif sigset_t pending_set; #if HUSH_DEBUG unsigned long memleak_value; @@ -892,12 +917,16 @@ static int builtin_memleak(char **argv) FAST_FUNC; static int builtin_printf(char **argv) FAST_FUNC; #endif static int builtin_pwd(char **argv) FAST_FUNC; +#if ENABLE_HUSH_READ static int builtin_read(char **argv) FAST_FUNC; +#endif static int builtin_set(char **argv) FAST_FUNC; static int builtin_shift(char **argv) FAST_FUNC; static int builtin_source(char **argv) FAST_FUNC; static int builtin_test(char **argv) FAST_FUNC; +#if ENABLE_HUSH_TRAP static int builtin_trap(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_TYPE static int builtin_type(char **argv) FAST_FUNC; #endif @@ -973,7 +1002,9 @@ static const struct built_in_command bltins1[] = { #if HUSH_DEBUG BLTIN("memleak" , builtin_memleak , NULL), #endif +#if ENABLE_HUSH_READ BLTIN("read" , builtin_read , "Input into variable"), +#endif #if ENABLE_HUSH_FUNCTIONS BLTIN("return" , builtin_return , "Return from a function"), #endif @@ -982,12 +1013,16 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_BASH_COMPAT BLTIN("source" , builtin_source , "Run commands in a file"), #endif +#if ENABLE_HUSH_TRAP BLTIN("trap" , builtin_trap , "Trap signals"), +#endif BLTIN("true" , builtin_true , NULL), #if ENABLE_HUSH_TYPE BLTIN("type" , builtin_type , "Show command type"), #endif +#if ENABLE_HUSH_ULIMIT BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), +#endif BLTIN("umask" , builtin_umask , "Set file creation mask"), BLTIN("unset" , builtin_unset , "Unset variables"), #if ENABLE_HUSH_WAIT @@ -1712,13 +1747,13 @@ static void hush_exit(int exitcode) #endif fflush_all(); - if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { + if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) { char *argv[3]; /* argv[0] is unused */ - argv[1] = G.traps[0]; + argv[1] = G_traps[0]; argv[2] = NULL; G.exiting = 1; /* prevent EXIT trap recursion */ - /* Note: G.traps[0] is not cleared! + /* Note: G_traps[0] is not cleared! * "trap" will still show it, if executed * in the handler */ builtin_eval(argv); @@ -1769,14 +1804,14 @@ static int check_and_run_traps(void) } while (sig < NSIG); break; got_sig: - if (G.traps && G.traps[sig]) { + if (G_traps && G_traps[sig]) { debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]); - if (G.traps[sig][0]) { + if (G_traps[sig][0]) { /* We have user-defined handler */ smalluint save_rcode; char *argv[3]; /* argv[0] is unused */ - argv[1] = G.traps[sig]; + argv[1] = G_traps[sig]; argv[2] = NULL; save_rcode = G.last_exitcode; builtin_eval(argv); @@ -5924,13 +5959,15 @@ static void switch_off_special_sigs(unsigned mask) sig++; if (!(mask & 1)) continue; - if (G.traps) { - if (G.traps[sig] && !G.traps[sig][0]) +#if ENABLE_HUSH_TRAP + if (G_traps) { + if (G_traps[sig] && !G_traps[sig][0]) /* trap is '', has to remain SIG_IGN */ continue; - free(G.traps[sig]); - G.traps[sig] = NULL; + free(G_traps[sig]); + G_traps[sig] = NULL; } +#endif /* We are here only if no trap or trap was not '' */ install_sighandler(sig, SIG_DFL); } @@ -5947,7 +5984,7 @@ static void reset_traps_to_defaults(void) /* This function is always called in a child shell * after fork (not vfork, NOMMU doesn't use this function). */ - unsigned sig; + IF_HUSH_TRAP(unsigned sig;) unsigned mask; /* Child shells are not interactive. @@ -5956,35 +5993,37 @@ static void reset_traps_to_defaults(void) * Same goes for SIGTERM, SIGHUP, SIGINT. */ mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask; - if (!G.traps && !mask) + if (!G_traps && !mask) return; /* already no traps and no special sigs */ /* Switch off special sigs */ switch_off_special_sigs(mask); -#if ENABLE_HUSH_JOB +# if ENABLE_HUSH_JOB G_fatal_sig_mask = 0; -#endif +# endif G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS; /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS * remain set in G.special_sig_mask */ - if (!G.traps) +# if ENABLE_HUSH_TRAP + if (!G_traps) return; /* Reset all sigs to default except ones with empty traps */ for (sig = 0; sig < NSIG; sig++) { - if (!G.traps[sig]) + if (!G_traps[sig]) continue; /* no trap: nothing to do */ - if (!G.traps[sig][0]) + if (!G_traps[sig][0]) continue; /* empty trap: has to remain SIG_IGN */ /* sig has non-empty trap, reset it: */ - free(G.traps[sig]); - G.traps[sig] = NULL; + free(G_traps[sig]); + G_traps[sig] = NULL; /* There is no signal for trap 0 (EXIT) */ if (sig == 0) continue; install_sighandler(sig, pick_sighandler(sig)); } +# endif } #else /* !BB_MMU */ @@ -6024,10 +6063,10 @@ static void re_execute_shell(char ***to_free, const char *s, cnt++; empty_trap_mask = 0; - if (G.traps) { + if (G_traps) { int sig; for (sig = 1; sig < NSIG; sig++) { - if (G.traps[sig] && !G.traps[sig][0]) + if (G_traps[sig] && !G_traps[sig][0]) empty_trap_mask |= 1LL << sig; } } @@ -6220,6 +6259,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) xmove_fd(channel[1], 1); /* Prevent it from trying to handle ctrl-z etc */ IF_HUSH_JOB(G.run_list_level = 1;) +# if ENABLE_HUSH_TRAP /* Awful hack for `trap` or $(trap). * * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html @@ -6263,6 +6303,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) fflush_all(); /* important */ _exit(0); } +# endif # if BB_MMU reset_traps_to_defaults(); parse_and_run_string(s); @@ -8160,10 +8201,12 @@ static void install_sighandlers(unsigned mask) if (old_handler == SIG_IGN) { /* oops... restore back to IGN, and record this fact */ install_sighandler(sig, old_handler); - if (!G.traps) - G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); - free(G.traps[sig]); - G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ +#if ENABLE_HUSH_TRAP + if (!G_traps) + G_traps = xzalloc(sizeof(G_traps[0]) * NSIG); + free(G_traps[sig]); + G_traps[sig] = xzalloc(1); /* == xstrdup(""); */ +#endif } } } @@ -8464,10 +8507,10 @@ int hush_main(int argc, char **argv) if (empty_trap_mask != 0) { int sig; install_special_sighandlers(); - G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); + G_traps = xzalloc(sizeof(G_traps[0]) * NSIG); for (sig = 1; sig < NSIG; sig++) { if (empty_trap_mask & (1LL << sig)) { - G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ + G_traps[sig] = xzalloc(1); /* == xstrdup(""); */ install_sighandler(sig, SIG_IGN); } } @@ -9114,6 +9157,7 @@ static int FAST_FUNC builtin_shift(char **argv) return EXIT_FAILURE; } +#if ENABLE_HUSH_READ /* Interruptibility of read builtin in bash * (tested on bash-4.2.8 by sending signals (not by ^C)): * @@ -9178,23 +9222,25 @@ static int FAST_FUNC builtin_read(char **argv) return (uintptr_t)r; } +#endif +#if ENABLE_HUSH_TRAP static int FAST_FUNC builtin_trap(char **argv) { int sig; char *new_cmd; - if (!G.traps) - G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); + if (!G_traps) + G_traps = xzalloc(sizeof(G_traps[0]) * NSIG); argv++; if (!*argv) { int i; /* No args: print all trapped */ for (i = 0; i < NSIG; ++i) { - if (G.traps[i]) { + if (G_traps[i]) { printf("trap -- "); - print_escaped(G.traps[i]); + print_escaped(G_traps[i]); /* note: bash adds "SIG", but only if invoked * as "bash". If called as "sh", or if set -o posix, * then it prints short signal names. @@ -9224,11 +9270,11 @@ static int FAST_FUNC builtin_trap(char **argv) continue; } - free(G.traps[sig]); - G.traps[sig] = xstrdup(new_cmd); + free(G_traps[sig]); + G_traps[sig] = xstrdup(new_cmd); debug_printf("trap: setting SIG%s (%i) to '%s'\n", - get_signame(sig), sig, G.traps[sig]); + get_signame(sig), sig, G_traps[sig]); /* There is no signal for 0 (EXIT) */ if (sig == 0) @@ -9268,6 +9314,7 @@ static int FAST_FUNC builtin_trap(char **argv) argv++; goto process_sig_list; } +#endif #if ENABLE_HUSH_TYPE /* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ -- cgit v1.2.3-55-g6feb From 10d5ece64ae6b2338a13a58340a03ff988d46a85 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 18:28:43 +0100 Subject: hush: make set/unset builtins optional Signed-off-by: Denys Vlasenko --- shell/hush.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index e6e8c1baf..4604240d8 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -258,6 +258,20 @@ //config: help //config: Enable read builtin in hush. //config: +//config:config HUSH_SET +//config: bool "set builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable set builtin in hush. +//config: +//config:config HUSH_UNSET +//config: bool "unset builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable unset builtin in hush. +//config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" //config: default n @@ -920,7 +934,9 @@ static int builtin_pwd(char **argv) FAST_FUNC; #if ENABLE_HUSH_READ static int builtin_read(char **argv) FAST_FUNC; #endif +#if ENABLE_HUSH_SET static int builtin_set(char **argv) FAST_FUNC; +#endif static int builtin_shift(char **argv) FAST_FUNC; static int builtin_source(char **argv) FAST_FUNC; static int builtin_test(char **argv) FAST_FUNC; @@ -932,7 +948,9 @@ static int builtin_type(char **argv) FAST_FUNC; #endif static int builtin_true(char **argv) FAST_FUNC; static int builtin_umask(char **argv) FAST_FUNC; +#if ENABLE_HUSH_UNSET static int builtin_unset(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_KILL static int builtin_kill(char **argv) FAST_FUNC; #endif @@ -1008,7 +1026,9 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_FUNCTIONS BLTIN("return" , builtin_return , "Return from a function"), #endif +#if ENABLE_HUSH_SET BLTIN("set" , builtin_set , "Set/unset positional parameters"), +#endif BLTIN("shift" , builtin_shift , "Shift positional parameters"), #if ENABLE_HUSH_BASH_COMPAT BLTIN("source" , builtin_source , "Run commands in a file"), @@ -1021,10 +1041,12 @@ static const struct built_in_command bltins1[] = { BLTIN("type" , builtin_type , "Show command type"), #endif #if ENABLE_HUSH_ULIMIT - BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), + BLTIN("ulimit" , shell_builtin_ulimit, "Control resource limits"), #endif BLTIN("umask" , builtin_umask , "Set file creation mask"), +#if ENABLE_HUSH_UNSET BLTIN("unset" , builtin_unset , "Unset variables"), +#endif #if ENABLE_HUSH_WAIT BLTIN("wait" , builtin_wait , "Wait for process"), #endif @@ -2107,10 +2129,12 @@ static int unset_local_var_len(const char *name, int name_len) return EXIT_SUCCESS; } +#if ENABLE_HUSH_UNSET static int unset_local_var(const char *name) { return unset_local_var_len(name, strlen(name)); } +#endif static void unset_vars(char **strings) { @@ -6712,6 +6736,7 @@ static struct function *new_function(char *name) return funcp; } +# if ENABLE_HUSH_UNSET static void unset_func(const char *name) { struct function **funcpp = find_function_slot(name); @@ -6727,13 +6752,14 @@ static void unset_func(const char *name) if (funcp->body) { free_pipe_list(funcp->body); free(funcp->name); -# if !BB_MMU +# if !BB_MMU free(funcp->body_as_string); -# endif +# endif } free(funcp); } } +# endif # if BB_MMU #define exec_function(to_free, funcp, argv) \ @@ -9016,6 +9042,7 @@ static int FAST_FUNC builtin_local(char **argv) } #endif +#if ENABLE_HUSH_UNSET /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */ static int FAST_FUNC builtin_unset(char **argv) { @@ -9043,16 +9070,18 @@ static int FAST_FUNC builtin_unset(char **argv) ret = EXIT_FAILURE; } } -#if ENABLE_HUSH_FUNCTIONS +# if ENABLE_HUSH_FUNCTIONS else { unset_func(*argv); } -#endif +# endif argv++; } return ret; } +#endif +#if ENABLE_HUSH_SET /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set * built-in 'set' handler * SUSv3 says: @@ -9135,6 +9164,7 @@ static int FAST_FUNC builtin_set(char **argv) bb_error_msg("set: %s: invalid option", arg); return EXIT_FAILURE; } +#endif static int FAST_FUNC builtin_shift(char **argv) { -- cgit v1.2.3-55-g6feb From d5933b112537f9cb9d6ebb0109a0a38cea71fa63 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 18:31:39 +0100 Subject: hush: make umask builtin optional Signed-off-by: Denys Vlasenko --- shell/hush.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index 4604240d8..a713a9680 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -272,6 +272,13 @@ //config: help //config: Enable unset builtin in hush. //config: +//config:config HUSH_UMASK +//config: bool "umask builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable umask builtin in hush. +//config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" //config: default n @@ -947,7 +954,9 @@ static int builtin_trap(char **argv) FAST_FUNC; static int builtin_type(char **argv) FAST_FUNC; #endif static int builtin_true(char **argv) FAST_FUNC; +#if ENABLE_HUSH_UMASK static int builtin_umask(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_UNSET static int builtin_unset(char **argv) FAST_FUNC; #endif @@ -1043,7 +1052,9 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_ULIMIT BLTIN("ulimit" , shell_builtin_ulimit, "Control resource limits"), #endif +#if ENABLE_HUSH_UMASK BLTIN("umask" , builtin_umask , "Set file creation mask"), +#endif #if ENABLE_HUSH_UNSET BLTIN("unset" , builtin_unset , "Unset variables"), #endif @@ -9610,6 +9621,7 @@ static int FAST_FUNC builtin_source(char **argv) return G.last_exitcode; } +#if ENABLE_HUSH_UMASK static int FAST_FUNC builtin_umask(char **argv) { int rc; @@ -9646,6 +9658,7 @@ static int FAST_FUNC builtin_umask(char **argv) return !rc; /* rc != 0 - success */ } +#endif #if ENABLE_HUSH_KILL static int FAST_FUNC builtin_kill(char **argv) -- cgit v1.2.3-55-g6feb From 6ec76d8719279dbda0b2a98163625b6f2ea013ff Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 18:40:41 +0100 Subject: hush: make export builtin optional Signed-off-by: Denys Vlasenko --- shell/hush.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index a713a9680..153867614 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -187,13 +187,6 @@ //config: Enable pseudorandom generator and dynamic variable "$RANDOM". //config: Each read of "$RANDOM" will generate a new pseudorandom value. //config: -//config:config HUSH_EXPORT_N -//config: bool "Support 'export -n' option" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: export -n unexports variables. It is a bash extension. -//config: //config:config HUSH_MODE_X //config: bool "Support 'hush -x' option and 'set -x' command" //config: default y @@ -202,6 +195,20 @@ //config: This instructs hush to print commands before execution. //config: Adds ~300 bytes. //config: +//config:config HUSH_EXPORT +//config: bool "export builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable export builtin in hush. +//config: +//config:config HUSH_EXPORT_N +//config: bool "Support 'export -n' option" +//config: default y +//config: depends on HUSH_EXPORT +//config: help +//config: export -n unexports variables. It is a bash extension. +//config: //config:config HUSH_HELP //config: bool "help builtin" //config: default y @@ -917,7 +924,9 @@ static int builtin_echo(char **argv) FAST_FUNC; static int builtin_eval(char **argv) FAST_FUNC; static int builtin_exec(char **argv) FAST_FUNC; static int builtin_exit(char **argv) FAST_FUNC; +#if ENABLE_HUSH_EXPORT static int builtin_export(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_JOB static int builtin_fg_bg(char **argv) FAST_FUNC; static int builtin_jobs(char **argv) FAST_FUNC; @@ -1007,7 +1016,9 @@ static const struct built_in_command bltins1[] = { BLTIN("eval" , builtin_eval , "Construct and run shell command"), BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"), BLTIN("exit" , builtin_exit , "Exit"), +#if ENABLE_HUSH_EXPORT BLTIN("export" , builtin_export , "Set environment variables"), +#endif #if ENABLE_HUSH_JOB BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"), #endif @@ -8935,10 +8946,11 @@ static void print_escaped(const char *s) } while (*s); } -#if !ENABLE_HUSH_LOCAL +#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL +# if !ENABLE_HUSH_LOCAL #define helper_export_local(argv, exp, lvl) \ helper_export_local(argv, exp) -#endif +# endif static void helper_export_local(char **argv, int exp, int lvl) { do { @@ -8971,14 +8983,14 @@ static void helper_export_local(char **argv, int exp, int lvl) continue; } } -#if ENABLE_HUSH_LOCAL +# if ENABLE_HUSH_LOCAL if (exp == 0 /* local? */ && var && var->func_nest_level == lvl ) { /* "local x=abc; ...; local x" - ignore second local decl */ continue; } -#endif +# endif /* Exporting non-existing variable. * bash does not put it in environment, * but remembers that it is exported, @@ -8994,7 +9006,9 @@ static void helper_export_local(char **argv, int exp, int lvl) set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0); } while (*++argv); } +#endif +#if ENABLE_HUSH_EXPORT static int FAST_FUNC builtin_export(char **argv) { unsigned opt_unexport; @@ -9040,6 +9054,7 @@ static int FAST_FUNC builtin_export(char **argv) return EXIT_SUCCESS; } +#endif #if ENABLE_HUSH_LOCAL static int FAST_FUNC builtin_local(char **argv) -- cgit v1.2.3-55-g6feb From 4471969db2102df9c97582b6577c7505caf64a34 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 18:44:41 +0100 Subject: hush: make memleak builtin optional Signed-off-by: Denys Vlasenko --- shell/hush.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 153867614..3050aeb8e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -286,6 +286,13 @@ //config: help //config: Enable umask builtin in hush. //config: +//config:config HUSH_MEMLEAK +//config: bool "memleak builtin (debugging)" +//config: default n +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable umask builtin in hush. +//config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" //config: default n @@ -897,8 +904,10 @@ struct globals { # define G_traps ((char**)NULL) #endif sigset_t pending_set; -#if HUSH_DEBUG +#if ENABLE_HUSH_MEMLEAK unsigned long memleak_value; +#endif +#if HUSH_DEBUG int debug_indent; #endif struct sigaction sa; @@ -940,7 +949,7 @@ static int builtin_history(char **argv) FAST_FUNC; #if ENABLE_HUSH_LOCAL static int builtin_local(char **argv) FAST_FUNC; #endif -#if HUSH_DEBUG +#if ENABLE_HUSH_MEMLEAK static int builtin_memleak(char **argv) FAST_FUNC; #endif #if ENABLE_HUSH_PRINTF @@ -1037,7 +1046,7 @@ static const struct built_in_command bltins1[] = { #if ENABLE_HUSH_LOCAL BLTIN("local" , builtin_local , "Set local variables"), #endif -#if HUSH_DEBUG +#if ENABLE_HUSH_MEMLEAK BLTIN("memleak" , builtin_memleak , NULL), #endif #if ENABLE_HUSH_READ @@ -9534,7 +9543,7 @@ static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) } #endif -#if HUSH_DEBUG +#if ENABLE_HUSH_MEMLEAK static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) { void *p; -- cgit v1.2.3-55-g6feb From 41ade05cacd61a42e348f21aeddb7b12b0ad5d3d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 8 Jan 2017 18:56:24 +0100 Subject: hush: conditionalize print_escaped() on EXPORT || TRAP Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index 3050aeb8e..9b62d5c0d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8936,6 +8936,7 @@ static int FAST_FUNC builtin_exit(char **argv) hush_exit(xatoi(argv[0]) & 0xff); } +#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP static void print_escaped(const char *s) { if (*s == '\'') @@ -8954,6 +8955,7 @@ static void print_escaped(const char *s) putchar('"'); } while (*s); } +#endif #if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL # if !ENABLE_HUSH_LOCAL -- cgit v1.2.3-55-g6feb From 442a414d66266336e09eae2ea6713b5bf054475e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 05:11:09 +0100 Subject: typo fix Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/hush.c b/shell/hush.c index 9b62d5c0d..01c334a46 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -291,7 +291,7 @@ //config: default n //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: help -//config: Enable umask builtin in hush. +//config: Enable memleak builtin in hush. //config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" -- cgit v1.2.3-55-g6feb From fd68f1e80dbed81e42a0298db5fcf578e8d944a9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 05:47:57 +0100 Subject: hush: fix kill builtin without jobs support Signed-off-by: Denys Vlasenko --- shell/hush.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 01c334a46..247ad7aab 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9443,7 +9443,7 @@ static struct pipe *parse_jobspec(const char *str) return pi; } } - bb_error_msg("%d: no such job", jobnum); + bb_error_msg("%u: no such job", jobnum); return NULL; } @@ -9691,9 +9691,9 @@ static int FAST_FUNC builtin_kill(char **argv) { int ret = 0; - argv = skip_dash_dash(argv); - if (argv[0] && strcmp(argv[0], "-l") != 0) { - int i = 0; +# if ENABLE_HUSH_JOB + if (argv[1] && strcmp(argv[1], "-l") != 0) { + int i = 1; do { struct pipe *pi; @@ -9735,12 +9735,9 @@ static int FAST_FUNC builtin_kill(char **argv) n = 1; dst = alloca(n * sizeof(int)*4); argv[i] = dst; -#if ENABLE_HUSH_JOB if (G_interactive_fd) dst += sprintf(dst, " -%u", (int)pi->pgrp); - else -#endif - for (j = 0; j < n; j++) { + else for (j = 0; j < n; j++) { struct command *cmd = &pi->cmds[j]; /* Skip exited members of the job */ if (cmd->pid == 0) @@ -9755,13 +9752,12 @@ static int FAST_FUNC builtin_kill(char **argv) *dst = '\0'; } while (argv[++i]); } +# endif - if (argv[0] || ret == 0) { - argv--; - argv[0] = (char*)"kill"; /* why? think about "kill -- PID" */ - /* kill_main also handles "killall" etc, so it does look at argv[0]! */ + if (argv[1] || ret == 0) { ret = run_applet_main(argv, kill_main); } + /* else: ret = 1, "kill %bad_jobspec" case */ return ret; } #endif -- cgit v1.2.3-55-g6feb From 5362cc4b8caa5c4b8bf815d8ac2fd50a0d8e9354 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 05:57:13 +0100 Subject: hush: remove redundand test for ENABLE_HUSH_JOB Signed-off-by: Denys Vlasenko --- shell/hush.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 247ad7aab..c10793060 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9730,9 +9730,7 @@ static int FAST_FUNC builtin_kill(char **argv) * sh -c 'true|sleep 2 & sleep 1; kill %1' * sh -c 'true|sleep 1 & sleep 2; kill %1' */ - n = pi->num_cmds; - if (ENABLE_HUSH_JOB && G_interactive_fd) - n = 1; + n = G_interactive_fd ? 1 : pi->num_cmds; dst = alloca(n * sizeof(int)*4); argv[i] = dst; if (G_interactive_fd) -- cgit v1.2.3-55-g6feb From cc2fd5a9867519da24672fae560e511a4a6940e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 06:19:55 +0100 Subject: hush: fix 'defined but not used' warning Signed-off-by: Denys Vlasenko --- shell/hush.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index c10793060..faff86d88 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2182,11 +2182,13 @@ static void unset_vars(char **strings) free(strings); } +#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_BASH_COMPAT || ENABLE_HUSH_READ static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) { char *var = xasprintf("%s=%s", name, val); set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0); } +#endif /* -- cgit v1.2.3-55-g6feb From 4e4f88e569e6e32669c856a86c60bb3fc104d588 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 07:57:38 +0100 Subject: hush: global_args_malloced is used only if set builtin is enabled function old new delta run_pipe 1623 1635 +12 builtin_source 210 222 +12 save_and_replace_G_args 70 60 -10 builtin_shift 132 94 -38 restore_G_args 98 - -98 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 2/2 up/down: 24/-146) Total: -122 bytes Signed-off-by: Denys Vlasenko --- shell/hush.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index faff86d88..c69e4ec8a 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -853,8 +853,13 @@ struct globals { smallint exiting; /* used to prevent EXIT trap recursion */ /* These four support $?, $#, and $1 */ smalluint last_exitcode; +#if ENABLE_HUSH_SET /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ smalluint global_args_malloced; +# define G_global_args_malloced (G.global_args_malloced) +#else +# define G_global_args_malloced 0 +#endif /* how many non-NULL argv's we have. NB: $# + 1 */ int global_argc; char **global_argv; @@ -893,7 +898,7 @@ struct globals { unsigned special_sig_mask; #if ENABLE_HUSH_JOB unsigned fatal_sig_mask; -# define G_fatal_sig_mask G.fatal_sig_mask +# define G_fatal_sig_mask (G.fatal_sig_mask) #else # define G_fatal_sig_mask 0 #endif @@ -1476,7 +1481,7 @@ typedef struct save_arg_t { char *sv_argv0; char **sv_g_argv; int sv_g_argc; - smallint sv_g_malloced; + IF_HUSH_SET(smallint sv_g_malloced;) } save_arg_t; static void save_and_replace_G_args(save_arg_t *sv, char **argv) @@ -1486,11 +1491,11 @@ static void save_and_replace_G_args(save_arg_t *sv, char **argv) sv->sv_argv0 = argv[0]; sv->sv_g_argv = G.global_argv; sv->sv_g_argc = G.global_argc; - sv->sv_g_malloced = G.global_args_malloced; + IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;) argv[0] = G.global_argv[0]; /* retain $0 */ G.global_argv = argv; - G.global_args_malloced = 0; + IF_HUSH_SET(G.global_args_malloced = 0;) n = 1; while (*++argv) @@ -1500,19 +1505,19 @@ static void save_and_replace_G_args(save_arg_t *sv, char **argv) static void restore_G_args(save_arg_t *sv, char **argv) { - char **pp; - +#if ENABLE_HUSH_SET if (G.global_args_malloced) { /* someone ran "set -- arg1 arg2 ...", undo */ - pp = G.global_argv; + char **pp = G.global_argv; while (*++pp) /* note: does not free $0 */ free(*pp); free(G.global_argv); } +#endif argv[0] = sv->sv_argv0; G.global_argv = sv->sv_g_argv; G.global_argc = sv->sv_g_argc; - G.global_args_malloced = sv->sv_g_malloced; + IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;) } @@ -9213,7 +9218,7 @@ static int FAST_FUNC builtin_shift(char **argv) n = atoi(argv[0]); } if (n >= 0 && n < G.global_argc) { - if (G.global_args_malloced) { + if (G_global_args_malloced) { int m = 1; while (m <= n) free(G.global_argv[m++]); -- cgit v1.2.3-55-g6feb From 2b1559056cf32c42675ecd937796e1455bcb5c2c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 08:13:21 +0100 Subject: hush: fix a bug in argv restoration after sourcing a file if sourced file "shift"ed argvs so that $1 is NULL, restore wasn't done. Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/source_argv_and_shift.right | 4 ++++ shell/ash_test/ash-misc/source_argv_and_shift.tests | 12 ++++++++++++ shell/hush.c | 6 ++++-- shell/hush_test/hush-misc/source_argv_and_shift.right | 4 ++++ shell/hush_test/hush-misc/source_argv_and_shift.tests | 12 ++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 shell/ash_test/ash-misc/source_argv_and_shift.right create mode 100755 shell/ash_test/ash-misc/source_argv_and_shift.tests create mode 100644 shell/hush_test/hush-misc/source_argv_and_shift.right create mode 100755 shell/hush_test/hush-misc/source_argv_and_shift.tests diff --git a/shell/ash_test/ash-misc/source_argv_and_shift.right b/shell/ash_test/ash-misc/source_argv_and_shift.right new file mode 100644 index 000000000..b15cc96e7 --- /dev/null +++ b/shell/ash_test/ash-misc/source_argv_and_shift.right @@ -0,0 +1,4 @@ +sourced_arg1:1 +arg1: +sourced_arg1:a +arg1:1 diff --git a/shell/ash_test/ash-misc/source_argv_and_shift.tests b/shell/ash_test/ash-misc/source_argv_and_shift.tests new file mode 100755 index 000000000..66353f3d7 --- /dev/null +++ b/shell/ash_test/ash-misc/source_argv_and_shift.tests @@ -0,0 +1,12 @@ +echo 'echo sourced_arg1:$1' >sourced1 +echo 'shift' >>sourced1 + +set -- 1 +. ./sourced1 +echo arg1:$1 + +set -- 1 +. ./sourced1 a +echo arg1:$1 + +rm sourced1 diff --git a/shell/hush.c b/shell/hush.c index c69e4ec8a..5c5715b3f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -9606,6 +9606,7 @@ static int FAST_FUNC builtin_source(char **argv) char *arg_path, *filename; FILE *input; save_arg_t sv; + char *args_need_save; #if ENABLE_HUSH_FUNCTIONS smallint sv_flg; #endif @@ -9637,7 +9638,8 @@ static int FAST_FUNC builtin_source(char **argv) /* "we are inside sourced file, ok to use return" */ G_flag_return_in_progress = -1; #endif - if (argv[1]) + args_need_save = argv[1]; /* used as a boolean variable */ + if (args_need_save) save_and_replace_G_args(&sv, argv); /* "false; . ./empty_line; echo Zero:$?" should print 0 */ @@ -9645,7 +9647,7 @@ static int FAST_FUNC builtin_source(char **argv) parse_and_run_file(input); fclose_and_forget(input); - if (argv[1]) + if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ restore_G_args(&sv, argv); #if ENABLE_HUSH_FUNCTIONS G_flag_return_in_progress = sv_flg; diff --git a/shell/hush_test/hush-misc/source_argv_and_shift.right b/shell/hush_test/hush-misc/source_argv_and_shift.right new file mode 100644 index 000000000..b15cc96e7 --- /dev/null +++ b/shell/hush_test/hush-misc/source_argv_and_shift.right @@ -0,0 +1,4 @@ +sourced_arg1:1 +arg1: +sourced_arg1:a +arg1:1 diff --git a/shell/hush_test/hush-misc/source_argv_and_shift.tests b/shell/hush_test/hush-misc/source_argv_and_shift.tests new file mode 100755 index 000000000..66353f3d7 --- /dev/null +++ b/shell/hush_test/hush-misc/source_argv_and_shift.tests @@ -0,0 +1,12 @@ +echo 'echo sourced_arg1:$1' >sourced1 +echo 'shift' >>sourced1 + +set -- 1 +. ./sourced1 +echo arg1:$1 + +set -- 1 +. ./sourced1 a +echo arg1:$1 + +rm sourced1 -- cgit v1.2.3-55-g6feb From fb87d93d1e0a6760049fa88aadd1232b7e1545e7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 08:22:06 +0100 Subject: ash: fix a bug in argv restoration after sourcing a file if sourced file "shift"ed argvs so that $1 is NULL, restore wasn't done. Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index efb4615db..9c46a93e0 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12548,6 +12548,7 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM) int status = 0; char *fullname; char **argv; + char *args_need_save; struct strlist *sp; volatile struct shparam saveparam; @@ -12567,7 +12568,8 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM) */ fullname = find_dot_file(argv[0]); argv++; - if (argv[0]) { /* . FILE ARGS, ARGS exist */ + args_need_save = argv[0]; + if (args_need_save) { /* . FILE ARGS, ARGS exist */ int argc; saveparam = shellparam; shellparam.malloced = 0; @@ -12586,7 +12588,7 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM) status = cmdloop(0); popfile(); - if (argv[0]) { + if (args_need_save) { freeparam(&shellparam); shellparam = saveparam; }; -- cgit v1.2.3-55-g6feb From b130f9f758b6404c6d0911a1c120937ae6ab47f8 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Sun, 8 Jan 2017 14:28:34 +0800 Subject: Allow 'gzip -d' and 'bzip2 -d' without gunzip or bunzip2 Idea copied from the "ip" applet. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 20 ++++++++++---------- archival/bzip2.c | 16 ++++++++++++++-- archival/gzip.c | 24 +++++++++++++++++------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 0eff58713..12c82eba4 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -12,9 +12,9 @@ //kbuild:lib-$(CONFIG_LZOPCAT) += bbunzip.o //kbuild:lib-$(CONFIG_UNLZOP) += bbunzip.o /* bzip2_main() too: */ -//kbuild:lib-$(CONFIG_BZIP2) += bbunzip.o +//kbuild:lib-$(CONFIG_FEATURE_BZIP2_DECOMPRESS) += bbunzip.o /* gzip_main() too: */ -//kbuild:lib-$(CONFIG_GZIP) += bbunzip.o +//kbuild:lib-$(CONFIG_FEATURE_GZIP_DECOMPRESS) += bbunzip.o /* Note: must be kept in sync with archival/lzop.c */ enum { @@ -197,7 +197,7 @@ int FAST_FUNC bbunpack(char **argv, } #if ENABLE_UNCOMPRESS \ - || ENABLE_BUNZIP2 || ENABLE_BZCAT \ + || ENABLE_FEATURE_BZIP2_DECOMPRESS \ || ENABLE_UNLZMA || ENABLE_LZCAT || ENABLE_LZMA \ || ENABLE_UNXZ || ENABLE_XZCAT || ENABLE_XZ static @@ -295,6 +295,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //config:config GUNZIP //config: bool "gunzip" //config: default y +//config: select FEATURE_GZIP_DECOMPRESS //config: help //config: gunzip is used to decompress archives created by gzip. //config: You can use the `-t' option to test the integrity of @@ -303,6 +304,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //config:config ZCAT //config: bool "zcat" //config: default y +//config: select FEATURE_GZIP_DECOMPRESS //config: help //config: Alias to "gunzip -c". //config: @@ -315,9 +317,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) //applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) -//kbuild:lib-$(CONFIG_GUNZIP) += bbunzip.o -//kbuild:lib-$(CONFIG_ZCAT) += bbunzip.o -#if ENABLE_GUNZIP || ENABLE_ZCAT +#if ENABLE_FEATURE_GZIP_DECOMPRESS static char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) { @@ -385,7 +385,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) return bbunpack(argv, unpack_gz_stream, make_new_name_gunzip, /*unused:*/ NULL); } -#endif +#endif /* FEATURE_GZIP_DECOMPRESS */ /* @@ -408,6 +408,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //config:config BUNZIP2 //config: bool "bunzip2" //config: default y +//config: select FEATURE_BZIP2_DECOMPRESS //config: help //config: bunzip2 is a compression utility using the Burrows-Wheeler block //config: sorting text compression algorithm, and Huffman coding. Compression @@ -421,14 +422,13 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //config:config BZCAT //config: bool "bzcat" //config: default y +//config: select FEATURE_BZIP2_DECOMPRESS //config: help //config: Alias to "bunzip2 -c". //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) //applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) -//kbuild:lib-$(CONFIG_BUNZIP2) += bbunzip.o -//kbuild:lib-$(CONFIG_BZCAT) += bbunzip.o -#if ENABLE_BUNZIP2 || ENABLE_BZCAT +#if ENABLE_FEATURE_BZIP2_DECOMPRESS int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int bunzip2_main(int argc UNUSED_PARAM, char **argv) { diff --git a/archival/bzip2.c b/archival/bzip2.c index 47fa29af3..7e38e78b3 100644 --- a/archival/bzip2.c +++ b/archival/bzip2.c @@ -19,6 +19,15 @@ //config: //config: Unless you have a specific application which requires bzip2, you //config: should probably say N here. +//config: +//config:config FEATURE_BZIP2_DECOMPRESS +//config: bool "Enable decompression" +//config: default y +//config: depends on BZIP2 || BUNZIP2 || BZCAT +//config: help +//config: Enable -d (--decompress) and -t (--test) options for bzip2. +//config: This will be automatically selected if bunzip2 or bzcat is +//config: enabled. //applet:IF_BZIP2(APPLET(bzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_BZIP2) += bzip2.o @@ -28,7 +37,10 @@ //usage:#define bzip2_full_usage "\n\n" //usage: "Compress FILEs (or stdin) with bzip2 algorithm\n" //usage: "\n -1..9 Compression level" +//usage: IF_FEATURE_BZIP2_DECOMPRESS( //usage: "\n -d Decompress" +//usage: "\n -t Test file integrity" +//usage: ) //usage: "\n -c Write to stdout" //usage: "\n -f Force" @@ -184,8 +196,8 @@ int bzip2_main(int argc UNUSED_PARAM, char **argv) opt_complementary = "s2"; /* -s means -2 (compatibility) */ /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - opt = getopt32(argv, "cfv" IF_BUNZIP2("dt") "123456789qzs"); -#if ENABLE_BUNZIP2 /* bunzip2_main may not be visible... */ + opt = getopt32(argv, "cfv" IF_FEATURE_BZIP2_DECOMPRESS("dt") "123456789qzs"); +#if ENABLE_FEATURE_BZIP2_DECOMPRESS /* bunzip2_main may not be visible... */ if (opt & 0x18) // -d and/or -t return bunzip2_main(argc, argv); opt >>= 5; diff --git a/archival/gzip.c b/archival/gzip.c index 9e0bee815..63bf76053 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -72,19 +72,29 @@ aa: 85.1% -- replaced with aa.gz //config: is 6. If levels 1-3 are specified, 4 is used. //config: If this option is not selected, -N options are ignored and -9 //config: is used. +//config: +//config:config FEATURE_GZIP_DECOMPRESS +//config: bool "Enable decompression" +//config: default y +//config: depends on GZIP || GUNZIP || ZCAT +//config: help +//config: Enable -d (--decompress) and -t (--test) options for gzip. +//config: This will be automatically selected if gunzip or zcat is +//config: enabled. //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_GZIP) += gzip.o //usage:#define gzip_trivial_usage -//usage: "[-cf" IF_GUNZIP("d") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." +//usage: "[-cf" IF_FEATURE_GZIP_DECOMPRESS("dt") IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." //usage:#define gzip_full_usage "\n\n" //usage: "Compress FILEs (or stdin)\n" //usage: IF_FEATURE_GZIP_LEVELS( //usage: "\n -1..9 Compression level" //usage: ) -//usage: IF_GUNZIP( +//usage: IF_FEATURE_GZIP_DECOMPRESS( //usage: "\n -d Decompress" +//usage: "\n -t Test file integrity" //usage: ) //usage: "\n -c Write to stdout" //usage: "\n -f Force" @@ -2154,7 +2164,7 @@ static const char gzip_longopts[] ALIGN1 = "to-stdout\0" No_argument "c" "force\0" No_argument "f" "verbose\0" No_argument "v" -#if ENABLE_GUNZIP +#if ENABLE_FEATURE_GZIP_DECOMPRESS "decompress\0" No_argument "d" "uncompress\0" No_argument "d" "test\0" No_argument "t" @@ -2181,7 +2191,7 @@ static const char gzip_longopts[] ALIGN1 = */ int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -#if ENABLE_GUNZIP +#if ENABLE_FEATURE_GZIP_DECOMPRESS int gzip_main(int argc, char **argv) #else int gzip_main(int argc UNUSED_PARAM, char **argv) @@ -2211,13 +2221,13 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) applet_long_options = gzip_longopts; #endif /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789"); -#if ENABLE_GUNZIP /* gunzip_main may not be visible... */ + opt = getopt32(argv, "cfv" IF_FEATURE_GZIP_DECOMPRESS("dt") "qn123456789"); +#if ENABLE_FEATURE_GZIP_DECOMPRESS /* gunzip_main may not be visible... */ if (opt & 0x18) // -d and/or -t return gunzip_main(argc, argv); #endif #ifdef ENABLE_FEATURE_GZIP_LEVELS - opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */ + opt >>= ENABLE_FEATURE_GZIP_DECOMPRESS ? 7 : 5; /* drop cfv[dt]qn bits */ if (opt == 0) opt = 1 << 6; /* default: 6 */ opt = ffs(opt >> 4); /* Maps -1..-4 to [0], -5 to [1] ... -9 to [5] */ -- cgit v1.2.3-55-g6feb From 80172e46221222f26680f3b9caf7637383205e7a Mon Sep 17 00:00:00 2001 From: Explorer09 Date: Mon, 9 Jan 2017 15:04:43 +0800 Subject: modprobe-small: optimizations for single applet build (I'm requesting for a review first because I fear such an aggressive change could lead to bugs. While I observe the sizes have reduced, I haven't test the functionality of each applet after that. So please test before merging.) Aggressively cut off unneeded code when the relevant applets are not built. Correct dependencies of FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE and FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED. Don't bother with the '-r' option check if only rmmod is built (assume true then), or when neither rmmod or mobprobe is built (assume false then). Size comparison before and after the change (single applet configuration): text data bss dec hex filename 34778 946 112 35836 8bfc old/busybox_DEPMOD 34151 946 112 35209 8989 new/busybox_DEPMOD 34903 946 112 35961 8c79 old/busybox_INSMOD 28316 778 112 29206 7216 new/busybox_INSMOD 35228 962 112 36302 8dce old/busybox_LSMOD 5011 706 40 5757 167d new/busybox_LSMOD 34830 946 112 35888 8c30 old/busybox_MODPROBE 34795 946 112 35853 8c0d new/busybox_MODPROBE 34718 946 112 35776 8bc0 old/busybox_RMMOD 7502 714 104 8320 2080 new/busybox_RMMOD Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 72 +++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 0fc9ea454..12e09938a 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -13,15 +13,14 @@ //config:config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE //config: bool "Accept module options on modprobe command line" //config: default y -//config: depends on MODPROBE_SMALL -//config: select PLATFORM_LINUX +//config: depends on MODPROBE_SMALL && (INSMOD || MODPROBE) //config: help //config: Allow insmod and modprobe take module options from command line. //config: //config:config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED //config: bool "Skip loading of already loaded modules" //config: default y -//config: depends on MODPROBE_SMALL +//config: depends on MODPROBE_SMALL && (DEPMOD || INSMOD || MODPROBE) //config: help //config: Check if the module is already loaded. @@ -59,6 +58,14 @@ #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" +#define ONLY_APPLET (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD \ + + ENABLE_LSMOD + ENABLE_RMMOD <= 1) +#define is_modprobe (ENABLE_MODPROBE && (ONLY_APPLET || applet_name[0] == 'm')) +#define is_depmod (ENABLE_DEPMOD && (ONLY_APPLET || applet_name[0] == 'd')) +#define is_insmod (ENABLE_INSMOD && (ONLY_APPLET || applet_name[0] == 'i')) +#define is_lsmod (ENABLE_LSMOD && (ONLY_APPLET || applet_name[0] == 'l')) +#define is_rmmod (ENABLE_RMMOD && (ONLY_APPLET || applet_name[0] == 'r')) + enum { OPT_q = (1 << 0), /* be quiet */ OPT_r = (1 << 1), /* module removal instead of loading */ @@ -361,6 +368,8 @@ static FAST_FUNC int fileAction(const char *pathname, { int cur; const char *fname; + bool is_remove = (ENABLE_RMMOD && ONLY_APPLET) + || ((ENABLE_RMMOD || ENABLE_MODPROBE) && (option_mask32 & OPT_r)); pathname += 2; /* skip "./" */ fname = bb_get_last_path_component_nostrip(pathname); @@ -385,7 +394,7 @@ static FAST_FUNC int fileAction(const char *pathname, if (parse_module(&modinfo[cur], pathname) != 0) return TRUE; /* failed to open/read it, no point in trying loading */ - if (!(option_mask32 & OPT_r)) { + if (!is_remove) { if (load_module(pathname, module_load_options) == 0) { /* Load was successful, there is nothing else to do. * This can happen ONLY for "top-level" module load, @@ -666,7 +675,8 @@ static int process_module(char *name, const char *cmdline_options) module_info **infovec; module_info *info; int infoidx; - int is_remove = (option_mask32 & OPT_r) != 0; + bool is_remove = (ENABLE_RMMOD && ONLY_APPLET) + || ((ENABLE_RMMOD || ENABLE_MODPROBE) && (option_mask32 & OPT_r)); int exitcode = EXIT_SUCCESS; dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); @@ -675,9 +685,8 @@ static int process_module(char *name, const char *cmdline_options) dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove); - if (applet_name[0] == 'r') { - /* rmmod. - * Does not remove dependencies, no need to scan, just remove. + if (is_rmmod) { + /* Does not remove dependencies, no need to scan, just remove. * (compat note: this allows and strips .ko suffix) */ rmmod(name); @@ -743,7 +752,7 @@ static int process_module(char *name, const char *cmdline_options) if (!infovec) { /* both dirscan and find_alias found nothing */ - if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ + if (!is_remove && !is_depmod) /* it wasn't rmmod or depmod */ bb_error_msg("module '%s' not found", name); //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? goto ret; @@ -926,11 +935,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) { int exitcode; struct utsname uts; - char applet0 = applet_name[0]; - IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options;) + IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options = NULL;) /* are we lsmod? -> just dump /proc/modules */ - if (ENABLE_LSMOD && 'l' == applet0) { + if (is_lsmod) { xprint_and_close_file(xfopen_for_read("/proc/modules")); return EXIT_SUCCESS; } @@ -940,14 +948,13 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* Prevent ugly corner cases with no modules at all */ modinfo = xzalloc(sizeof(modinfo[0])); - if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */ + if (!is_insmod) { /* Goto modules directory */ xchdir(CONFIG_DEFAULT_MODULES_DIR); } uname(&uts); /* never fails */ - /* depmod? */ - if (ENABLE_DEPMOD && 'd' == applet0) { + if (is_depmod) { /* Supported: * -n: print result to stdout * -a: process all modules (default) @@ -978,28 +985,28 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) return !wrote_dep_bb_ok; } - /* insmod, modprobe, rmmod require at least one argument */ +#if ENABLE_MODPROBE || ENABLE_INSMOD || ENABLE_RMMOD + /* modprobe, insmod, rmmod require at least one argument */ opt_complementary = "-1"; /* only -q (quiet) and -r (rmmod), * the rest are accepted and ignored (compat) */ getopt32(argv, "qrfsvwb"); argv += optind; - /* are we rmmod? -> simulate modprobe -r */ - if (ENABLE_RMMOD && 'r' == applet0) { - option_mask32 |= OPT_r; - } - - if (!ENABLE_INSMOD || 'i' != applet0) { /* not insmod */ + if (!is_insmod) { /* Goto $VERSION directory */ xchdir(uts.release); } -#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE + /* are we rmmod? -> simulate modprobe -r, but don't bother the flag if + * there're no other applets here */ + if (is_rmmod) { + if (!ONLY_APPLET) + option_mask32 |= OPT_r; + } else if (!ENABLE_MODPROBE || !(option_mask32 & OPT_r)) { +# if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE /* If not rmmod/-r, parse possible module options given on command line. * insmod/modprobe takes one module name, the rest are parameters. */ - options = NULL; - if (!(option_mask32 & OPT_r)) { char **arg = argv; while (*++arg) { /* Enclose options in quotes */ @@ -1008,13 +1015,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) free(s); *arg = NULL; } - } -#else - if (!(option_mask32 & OPT_r)) +# else argv[1] = NULL; -#endif +# endif + } - if (ENABLE_INSMOD && 'i' == applet0) { /* insmod */ + if (is_insmod) { size_t len; void *map; @@ -1023,8 +1029,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) if (!map) bb_perror_msg_and_die("can't read '%s'", *argv); if (init_module(map, len, - IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "") - IF_NOT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("") + (IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : ) "") ) != 0 ) { bb_error_msg_and_die("can't insert '%s': %s", @@ -1034,7 +1039,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } /* Try to load modprobe.dep.bb */ - if (!ENABLE_RMMOD || 'r' != applet0) { /* not rmmod */ + if (!is_rmmod) { load_dep_bb(); } @@ -1049,4 +1054,5 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) } return exitcode; +#endif /* MODPROBE || INSMOD || RMMOD */ } -- cgit v1.2.3-55-g6feb From 6bf52b615d78542e41e684438c844af1fa4fb36e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 09:48:58 +0100 Subject: modprobe-small: build fixes Was throwing some build errors: CONFIG_MODPROBE_SMALL=y CONFIG_DEPMOD=y CONFIG_LSMOD=y CONFIG_MODINFO=y CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y error: unused variable 'exitcode' modutils/modprobe-small.c: In function 'modprobe_main': modutils/modprobe-small.c:1060: error: control reaches end of non-void function Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 12e09938a..75b36f748 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -58,8 +58,8 @@ #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" -#define ONLY_APPLET (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD \ - + ENABLE_LSMOD + ENABLE_RMMOD <= 1) +#define MOD_APPLET_CNT (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD + ENABLE_LSMOD + ENABLE_RMMOD) +#define ONLY_APPLET (MOD_APPLET_CNT <= 1) #define is_modprobe (ENABLE_MODPROBE && (ONLY_APPLET || applet_name[0] == 'm')) #define is_depmod (ENABLE_DEPMOD && (ONLY_APPLET || applet_name[0] == 'd')) #define is_insmod (ENABLE_INSMOD && (ONLY_APPLET || applet_name[0] == 'i')) @@ -933,7 +933,9 @@ The following options are useful for people managing distributions: int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int modprobe_main(int argc UNUSED_PARAM, char **argv) { +#if ENABLE_MODPROBE || ENABLE_INSMOD || ENABLE_RMMOD int exitcode; +#endif struct utsname uts; IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options = NULL;) @@ -954,7 +956,12 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } uname(&uts); /* never fails */ - if (is_depmod) { + /* depmod? */ + if ((MOD_APPLET_CNT == 2 && ENABLE_DEPMOD && ENABLE_LSMOD) + /* ^^^^only depmod and lsmod is configured^^^^^^^^^^^^^^^ */ + /* note: we already know here it is not lsmod (handled before) */ + || is_depmod + ) { /* Supported: * -n: print result to stdout * -a: process all modules (default) -- cgit v1.2.3-55-g6feb From 2a0867a5ed277e4c3cf4c5e17e539d225286ef07 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 10:58:37 +0100 Subject: unzip: optional support for bzip2 and lzma function old new delta unzip_main 2376 2476 +100 bbunpack 750 745 -5 Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 2 +- archival/libarchive/Kbuild.src | 2 + archival/unzip.c | 93 ++++++++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 36 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 12c82eba4..aa8453440 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -127,7 +127,7 @@ int FAST_FUNC bbunpack(char **argv, if (!(option_mask32 & SEAMLESS_MAGIC)) { init_transformer_state(&xstate); - xstate.signature_skipped = 0; + /*xstate.signature_skipped = 0; - already is */ /*xstate.src_fd = STDIN_FILENO; - already is */ xstate.dst_fd = STDOUT_FILENO; status = unpacker(&xstate); diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index ad5c5c42d..84117fa85 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -53,9 +53,11 @@ lib-$(CONFIG_LZOPCAT) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o lib-$(CONFIG_BUNZIP2) += open_transformer.o decompress_bunzip2.o lib-$(CONFIG_BZCAT) += open_transformer.o decompress_bunzip2.o +lib-$(CONFIG_FEATURE_UNZIP_BZIP2) += open_transformer.o decompress_bunzip2.o lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma.o lib-$(CONFIG_LZCAT) += open_transformer.o decompress_unlzma.o lib-$(CONFIG_LZMA) += open_transformer.o decompress_unlzma.o +lib-$(CONFIG_FEATURE_UNZIP_LZMA) += open_transformer.o decompress_unlzma.o lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o diff --git a/archival/unzip.c b/archival/unzip.c index 921493591..997543c50 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -34,6 +34,18 @@ //config: ZIP files without deleted/updated files, SFX archives etc, //config: you can reduce code size by unselecting this option. //config: To support less trivial ZIPs, say Y. +//config: +//config:config FEATURE_UNZIP_BZIP2 +//config: bool "Support compression method 12 (bzip2)" +//config: default y +//config: depends on FEATURE_UNZIP_CDF && DESKTOP +// FEATURE_UNZIP_CDF is needed, otherwise we can't find start of next file +// DESKTOP is needed to get back uncompressed length +//config: +//config:config FEATURE_UNZIP_LZMA +//config: bool "Support compression method 14 (lzma)" +//config: default y +//config: depends on FEATURE_UNZIP_CDF && DESKTOP //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_UNZIP) += unzip.o @@ -319,32 +331,57 @@ static void unzip_create_leading_dirs(const char *fn) static void unzip_extract(zip_header_t *zip, int dst_fd) { + transformer_state_t xstate; + if (zip->fmt.method == 0) { /* Method 0 - stored (not compressed) */ off_t size = zip->fmt.ucmpsize; if (size) bb_copyfd_exact_size(zip_fd, dst_fd, size); - } else { + return; + } + + init_transformer_state(&xstate); + xstate.bytes_in = zip->fmt.cmpsize; + xstate.src_fd = zip_fd; + xstate.dst_fd = dst_fd; + if (zip->fmt.method == 8) { /* Method 8 - inflate */ - transformer_state_t xstate; - init_transformer_state(&xstate); - xstate.bytes_in = zip->fmt.cmpsize; - xstate.src_fd = zip_fd; - xstate.dst_fd = dst_fd; if (inflate_unzip(&xstate) < 0) bb_error_msg_and_die("inflate error"); /* Validate decompression - crc */ if (zip->fmt.crc32 != (xstate.crc32 ^ 0xffffffffL)) { bb_error_msg_and_die("crc error"); } - /* Validate decompression - size */ - if (zip->fmt.ucmpsize != xstate.bytes_out) { - /* Don't die. Who knows, maybe len calculation - * was botched somewhere. After all, crc matched! */ - bb_error_msg("bad length"); - } } - /* TODO? method 12: bzip2, method 14: LZMA */ +#if ENABLE_FEATURE_UNZIP_BZIP2 + else if (zip->fmt.method == 12) { + /* Tested. Unpacker reads too much, but we use CDF + * and will seek to the correct beginning of next file. + */ + xstate.bytes_out = unpack_bz2_stream(&xstate); + if (xstate.bytes_out < 0) + bb_error_msg_and_die("inflate error"); + } +#endif +#if ENABLE_FEATURE_UNZIP_LZMA + else if (zip->fmt.method == 14) { + /* Not tested yet */ + xstate.bytes_out = unpack_lzma_stream(&xstate); + if (xstate.bytes_out < 0) + bb_error_msg_and_die("inflate error"); + } +#endif + else { + bb_error_msg_and_die("unsupported method %u", zip->fmt.method); + } + + /* Validate decompression - size */ + if (zip->fmt.ucmpsize != xstate.bytes_out) { + /* Don't die. Who knows, maybe len calculation + * was botched somewhere. After all, crc matched! */ + bb_error_msg("bad length"); + } } static void my_fgets80(char *buf80) @@ -609,12 +646,6 @@ int unzip_main(int argc, char **argv) xread(zip_fd, zip.raw, ZIP_HEADER_LEN); FIX_ENDIANNESS_ZIP(zip); - if ((zip.fmt.method != 0) - && (zip.fmt.method != 8) - ) { - /* TODO? method 12: bzip2, method 14: LZMA */ - bb_error_msg_and_die("unsupported method %d", zip.fmt.method); - } if (zip.fmt.zip_flags & SWAP_LE16(0x0009)) { bb_error_msg_and_die("zip flags 1 and 8 are not supported"); } @@ -704,7 +735,11 @@ int unzip_main(int argc, char **argv) dtbuf, dst_fn); } else { - unsigned long percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; + char method6[7]; + unsigned long percents; + + sprintf(method6, "%6u", zip.fmt.method); + percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; if ((int32_t)percents < 0) percents = 0; /* happens if ucmpsize < cmpsize */ percents = percents * 100; @@ -714,21 +749,9 @@ int unzip_main(int argc, char **argv) // "-------- ------ ------- ---- ---------- ----- -------- ----" printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", (unsigned)zip.fmt.ucmpsize, - zip.fmt.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */ -/* TODO: show other methods? - * 1 - Shrunk - * 2 - Reduced with compression factor 1 - * 3 - Reduced with compression factor 2 - * 4 - Reduced with compression factor 3 - * 5 - Reduced with compression factor 4 - * 6 - Imploded - * 7 - Reserved for Tokenizing compression algorithm - * 9 - Deflate64 - * 10 - PKWARE Data Compression Library Imploding - * 11 - Reserved by PKWARE - * 12 - BZIP2 - * 14 - LZMA - */ + zip.fmt.method == 0 ? "Stored" + : zip.fmt.method == 8 ? "Defl:N" + : method6, (unsigned)zip.fmt.cmpsize, (unsigned)percents, dtbuf, -- cgit v1.2.3-55-g6feb From 6b4f4b52845d903f6e06f4dbca22ad0e2f67f473 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 11:12:01 +0100 Subject: unzip: optional support for xz function old new delta unzip_main 2476 2491 +15 Signed-off-by: Denys Vlasenko --- archival/libarchive/Kbuild.src | 1 + archival/unzip.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 84117fa85..eaf67451f 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -61,6 +61,7 @@ lib-$(CONFIG_FEATURE_UNZIP_LZMA) += open_transformer.o decompress_unlzma. lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_XZCAT) += open_transformer.o decompress_unxz.o lib-$(CONFIG_XZ) += open_transformer.o decompress_unxz.o +lib-$(CONFIG_FEATURE_UNZIP_XZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o lib-$(CONFIG_ZCAT) += open_transformer.o decompress_gunzip.o lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o diff --git a/archival/unzip.c b/archival/unzip.c index 997543c50..6dc5d89c2 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -46,6 +46,11 @@ //config: bool "Support compression method 14 (lzma)" //config: default y //config: depends on FEATURE_UNZIP_CDF && DESKTOP +//config: +//config:config FEATURE_UNZIP_XZ +//config: bool "Support compression method 95 (xz)" +//config: default y +//config: depends on FEATURE_UNZIP_CDF && DESKTOP //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_UNZIP) += unzip.o @@ -371,6 +376,14 @@ static void unzip_extract(zip_header_t *zip, int dst_fd) if (xstate.bytes_out < 0) bb_error_msg_and_die("inflate error"); } +#endif +#if ENABLE_FEATURE_UNZIP_XZ + else if (zip->fmt.method == 95) { + /* Not tested yet */ + xstate.bytes_out = unpack_xz_stream(&xstate); + if (xstate.bytes_out < 0) + bb_error_msg_and_die("inflate error"); + } #endif else { bb_error_msg_and_die("unsupported method %u", zip->fmt.method); -- cgit v1.2.3-55-g6feb From 8c1d857d2582c689681c7e6d3dc299613b4a7167 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 13:10:10 +0100 Subject: unzip: match "Defl:?" display with info-zip; cosmetic code shuffling Large nested indented code blocks made more sane with a few gotos. function old new delta unzip_main 2491 2519 +28 Signed-off-by: Denys Vlasenko --- archival/unzip.c | 211 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 109 insertions(+), 102 deletions(-) diff --git a/archival/unzip.c b/archival/unzip.c index 6dc5d89c2..028e4e62e 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -659,8 +659,9 @@ int unzip_main(int argc, char **argv) xread(zip_fd, zip.raw, ZIP_HEADER_LEN); FIX_ENDIANNESS_ZIP(zip); - if (zip.fmt.zip_flags & SWAP_LE16(0x0009)) { - bb_error_msg_and_die("zip flags 1 and 8 are not supported"); + if (zip.fmt.zip_flags & SWAP_LE16(0x0008)) { + bb_error_msg_and_die("zip flag %s is not supported", + "8 (streaming)"); } } #if ENABLE_FEATURE_UNZIP_CDF @@ -704,7 +705,8 @@ int unzip_main(int argc, char **argv) if (zip.fmt.zip_flags & SWAP_LE16(0x0001)) { /* 0x0001 - encrypted */ - bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); + bb_error_msg_and_die("zip flag %s is not supported", + "1 (encryption)"); } dbg("File cmpsize:0x%x extra_len:0x%x ucmpsize:0x%x", (unsigned)zip.fmt.cmpsize, @@ -727,118 +729,123 @@ int unzip_main(int argc, char **argv) if (find_list_entry(zreject, dst_fn) || (zaccept && !find_list_entry(zaccept, dst_fn)) ) { /* Skip entry */ - i = 'n'; - } else { - if (listing) { - /* List entry */ - char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; - sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", - (zip.fmt.moddate >> 5) & 0xf, // mm: 0x01e0 - (zip.fmt.moddate) & 0x1f, // dd: 0x001f - (zip.fmt.moddate >> 9) + 1980, // yy: 0xfe00 - (zip.fmt.modtime >> 11), // hh: 0xf800 - (zip.fmt.modtime >> 5) & 0x3f // mm: 0x07e0 - // seconds/2 not shown, encoded in -- 0x001f - ); - if (!verbose) { - // " Length Date Time Name\n" - // "--------- ---------- ----- ----" - printf( "%9u " "%s " "%s\n", - (unsigned)zip.fmt.ucmpsize, - dtbuf, - dst_fn); - } else { - char method6[7]; - unsigned long percents; - - sprintf(method6, "%6u", zip.fmt.method); - percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; - if ((int32_t)percents < 0) - percents = 0; /* happens if ucmpsize < cmpsize */ - percents = percents * 100; - if (zip.fmt.ucmpsize) - percents /= zip.fmt.ucmpsize; - // " Length Method Size Cmpr Date Time CRC-32 Name\n" - // "-------- ------ ------- ---- ---------- ----- -------- ----" - printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", - (unsigned)zip.fmt.ucmpsize, - zip.fmt.method == 0 ? "Stored" - : zip.fmt.method == 8 ? "Defl:N" - : method6, - (unsigned)zip.fmt.cmpsize, - (unsigned)percents, - dtbuf, - zip.fmt.crc32, - dst_fn); - total_size += zip.fmt.cmpsize; + goto skip_cmpsize; + } + + if (listing) { + /* List entry */ + char dtbuf[sizeof("mm-dd-yyyy hh:mm")]; + sprintf(dtbuf, "%02u-%02u-%04u %02u:%02u", + (zip.fmt.moddate >> 5) & 0xf, // mm: 0x01e0 + (zip.fmt.moddate) & 0x1f, // dd: 0x001f + (zip.fmt.moddate >> 9) + 1980, // yy: 0xfe00 + (zip.fmt.modtime >> 11), // hh: 0xf800 + (zip.fmt.modtime >> 5) & 0x3f // mm: 0x07e0 + // seconds/2 not shown, encoded in -- 0x001f + ); + if (!verbose) { + // " Length Date Time Name\n" + // "--------- ---------- ----- ----" + printf( "%9u " "%s " "%s\n", + (unsigned)zip.fmt.ucmpsize, + dtbuf, + dst_fn); + } else { + char method6[7]; + unsigned long percents; + + sprintf(method6, "%6u", zip.fmt.method); + if (zip.fmt.method == 0) { + strcpy(method6, "Stored"); } - total_usize += zip.fmt.ucmpsize; - i = 'n'; - } else if (dst_fd == STDOUT_FILENO) { - /* Extracting to STDOUT */ - i = -1; - } else if (last_char_is(dst_fn, '/')) { - /* Extract directory */ - if (stat(dst_fn, &stat_buf) == -1) { - if (errno != ENOENT) { - bb_perror_msg_and_die("can't stat '%s'", dst_fn); - } - if (!quiet) { - printf(" creating: %s\n", dst_fn); - } - unzip_create_leading_dirs(dst_fn); - if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { - xfunc_die(); - } - } else { - if (!S_ISDIR(stat_buf.st_mode)) { - bb_error_msg_and_die("'%s' exists but is not a %s", - dst_fn, "directory"); - } + if (zip.fmt.method == 8) { + strcpy(method6, "Defl:N"); + /* normal, maximum, fast, superfast */ + IF_DESKTOP(method6[5] = "NXFS"[(zip.fmt.zip_flags >> 1) & 3];) + } + percents = zip.fmt.ucmpsize - zip.fmt.cmpsize; + if ((int32_t)percents < 0) + percents = 0; /* happens if ucmpsize < cmpsize */ + percents = percents * 100; + if (zip.fmt.ucmpsize) + percents /= zip.fmt.ucmpsize; + // " Length Method Size Cmpr Date Time CRC-32 Name\n" + // "-------- ------ ------- ---- ---------- ----- -------- ----" + printf( "%8u %s" "%9u%4u%% " "%s " "%08x " "%s\n", + (unsigned)zip.fmt.ucmpsize, + method6, + (unsigned)zip.fmt.cmpsize, + (unsigned)percents, + dtbuf, + zip.fmt.crc32, + dst_fn); + total_size += zip.fmt.cmpsize; + } + total_usize += zip.fmt.ucmpsize; + goto skip_cmpsize; + } + + if (dst_fd == STDOUT_FILENO) { + /* Extracting to STDOUT */ + goto do_extract; + } + if (last_char_is(dst_fn, '/')) { + /* Extract directory */ + if (stat(dst_fn, &stat_buf) == -1) { + if (errno != ENOENT) { + bb_perror_msg_and_die("can't stat '%s'", dst_fn); + } + if (!quiet) { + printf(" creating: %s\n", dst_fn); + } + unzip_create_leading_dirs(dst_fn); + if (bb_make_directory(dst_fn, dir_mode, FILEUTILS_IGNORE_CHMOD_ERR)) { + xfunc_die(); } - i = 'n'; } else { - /* Extract file */ - check_file: - if (stat(dst_fn, &stat_buf) == -1) { - /* File does not exist */ - if (errno != ENOENT) { - bb_perror_msg_and_die("can't stat '%s'", dst_fn); - } - i = 'y'; - } else { - /* File already exists */ - if (overwrite == O_NEVER) { - i = 'n'; - } else if (S_ISREG(stat_buf.st_mode)) { - /* File is regular file */ - if (overwrite == O_ALWAYS) { - i = 'y'; - } else { - printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); - my_fgets80(key_buf); - i = key_buf[0]; - } - } else { - /* File is not regular file */ - bb_error_msg_and_die("'%s' exists but is not a %s", - dst_fn, "regular file"); - } + if (!S_ISDIR(stat_buf.st_mode)) { + bb_error_msg_and_die("'%s' exists but is not a %s", + dst_fn, "directory"); } } + goto skip_cmpsize; + } + check_file: + /* Extract file */ + if (stat(dst_fn, &stat_buf) == -1) { + /* File does not exist */ + if (errno != ENOENT) { + bb_perror_msg_and_die("can't stat '%s'", dst_fn); + } + goto do_open_and_extract; + } + /* File already exists */ + if (overwrite == O_NEVER) { + goto skip_cmpsize; + } + if (!S_ISREG(stat_buf.st_mode)) { + /* File is not regular file */ + bb_error_msg_and_die("'%s' exists but is not a %s", + dst_fn, "regular file"); } + /* File is regular file */ + if (overwrite == O_ALWAYS) + goto do_open_and_extract; + printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); + my_fgets80(key_buf); - switch (i) { + switch (key_buf[0]) { case 'A': overwrite = O_ALWAYS; case 'y': /* Open file and fall into unzip */ + do_open_and_extract: unzip_create_leading_dirs(dst_fn); #if ENABLE_FEATURE_UNZIP_CDF dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); #else dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); #endif - case -1: /* Unzip */ + do_extract: if (!quiet) { printf(/* zip.fmt.method == 0 ? " extracting: %s\n" @@ -853,8 +860,8 @@ int unzip_main(int argc, char **argv) case 'N': overwrite = O_NEVER; - case 'n': - /* Skip entry data */ + case 'n': /* Skip entry data */ + skip_cmpsize: unzip_skip(zip.fmt.cmpsize); break; @@ -868,7 +875,7 @@ int unzip_main(int argc, char **argv) goto check_file; default: - printf("error: invalid response [%c]\n", (char)i); + printf("error: invalid response [%c]\n", (char)key_buf[0]); goto check_file; } -- cgit v1.2.3-55-g6feb From 3989e5adf454a3ab98412b249c2c9bd2a3175ae0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 13:55:11 +0100 Subject: unlzma: fix erroneous "while" instead of "if". Closes 4682 These parts of the code essentially check whether stepping back by rep0 goes negative or not. LZMA SDK from lzma1604.7z has the following in the corresponding places: ... = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)] Clearly, not loop here. Technically, "while" here works: if condition is false (because pos underflowed), it iterates once, adds header.dict_size (a.k.a. dicBufSize), this makes pos positive but smaller than header.dict_size, and loop exits. Now we'll just check for negative result of subtraction, which is less code: function old new delta unpack_lzma_stream 2659 2641 -18 (I hope 2 Gbyte+ dictionaries won't be in use soon). Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_unlzma.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index c8622f97b..90a428583 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c @@ -278,9 +278,10 @@ unpack_lzma_stream(transformer_state_t *xstate) if (state >= LZMA_NUM_LIT_STATES) { int match_byte; - uint32_t pos = buffer_pos - rep0; + uint32_t pos; - while (pos >= header.dict_size) + pos = buffer_pos - rep0; + if ((int32_t)pos < 0) pos += header.dict_size; match_byte = buffer[pos]; do { @@ -336,9 +337,11 @@ unpack_lzma_stream(transformer_state_t *xstate) ); if (!rc_is_bit_1(rc, prob2)) { #if ENABLE_FEATURE_LZMA_FAST - uint32_t pos = buffer_pos - rep0; + uint32_t pos; state = state < LZMA_NUM_LIT_STATES ? 9 : 11; - while (pos >= header.dict_size) + + pos = buffer_pos - rep0; + if ((int32_t)pos < 0) pos += header.dict_size; previous_byte = buffer[pos]; goto one_byte1; @@ -432,7 +435,7 @@ unpack_lzma_stream(transformer_state_t *xstate) IF_NOT_FEATURE_LZMA_FAST(string:) do { uint32_t pos = buffer_pos - rep0; - while (pos >= header.dict_size) + if ((int32_t)pos < 0) pos += header.dict_size; previous_byte = buffer[pos]; IF_NOT_FEATURE_LZMA_FAST(one_byte2:) -- cgit v1.2.3-55-g6feb From 590402bb55be940310f68d14a540f2d109420a98 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 14:28:25 +0100 Subject: unlzma: expand comments, no code changes Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_unlzma.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index 90a428583..a9040877e 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c @@ -432,6 +432,21 @@ unpack_lzma_stream(transformer_state_t *xstate) } len += LZMA_MATCH_MIN_LEN; + /* + * LZMA SDK has this optimized: + * it precalculates size and copies many bytes + * in a loop with simpler checks, a-la: + * do + * *(dest) = *(dest + ofs); + * while (++dest != lim); + * and + * do { + * buffer[buffer_pos++] = buffer[pos]; + * if (++pos == header.dict_size) + * pos = 0; + * } while (--cur_len != 0); + * Our code is slower (more checks per byte copy): + */ IF_NOT_FEATURE_LZMA_FAST(string:) do { uint32_t pos = buffer_pos - rep0; @@ -451,6 +466,9 @@ unpack_lzma_stream(transformer_state_t *xstate) } while (len != 0 && buffer_pos < header.dst_size); /* FIXME: ...........^^^^^ * shouldn't it be "global_pos + buffer_pos < header.dst_size"? + * It probably should, but it is a "do we accidentally + * unpack more bytes than expected?" check - which + * never happens for well-formed compression data... */ } } -- cgit v1.2.3-55-g6feb From e7b54d0fcce26fdbb0559728e317fb852c63e02b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 16:31:21 +0100 Subject: make_single_applets.sh: show errors and warnings While at it, fix one warning in modprobe-small.c Signed-off-by: Denys Vlasenko --- make_single_applets.sh | 8 +++++++- modutils/modprobe-small.c | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/make_single_applets.sh b/make_single_applets.sh index 00f502eda..03a5c324f 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -28,6 +28,8 @@ for app in $apps; do done #echo "$allno" >.config_allno +trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT + # Turn on each applet individually and build single-applet executable fail=0 for app in $apps; do @@ -54,16 +56,20 @@ for app in $apps; do mv .config busybox_config_${app} elif ! make $makeopts >>busybox_make_${app}.log 2>&1; then : $((fail++)) + grep -i -e error: -e warning: busybox_make_${app}.log echo "Build error for ${app}" mv .config busybox_config_${app} elif ! grep -q '^#define NUM_APPLETS 1$' include/NUM_APPLETS.h; then + grep -i -e error: -e warning: busybox_make_${app}.log mv busybox busybox_${app} : $((fail++)) echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`" mv .config busybox_config_${app} else + grep -i -e error: -e warning: busybox_make_${app}.log \ + || rm busybox_make_${app}.log mv busybox busybox_${app} - rm busybox_make_${app}.log + #mv .config busybox_config_${app} fi mv .config.SV .config #exit diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 75b36f748..21fa9dbdd 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -59,7 +59,12 @@ #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" #define MOD_APPLET_CNT (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD + ENABLE_LSMOD + ENABLE_RMMOD) -#define ONLY_APPLET (MOD_APPLET_CNT <= 1) + +/* Do not bother if MODPROBE_SMALL=y but no applets selected. */ +/* The rest of the file is in this if block. */ +#if MOD_APPLET_CNT > 0 + +#define ONLY_APPLET (MOD_APPLET_CNT == 1) #define is_modprobe (ENABLE_MODPROBE && (ONLY_APPLET || applet_name[0] == 'm')) #define is_depmod (ENABLE_DEPMOD && (ONLY_APPLET || applet_name[0] == 'd')) #define is_insmod (ENABLE_INSMOD && (ONLY_APPLET || applet_name[0] == 'i')) @@ -1063,3 +1068,5 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) return exitcode; #endif /* MODPROBE || INSMOD || RMMOD */ } + +#endif /* MOD_APPLET_CNT > 0 */ -- cgit v1.2.3-55-g6feb From 53487a8d221d9568b6d2ea81e729456b084dcdf9 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Mon, 9 Jan 2017 17:02:51 +0100 Subject: kill: need not build kill.c when ash's job control is off ash kill builtin depends on the job control config option. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- procps/Kbuild.src | 5 +---- procps/kill.c | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/procps/Kbuild.src b/procps/Kbuild.src index 82f37f0df..dedef8881 100644 --- a/procps/Kbuild.src +++ b/procps/Kbuild.src @@ -8,8 +8,5 @@ lib-y:= INSERT -lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash -lib-$(CONFIG_SH_IS_ASH) += kill.o # used for built-in kill by ash -lib-$(CONFIG_BASH_IS_ASH) += kill.o # used for built-in kill by ash - +lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o # used for built-in kill by ash lib-$(CONFIG_HUSH_KILL) += kill.o # used for built-in kill by hush diff --git a/procps/kill.c b/procps/kill.c index 579c8e53c..7c0822542 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -285,8 +285,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv) /* Looks like they want to do a kill. Do that */ while (arg) { -#if ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH \ - || ENABLE_HUSH_KILL +#if ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL /* * We need to support shell's "hack formats" of * " -PRGP_ID" (yes, with a leading space) -- cgit v1.2.3-55-g6feb From 1cc6804f6980d2732df97f15933c93d34041dd83 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 9 Jan 2017 17:10:04 +0100 Subject: hush: make echo builtin optional It's a bit overkill (who would want it off?) but ash already has it configurable. Let's be symmetric. Also tweak kbuild logic to use ASH_BUILTIN_ECHO to select echo.o, not ASH. Signed-off-by: Denys Vlasenko --- coreutils/Kbuild.src | 12 ++++-------- shell/hush.c | 29 ++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src index 9ac6b9e78..d0b3f629b 100644 --- a/coreutils/Kbuild.src +++ b/coreutils/Kbuild.src @@ -14,15 +14,11 @@ lib-$(CONFIG_MORE) += cat.o # more uses it if stdout isn't a tty lib-$(CONFIG_LESS) += cat.o # less too lib-$(CONFIG_CRONTAB) += cat.o # crontab -l lib-$(CONFIG_ADDUSER) += chown.o # used by adduser -lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser +lib-$(CONFIG_ADDGROUP) += chown.o # used by addgroup lib-$(CONFIG_FTPD) += ls.o # used by ftpd -lib-$(CONFIG_ASH) += echo.o # used by ash -lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash -lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash -lib-$(CONFIG_HUSH) += echo.o # used by hush -lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush -lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush +lib-$(CONFIG_ASH_BUILTIN_ECHO) += echo.o +lib-$(CONFIG_HUSH_ECHO) += echo.o lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o -lib-$(CONFIG_HUSH_PRINTF) += printf.o +lib-$(CONFIG_HUSH_PRINTF) += printf.o diff --git a/shell/hush.c b/shell/hush.c index 5c5715b3f..22d71cb07 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -195,6 +195,20 @@ //config: This instructs hush to print commands before execution. //config: Adds ~300 bytes. //config: +//config:config HUSH_ECHO +//config: bool "echo builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable echo builtin in hush. +//config: +//config:config HUSH_PRINTF +//config: bool "printf builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: help +//config: Enable printf builtin in hush. +//config: //config:config HUSH_EXPORT //config: bool "export builtin" //config: default y @@ -216,13 +230,6 @@ //config: help //config: Enable help builtin in hush. Code size + ~1 kbyte. //config: -//config:config HUSH_PRINTF -//config: bool "printf builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable printf builtin in hush. -//config: //config:config HUSH_KILL //config: bool "kill builtin (for kill %jobspec)" //config: default y @@ -934,7 +941,9 @@ struct globals { /* Function prototypes for builtins */ static int builtin_cd(char **argv) FAST_FUNC; +#if ENABLE_HUSH_ECHO static int builtin_echo(char **argv) FAST_FUNC; +#endif static int builtin_eval(char **argv) FAST_FUNC; static int builtin_exec(char **argv) FAST_FUNC; static int builtin_exit(char **argv) FAST_FUNC; @@ -1091,7 +1100,9 @@ static const struct built_in_command bltins1[] = { * Maybe make it configurable? */ static const struct built_in_command bltins2[] = { BLTIN("[" , builtin_test , NULL), +#if ENABLE_HUSH_ECHO BLTIN("echo" , builtin_echo , NULL), +#endif #if ENABLE_HUSH_PRINTF BLTIN("printf" , builtin_printf , NULL), #endif @@ -8832,12 +8843,12 @@ static int FAST_FUNC builtin_test(char **argv) { return run_applet_main(argv, test_main); } - +#if ENABLE_HUSH_ECHO static int FAST_FUNC builtin_echo(char **argv) { return run_applet_main(argv, echo_main); } - +#endif #if ENABLE_HUSH_PRINTF static int FAST_FUNC builtin_printf(char **argv) { -- cgit v1.2.3-55-g6feb From 61a91af63dbc91f85058efda5c542dfc859ab1be Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Mon, 9 Jan 2017 18:46:58 +0100 Subject: kill: optimizations for single-applet build * Fix a bug with a configuration in which the shell's kill builtin would be mistreated as a killall command (i.e. '-q' works, and 'kill process_name' succeeds when it shouldn't): CONFIG_ASH_JOB_CONTROL=y CONFIG_HUSH_KILL=y # CONFIG_KILL is not set CONFIG_KILLALL=y # CONFIG_KILLALL5 is not set * Optimize out unneeded code when the relevant applets are not selected. * Move kbuild lines about shells' kill builtins from Kbuild.src to kill.c, to accompany the new HAVE_SH_KILL macro. I hope this would make maintanence a little bit easier. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- procps/Kbuild.src | 3 --- procps/kill.c | 46 ++++++++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/procps/Kbuild.src b/procps/Kbuild.src index dedef8881..6b4fb7470 100644 --- a/procps/Kbuild.src +++ b/procps/Kbuild.src @@ -7,6 +7,3 @@ lib-y:= INSERT - -lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o # used for built-in kill by ash -lib-$(CONFIG_HUSH_KILL) += kill.o # used for built-in kill by hush diff --git a/procps/kill.c b/procps/kill.c index 7c0822542..0ef1716a4 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -92,28 +92,34 @@ * This is needed to avoid collision with kill -9 ... syntax */ +//kbuild:lib-$(CONFIG_ASH_JOB_CONTROL) += kill.o +//kbuild:lib-$(CONFIG_HUSH_KILL) += kill.o + +#define SH_KILL (ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL) +/* If shells want to have "kill", for ifdefs it's like ENABLE_KILL=1 */ +#if SH_KILL +# undef ENABLE_KILL +# define ENABLE_KILL 1 +#endif +#define KILL_APPLET_CNT (ENABLE_KILL + ENABLE_KILLALL + ENABLE_KILLALL5) + int kill_main(int argc UNUSED_PARAM, char **argv) { char *arg; pid_t pid; int signo = SIGTERM, errors = 0, quiet = 0; -#if ENABLE_KILL && !ENABLE_KILLALL && !ENABLE_KILLALL5 -# define killall 0 -# define killall5 0 -#elif !ENABLE_KILL && ENABLE_KILLALL && !ENABLE_KILLALL5 -# define killall 1 -# define killall5 0 -#elif !ENABLE_KILL && !ENABLE_KILLALL && ENABLE_KILLALL5 -# define killall 0 -# define killall5 1 + +#if KILL_APPLET_CNT == 1 +# define is_killall ENABLE_KILLALL +# define is_killall5 ENABLE_KILLALL5 #else /* How to determine who we are? find 3rd char from the end: * kill, killall, killall5 * ^i ^a ^l - it's unique * (checking from the start is complicated by /bin/kill... case) */ const char char3 = argv[0][strlen(argv[0]) - 3]; -# define killall (ENABLE_KILLALL && char3 == 'a') -# define killall5 (ENABLE_KILLALL5 && char3 == 'l') +# define is_killall (ENABLE_KILLALL && char3 == 'a') +# define is_killall5 (ENABLE_KILLALL5 && char3 == 'l') #endif /* Parse any options */ @@ -162,7 +168,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv) } /* The -q quiet option */ - if (killall && arg[1] == 'q' && arg[2] == '\0') { + if (is_killall && arg[1] == 'q' && arg[2] == '\0') { quiet = 1; arg = *++argv; if (!arg) @@ -174,7 +180,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv) arg++; /* skip '-' */ /* -o PID? (if present, it always is at the end of command line) */ - if (killall5 && arg[0] == 'o') + if (is_killall5 && arg[0] == 'o') goto do_it_now; if (argv[1] && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */ @@ -190,7 +196,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv) do_it_now: pid = getpid(); - if (killall5) { + if (is_killall5) { pid_t sid; procps_status_t* p = NULL; /* compat: exitcode 2 is "no one was signaled" */ @@ -248,13 +254,14 @@ int kill_main(int argc UNUSED_PARAM, char **argv) return ret; } +#if ENABLE_KILL || ENABLE_KILLALL /* Pid or name is required for kill/killall */ if (!arg) { bb_error_msg("you need to specify whom to kill"); return EXIT_FAILURE; } - if (killall) { + if (!ENABLE_KILL || is_killall) { /* Looks like they want to do a killall. Do that */ do { pid_t* pidList; @@ -282,10 +289,12 @@ int kill_main(int argc UNUSED_PARAM, char **argv) } while (arg); return errors; } +#endif +#if ENABLE_KILL /* Looks like they want to do a kill. Do that */ while (arg) { -#if ENABLE_ASH_JOB_CONTROL || ENABLE_HUSH_KILL +# if SH_KILL /* * We need to support shell's "hack formats" of * " -PRGP_ID" (yes, with a leading space) @@ -307,7 +316,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv) } arg = end; /* can only point to ' ' or '\0' now */ } -#else +# else /* ENABLE_KILL but !SH_KILL */ pid = bb_strtoi(arg, NULL, 10); if (errno) { bb_error_msg("invalid number '%s'", arg); @@ -316,8 +325,9 @@ int kill_main(int argc UNUSED_PARAM, char **argv) bb_perror_msg("can't kill pid %d", (int)pid); errors++; } -#endif +# endif arg = *++argv; } return errors; +#endif } -- cgit v1.2.3-55-g6feb From f10f7a21d40d5ce0846414973e88602a59d4580e Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Thu, 5 Jan 2017 09:25:03 +0800 Subject: Allow FAST_FUNC to be overridden at build time Busybox uses FAST_FUNC macro to tweak with IA-32 calling conventions in order to make the function call slightly smaller or slightly faster. However, when I experiment with GCC's LTO (Link Time Optimization), I discovered that FAST_FUNC could hinder LTO's optimization so that the resulting executable become a few bytes larger (than what is compiled without FAST_FUNC). This change allows to specify e.g. CONFIG_EXTRA_CFLAGS="-DFAST_FUNC= -flto" and compile with LTO without a source code hack. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- include/platform.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/platform.h b/include/platform.h index c987d418c..6c7d03dc7 100644 --- a/include/platform.h +++ b/include/platform.h @@ -108,13 +108,18 @@ * and/or smaller by using modified ABI. It is usually only needed * on non-static, busybox internal functions. Recent versions of gcc * optimize statics automatically. FAST_FUNC on static is required - * only if you need to match a function pointer's type */ -#if __GNUC_PREREQ(3,0) && defined(i386) /* || defined(__x86_64__)? */ + * only if you need to match a function pointer's type. + * FAST_FUNC may not work well with -flto so allow user to disable this. + * (-DFAST_FUNC= ) + */ +#ifndef FAST_FUNC +# if __GNUC_PREREQ(3,0) && defined(i386) /* stdcall makes callee to pop arguments from stack, not caller */ -# define FAST_FUNC __attribute__((regparm(3),stdcall)) +# define FAST_FUNC __attribute__((regparm(3),stdcall)) /* #elif ... - add your favorite arch today! */ -#else -# define FAST_FUNC +# else +# define FAST_FUNC +# endif #endif /* Make all declarations hidden (-fvisibility flag only affects definitions) */ -- cgit v1.2.3-55-g6feb From f560422fa079b07a761a572ca4f9cf287c2cc47e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 14:58:54 +0100 Subject: Big cleanup in config help and description Redundant help texts (one which only repeats the description) are deleted. Descriptions and help texts are trimmed. Some config options are moved, even across menus. No config option _names_ are changed. Signed-off-by: Denys Vlasenko --- Config.in | 32 +++++++++-- archival/Config.src | 10 ---- archival/ar.c | 2 +- archival/bbunzip.c | 4 +- archival/cpio.c | 4 +- archival/gzip.c | 4 +- archival/tar.c | 35 +++++------- console-tools/loadfont.c | 8 +-- console-tools/setconsole.c | 2 - coreutils/Config.src | 16 +----- coreutils/chown.c | 2 - coreutils/cp.c | 4 +- coreutils/dd.c | 4 +- coreutils/df.c | 8 ++- coreutils/echo.c | 6 +-- coreutils/env.c | 2 - coreutils/expand.c | 4 -- coreutils/head.c | 4 +- coreutils/install.c | 2 - coreutils/ls.c | 6 --- coreutils/md5_sha1_sum.c | 1 - coreutils/mkdir.c | 2 - coreutils/mv.c | 2 - coreutils/split.c | 2 +- coreutils/tail.c | 7 ++- coreutils/wc.c | 4 +- debianutils/run_parts.c | 2 - debianutils/start_stop_daemon.c | 13 ++--- editors/Config.src | 2 +- editors/diff.c | 2 - editors/vi.c | 33 ++++++------ findutils/find.c | 14 ----- init/init.c | 4 +- libbb/Config.src | 17 +----- loginutils/Config.src | 2 +- loginutils/addgroup.c | 6 +-- loginutils/adduser.c | 2 - loginutils/deluser.c | 2 +- loginutils/login.c | 6 +-- loginutils/su.c | 9 ++-- miscutils/devfsd.c | 2 +- miscutils/hdparm.c | 12 ++--- miscutils/last.c | 2 +- miscutils/less.c | 5 +- modutils/Config.src | 4 +- networking/ftpd.c | 2 +- networking/ftpgetput.c | 2 - networking/httpd.c | 10 ++-- networking/ifupdown.c | 8 +-- networking/ipcalc.c | 12 ++--- networking/netstat.c | 2 +- networking/tftp.c | 4 +- networking/traceroute.c | 2 - networking/udhcp/Config.src | 4 +- networking/wget.c | 16 +++--- procps/Config.src | 2 +- procps/pidof.c | 8 +-- procps/ps.c | 16 +++--- procps/uptime.c | 4 +- selinux/chcon.c | 2 - selinux/runcon.c | 2 - shell/ash.c | 85 +++++++++++++----------------- shell/hush.c | 68 ++++++------------------ util-linux/Config.src | 2 +- util-linux/dmesg.c | 2 +- util-linux/fbset.c | 4 +- util-linux/fdisk.c | 2 - util-linux/hwclock.c | 4 -- util-linux/mount.c | 2 +- util-linux/volume_id/bcache.c | 4 -- util-linux/volume_id/btrfs.c | 4 -- util-linux/volume_id/cramfs.c | 4 -- util-linux/volume_id/exfat.c | 2 - util-linux/volume_id/ext.c | 4 -- util-linux/volume_id/f2fs.c | 2 - util-linux/volume_id/fat.c | 4 -- util-linux/volume_id/hfs.c | 4 -- util-linux/volume_id/iso9660.c | 4 -- util-linux/volume_id/jfs.c | 4 -- util-linux/volume_id/linux_raid.c | 4 -- util-linux/volume_id/linux_swap.c | 4 -- util-linux/volume_id/luks.c | 4 -- util-linux/volume_id/nilfs.c | 2 - util-linux/volume_id/ntfs.c | 4 -- util-linux/volume_id/ocfs2.c | 4 -- util-linux/volume_id/reiserfs.c | 4 -- util-linux/volume_id/romfs.c | 4 -- util-linux/volume_id/squashfs.c | 2 - util-linux/volume_id/sysv.c | 4 -- util-linux/volume_id/ubifs.c | 2 - util-linux/volume_id/udf.c | 4 -- util-linux/volume_id/unused_highpoint.c | 4 -- util-linux/volume_id/unused_hpfs.c | 4 -- util-linux/volume_id/unused_isw_raid.c | 4 -- util-linux/volume_id/unused_lsi_raid.c | 4 -- util-linux/volume_id/unused_lvm.c | 4 -- util-linux/volume_id/unused_mac.c | 4 -- util-linux/volume_id/unused_minix.c | 4 -- util-linux/volume_id/unused_msdos.c | 4 -- util-linux/volume_id/unused_nvidia_raid.c | 4 -- util-linux/volume_id/unused_promise_raid.c | 4 -- util-linux/volume_id/unused_silicon_raid.c | 4 -- util-linux/volume_id/unused_ufs.c | 4 -- util-linux/volume_id/unused_via_raid.c | 4 -- util-linux/volume_id/xfs.c | 4 -- 105 files changed, 203 insertions(+), 512 deletions(-) diff --git a/Config.in b/Config.in index 66f7787d2..db1587169 100644 --- a/Config.in +++ b/Config.in @@ -22,7 +22,7 @@ config DESKTOP If you are preparing your build to be used on an embedded box where you have tighter control over the entire set of userspace - tools, you can unselect this option for smaller code size. + tools, you can unselect this option for smaller code size. config EXTRA_COMPAT bool "Provide compatible behavior for rare corner cases (bigger code)" @@ -50,6 +50,26 @@ config USE_PORTABLE_CODE compiler other than gcc. If you do use gcc, this option may needlessly increase code size. +#fixme: delete, create suboptions for applets which use this +config FEATURE_AUTOWIDTH + bool "Calculate terminal & column widths" + default y + help + This option allows utilities such as 'ls', 'telnet' etc + to determine the width of the screen, which can allow them to + display additional text or avoid wrapping text onto the next line. + If you leave this disabled, your utilities will be especially + primitive and will be unable to determine the current screen width. + +#fixme: delete, create suboptions for applets which use this +config FEATURE_USE_TERMIOS + bool "Use termios for one-stroke input" + default y + help + This option allows utilities such as 'top' to accept keyboard + commands. Without this option, they simply refresh display + after a fixed period. + config SHOW_USAGE bool "Show applet usage messages" default y @@ -113,14 +133,14 @@ config INSTALL_NO_USR never to /usr/bin or /usr/sbin. config PAM - bool "Support for PAM (Pluggable Authentication Modules)" + bool "Support PAM (Pluggable Authentication Modules)" default n help Use PAM in some busybox applets (currently login and httpd) instead of direct access to password database. config LONG_OPTS - bool "Support for --long-options" + bool "Support --long-options" default y help Enable this if you want busybox applets to use the gnu --long-option @@ -187,7 +207,7 @@ config PID_FILE_PATH specify a pidfile path. config FEATURE_SUID - bool "Support for SUID/SGID handling" + bool "Support SUID/SGID handling" default y help With this option you can install the busybox binary belonging @@ -611,6 +631,8 @@ config DEBUG_SANITIZE catch bad memory accesses (e.g. buffer overflows), but will make the executable larger and slow down runtime a bit. + This adds -fsanitize=foo options to gcc command line. + If you aren't developing/testing busybox, say N here. config UNIT_TEST @@ -625,7 +647,7 @@ config WERROR bool "Abort compilation on any warning" default n help - Selecting this will add -Werror to gcc command line. + This adds -Werror to gcc command line. Most people should answer N. diff --git a/archival/Config.src b/archival/Config.src index 5e7cfc0a4..0c97f3d7c 100644 --- a/archival/Config.src +++ b/archival/Config.src @@ -8,32 +8,22 @@ menu "Archival Utilities" config FEATURE_SEAMLESS_XZ bool "Make tar, rpm, modprobe etc understand .xz data" default y - help - Make tar, rpm, modprobe etc understand .xz data. config FEATURE_SEAMLESS_LZMA bool "Make tar, rpm, modprobe etc understand .lzma data" default y - help - Make tar, rpm, modprobe etc understand .lzma data. config FEATURE_SEAMLESS_BZ2 bool "Make tar, rpm, modprobe etc understand .bz2 data" default y - help - Make tar, rpm, modprobe etc understand .bz2 data. config FEATURE_SEAMLESS_GZ bool "Make tar, rpm, modprobe etc understand .gz data" default y - help - Make tar, rpm, modprobe etc understand .gz data. config FEATURE_SEAMLESS_Z bool "Make tar, rpm, modprobe etc understand .Z data" default n # it is ancient - help - Make tar, rpm, modprobe etc understand .Z data. INSERT diff --git a/archival/ar.c b/archival/ar.c index e49d5cb2b..d119c75ad 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -31,7 +31,7 @@ //config: probably say N here: most compilers come with their own ar utility. //config: //config:config FEATURE_AR_LONG_FILENAMES -//config: bool "Support for long filenames (not needed for debs)" +//config: bool "Support long filenames (not needed for debs)" //config: default y //config: depends on AR //config: help diff --git a/archival/bbunzip.c b/archival/bbunzip.c index aa8453440..fb7a3678d 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -312,8 +312,6 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //config: bool "Enable long options" //config: default y //config: depends on (GUNZIP || ZCAT) && LONG_OPTS -//config: help -//config: Enable use of long options. //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) //applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) @@ -522,7 +520,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //config: IOW: you'll get lzma applet, but it will always require -d option. //config: //config:config FEATURE_LZMA_FAST -//config: bool "Optimize unlzma for speed" +//config: bool "Optimize for speed" //config: default n //config: depends on UNLZMA || LZCAT || LZMA //config: help diff --git a/archival/cpio.c b/archival/cpio.c index 540218cb2..683f0bb1f 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -29,7 +29,7 @@ //config: should probably say N here. //config: //config:config FEATURE_CPIO_O -//config: bool "Support for archive creation" +//config: bool "Support archive creation" //config: default y //config: depends on CPIO //config: help @@ -37,7 +37,7 @@ //config: format only. //config: //config:config FEATURE_CPIO_P -//config: bool "Support for passthrough mode" +//config: bool "Support passthrough mode" //config: default y //config: depends on FEATURE_CPIO_O //config: help diff --git a/archival/gzip.c b/archival/gzip.c index 63bf76053..e698c26cd 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -48,11 +48,9 @@ aa: 85.1% -- replaced with aa.gz //config: bool "Enable long options" //config: default y //config: depends on GZIP && LONG_OPTS -//config: help -//config: Enable use of long options, increases size by about 106 Bytes //config: //config:config GZIP_FAST -//config: int "Trade memory for gzip speed (0:small,slow - 2:fast,big)" +//config: int "Trade memory for speed (0:small,slow - 2:fast,big)" //config: default 0 //config: range 0 2 //config: depends on GZIP diff --git a/archival/tar.c b/archival/tar.c index 8e315c610..b1d58a2df 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -49,13 +49,15 @@ //config: create compressed archives. It's probably the most widely used //config: UNIX archive program. //config: +//config:config FEATURE_TAR_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on TAR && LONG_OPTS +//config: //config:config FEATURE_TAR_CREATE -//config: bool "Enable archive creation" +//config: bool "Enable -c (archive creation)" //config: default y //config: depends on TAR -//config: help -//config: If you enable this option you'll be able to create -//config: tar archives using the `-c' option. //config: //config:config FEATURE_TAR_AUTODETECT //config: bool "Autodetect compressed tarballs" @@ -74,7 +76,7 @@ //config: a list of files to include or exclude from an archive. //config: //config:config FEATURE_TAR_OLDGNU_COMPATIBILITY -//config: bool "Support for old tar header format" +//config: bool "Support old tar header format" //config: default y //config: depends on TAR || DPKG //config: help @@ -93,22 +95,12 @@ //config: tarballs still exist. //config: //config:config FEATURE_TAR_GNU_EXTENSIONS -//config: bool "Support for GNU tar extensions (long filenames)" +//config: bool "Support GNU tar extensions (long filenames)" //config: default y //config: depends on TAR || DPKG -//config: help -//config: With this option busybox supports GNU long filenames and -//config: linknames. -//config: -//config:config FEATURE_TAR_LONG_OPTIONS -//config: bool "Enable long options" -//config: default y -//config: depends on TAR && LONG_OPTS -//config: help -//config: Enable use of long options, increases size by about 400 Bytes //config: //config:config FEATURE_TAR_TO_COMMAND -//config: bool "Support for writing to an external program" +//config: bool "Support writing to an external program (--to-command)" //config: default y //config: depends on TAR && FEATURE_TAR_LONG_OPTIONS //config: help @@ -121,20 +113,17 @@ //config: default y //config: depends on TAR //config: help -//config: Enables use of user and group names in tar. This affects contents +//config: Enable use of user and group names in tar. This affects contents //config: listings (-t) and preserving permissions when unpacking (-p). //config: +200 bytes. //config: //config:config FEATURE_TAR_NOPRESERVE_TIME -//config: bool "Enable -m (do not preserve time) option" +//config: bool "Enable -m (do not preserve time) GNU option" //config: default y //config: depends on TAR -//config: help -//config: With this option busybox supports GNU tar -m -//config: (do not preserve time) option. //config: //config:config FEATURE_TAR_SELINUX -//config: bool "Support for extracting SELinux labels" +//config: bool "Support extracting SELinux labels" //config: default n //config: depends on TAR && SELINUX //config: help diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c index 52605baa1..29f723ec0 100644 --- a/console-tools/loadfont.c +++ b/console-tools/loadfont.c @@ -42,18 +42,14 @@ //config: depends on LOADFONT || SETFONT //config: //config:config FEATURE_LOADFONT_PSF2 -//config: bool "Support for PSF2 console fonts" +//config: bool "Support PSF2 console fonts" //config: default y //config: depends on LOADFONT || SETFONT -//config: help -//config: Support PSF2 console fonts. //config: //config:config FEATURE_LOADFONT_RAW -//config: bool "Support for old (raw) console fonts" +//config: bool "Support old (raw) console fonts" //config: default y //config: depends on LOADFONT || SETFONT -//config: help -//config: Support old (raw) console fonts. //applet:IF_LOADFONT(APPLET(loadfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) //applet:IF_SETFONT(APPLET(setfont, BB_DIR_USR_SBIN, BB_SUID_DROP)) diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c index 58057268d..d47a33d59 100644 --- a/console-tools/setconsole.c +++ b/console-tools/setconsole.c @@ -19,8 +19,6 @@ //config: bool "Enable long options" //config: default y //config: depends on SETCONSOLE && LONG_OPTS -//config: help -//config: Support long options for the setconsole applet. //applet:IF_SETCONSOLE(APPLET(setconsole, BB_DIR_SBIN, BB_SUID_DROP)) diff --git a/coreutils/Config.src b/coreutils/Config.src index c056320f8..1d2fea1fb 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -27,25 +27,11 @@ config FEATURE_PRESERVE_HARDLINKS help Allow cp and mv to preserve hard links. -comment "Common options for ls, more and telnet" - depends on LS || MORE || TELNET - -config FEATURE_AUTOWIDTH - bool "Calculate terminal & column widths" - default y - depends on LS || MORE || TELNET - help - This option allows utilities such as 'ls', 'more' and 'telnet' - to determine the width of the screen, which can allow them to - display additional text or avoid wrapping text onto the next line. - If you leave this disabled, your utilities will be especially - primitive and will be unable to determine the current screen width. - comment "Common options for df, du, ls" depends on DF || DU || LS config FEATURE_HUMAN_READABLE - bool "Support for human readable output (example 13k, 23M, 235G)" + bool "Support human readable output (example 13k, 23M, 235G)" default y depends on DF || DU || LS help diff --git a/coreutils/chown.c b/coreutils/chown.c index 50b06d73a..12cd0eacc 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -17,8 +17,6 @@ //config: bool "Enable long options" //config: default y //config: depends on CHOWN && LONG_OPTS -//config: help -//config: Enable use of long options //applet:IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown)) diff --git a/coreutils/cp.c b/coreutils/cp.c index 4ecdaafda..1e5f36d10 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -18,11 +18,11 @@ //config: cp is used to copy files and directories. //config: //config:config FEATURE_CP_LONG_OPTIONS -//config: bool "Enable long options for cp" +//config: bool "Enable long options" //config: default y //config: depends on CP && LONG_OPTS //config: help -//config: Enable long options for cp. +//config: Enable long options. //config: Also add support for --parents option. //applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) diff --git a/coreutils/dd.c b/coreutils/dd.c index 3d1ba2ee6..5e68087fc 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -41,7 +41,7 @@ //config: default y //config: depends on DD //config: help -//config: Enables support for writing a certain number of bytes in and out, +//config: Enable support for writing a certain number of bytes in and out, //config: at a time, and performing conversions on the data stream. //config: //config:config FEATURE_DD_STATUS @@ -49,7 +49,7 @@ //config: default y //config: depends on DD //config: help -//config: Enables support for status=noxfer/none option. +//config: Enable support for status=noxfer/none option. //applet:IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) diff --git a/coreutils/df.c b/coreutils/df.c index 79e4c4670..cf367161a 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -29,11 +29,9 @@ //config: default y //config: depends on DF //config: help -//config: This option enables -a, -i and -B. -//config: -//config: -a Show all filesystems -//config: -i Inodes -//config: -B Blocksize +//config: -a Show all filesystems +//config: -i Inodes +//config: -B Blocksize //applet:IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) diff --git a/coreutils/echo.c b/coreutils/echo.c index fd0d9b780..d0dba650d 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -26,11 +26,9 @@ //config: //config:# this entry also appears in shell/Config.in, next to the echo builtin //config:config FEATURE_FANCY_ECHO -//config: bool "Enable echo options (-n and -e)" +//config: bool "Enable -n and -e options" //config: default y -//config: depends on ECHO || ASH_BUILTIN_ECHO || HUSH -//config: help -//config: This adds options (-n and -e) to echo. +//config: depends on ECHO || ASH_BUILTIN_ECHO || HUSH_ECHO //applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo)) diff --git a/coreutils/env.c b/coreutils/env.c index e91eddb5c..2bd5f41d0 100644 --- a/coreutils/env.c +++ b/coreutils/env.c @@ -35,8 +35,6 @@ //config: bool "Enable long options" //config: default y //config: depends on ENV && LONG_OPTS -//config: help -//config: Support long options for the env applet. //applet:IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) diff --git a/coreutils/expand.c b/coreutils/expand.c index bb59af46d..29affc932 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -30,8 +30,6 @@ //config: bool "Enable long options" //config: default y //config: depends on EXPAND && LONG_OPTS -//config: help -//config: Support long options for the expand applet. //config: //config:config UNEXPAND //config: bool "unexpand" @@ -43,8 +41,6 @@ //config: bool "Enable long options" //config: default y //config: depends on UNEXPAND && LONG_OPTS -//config: help -//config: Support long options for the unexpand applet. //applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) //applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand)) diff --git a/coreutils/head.c b/coreutils/head.c index 176e91e3a..d49113e7f 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -14,11 +14,9 @@ //config: from files. //config: //config:config FEATURE_FANCY_HEAD -//config: bool "Enable head options (-c, -q, and -v)" +//config: bool "Enable -c, -q, and -v" //config: default y //config: depends on HEAD -//config: help -//config: This enables the head options (-c, -q, and -v). //applet:IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head)) diff --git a/coreutils/install.c b/coreutils/install.c index 831f9b802..2a642bdb6 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -15,8 +15,6 @@ //config: bool "Enable long options" //config: default y //config: depends on INSTALL && LONG_OPTS -//config: help -//config: Support long options for the install applet. //applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/coreutils/ls.c b/coreutils/ls.c index 0f35c70d5..531eb85b5 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -37,22 +37,16 @@ //config: bool "Enable filetyping options (-p and -F)" //config: default y //config: depends on LS -//config: help -//config: Enable the ls options (-p and -F). //config: //config:config FEATURE_LS_FOLLOWLINKS //config: bool "Enable symlinks dereferencing (-L)" //config: default y //config: depends on LS -//config: help -//config: Enable the ls option (-L). //config: //config:config FEATURE_LS_RECURSIVE //config: bool "Enable recursion (-R)" //config: default y //config: depends on LS -//config: help -//config: Enable the ls option (-R). //config: //config:config FEATURE_LS_SORTFILES //config: bool "Sort the file names" diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 783f44027..76788554c 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -45,7 +45,6 @@ //config: help //config: Enabling the -c options allows files to be checked //config: against pre-calculated hash values. -//config: //config: -s and -w are useful options when verifying checksums. //applet:IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum)) diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 3afe76c28..fcc34f1ad 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -23,8 +23,6 @@ //config: bool "Enable long options" //config: default y //config: depends on MKDIR && LONG_OPTS -//config: help -//config: Support long options for the mkdir applet. //applet:IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir)) diff --git a/coreutils/mv.c b/coreutils/mv.c index 1cc318fd1..df2ef0a52 100644 --- a/coreutils/mv.c +++ b/coreutils/mv.c @@ -21,8 +21,6 @@ //config: bool "Enable long options" //config: default y //config: depends on MV && LONG_OPTS -//config: help -//config: Support long options for the mv applet. //applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) diff --git a/coreutils/split.c b/coreutils/split.c index 50918a1ce..7af359d0e 100644 --- a/coreutils/split.c +++ b/coreutils/split.c @@ -9,7 +9,7 @@ //config: bool "split" //config: default y //config: help -//config: split a file into pieces. +//config: Split a file into pieces. //config: //config:config FEATURE_SPLIT_FANCY //config: bool "Fancy extensions" diff --git a/coreutils/tail.c b/coreutils/tail.c index 99f58ddd8..e7a24a7a8 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -26,13 +26,12 @@ //config: from files. //config: //config:config FEATURE_FANCY_TAIL -//config: bool "Enable extra tail options (-q, -s, -v, and -F)" +//config: bool "Enable -q, -s, -v, and -F options" //config: default y //config: depends on TAIL //config: help -//config: The options (-q, -s, -v and -F) are provided by GNU tail, but -//config: are not specific in the SUSv3 standard. -//config: +//config: These options are provided by GNU tail, but +//config: are not specific in the SUSv3 standard: //config: -q Never output headers giving file names //config: -s SEC Wait SEC seconds between reads with -f //config: -v Always output headers giving file names diff --git a/coreutils/wc.c b/coreutils/wc.c index 73837141e..4c53049b0 100644 --- a/coreutils/wc.c +++ b/coreutils/wc.c @@ -40,11 +40,11 @@ //config: in specified files. //config: //config:config FEATURE_WC_LARGE -//config: bool "Support very large files in wc" +//config: bool "Support very large counts" //config: default y //config: depends on WC //config: help -//config: Use "unsigned long long" in wc for counter variables. +//config: Use "unsigned long long" for counter variables. //applet:IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c index 0bb666abc..3ef28f1d4 100644 --- a/debianutils/run_parts.c +++ b/debianutils/run_parts.c @@ -41,8 +41,6 @@ //config: bool "Enable long options" //config: default y //config: depends on RUN_PARTS && LONG_OPTS -//config: help -//config: Support long options for the run-parts applet. //config: //config:config FEATURE_RUN_PARTS_FANCY //config: bool "Support additional arguments" diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 3625ffee8..4a9e0653e 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -64,22 +64,19 @@ Misc options: //config: termination of system-level processes, usually the ones //config: started during the startup of the system. //config: +//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on START_STOP_DAEMON && LONG_OPTS +//config: //config:config FEATURE_START_STOP_DAEMON_FANCY //config: bool "Support additional arguments" //config: default y //config: depends on START_STOP_DAEMON //config: help -//config: Support additional arguments. //config: -o|--oknodo ignored since we exit with 0 anyway //config: -v|--verbose //config: -N|--nicelevel N -//config: -//config:config FEATURE_START_STOP_DAEMON_LONG_OPTIONS -//config: bool "Enable long options" -//config: default y -//config: depends on START_STOP_DAEMON && LONG_OPTS -//config: help -//config: Support long options for the start-stop-daemon applet. //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) diff --git a/editors/Config.src b/editors/Config.src index c6e9d92af..8f2b265bd 100644 --- a/editors/Config.src +++ b/editors/Config.src @@ -12,7 +12,7 @@ config FEATURE_ALLOW_EXEC default y depends on VI || AWK help - Enables vi and awk features which allows user to execute + Enables vi and awk features which allow user to execute shell commands (using system() C call). endmenu diff --git a/editors/diff.c b/editors/diff.c index 75229ad8c..0eb825cfb 100644 --- a/editors/diff.c +++ b/editors/diff.c @@ -88,8 +88,6 @@ //config: bool "Enable long options" //config: default y //config: depends on DIFF && LONG_OPTS -//config: help -//config: Enable use of long options. //config: //config:config FEATURE_DIFF_DIR //config: bool "Enable directory support" diff --git a/editors/vi.c b/editors/vi.c index 38a4692fd..b56b04bdd 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -30,7 +30,7 @@ //config: you may wish to use something else. //config: //config:config FEATURE_VI_MAX_LEN -//config: int "Maximum screen width in vi" +//config: int "Maximum screen width" //config: range 256 16384 //config: default 4096 //config: depends on VI @@ -39,7 +39,7 @@ //config: Make it smaller than 4k only if you are very limited on memory. //config: //config:config FEATURE_VI_8BIT -//config: bool "Allow vi to display 8-bit chars (otherwise shows dots)" +//config: bool "Allow to display 8-bit chars (otherwise shows dots)" //config: default n //config: depends on VI //config: help @@ -53,7 +53,7 @@ //config: default y //config: depends on VI //config: help -//config: Enable a limited set of colon commands for vi. This does not +//config: Enable a limited set of colon commands. This does not //config: provide an "ex" mode. //config: //config:config FEATURE_VI_YANKMARK @@ -61,16 +61,14 @@ //config: default y //config: depends on VI //config: help -//config: This will enable you to use yank and put, as well as mark in -//config: busybox vi. +//config: This will enable you to use yank and put, as well as mark. //config: //config:config FEATURE_VI_SEARCH //config: bool "Enable search and replace cmds" //config: default y //config: depends on VI //config: help -//config: Select this if you wish to be able to do search and replace in -//config: busybox vi. +//config: Select this if you wish to be able to do search and replace. //config: //config:config FEATURE_VI_REGEX_SEARCH //config: bool "Enable regex in search and replace" @@ -84,16 +82,15 @@ //config: default y //config: depends on VI //config: help -//config: Selecting this option will make busybox vi signal aware. This will -//config: make busybox vi support SIGWINCH to deal with Window Changes, catch -//config: Ctrl-Z and Ctrl-C and alarms. +//config: Selecting this option will make vi signal aware. This will support +//config: SIGWINCH to deal with Window Changes, catch ^Z and ^C and alarms. //config: //config:config FEATURE_VI_DOT_CMD //config: bool "Remember previous cmd and \".\" cmd" //config: default y //config: depends on VI //config: help -//config: Make busybox vi remember the last command and be able to repeat it. +//config: Make vi remember the last command and be able to repeat it. //config: //config:config FEATURE_VI_READONLY //config: bool "Enable -R option and \"view\" mode" @@ -104,25 +101,23 @@ //config: open a file in read-only mode. //config: //config:config FEATURE_VI_SETOPTS -//config: bool "Enable set-able options, ai ic showmatch" +//config: bool "Enable settable options, ai ic showmatch" //config: default y //config: depends on VI //config: help //config: Enable the editor to set some (ai, ic, showmatch) options. //config: //config:config FEATURE_VI_SET -//config: bool "Support for :set" +//config: bool "Support :set" //config: default y //config: depends on VI -//config: help -//config: Support for ":set". //config: //config:config FEATURE_VI_WIN_RESIZE //config: bool "Handle window resize" //config: default y //config: depends on VI //config: help -//config: Make busybox vi behave nicely with terminals that get resized. +//config: Behave nicely with terminals that get resized. //config: //config:config FEATURE_VI_ASK_TERMINAL //config: bool "Use 'tell me cursor position' ESC sequence to measure window" @@ -133,15 +128,16 @@ //config: this option makes vi perform a last-ditch effort to find it: //config: position cursor to 999,999 and ask terminal to report real //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. -//config: //config: This is not clean but helps a lot on serial lines and such. +//config: //config:config FEATURE_VI_UNDO -//config: bool "Support undo command 'u'" +//config: bool "Support undo command \"u\"" //config: default y //config: depends on VI //config: help //config: Support the 'u' command to undo insertion, deletion, and replacement //config: of text. +//config: //config:config FEATURE_VI_UNDO_QUEUE //config: bool "Enable undo operation queuing" //config: default y @@ -152,6 +148,7 @@ //config: reached, the contents of the queue are committed to the undo stack. //config: This increases the size of the undo code and allows some undo //config: operations (especially un-typing/backspacing) to be far more useful. +//config: //config:config FEATURE_VI_UNDO_QUEUE_MAX //config: int "Maximum undo character queue size" //config: default 256 diff --git a/findutils/find.c b/findutils/find.c index 27698e537..67aa40b21 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -89,8 +89,6 @@ //config: bool "Enable -perm: permissions matching" //config: default y //config: depends on FIND -//config: help -//config: Enable searching based on file permissions. //config: //config:config FEATURE_FIND_TYPE //config: bool "Enable -type: file type matching (file/dir/link/...)" @@ -104,15 +102,11 @@ //config: bool "Enable -xdev: 'stay in filesystem'" //config: default y //config: depends on FIND -//config: help -//config: This option allows find to restrict searches to a single filesystem. //config: //config:config FEATURE_FIND_MAXDEPTH //config: bool "Enable -mindepth N and -maxdepth N" //config: default y //config: depends on FIND -//config: help -//config: This option enables -mindepth N and -maxdepth N option. //config: //config:config FEATURE_FIND_NEWER //config: bool "Enable -newer: compare file modification times" @@ -126,8 +120,6 @@ //config: bool "Enable -inum: inode number matching" //config: default y //config: depends on FIND -//config: help -//config: Support the 'find -inum' option for searching by inode number. //config: //config:config FEATURE_FIND_EXEC //config: bool "Enable -exec: execute commands" @@ -151,15 +143,11 @@ //config: bool "Enable -user: username/uid matching" //config: default y //config: depends on FIND -//config: help -//config: Support the 'find -user' option for searching by username or uid. //config: //config:config FEATURE_FIND_GROUP //config: bool "Enable -group: group/gid matching" //config: default y //config: depends on FIND -//config: help -//config: Support the 'find -group' option for searching by group name or gid. //config: //config:config FEATURE_FIND_NOT //config: bool "Enable the 'not' (!) operator" @@ -188,8 +176,6 @@ //config: bool "Enable -size: file size matching" //config: default y //config: depends on FIND -//config: help -//config: Support the 'find -size' option for searching by file size. //config: //config:config FEATURE_FIND_PRUNE //config: bool "Enable -prune: exclude subdirectories" diff --git a/init/init.c b/init/init.c index 08cfa2f8c..8db4ced58 100644 --- a/init/init.c +++ b/init/init.c @@ -104,13 +104,13 @@ //config: sets TERM to "vt102" if one is found. //config: //config:config FEATURE_INIT_MODIFY_CMDLINE -//config: bool "Modify the command-line to \"init\"" +//config: bool "Clear init's command line" //config: default y //config: depends on INIT || LINUXRC //config: help //config: When launched as PID 1 and after parsing its arguments, init //config: wipes all the arguments but argv[0] and rewrites argv[0] to -//config: contain only "init", so that its command-line appears solely as +//config: contain only "init", so that its command line appears solely as //config: "init" in tools such as ps. //config: If this option is set to Y, init will keep its original behavior, //config: otherwise, all the arguments including argv[0] will be preserved, diff --git a/libbb/Config.src b/libbb/Config.src index 172fbcc0e..c51640305 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -70,24 +70,13 @@ config FEATURE_FAST_TOP but code size is slightly bigger. config FEATURE_ETC_NETWORKS - bool "Support for /etc/networks" + bool "Support /etc/networks" default n help Enable support for network names in /etc/networks. This is a rarely used feature which allows you to use names instead of IP/mask pairs in route command. -config FEATURE_USE_TERMIOS - bool "Use termios to manipulate the screen" - default y - depends on MORE || TOP || POWERTOP - help - This option allows utilities such as 'more' and 'top' to determine - the size of the screen. If you leave this disabled, your utilities - that display things on the screen will be especially primitive and - will be unable to determine the current screen size, and will be - unable to move the cursor. - config FEATURE_EDITING bool "Command line editing" default y @@ -147,15 +136,11 @@ config FEATURE_TAB_COMPLETION bool "Tab completion" default y depends on FEATURE_EDITING - help - Enable tab completion. config FEATURE_USERNAME_COMPLETION bool "Username completion" default y depends on FEATURE_TAB_COMPLETION - help - Enable username completion. config FEATURE_EDITING_FANCY_PROMPT bool "Fancy shell prompts" diff --git a/loginutils/Config.src b/loginutils/Config.src index efb954b6c..beb4eb855 100644 --- a/loginutils/Config.src +++ b/loginutils/Config.src @@ -6,7 +6,7 @@ menu "Login/Password Management Utilities" config FEATURE_SHADOWPASSWDS - bool "Support for shadow passwords" + bool "Support shadow passwords" default y help Build support for shadow password in /etc/shadow. This file is only diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 6b2fd7ba9..94da4efbb 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -19,15 +19,13 @@ //config: bool "Enable long options" //config: default y //config: depends on ADDGROUP && LONG_OPTS -//config: help -//config: Support long options for the addgroup applet. //config: //config:config FEATURE_ADDUSER_TO_GROUP -//config: bool "Support for adding users to groups" +//config: bool "Support adding users to groups" //config: default y //config: depends on ADDGROUP //config: help -//config: If called with two non-option arguments, +//config: If called with two non-option arguments, //config: addgroup will add an existing user to an //config: existing group. diff --git a/loginutils/adduser.c b/loginutils/adduser.c index 608fb8437..c218ac4aa 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c @@ -17,8 +17,6 @@ //config: bool "Enable long options" //config: default y //config: depends on ADDUSER && LONG_OPTS -//config: help -//config: Support long options for the adduser applet. //config: //config:config FEATURE_CHECK_NAMES //config: bool "Enable sanity check on user/group names in adduser and addgroup" diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 7c3caf9e3..fbb1614fb 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -21,7 +21,7 @@ //config: Utility for deleting a group account. //config: //config:config FEATURE_DEL_USER_FROM_GROUP -//config: bool "Support for removing users from groups" +//config: bool "Support removing users from groups" //config: default y //config: depends on DELGROUP //config: help diff --git a/loginutils/login.c b/loginutils/login.c index 3ca8213bb..d1757a65d 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -24,7 +24,7 @@ //config: will not be cleaned up. //config: //config:config LOGIN_SCRIPTS -//config: bool "Support for login scripts" +//config: bool "Support login scripts" //config: depends on LOGIN //config: default y //config: help @@ -32,7 +32,7 @@ //config: just prior to switching from root to logged-in user. //config: //config:config FEATURE_NOLOGIN -//config: bool "Support for /etc/nologin" +//config: bool "Support /etc/nologin" //config: default y //config: depends on LOGIN //config: help @@ -40,7 +40,7 @@ //config: If it exists, non-root logins are prohibited. //config: //config:config FEATURE_SECURETTY -//config: bool "Support for /etc/securetty" +//config: bool "Support /etc/securetty" //config: default y //config: depends on LOGIN //config: help diff --git a/loginutils/su.c b/loginutils/su.c index 24ffbde86..d04b85fb1 100644 --- a/loginutils/su.c +++ b/loginutils/su.c @@ -11,19 +11,18 @@ //config: help //config: su is used to become another user during a login session. //config: Invoked without a username, su defaults to becoming the super user. -//config: -//config: Note that Busybox binary must be setuid root for this applet to +//config: Note that busybox binary must be setuid root for this applet to //config: work properly. //config: //config:config FEATURE_SU_SYSLOG -//config: bool "Enable su to write to syslog" +//config: bool "Log to syslog all attempts to use su" //config: default y //config: depends on SU //config: //config:config FEATURE_SU_CHECKS_SHELLS -//config: bool "Enable su to check user's shell to be listed in /etc/shells" -//config: depends on SU +//config: bool "If user's shell is not in /etc/shells, disallow -s PROG" //config: default y +//config: depends on SU //applet:/* Needs to be run by root or be suid root - needs to change uid and gid: */ //applet:IF_SU(APPLET(su, BB_DIR_BIN, BB_SUID_REQUIRE)) diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 99bdc72b8..334f1071b 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -82,7 +82,7 @@ //config: the external modutils. //config: //config:config DEVFSD_FG_NP -//config: bool "Enables the -fg and -np options" +//config: bool "Enable the -fg and -np options" //config: default y //config: depends on DEVFSD //config: help diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c index e43a0dec2..84675285a 100644 --- a/miscutils/hdparm.c +++ b/miscutils/hdparm.c @@ -25,7 +25,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the -I and -i options to obtain detailed information +//config: Enable the -I and -i options to obtain detailed information //config: directly from drives about their capabilities and supported ATA //config: feature set. If no device name is specified, hdparm will read //config: identify data from stdin. Enabling this option will add about 16k... @@ -35,7 +35,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the 'hdparm -R' option to register an IDE interface. +//config: Enable the 'hdparm -R' option to register an IDE interface. //config: This is dangerous stuff, so you should probably say N. //config: //config:config FEATURE_HDPARM_HDIO_UNREGISTER_HWIF @@ -43,7 +43,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the 'hdparm -U' option to un-register an IDE interface. +//config: Enable the 'hdparm -U' option to un-register an IDE interface. //config: This is dangerous stuff, so you should probably say N. //config: //config:config FEATURE_HDPARM_HDIO_DRIVE_RESET @@ -51,7 +51,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the 'hdparm -w' option to perform a device reset. +//config: Enable the 'hdparm -w' option to perform a device reset. //config: This is dangerous stuff, so you should probably say N. //config: //config:config FEATURE_HDPARM_HDIO_TRISTATE_HWIF @@ -59,7 +59,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the 'hdparm -x' option to tristate device for hotswap, +//config: Enable the 'hdparm -x' option to tristate device for hotswap, //config: and the '-b' option to get/set bus state. This is dangerous //config: stuff, so you should probably say N. //config: @@ -68,7 +68,7 @@ //config: default y //config: depends on HDPARM //config: help -//config: Enables the 'hdparm -d' option to get/set using_dma flag. +//config: Enable the 'hdparm -d' option to get/set using_dma flag. //applet:IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP)) diff --git a/miscutils/last.c b/miscutils/last.c index 67c1343f1..b3f125c3f 100644 --- a/miscutils/last.c +++ b/miscutils/last.c @@ -14,7 +14,7 @@ //config: 'last' displays a list of the last users that logged into the system. //config: //config:config FEATURE_LAST_FANCY -//config: bool "Turn on output of extra information" +//config: bool "Output extra information" //config: default y //config: depends on LAST //config: help diff --git a/miscutils/less.c b/miscutils/less.c index e90691b49..0b0a9aed4 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -87,7 +87,6 @@ //config: this option makes less perform a last-ditch effort to find it: //config: position cursor to 999,999 and ask terminal to report real //config: cursor position using "ESC [ 6 n" escape sequence, then read stdin. -//config: //config: This is not clean but helps a lot on serial lines and such. //config: //config:config FEATURE_LESS_DASHCMD @@ -99,11 +98,9 @@ //config: less itself ('-' keyboard command). //config: //config:config FEATURE_LESS_LINENUMS -//config: bool "Enable dynamic switching of line numbers" +//config: bool "Enable -N (dynamic switching of line numbers)" //config: default y //config: depends on FEATURE_LESS_DASHCMD -//config: help -//config: Enables "-N" command. //applet:IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/modutils/Config.src b/modutils/Config.src index 84ff34a08..1808f332d 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -133,7 +133,7 @@ config FEATURE_CHECK_TAINTED_MODULE This option is required to support GPLONLY modules. config FEATURE_MODUTILS_ALIAS - bool "Support for module.aliases file" + bool "Support module.aliases file" default y depends on DEPMOD || MODPROBE select PLATFORM_LINUX @@ -150,7 +150,7 @@ config FEATURE_MODUTILS_ALIAS Say Y if unsure. config FEATURE_MODUTILS_SYMBOLS - bool "Support for module.symbols file" + bool "Support module.symbols file" default y depends on DEPMOD || MODPROBE select PLATFORM_LINUX diff --git a/networking/ftpd.c b/networking/ftpd.c index bcd60a2ad..a4626c0b5 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -15,7 +15,7 @@ //config: bool "ftpd" //config: default y //config: help -//config: simple FTP daemon. You have to run it via inetd. +//config: Simple FTP daemon. You have to run it via inetd. //config: //config:config FEATURE_FTPD_WRITE //config: bool "Enable upload commands" diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 40a3271ab..35b4e4b64 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -28,8 +28,6 @@ //config: bool "Enable long options in ftpget/ftpput" //config: default y //config: depends on LONG_OPTS && (FTPGET || FTPPUT) -//config: help -//config: Support long options for the ftpget/ftpput applet. //applet:IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget)) //applet:IF_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpput)) diff --git a/networking/httpd.c b/networking/httpd.c index cfcd2a06e..39aad90a8 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -102,7 +102,7 @@ //config: bool "httpd" //config: default y //config: help -//config: Serve web pages via an HTTP server. +//config: HTTP server. //config: //config:config FEATURE_HTTPD_RANGES //config: bool "Support 'Ranges:' header" @@ -156,7 +156,7 @@ //config: when specific URLs are requested. //config: //config:config FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR -//config: bool "Support for running scripts through an interpreter" +//config: bool "Support running scripts through an interpreter" //config: default y //config: depends on FEATURE_HTTPD_CGI //config: help @@ -185,7 +185,7 @@ //config: "<Hello World>". //config: //config:config FEATURE_HTTPD_ERROR_PAGES -//config: bool "Support for custom error pages" +//config: bool "Support custom error pages" //config: default y //config: depends on HTTPD //config: help @@ -198,7 +198,7 @@ //config: message. //config: //config:config FEATURE_HTTPD_PROXY -//config: bool "Support for reverse proxy" +//config: bool "Support reverse proxy" //config: default y //config: depends on HTTPD //config: help @@ -210,7 +210,7 @@ //config: http://hostname[:port]/new/path/myfile. //config: //config:config FEATURE_HTTPD_GZIP -//config: bool "Support for GZIP content encoding" +//config: bool "Support GZIP content encoding" //config: default y //config: depends on HTTPD //config: help diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 1806a6ccc..78baa6690 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -66,14 +66,14 @@ //config: utilities, or enable these applets in Busybox. //config: //config:config FEATURE_IFUPDOWN_IPV4 -//config: bool "Support for IPv4" +//config: bool "Support IPv4" //config: default y //config: depends on IFUP || IFDOWN //config: help //config: If you want ifup/ifdown to talk IPv4, leave this on. //config: //config:config FEATURE_IFUPDOWN_IPV6 -//config: bool "Support for IPv6" +//config: bool "Support IPv6" //config: default y //config: depends on (IFUP || IFDOWN) && FEATURE_IPV6 //config: help @@ -81,7 +81,7 @@ //config: //UNUSED: ////////:config FEATURE_IFUPDOWN_IPX -////////: bool "Support for IPX" +////////: bool "Support IPX" ////////: default y ////////: depends on IFUP || IFDOWN ////////: help @@ -97,7 +97,7 @@ //config: a weird network setup you don't need it. //config: //config:config FEATURE_IFUPDOWN_EXTERNAL_DHCP -//config: bool "Support for external dhcp clients" +//config: bool "Support external DHCP clients" //config: default n //config: depends on IFUP || IFDOWN //config: help diff --git a/networking/ipcalc.c b/networking/ipcalc.c index 21219424f..9359f9016 100644 --- a/networking/ipcalc.c +++ b/networking/ipcalc.c @@ -18,6 +18,11 @@ //config: ipcalc takes an IP address and netmask and calculates the //config: resulting broadcast, network, and host range. //config: +//config:config FEATURE_IPCALC_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on IPCALC && LONG_OPTS +//config: //config:config FEATURE_IPCALC_FANCY //config: bool "Fancy IPCALC, more options, adds 1 kbyte" //config: default y @@ -25,13 +30,6 @@ //config: help //config: Adds the options hostname, prefix and silent to the output of //config: "ipcalc". -//config: -//config:config FEATURE_IPCALC_LONG_OPTIONS -//config: bool "Enable long options" -//config: default y -//config: depends on IPCALC && LONG_OPTS -//config: help -//config: Support long options for the ipcalc applet. //applet:IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP)) diff --git a/networking/netstat.c b/networking/netstat.c index 90da6cdb8..68e0c1a04 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -21,7 +21,7 @@ //config: netstat prints information about the Linux networking subsystem. //config: //config:config FEATURE_NETSTAT_WIDE -//config: bool "Enable wide netstat output" +//config: bool "Enable wide output" //config: default y //config: depends on NETSTAT //config: help diff --git a/networking/tftp.c b/networking/tftp.c index ed8672025..189364f0c 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -69,11 +69,9 @@ //config: "blksize" and "tsize" options. //config: //config:config FEATURE_TFTP_PROGRESS_BAR -//config: bool "Enable tftp progress meter" +//config: bool "Enable progress bar" //config: default y //config: depends on TFTP && FEATURE_TFTP_BLOCKSIZE -//config: help -//config: Show progress bar. //config: //config:config TFTP_DEBUG //config: bool "Enable debug" diff --git a/networking/traceroute.c b/networking/traceroute.c index a463b0faa..6817861ef 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -235,8 +235,6 @@ //config: bool "Enable -I option (use ICMP instead of UDP)" //config: default y //config: depends on TRACEROUTE || TRACEROUTE6 -//config: help -//config: Add option -I to use ICMP ECHO instead of UDP datagrams. /* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */ //applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE)) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index 7bc13a719..5c068441a 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -123,7 +123,7 @@ config UDHCP_DEBUG are very verbose and useful for debugging only. config FEATURE_UDHCP_RFC3397 - bool "Support for RFC3397 domain search (experimental)" + bool "Support RFC3397 domain search (experimental)" default y depends on UDHCPD || UDHCPC help @@ -132,7 +132,7 @@ config FEATURE_UDHCP_RFC3397 and SIP servers option 120, specified in RFC 3361. config FEATURE_UDHCP_8021Q - bool "Support for 802.1Q VLAN parameters" + bool "Support 802.1Q VLAN parameters" default y depends on UDHCPD || UDHCPC help diff --git a/networking/wget.c b/networking/wget.c index b082a0f59..c82086878 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -16,12 +16,15 @@ //config: wget is a utility for non-interactive download of files from HTTP //config: and FTP servers. //config: +//config:config FEATURE_WGET_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on WGET && LONG_OPTS +//config: //config:config FEATURE_WGET_STATUSBAR -//config: bool "Enable a nifty process meter (+2k)" +//config: bool "Enable progress bar (+2k)" //config: default y //config: depends on WGET -//config: help -//config: Enable the transfer progress bar for wget transfers. //config: //config:config FEATURE_WGET_AUTHENTICATION //config: bool "Enable HTTP authentication" @@ -30,13 +33,6 @@ //config: help //config: Support authenticated HTTP transfers. //config: -//config:config FEATURE_WGET_LONG_OPTIONS -//config: bool "Enable long options" -//config: default y -//config: depends on WGET && LONG_OPTS -//config: help -//config: Support long options for the wget applet. -//config: //config:config FEATURE_WGET_TIMEOUT //config: bool "Enable timeout option -T SEC" //config: default y diff --git a/procps/Config.src b/procps/Config.src index eb4760752..35fef2eda 100644 --- a/procps/Config.src +++ b/procps/Config.src @@ -8,7 +8,7 @@ menu "Process Utilities" INSERT config FEATURE_SHOW_THREADS - bool "Support for showing threads in ps/pstree/top" + bool "Support thread display in ps/pstree/top" default y depends on PS || TOP || PSTREE help diff --git a/procps/pidof.c b/procps/pidof.c index 069adb7a4..b64f0cbd6 100644 --- a/procps/pidof.c +++ b/procps/pidof.c @@ -14,18 +14,18 @@ //config: those id's on the standard output. //config: //config:config FEATURE_PIDOF_SINGLE -//config: bool "Enable argument for single shot (-s)" +//config: bool "Enable single shot (-s)" //config: default y //config: depends on PIDOF //config: help -//config: Support argument '-s' for returning only the first pid found. +//config: Support '-s' for returning only the first pid found. //config: //config:config FEATURE_PIDOF_OMIT -//config: bool "Enable argument for omitting pids (-o)" +//config: bool "Enable omitting pids (-o PID)" //config: default y //config: depends on PIDOF //config: help -//config: Support argument '-o' for omitting the given pids in output. +//config: Support '-o PID' for omitting the given pid(s) in output. //config: The special pid %PPID can be used to name the parent process //config: of the pidof, in other words the calling shell or shell script. diff --git a/procps/ps.c b/procps/ps.c index e291ecd7e..1d380590d 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -32,19 +32,10 @@ //config: Adds fields PPID, RSS, START, TIME & TTY //config: //config:config FEATURE_PS_TIME -//config: bool "Enable time and elapsed time output" +//config: bool "Support -o time and -o etime output specifiers" //config: default y //config: depends on PS && DESKTOP //config: select PLATFORM_LINUX -//config: help -//config: Support -o time and -o etime output specifiers. -//config: -//config:config FEATURE_PS_ADDITIONAL_COLUMNS -//config: bool "Enable additional ps columns" -//config: default y -//config: depends on PS && DESKTOP -//config: help -//config: Support -o rgroup, -o ruser, -o nice output specifiers. //config: //config:config FEATURE_PS_UNUSUAL_SYSTEMS //config: bool "Support Linux prior to 2.4.0 and non-ELF systems" @@ -53,6 +44,11 @@ //config: help //config: Include support for measuring HZ on old kernels and non-ELF systems //config: (if you are on Linux 2.4.0+ and use ELF, you don't need this) +//config: +//config:config FEATURE_PS_ADDITIONAL_COLUMNS +//config: bool "Support -o rgroup, -o ruser, -o nice specifiers" +//config: default y +//config: depends on PS && DESKTOP //applet:IF_PS(APPLET(ps, BB_DIR_BIN, BB_SUID_DROP)) diff --git a/procps/uptime.c b/procps/uptime.c index 436193925..8e8956c0f 100644 --- a/procps/uptime.c +++ b/procps/uptime.c @@ -21,11 +21,11 @@ //config: on, and the system load averages for the past 1, 5, and 15 minutes. //config: //config:config FEATURE_UPTIME_UTMP_SUPPORT -//config: bool "Support for showing the number of users" +//config: bool "Show the number of users" //config: default y //config: depends on UPTIME && FEATURE_UTMP //config: help -//config: Makes uptime display the number of users currently logged on. +//config: Display the number of users currently logged on. //applet:IF_UPTIME(APPLET(uptime, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/selinux/chcon.c b/selinux/chcon.c index c743013ce..4a9a4d3d5 100644 --- a/selinux/chcon.c +++ b/selinux/chcon.c @@ -18,8 +18,6 @@ //config: bool "Enable long options" //config: default y //config: depends on CHCON && LONG_OPTS -//config: help -//config: Support long options for the chcon applet. //applet:IF_CHCON(APPLET(chcon, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/selinux/runcon.c b/selinux/runcon.c index 16f171101..a30e3552f 100644 --- a/selinux/runcon.c +++ b/selinux/runcon.c @@ -39,8 +39,6 @@ //config: bool "Enable long options" //config: default y //config: depends on RUNCON && LONG_OPTS -//config: help -//config: Support long options for the runcon applet. //applet:IF_RUNCON(APPLET(runcon, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/shell/ash.c b/shell/ash.c index 9c46a93e0..20ed9652c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -35,8 +35,6 @@ //config: bool "Optimize for size instead of speed" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Compile ash for reduced size at the price of speed. //config: //config:config ASH_INTERNAL_GLOB //config: bool "Use internal glob() implementation" @@ -46,6 +44,23 @@ //config: Do not use glob() function from libc, use internal implementation. //config: Use this if you are getting "glob.h: No such file or directory" //config: or similar build errors. +//config: Note that as of now (2017-01), uclibc and musl glob() both have bugs +//config: which would break ash if you select N here. +//config: +//config:config ASH_BASH_COMPAT +//config: bool "bash-compatible extensions" +//config: default y +//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: +//config:config ASH_JOB_CONTROL +//config: bool "Job control" +//config: default y +//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH +//config: +//config:config ASH_ALIAS +//config: bool "Alias support" +//config: default y +//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: //config:config ASH_RANDOM_SUPPORT //config: bool "Pseudorandom generator and $RANDOM variable" @@ -63,88 +78,60 @@ //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: help -//config: "PS#" may contain volatile content, such as backquote commands. +//config: $PS# may contain volatile content, such as backquote commands. //config: This option recreates the prompt string from the environment //config: variable each time it is displayed. //config: -//config:config ASH_BASH_COMPAT -//config: bool "bash-compatible extensions" -//config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable bash-compatible extensions. -//config: //config:config ASH_IDLE_TIMEOUT -//config: bool "Idle timeout variable" -//config: default n -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enables bash-like auto-logout after $TMOUT seconds of idle time. -//config: -//config:config ASH_JOB_CONTROL -//config: bool "Job control" -//config: default y -//config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable job control in the ash shell. -//config: -//config:config ASH_ALIAS -//config: bool "Alias support" +//config: bool "Idle timeout variable $TMOUT" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: help -//config: Enable alias support in the ash shell. +//config: Enable bash-like auto-logout after $TMOUT seconds of idle time. //config: -//config:config ASH_GETOPTS -//config: bool "Builtin getopt to parse positional parameters" +//config:config ASH_MAIL +//config: bool "Check for new mail in interactive shell" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: help -//config: Enable support for getopts builtin in ash. +//config: Enable "check for new mail" function: +//config: if set, $MAIL file and $MAILPATH list of files +//config: are checked for mtime changes, and "you have mail" +//config: message is printed if change is detected. //config: //config:config ASH_BUILTIN_ECHO -//config: bool "Builtin version of 'echo'" +//config: bool "echo builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable support for echo builtin in ash. //config: //config:config ASH_BUILTIN_PRINTF -//config: bool "Builtin version of 'printf'" +//config: bool "printf builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable support for printf builtin in ash. //config: //config:config ASH_BUILTIN_TEST -//config: bool "Builtin version of 'test'" +//config: bool "test builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable support for test builtin in ash. //config: //config:config ASH_HELP //config: bool "help builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable help builtin in ash. //config: -//config:config ASH_CMDCMD -//config: bool "'command' command to override shell builtins" +//config:config ASH_GETOPTS +//config: bool "getopts builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH -//config: help -//config: Enable support for the ash 'command' builtin, which allows -//config: you to run the specified command with the specified arguments, -//config: even when there is an ash builtin command with the same name. //config: -//config:config ASH_MAIL -//config: bool "Check for new mail on interactive shells" +//config:config ASH_CMDCMD +//config: bool "command builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: help -//config: Enable "check for new mail" function in the ash shell. +//config: Enable support for the 'command' builtin, which allows +//config: you to run the specified command or builtin, +//config: even when there is a function with the same name. //config: //config:endif # ash options diff --git a/shell/hush.c b/shell/hush.c index 22d71cb07..9e508fc6d 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -99,8 +99,6 @@ //config: bool "bash-compatible extensions" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable bash-compatible extensions. //config: //config:config HUSH_BRACE_EXPANSION //config: bool "Brace expansion" @@ -123,8 +121,6 @@ //config: bool "Save command history to .hush_history" //config: default y //config: depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY -//config: help -//config: Enable history saving in hush. //config: //config:config HUSH_JOB //config: bool "Job control" @@ -138,39 +134,35 @@ //config: but no separate process group is formed. //config: //config:config HUSH_TICK -//config: bool "Process substitution" +//config: bool "Support process substitution" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: help -//config: Enable process substitution `command` and $(command) in hush. +//config: Enable `command` and $(command). //config: //config:config HUSH_IF //config: bool "Support if/then/elif/else/fi" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable if/then/elif/else/fi in hush. //config: //config:config HUSH_LOOPS //config: bool "Support for, while and until loops" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable for, while and until loops in hush. //config: //config:config HUSH_CASE //config: bool "Support case ... esac statement" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: help -//config: Enable case ... esac statement in hush. +400 bytes. +//config: Enable case ... esac statement. +400 bytes. //config: //config:config HUSH_FUNCTIONS //config: bool "Support funcname() { commands; } syntax" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: help -//config: Enable support for shell functions in hush. +800 bytes. +//config: Enable support for shell functions. +800 bytes. //config: //config:config HUSH_LOCAL //config: bool "local builtin" @@ -199,22 +191,21 @@ //config: bool "echo builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable echo builtin in hush. //config: //config:config HUSH_PRINTF //config: bool "printf builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable printf builtin in hush. +//config: +//config:config HUSH_HELP +//config: bool "help builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: //config:config HUSH_EXPORT //config: bool "export builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable export builtin in hush. //config: //config:config HUSH_EXPORT_N //config: bool "Support 'export -n' option" @@ -223,82 +214,55 @@ //config: help //config: export -n unexports variables. It is a bash extension. //config: -//config:config HUSH_HELP -//config: bool "help builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable help builtin in hush. Code size + ~1 kbyte. -//config: //config:config HUSH_KILL -//config: bool "kill builtin (for kill %jobspec)" +//config: bool "kill builtin (supports kill %jobspec)" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable kill builtin in hush. //config: //config:config HUSH_WAIT //config: bool "wait builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable wait builtin in hush. //config: //config:config HUSH_TRAP //config: bool "trap builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable trap builtin in hush. -//config: -//config:config HUSH_ULIMIT -//config: bool "ulimit builtin" -//config: default y -//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable ulimit builtin in hush. //config: //config:config HUSH_TYPE //config: bool "type builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable type builtin in hush. //config: //config:config HUSH_READ //config: bool "read builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable read builtin in hush. //config: //config:config HUSH_SET //config: bool "set builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable set builtin in hush. //config: //config:config HUSH_UNSET //config: bool "unset builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable unset builtin in hush. +//config: +//config:config HUSH_ULIMIT +//config: bool "ulimit builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: //config:config HUSH_UMASK //config: bool "umask builtin" //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable umask builtin in hush. //config: //config:config HUSH_MEMLEAK //config: bool "memleak builtin (debugging)" //config: default n //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH -//config: help -//config: Enable memleak builtin in hush. //config: //config:config MSH //config: bool "msh (deprecated: aliased to hush)" @@ -1096,8 +1060,6 @@ static const struct built_in_command bltins1[] = { BLTIN("wait" , builtin_wait , "Wait for process"), #endif }; -/* For now, echo and test are unconditionally enabled. - * Maybe make it configurable? */ static const struct built_in_command bltins2[] = { BLTIN("[" , builtin_test , NULL), #if ENABLE_HUSH_ECHO diff --git a/util-linux/Config.src b/util-linux/Config.src index 3c522f948..0971d714a 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src @@ -40,7 +40,7 @@ config FEATURE_MOUNT_LOOP_CREATE if it does not find a free one. config FEATURE_MTAB_SUPPORT - bool "Support for the old /etc/mtab file" + bool "Support old /etc/mtab file" default n depends on MOUNT || UMOUNT select FEATURE_MOUNT_FAKE diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c index b7b2c6924..c3574f8f5 100644 --- a/util-linux/dmesg.c +++ b/util-linux/dmesg.c @@ -22,7 +22,7 @@ //config: wish to enable the 'dmesg' utility. //config: //config:config FEATURE_DMESG_PRETTY -//config: bool "Pretty dmesg output" +//config: bool "Pretty output" //config: default y //config: depends on DMESG //config: help diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 8a78c1ef9..673bf9aa4 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -22,7 +22,7 @@ //config: if you wish to enable the 'fbset' utility. //config: //config:config FEATURE_FBSET_FANCY -//config: bool "Turn on extra fbset options" +//config: bool "Enable extra options" //config: default y //config: depends on FBSET //config: help @@ -32,7 +32,7 @@ //config: options. //config: //config:config FEATURE_FBSET_READMODE -//config: bool "Turn on fbset readmode support" +//config: bool "Enable readmode support" //config: default y //config: depends on FBSET //config: help diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index b988e65a9..54f37baa6 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -21,8 +21,6 @@ //config: default y //config: depends on FDISK //config: depends on !LFS # with LFS no special code is needed -//config: help -//config: Enable this option to support large disks > 4GB. //config: //config:config FEATURE_FDISK_WRITABLE //config: bool "Write support" diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 084a7f1e9..d65011a71 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -20,10 +20,6 @@ //config: bool "Support long options (--hctosys,...)" //config: default y //config: depends on HWCLOCK && LONG_OPTS -//config: help -//config: By default, the hwclock utility only uses short options. If you -//config: are overly fond of its long options, such as --hctosys, --utc, etc) -//config: then enable this option. //config: //config:config FEATURE_HWCLOCK_ADJTIME_FHS //config: bool "Use FHS /var/lib/hwclock/adjtime" diff --git a/util-linux/mount.c b/util-linux/mount.c index 42962b859..4f5dced10 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -90,7 +90,7 @@ //config: //config:config FEATURE_MOUNT_FLAGS //config: depends on MOUNT -//config: bool "Support lots of -o flags in mount" +//config: bool "Support lots of -o flags" //config: default y //config: help //config: Without this, mount only supports ro/rw/remount. With this, it diff --git a/util-linux/volume_id/bcache.c b/util-linux/volume_id/bcache.c index fd40eb081..334a341c3 100644 --- a/util-linux/volume_id/bcache.c +++ b/util-linux/volume_id/bcache.c @@ -10,14 +10,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BCACHE) += bcache.o -//config: //config:config FEATURE_VOLUMEID_BCACHE //config: bool "bcache filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/btrfs.c b/util-linux/volume_id/btrfs.c index e4dddf26d..338a48762 100644 --- a/util-linux/volume_id/btrfs.c +++ b/util-linux/volume_id/btrfs.c @@ -21,14 +21,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_BTRFS) += btrfs.o -//config: //config:config FEATURE_VOLUMEID_BTRFS //config: bool "btrfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c index aeb7f20ac..c63223e2b 100644 --- a/util-linux/volume_id/cramfs.c +++ b/util-linux/volume_id/cramfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o -//config: //config:config FEATURE_VOLUMEID_CRAMFS //config: bool "cramfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/exfat.c b/util-linux/volume_id/exfat.c index c3aa36804..7ed13a70e 100644 --- a/util-linux/volume_id/exfat.c +++ b/util-linux/volume_id/exfat.c @@ -20,7 +20,6 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXFAT) += exfat.o -//config: //config:config FEATURE_VOLUMEID_EXFAT //config: bool "exFAT filesystem" //config: default y @@ -29,7 +28,6 @@ //config: exFAT (extended FAT) is a proprietary file system designed especially //config: for flash drives. It has many features from NTFS, but with less //config: overhead. exFAT is used on most SDXC cards for consumer electronics. -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c index df39d9342..473b3229a 100644 --- a/util-linux/volume_id/ext.c +++ b/util-linux/volume_id/ext.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o -//config: //config:config FEATURE_VOLUMEID_EXT //config: bool "Ext filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" #include "bb_e2fs_defs.h" diff --git a/util-linux/volume_id/f2fs.c b/util-linux/volume_id/f2fs.c index bf0b66278..1d3bdae36 100644 --- a/util-linux/volume_id/f2fs.c +++ b/util-linux/volume_id/f2fs.c @@ -8,7 +8,6 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_F2FS) += f2fs.o -//config: //config:config FEATURE_VOLUMEID_F2FS //config: bool "f2fs filesystem" //config: default y @@ -18,7 +17,6 @@ //config: which is adapted to newer forms of storage. F2FS also remedies some //config: known issues of the older log structured file systems, such as high //config: cleaning overhead. -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c index 476d500a6..bc3433daf 100644 --- a/util-linux/volume_id/fat.c +++ b/util-linux/volume_id/fat.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o -//config: //config:config FEATURE_VOLUMEID_FAT //config: bool "fat filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c index 8d34aaf68..78dae0790 100644 --- a/util-linux/volume_id/hfs.c +++ b/util-linux/volume_id/hfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o -//config: //config:config FEATURE_VOLUMEID_HFS //config: bool "hfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c index 3848de453..23072f87c 100644 --- a/util-linux/volume_id/iso9660.c +++ b/util-linux/volume_id/iso9660.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o -//config: //config:config FEATURE_VOLUMEID_ISO9660 //config: bool "iso9660 filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c index a6eaff45b..543d90fe5 100644 --- a/util-linux/volume_id/jfs.c +++ b/util-linux/volume_id/jfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o -//config: //config:config FEATURE_VOLUMEID_JFS //config: bool "jfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c index f20823a6e..0db6e8662 100644 --- a/util-linux/volume_id/linux_raid.c +++ b/util-linux/volume_id/linux_raid.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o -//config: //config:config FEATURE_VOLUMEID_LINUXRAID //config: bool "linuxraid" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c index 39470d48c..a35769dfc 100644 --- a/util-linux/volume_id/linux_swap.c +++ b/util-linux/volume_id/linux_swap.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o -//config: //config:config FEATURE_VOLUMEID_LINUXSWAP //config: bool "linux swap filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c index 21cb26f51..4b80b7a6d 100644 --- a/util-linux/volume_id/luks.c +++ b/util-linux/volume_id/luks.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o -//config: //config:config FEATURE_VOLUMEID_LUKS //config: bool "luks filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/nilfs.c b/util-linux/volume_id/nilfs.c index f3a9ef58d..ffe919f36 100644 --- a/util-linux/volume_id/nilfs.c +++ b/util-linux/volume_id/nilfs.c @@ -21,7 +21,6 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NILFS) += nilfs.o -//config: //config:config FEATURE_VOLUMEID_NILFS //config: bool "nilfs filesystem" //config: default y @@ -37,7 +36,6 @@ //config: SOX compliance logging, and so forth. It can serve as an alternative //config: filesystem for Linux desktop environment, or as a basis of advanced //config: storage appliances. -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c index 46f687a56..bf85f7ed3 100644 --- a/util-linux/volume_id/ntfs.c +++ b/util-linux/volume_id/ntfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o -//config: //config:config FEATURE_VOLUMEID_NTFS //config: bool "ntfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c index 415e0bf61..2dedac98b 100644 --- a/util-linux/volume_id/ocfs2.c +++ b/util-linux/volume_id/ocfs2.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o -//config: //config:config FEATURE_VOLUMEID_OCFS2 //config: bool "ocfs2 filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c index 24979fb1c..369d4d9bb 100644 --- a/util-linux/volume_id/reiserfs.c +++ b/util-linux/volume_id/reiserfs.c @@ -21,14 +21,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o -//config: //config:config FEATURE_VOLUMEID_REISERFS //config: bool "Reiser filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c index 4754fdb37..95a65f9ef 100644 --- a/util-linux/volume_id/romfs.c +++ b/util-linux/volume_id/romfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o -//config: //config:config FEATURE_VOLUMEID_ROMFS //config: bool "romfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/squashfs.c b/util-linux/volume_id/squashfs.c index 079b6cc31..6bba199cd 100644 --- a/util-linux/volume_id/squashfs.c +++ b/util-linux/volume_id/squashfs.c @@ -8,7 +8,6 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SQUASHFS) += squashfs.o -//config: //config:config FEATURE_VOLUMEID_SQUASHFS //config: bool "SquashFS filesystem" //config: default y @@ -18,7 +17,6 @@ //config: intended for general read-only filesystem use and in constrained block //config: device/memory systems (e.g. embedded systems) where low overhead is //config: needed. -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c index 7b4b5360b..cd4cd906b 100644 --- a/util-linux/volume_id/sysv.c +++ b/util-linux/volume_id/sysv.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o -//config: //config:config FEATURE_VOLUMEID_SYSV //config: bool "sysv filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/ubifs.c b/util-linux/volume_id/ubifs.c index 13604ec35..99b0aa830 100644 --- a/util-linux/volume_id/ubifs.c +++ b/util-linux/volume_id/ubifs.c @@ -8,7 +8,6 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UBIFS) += ubifs.o -//config: //config:config FEATURE_VOLUMEID_UBIFS //config: bool "UBIFS filesystem" //config: default y @@ -16,7 +15,6 @@ //config: help //config: UBIFS (Unsorted Block Image File System) is a file //config: system for use with raw flash memory media. -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c index 921454503..613c80c86 100644 --- a/util-linux/volume_id/udf.c +++ b/util-linux/volume_id/udf.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o -//config: //config:config FEATURE_VOLUMEID_UDF //config: bool "udf filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_highpoint.c b/util-linux/volume_id/unused_highpoint.c index 7231a1db2..4afa6d927 100644 --- a/util-linux/volume_id/unused_highpoint.c +++ b/util-linux/volume_id/unused_highpoint.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o -//config: //config:### config FEATURE_VOLUMEID_HIGHPOINTRAID //config:### bool "highpoint raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_hpfs.c b/util-linux/volume_id/unused_hpfs.c index a87c89fb3..3e16dedbd 100644 --- a/util-linux/volume_id/unused_hpfs.c +++ b/util-linux/volume_id/unused_hpfs.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o -//config: //config:### config FEATURE_VOLUMEID_HPFS //config:### bool "hpfs filesystem" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_isw_raid.c b/util-linux/volume_id/unused_isw_raid.c index 851bd2f8f..fba99be58 100644 --- a/util-linux/volume_id/unused_isw_raid.c +++ b/util-linux/volume_id/unused_isw_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o -//config: //config:### config FEATURE_VOLUMEID_ISWRAID //config:### bool "intel raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_lsi_raid.c b/util-linux/volume_id/unused_lsi_raid.c index 52d68deab..9dd2b409c 100644 --- a/util-linux/volume_id/unused_lsi_raid.c +++ b/util-linux/volume_id/unused_lsi_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o -//config: //config:### config FEATURE_VOLUMEID_LSIRAID //config:### bool "lsi raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_lvm.c b/util-linux/volume_id/unused_lvm.c index 08fa05243..5ad6d585c 100644 --- a/util-linux/volume_id/unused_lvm.c +++ b/util-linux/volume_id/unused_lvm.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o -//config: //config:### config FEATURE_VOLUMEID_LVM //config:### bool "lvm" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_mac.c b/util-linux/volume_id/unused_mac.c index a1a53d1fb..997d330a4 100644 --- a/util-linux/volume_id/unused_mac.c +++ b/util-linux/volume_id/unused_mac.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o -//config: //config:### config FEATURE_VOLUMEID_MAC //config:### bool "mac filesystem" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_minix.c b/util-linux/volume_id/unused_minix.c index 50afd5c3e..443dbc272 100644 --- a/util-linux/volume_id/unused_minix.c +++ b/util-linux/volume_id/unused_minix.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o -//config: //config:### config FEATURE_VOLUMEID_MINIX //config:### bool "minix filesystem" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_msdos.c b/util-linux/volume_id/unused_msdos.c index 5ebaa3eef..f84c0f06f 100644 --- a/util-linux/volume_id/unused_msdos.c +++ b/util-linux/volume_id/unused_msdos.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o -//config: //config:### config FEATURE_VOLUMEID_MSDOS //config:### bool "msdos filesystem" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_nvidia_raid.c b/util-linux/volume_id/unused_nvidia_raid.c index d99a108f3..dfb54fa9d 100644 --- a/util-linux/volume_id/unused_nvidia_raid.c +++ b/util-linux/volume_id/unused_nvidia_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o -//config: //config:### config FEATURE_VOLUMEID_NVIDIARAID //config:### bool "nvidia raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_promise_raid.c b/util-linux/volume_id/unused_promise_raid.c index cebebe35f..d594de39c 100644 --- a/util-linux/volume_id/unused_promise_raid.c +++ b/util-linux/volume_id/unused_promise_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o -//config: //config:### config FEATURE_VOLUMEID_PROMISERAID //config:### bool "promise raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_silicon_raid.c b/util-linux/volume_id/unused_silicon_raid.c index 40c8faa9e..886721b61 100644 --- a/util-linux/volume_id/unused_silicon_raid.c +++ b/util-linux/volume_id/unused_silicon_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o -//config: //config:### config FEATURE_VOLUMEID_SILICONRAID //config:### bool "silicon raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_ufs.c b/util-linux/volume_id/unused_ufs.c index d33c10fc4..78ef26ad4 100644 --- a/util-linux/volume_id/unused_ufs.c +++ b/util-linux/volume_id/unused_ufs.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o -//config: //config:### config FEATURE_VOLUMEID_UFS //config:### bool "ufs filesystem" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/unused_via_raid.c b/util-linux/volume_id/unused_via_raid.c index 258f93a4f..f82626655 100644 --- a/util-linux/volume_id/unused_via_raid.c +++ b/util-linux/volume_id/unused_via_raid.c @@ -20,14 +20,10 @@ //kbuild:### lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o -//config: //config:### config FEATURE_VOLUMEID_VIARAID //config:### bool "via raid" //config:### default y //config:### depends on VOLUMEID -//config:### help -//config:### TODO -//config: #include "volume_id_internal.h" diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c index 5eefc201d..656d5bfcf 100644 --- a/util-linux/volume_id/xfs.c +++ b/util-linux/volume_id/xfs.c @@ -20,14 +20,10 @@ //kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o -//config: //config:config FEATURE_VOLUMEID_XFS //config: bool "xfs filesystem" //config: default y //config: depends on VOLUMEID -//config: help -//config: TODO -//config: #include "volume_id_internal.h" -- cgit v1.2.3-55-g6feb From 265062d59dd46065ad34519f04615fb2cecefe8a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 15:13:30 +0100 Subject: shells: make hush test optional, rename ASH_BUILTIN_foo -> ASH_foo This makes hash and ash more symmetrical wrt config menu and config options. Signed-off-by: Denys Vlasenko --- configs/TEST_nommu_defconfig | 6 +++--- configs/TEST_noprintf_defconfig | 6 +++--- configs/TEST_rh9_defconfig | 6 +++--- configs/android2_defconfig | 6 +++--- configs/android_502_defconfig | 6 +++--- configs/android_defconfig | 6 +++--- configs/android_ndk_defconfig | 6 +++--- configs/cygwin_defconfig | 6 +++--- configs/freebsd_defconfig | 6 +++--- coreutils/Kbuild.src | 6 ------ coreutils/echo.c | 5 ++++- coreutils/printf.c | 5 ++++- coreutils/test.c | 17 ++++++++--------- shell/ash.c | 26 +++++++++++++------------- shell/hush.c | 16 +++++++++++++++- testsuite/mdev.tests | 2 +- 16 files changed, 72 insertions(+), 59 deletions(-) diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index 08351a294..d9ec41cd0 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -879,9 +879,9 @@ CONFIG_FEATURE_SH_IS_HUSH=y # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set # CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig index 70dacece0..c7330ed5d 100644 --- a/configs/TEST_noprintf_defconfig +++ b/configs/TEST_noprintf_defconfig @@ -873,9 +873,9 @@ CONFIG_SV_DEFAULT_SERVICE_DIR="" # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set # CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 4a5fad324..86e13cd53 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig @@ -893,9 +893,9 @@ CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y CONFIG_ASH_ALIAS=y CONFIG_ASH_GETOPTS=y -CONFIG_ASH_BUILTIN_ECHO=y -CONFIG_ASH_BUILTIN_PRINTF=y -CONFIG_ASH_BUILTIN_TEST=y +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y CONFIG_ASH_CMDCMD=y # CONFIG_ASH_MAIL is not set CONFIG_ASH_OPTIMIZE_FOR_SIZE=y diff --git a/configs/android2_defconfig b/configs/android2_defconfig index 754f612c6..9338f66ac 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig @@ -936,9 +936,9 @@ CONFIG_SOFTLIMIT=y # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set # CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 8ea6c295d..316063440 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig @@ -1081,9 +1081,9 @@ CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y CONFIG_ASH_ALIAS=y CONFIG_ASH_GETOPTS=y -CONFIG_ASH_BUILTIN_ECHO=y -CONFIG_ASH_BUILTIN_PRINTF=y -CONFIG_ASH_BUILTIN_TEST=y +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y CONFIG_ASH_HELP=y CONFIG_ASH_CMDCMD=y # CONFIG_ASH_MAIL is not set diff --git a/configs/android_defconfig b/configs/android_defconfig index 30e888ac7..cd3490c4e 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig @@ -968,9 +968,9 @@ CONFIG_SOFTLIMIT=y # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set # CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index 716ec9a5d..f2773be46 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig @@ -996,9 +996,9 @@ CONFIG_SOFTLIMIT=y # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_HELP is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig index b856482f6..816f76e65 100644 --- a/configs/cygwin_defconfig +++ b/configs/cygwin_defconfig @@ -936,9 +936,9 @@ CONFIG_ASH_BASH_COMPAT=y CONFIG_ASH_JOB_CONTROL=y CONFIG_ASH_ALIAS=y CONFIG_ASH_GETOPTS=y -CONFIG_ASH_BUILTIN_ECHO=y -CONFIG_ASH_BUILTIN_PRINTF=y -CONFIG_ASH_BUILTIN_TEST=y +CONFIG_ASH_ECHO=y +CONFIG_ASH_PRINTF=y +CONFIG_ASH_TEST=y CONFIG_ASH_CMDCMD=y # CONFIG_ASH_MAIL is not set CONFIG_ASH_OPTIMIZE_FOR_SIZE=y diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig index 4f14d3be9..d223b7230 100644 --- a/configs/freebsd_defconfig +++ b/configs/freebsd_defconfig @@ -912,9 +912,9 @@ CONFIG_ASH=y # CONFIG_ASH_JOB_CONTROL is not set # CONFIG_ASH_ALIAS is not set # CONFIG_ASH_GETOPTS is not set -# CONFIG_ASH_BUILTIN_ECHO is not set -# CONFIG_ASH_BUILTIN_PRINTF is not set -# CONFIG_ASH_BUILTIN_TEST is not set +# CONFIG_ASH_ECHO is not set +# CONFIG_ASH_PRINTF is not set +# CONFIG_ASH_TEST is not set # CONFIG_ASH_CMDCMD is not set # CONFIG_ASH_MAIL is not set # CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src index d0b3f629b..a805b64fe 100644 --- a/coreutils/Kbuild.src +++ b/coreutils/Kbuild.src @@ -16,9 +16,3 @@ lib-$(CONFIG_CRONTAB) += cat.o # crontab -l lib-$(CONFIG_ADDUSER) += chown.o # used by adduser lib-$(CONFIG_ADDGROUP) += chown.o # used by addgroup lib-$(CONFIG_FTPD) += ls.o # used by ftpd - -lib-$(CONFIG_ASH_BUILTIN_ECHO) += echo.o -lib-$(CONFIG_HUSH_ECHO) += echo.o - -lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o -lib-$(CONFIG_HUSH_PRINTF) += printf.o diff --git a/coreutils/echo.c b/coreutils/echo.c index d0dba650d..a7e4ca9ac 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -28,12 +28,15 @@ //config:config FEATURE_FANCY_ECHO //config: bool "Enable -n and -e options" //config: default y -//config: depends on ECHO || ASH_BUILTIN_ECHO || HUSH_ECHO +//config: depends on ECHO || ASH_ECHO || HUSH_ECHO //applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo)) //kbuild:lib-$(CONFIG_ECHO) += echo.o +//kbuild:lib-$(CONFIG_ASH_ECHO) += echo.o +//kbuild:lib-$(CONFIG_HUSH_ECHO) += echo.o + /* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ diff --git a/coreutils/printf.c b/coreutils/printf.c index 6c8e115d8..bc22e0ee7 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -49,6 +49,9 @@ //kbuild:lib-$(CONFIG_PRINTF) += printf.o +//kbuild:lib-$(CONFIG_ASH_PRINTF) += printf.o +//kbuild:lib-$(CONFIG_HUSH_PRINTF) += printf.o + //usage:#define printf_trivial_usage //usage: "FORMAT [ARG]..." //usage:#define printf_full_usage "\n\n" @@ -417,7 +420,7 @@ int printf_main(int argc UNUSED_PARAM, char **argv) if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2]) argv++; if (!argv[1]) { - if (ENABLE_ASH_BUILTIN_PRINTF + if (ENABLE_ASH_PRINTF && applet_name[0] != 'p' ) { bb_error_msg("usage: printf FORMAT [ARGUMENT...]"); diff --git a/coreutils/test.c b/coreutils/test.c index 288f66508..edc625f57 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -42,21 +42,20 @@ //config:config FEATURE_TEST_64 //config: bool "Extend test to 64 bit" //config: default y -//config: depends on TEST || TEST1 || TEST2 || ASH_BUILTIN_TEST || HUSH +//config: depends on TEST || TEST1 || TEST2 || ASH_TEST || HUSH_TEST //config: help //config: Enable 64-bit support in test. //applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) -//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) -//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) +//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) +//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) -//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o +//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o //kbuild:lib-$(CONFIG_TEST1) += test.o test_ptr_hack.o //kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o -//kbuild:lib-$(CONFIG_ASH_BUILTIN_TEST) += test.o test_ptr_hack.o -//kbuild:lib-$(CONFIG_HUSH) += test.o test_ptr_hack.o -//kbuild:lib-$(CONFIG_SH_IS_HUSH) += test.o test_ptr_hack.o -//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += test.o test_ptr_hack.o + +//kbuild:lib-$(CONFIG_ASH_TEST) += test.o test_ptr_hack.o +//kbuild:lib-$(CONFIG_HUSH_TEST) += test.o test_ptr_hack.o /* "test --help" is special-cased to ignore --help */ //usage:#define test_trivial_usage NOUSAGE_STR @@ -843,7 +842,7 @@ int test_main(int argc, char **argv) const char *arg0; arg0 = bb_basename(argv[0]); - if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_BUILTIN_TEST || ENABLE_HUSH) + if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_TEST || ENABLE_HUSH_TEST) && (arg0[0] == '[') ) { --argc; diff --git a/shell/ash.c b/shell/ash.c index 20ed9652c..7c1204a47 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -99,17 +99,17 @@ //config: are checked for mtime changes, and "you have mail" //config: message is printed if change is detected. //config: -//config:config ASH_BUILTIN_ECHO +//config:config ASH_ECHO //config: bool "echo builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: -//config:config ASH_BUILTIN_PRINTF +//config:config ASH_PRINTF //config: bool "printf builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH //config: -//config:config ASH_BUILTIN_TEST +//config:config ASH_TEST //config: bool "test builtin" //config: default y //config: depends on ASH || SH_IS_ASH || BASH_IS_ASH @@ -9292,13 +9292,13 @@ static int ulimitcmd(int, char **) FAST_FUNC; #define BUILTIN_SPEC_REG_ASSG "7" /* Stubs for calling non-FAST_FUNC's */ -#if ENABLE_ASH_BUILTIN_ECHO +#if ENABLE_ASH_ECHO static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); } #endif -#if ENABLE_ASH_BUILTIN_PRINTF +#if ENABLE_ASH_PRINTF static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } #endif -#if ENABLE_ASH_BUILTIN_TEST +#if ENABLE_ASH_TEST static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } #endif @@ -9306,7 +9306,7 @@ static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, a static const struct builtincmd builtintab[] = { { BUILTIN_SPEC_REG "." , dotcmd }, { BUILTIN_SPEC_REG ":" , truecmd }, -#if ENABLE_ASH_BUILTIN_TEST +#if ENABLE_ASH_TEST { BUILTIN_REGULAR "[" , testcmd }, # if ENABLE_ASH_BASH_COMPAT { BUILTIN_REGULAR "[[" , testcmd }, @@ -9325,7 +9325,7 @@ static const struct builtincmd builtintab[] = { { BUILTIN_REGULAR "command" , commandcmd }, #endif { BUILTIN_SPEC_REG "continue", breakcmd }, -#if ENABLE_ASH_BUILTIN_ECHO +#if ENABLE_ASH_ECHO { BUILTIN_REGULAR "echo" , echocmd }, #endif { BUILTIN_SPEC_REG "eval" , NULL }, /*evalcmd() has a differing prototype*/ @@ -9354,7 +9354,7 @@ static const struct builtincmd builtintab[] = { { BUILTIN_NOSPEC "let" , letcmd }, #endif { BUILTIN_ASSIGN "local" , localcmd }, -#if ENABLE_ASH_BUILTIN_PRINTF +#if ENABLE_ASH_PRINTF { BUILTIN_REGULAR "printf" , printfcmd }, #endif { BUILTIN_NOSPEC "pwd" , pwdcmd }, @@ -9366,7 +9366,7 @@ static const struct builtincmd builtintab[] = { #if ENABLE_ASH_BASH_COMPAT { BUILTIN_SPEC_REG "source" , dotcmd }, #endif -#if ENABLE_ASH_BUILTIN_TEST +#if ENABLE_ASH_TEST { BUILTIN_REGULAR "test" , testcmd }, #endif { BUILTIN_SPEC_REG "times" , timescmd }, @@ -9385,15 +9385,15 @@ static const struct builtincmd builtintab[] = { /* Should match the above table! */ #define COMMANDCMD (builtintab + \ /* . : */ 2 + \ - /* [ */ 1 * ENABLE_ASH_BUILTIN_TEST + \ - /* [[ */ 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \ + /* [ */ 1 * ENABLE_ASH_TEST + \ + /* [[ */ 1 * ENABLE_ASH_TEST * ENABLE_ASH_BASH_COMPAT + \ /* alias */ 1 * ENABLE_ASH_ALIAS + \ /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ /* break cd cddir */ 3) #define EVALCMD (COMMANDCMD + \ /* command */ 1 * ENABLE_ASH_CMDCMD + \ /* continue */ 1 + \ - /* echo */ 1 * ENABLE_ASH_BUILTIN_ECHO + \ + /* echo */ 1 * ENABLE_ASH_ECHO + \ 0) #define EXECCMD (EVALCMD + \ /* eval */ 1) diff --git a/shell/hush.c b/shell/hush.c index 9e508fc6d..c0325cf5e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -197,6 +197,11 @@ //config: default y //config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH //config: +//config:config HUSH_TEST +//config: bool "test builtin" +//config: default y +//config: depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH +//config: //config:config HUSH_HELP //config: bool "help builtin" //config: default y @@ -942,7 +947,9 @@ static int builtin_set(char **argv) FAST_FUNC; #endif static int builtin_shift(char **argv) FAST_FUNC; static int builtin_source(char **argv) FAST_FUNC; +#if ENABLE_HUSH_TEST static int builtin_test(char **argv) FAST_FUNC; +#endif #if ENABLE_HUSH_TRAP static int builtin_trap(char **argv) FAST_FUNC; #endif @@ -1061,7 +1068,9 @@ static const struct built_in_command bltins1[] = { #endif }; static const struct built_in_command bltins2[] = { +#if ENABLE_HUSH_TEST BLTIN("[" , builtin_test , NULL), +#endif #if ENABLE_HUSH_ECHO BLTIN("echo" , builtin_echo , NULL), #endif @@ -1069,7 +1078,9 @@ static const struct built_in_command bltins2[] = { BLTIN("printf" , builtin_printf , NULL), #endif BLTIN("pwd" , builtin_pwd , NULL), +#if ENABLE_HUSH_TEST BLTIN("test" , builtin_test , NULL), +#endif }; @@ -8791,6 +8802,7 @@ static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM) return 0; } +#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv)) { int argc = 0; @@ -8800,11 +8812,13 @@ static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char * } return applet_main_func(argc, argv - argc); } - +#endif +#if ENABLE_HUSH_TEST static int FAST_FUNC builtin_test(char **argv) { return run_applet_main(argv, test_main); } +#endif #if ENABLE_HUSH_ECHO static int FAST_FUNC builtin_echo(char **argv) { diff --git a/testsuite/mdev.tests b/testsuite/mdev.tests index 59873011a..8515aff31 100755 --- a/testsuite/mdev.tests +++ b/testsuite/mdev.tests @@ -168,7 +168,7 @@ SKIP= # continuing to use directory structure from prev test rm -rf mdev.testdir/dev/* echo "sda 0:0 644 @echo @echo TEST" >mdev.testdir/etc/mdev.conf -optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_BUILTIN_ECHO +optional STATIC FEATURE_MDEV_CONF FEATURE_MDEV_EXEC FEATURE_LS_RECURSIVE FEATURE_LS_TIMESTAMPS FEATURE_LS_USERNAME FEATURE_SH_IS_ASH ASH_ECHO testing "mdev command" \ "env - PATH=$PATH ACTION=add DEVPATH=/block/sda chroot mdev.testdir /mdev 2>&1; ls -lnR mdev.testdir/dev | $FILTER_LS" \ -- cgit v1.2.3-55-g6feb From 2b4c258e74d033b75b7f34bb384290eceb5da8a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 15:18:38 +0100 Subject: ash: revert "make dot command search current directory first" Reverts this: commit 8ad78e1ec7b2e873953f9f476fb63b5893526c39 Author: Denis Vlasenko Date: Sun Feb 15 12:40:30 2009 +0000 ash: make dot command search current directory first, as bash does. Signed-off-by: Denys Vlasenko --- shell/ash.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 7c1204a47..866c7de05 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12502,16 +12502,7 @@ find_dot_file(char *name) if (strchr(name, '/')) return name; - /* IIRC standards do not say whether . is to be searched. - * And it is even smaller this way, making it unconditional for now: - */ - if (1) { /* ENABLE_ASH_BASH_COMPAT */ - fullname = name; - goto try_cur_dir; - } - while ((fullname = path_advance(&path, name)) != NULL) { - try_cur_dir: if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { /* * Don't bother freeing here, since it will -- cgit v1.2.3-55-g6feb From f35ad3bd1287627fc6ca7cc9c1f48b186257dd87 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 15:24:13 +0100 Subject: init: rename FEATURE_EXTRA_QUIET -> FEATURE_INIT_QUIET The former name had no INIT anywhere in its name, sounded generic Signed-off-by: Denys Vlasenko --- configs/TEST_nommu_defconfig | 2 +- configs/TEST_noprintf_defconfig | 2 +- configs/TEST_rh9_defconfig | 2 +- configs/android2_defconfig | 2 +- configs/android_502_defconfig | 2 +- configs/android_defconfig | 2 +- configs/android_ndk_defconfig | 2 +- configs/cygwin_defconfig | 2 +- configs/freebsd_defconfig | 2 +- init/init.c | 10 ++++------ 10 files changed, 13 insertions(+), 15 deletions(-) diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index d9ec41cd0..d7a9cfe25 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -387,7 +387,7 @@ CONFIG_FEATURE_KILL_REMOVED=y CONFIG_FEATURE_KILL_DELAY=1 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_HALT=y diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig index c7330ed5d..adb6b7036 100644 --- a/configs/TEST_noprintf_defconfig +++ b/configs/TEST_noprintf_defconfig @@ -392,7 +392,7 @@ CONFIG_FEATURE_VI_MAX_LEN=0 CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set -# CONFIG_FEATURE_EXTRA_QUIET is not set +# CONFIG_FEATURE_INIT_QUIET is not set # CONFIG_FEATURE_INIT_COREDUMPS is not set # CONFIG_LINUXRC is not set # CONFIG_HALT is not set diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 86e13cd53..0d72cdac9 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig @@ -404,7 +404,7 @@ CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_HALT=y diff --git a/configs/android2_defconfig b/configs/android2_defconfig index 9338f66ac..866a87989 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig @@ -422,7 +422,7 @@ CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_INIT_TERMINAL_TYPE="linux" diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 316063440..8d8dd250f 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig @@ -529,7 +529,7 @@ CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_INIT_TERMINAL_TYPE="linux" diff --git a/configs/android_defconfig b/configs/android_defconfig index cd3490c4e..1eaab9eae 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig @@ -445,7 +445,7 @@ CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_INIT_TERMINAL_TYPE="linux" diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index f2773be46..dc9d21ce5 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig @@ -455,7 +455,7 @@ CONFIG_FEATURE_USE_INITTAB=y CONFIG_FEATURE_KILL_DELAY=0 CONFIG_FEATURE_INIT_SCTTY=y CONFIG_FEATURE_INIT_SYSLOG=y -CONFIG_FEATURE_EXTRA_QUIET=y +CONFIG_FEATURE_INIT_QUIET=y CONFIG_FEATURE_INIT_COREDUMPS=y CONFIG_LINUXRC=y CONFIG_INIT_TERMINAL_TYPE="linux" diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig index 816f76e65..37e3e210f 100644 --- a/configs/cygwin_defconfig +++ b/configs/cygwin_defconfig @@ -422,7 +422,7 @@ CONFIG_TELINIT_PATH="" CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set -# CONFIG_FEATURE_EXTRA_QUIET is not set +# CONFIG_FEATURE_INIT_QUIET is not set # CONFIG_FEATURE_INIT_COREDUMPS is not set # CONFIG_LINUXRC is not set CONFIG_INIT_TERMINAL_TYPE="" diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig index d223b7230..90e0a8bda 100644 --- a/configs/freebsd_defconfig +++ b/configs/freebsd_defconfig @@ -419,7 +419,7 @@ CONFIG_TELINIT_PATH="" CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set -# CONFIG_FEATURE_EXTRA_QUIET is not set +# CONFIG_FEATURE_INIT_QUIET is not set # CONFIG_FEATURE_INIT_COREDUMPS is not set # CONFIG_LINUXRC is not set CONFIG_INIT_TERMINAL_TYPE="" diff --git a/init/init.c b/init/init.c index 8db4ced58..833759341 100644 --- a/init/init.c +++ b/init/init.c @@ -17,7 +17,7 @@ //config: init is the first program run when the system boots. //config: //config:config LINUXRC -//config: bool "Support running init from within an initrd (not initramfs)" +//config: bool "linuxrc: support running init from initrd (not initramfs)" //config: default y //config: select FEATURE_SYSLOG //config: help @@ -74,12 +74,10 @@ //config: default y //config: depends on INIT || LINUXRC //config: -//config:config FEATURE_EXTRA_QUIET -//config: bool "Be _extra_ quiet on boot" +//config:config FEATURE_INIT_QUIET +//config: bool "Be quiet on boot (no 'init started:' message)" //config: default y //config: depends on INIT || LINUXRC -//config: help -//config: Prevent init from logging some messages to the console during boot. //config: //config:config FEATURE_INIT_COREDUMPS //config: bool "Support dumping core for child processes (debugging only)" @@ -1098,7 +1096,7 @@ int init_main(int argc UNUSED_PARAM, char **argv) if (argv[1]) xsetenv("RUNLEVEL", argv[1]); -#if !ENABLE_FEATURE_EXTRA_QUIET +#if !ENABLE_FEATURE_INIT_QUIET /* Hello world */ message(L_CONSOLE | L_LOG, "init started: %s", bb_banner); #endif -- cgit v1.2.3-55-g6feb From a1184af5f87b82df34af7782f76df9a1041200f1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 15:58:02 +0100 Subject: hush: reorder builtins (cd and pwd ought to be close, etc), no code changes Signed-off-by: Denys Vlasenko --- shell/hush.c | 602 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 300 insertions(+), 302 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index c0325cf5e..7cce89183 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8832,6 +8832,30 @@ static int FAST_FUNC builtin_printf(char **argv) } #endif +#if ENABLE_HUSH_HELP +static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) +{ + const struct built_in_command *x; + + printf( + "Built-in commands:\n" + "------------------\n"); + for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) { + if (x->b_descr) + printf("%-10s%s\n", x->b_cmd, x->b_descr); + } + return EXIT_SUCCESS; +} +#endif + +#if MAX_HISTORY && ENABLE_FEATURE_EDITING +static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) +{ + show_history(G.line_input_state); + return EXIT_SUCCESS; +} +#endif + static char **skip_dash_dash(char **argv) { argv++; @@ -8840,24 +8864,6 @@ static char **skip_dash_dash(char **argv) return argv; } -static int FAST_FUNC builtin_eval(char **argv) -{ - int rcode = EXIT_SUCCESS; - - argv = skip_dash_dash(argv); - if (*argv) { - char *str = expand_strvec_to_string(argv); - /* bash: - * eval "echo Hi; done" ("done" is syntax error): - * "echo Hi" will not execute too. - */ - parse_and_run_string(str); - free(str); - rcode = G.last_exitcode; - } - return rcode; -} - static int FAST_FUNC builtin_cd(char **argv) { const char *newdir; @@ -8885,6 +8891,30 @@ static int FAST_FUNC builtin_cd(char **argv) return EXIT_SUCCESS; } +static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) +{ + puts(get_cwd(0)); + return EXIT_SUCCESS; +} + +static int FAST_FUNC builtin_eval(char **argv) +{ + int rcode = EXIT_SUCCESS; + + argv = skip_dash_dash(argv); + if (*argv) { + char *str = expand_strvec_to_string(argv); + /* bash: + * eval "echo Hi; done" ("done" is syntax error): + * "echo Hi" will not execute too. + */ + parse_and_run_string(str); + free(str); + rcode = G.last_exitcode; + } + return rcode; +} + static int FAST_FUNC builtin_exec(char **argv) { argv = skip_dash_dash(argv); @@ -8930,6 +8960,147 @@ static int FAST_FUNC builtin_exit(char **argv) hush_exit(xatoi(argv[0]) & 0xff); } +#if ENABLE_HUSH_TYPE +/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ +static int FAST_FUNC builtin_type(char **argv) +{ + int ret = EXIT_SUCCESS; + + while (*++argv) { + const char *type; + char *path = NULL; + + if (0) {} /* make conditional compile easier below */ + /*else if (find_alias(*argv)) + type = "an alias";*/ +#if ENABLE_HUSH_FUNCTIONS + else if (find_function(*argv)) + type = "a function"; +#endif + else if (find_builtin(*argv)) + type = "a shell builtin"; + else if ((path = find_in_path(*argv)) != NULL) + type = path; + else { + bb_error_msg("type: %s: not found", *argv); + ret = EXIT_FAILURE; + continue; + } + + printf("%s is %s\n", *argv, type); + free(path); + } + + return ret; +} +#endif + +#if ENABLE_HUSH_READ +/* Interruptibility of read builtin in bash + * (tested on bash-4.2.8 by sending signals (not by ^C)): + * + * Empty trap makes read ignore corresponding signal, for any signal. + * + * SIGINT: + * - terminates non-interactive shell; + * - interrupts read in interactive shell; + * if it has non-empty trap: + * - executes trap and returns to command prompt in interactive shell; + * - executes trap and returns to read in non-interactive shell; + * SIGTERM: + * - is ignored (does not interrupt) read in interactive shell; + * - terminates non-interactive shell; + * if it has non-empty trap: + * - executes trap and returns to read; + * SIGHUP: + * - terminates shell (regardless of interactivity); + * if it has non-empty trap: + * - executes trap and returns to read; + */ +static int FAST_FUNC builtin_read(char **argv) +{ + const char *r; + char *opt_n = NULL; + char *opt_p = NULL; + char *opt_t = NULL; + char *opt_u = NULL; + const char *ifs; + int read_flags; + + /* "!": do not abort on errors. + * Option string must start with "sr" to match BUILTIN_READ_xxx + */ + read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); + if (read_flags == (uint32_t)-1) + return EXIT_FAILURE; + argv += optind; + ifs = get_local_var_value("IFS"); /* can be NULL */ + + again: + r = shell_builtin_read(set_local_var_from_halves, + argv, + ifs, + read_flags, + opt_n, + opt_p, + opt_t, + opt_u + ); + + if ((uintptr_t)r == 1 && errno == EINTR) { + unsigned sig = check_and_run_traps(); + if (sig && sig != SIGINT) + goto again; + } + + if ((uintptr_t)r > 1) { + bb_error_msg("%s", r); + r = (char*)(uintptr_t)1; + } + + return (uintptr_t)r; +} +#endif + +#if ENABLE_HUSH_UMASK +static int FAST_FUNC builtin_umask(char **argv) +{ + int rc; + mode_t mask; + + rc = 1; + mask = umask(0); + argv = skip_dash_dash(argv); + if (argv[0]) { + mode_t old_mask = mask; + + /* numeric umasks are taken as-is */ + /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ + if (!isdigit(argv[0][0])) + mask ^= 0777; + mask = bb_parse_mode(argv[0], mask); + if (!isdigit(argv[0][0])) + mask ^= 0777; + if ((unsigned)mask > 0777) { + mask = old_mask; + /* bash messages: + * bash: umask: 'q': invalid symbolic mode operator + * bash: umask: 999: octal number out of range + */ + bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); + rc = 0; + } + } else { + /* Mimic bash */ + printf("%04o\n", (unsigned) mask); + /* fall through and restore mask which we set to 0 */ + } + umask(mask); + + return !rc; /* rc != 0 - success */ +} +#endif + #if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP static void print_escaped(const char *s) { @@ -9218,72 +9389,60 @@ static int FAST_FUNC builtin_shift(char **argv) return EXIT_FAILURE; } -#if ENABLE_HUSH_READ -/* Interruptibility of read builtin in bash - * (tested on bash-4.2.8 by sending signals (not by ^C)): - * - * Empty trap makes read ignore corresponding signal, for any signal. - * - * SIGINT: - * - terminates non-interactive shell; - * - interrupts read in interactive shell; - * if it has non-empty trap: - * - executes trap and returns to command prompt in interactive shell; - * - executes trap and returns to read in non-interactive shell; - * SIGTERM: - * - is ignored (does not interrupt) read in interactive shell; - * - terminates non-interactive shell; - * if it has non-empty trap: - * - executes trap and returns to read; - * SIGHUP: - * - terminates shell (regardless of interactivity); - * if it has non-empty trap: - * - executes trap and returns to read; - */ -static int FAST_FUNC builtin_read(char **argv) +static int FAST_FUNC builtin_source(char **argv) { - const char *r; - char *opt_n = NULL; - char *opt_p = NULL; - char *opt_t = NULL; - char *opt_u = NULL; - const char *ifs; - int read_flags; + char *arg_path, *filename; + FILE *input; + save_arg_t sv; + char *args_need_save; +#if ENABLE_HUSH_FUNCTIONS + smallint sv_flg; +#endif - /* "!": do not abort on errors. - * Option string must start with "sr" to match BUILTIN_READ_xxx - */ - read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u); - if (read_flags == (uint32_t)-1) + argv = skip_dash_dash(argv); + filename = argv[0]; + if (!filename) { + /* bash says: "bash: .: filename argument required" */ + return 2; /* bash compat */ + } + arg_path = NULL; + if (!strchr(filename, '/')) { + arg_path = find_in_path(filename); + if (arg_path) + filename = arg_path; + } + input = remember_FILE(fopen_or_warn(filename, "r")); + free(arg_path); + if (!input) { + /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ + /* POSIX: non-interactive shell should abort here, + * not merely fail. So far no one complained :) + */ return EXIT_FAILURE; - argv += optind; - ifs = get_local_var_value("IFS"); /* can be NULL */ + } - again: - r = shell_builtin_read(set_local_var_from_halves, - argv, - ifs, - read_flags, - opt_n, - opt_p, - opt_t, - opt_u - ); +#if ENABLE_HUSH_FUNCTIONS + sv_flg = G_flag_return_in_progress; + /* "we are inside sourced file, ok to use return" */ + G_flag_return_in_progress = -1; +#endif + args_need_save = argv[1]; /* used as a boolean variable */ + if (args_need_save) + save_and_replace_G_args(&sv, argv); - if ((uintptr_t)r == 1 && errno == EINTR) { - unsigned sig = check_and_run_traps(); - if (sig && sig != SIGINT) - goto again; - } + /* "false; . ./empty_line; echo Zero:$?" should print 0 */ + G.last_exitcode = 0; + parse_and_run_file(input); + fclose_and_forget(input); - if ((uintptr_t)r > 1) { - bb_error_msg("%s", r); - r = (char*)(uintptr_t)1; - } + if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ + restore_G_args(&sv, argv); +#if ENABLE_HUSH_FUNCTIONS + G_flag_return_in_progress = sv_flg; +#endif - return (uintptr_t)r; + return G.last_exitcode; } -#endif #if ENABLE_HUSH_TRAP static int FAST_FUNC builtin_trap(char **argv) @@ -9368,47 +9527,12 @@ static int FAST_FUNC builtin_trap(char **argv) if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */ argv++; } - /* else: "-something", no special meaning */ - } - new_cmd = *argv; - reset_traps: - argv++; - goto process_sig_list; -} -#endif - -#if ENABLE_HUSH_TYPE -/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */ -static int FAST_FUNC builtin_type(char **argv) -{ - int ret = EXIT_SUCCESS; - - while (*++argv) { - const char *type; - char *path = NULL; - - if (0) {} /* make conditional compile easier below */ - /*else if (find_alias(*argv)) - type = "an alias";*/ -#if ENABLE_HUSH_FUNCTIONS - else if (find_function(*argv)) - type = "a function"; -#endif - else if (find_builtin(*argv)) - type = "a shell builtin"; - else if ((path = find_in_path(*argv)) != NULL) - type = path; - else { - bb_error_msg("type: %s: not found", *argv); - ret = EXIT_FAILURE; - continue; - } - - printf("%s is %s\n", *argv, type); - free(path); + /* else: "-something", no special meaning */ } - - return ret; + new_cmd = *argv; + reset_traps: + argv++; + goto process_sig_list; } #endif @@ -9441,6 +9565,23 @@ static struct pipe *parse_jobspec(const char *str) return NULL; } +static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) +{ + struct pipe *job; + const char *status_string; + + checkjobs(NULL, 0 /*(no pid to wait for)*/); + for (job = G.job_list; job; job = job->next) { + if (job->alive_cmds == job->stopped_cmds) + status_string = "Stopped"; + else + status_string = "Running"; + + printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); + } + return EXIT_SUCCESS; +} + /* built-in 'fg' and 'bg' handler */ static int FAST_FUNC builtin_fg_bg(char **argv) { @@ -9496,192 +9637,6 @@ static int FAST_FUNC builtin_fg_bg(char **argv) } #endif -#if ENABLE_HUSH_HELP -static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) -{ - const struct built_in_command *x; - - printf( - "Built-in commands:\n" - "------------------\n"); - for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) { - if (x->b_descr) - printf("%-10s%s\n", x->b_cmd, x->b_descr); - } - return EXIT_SUCCESS; -} -#endif - -#if MAX_HISTORY && ENABLE_FEATURE_EDITING -static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) -{ - show_history(G.line_input_state); - return EXIT_SUCCESS; -} -#endif - -#if ENABLE_HUSH_JOB -static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM) -{ - struct pipe *job; - const char *status_string; - - checkjobs(NULL, 0 /*(no pid to wait for)*/); - for (job = G.job_list; job; job = job->next) { - if (job->alive_cmds == job->stopped_cmds) - status_string = "Stopped"; - else - status_string = "Running"; - - printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext); - } - return EXIT_SUCCESS; -} -#endif - -#if ENABLE_HUSH_MEMLEAK -static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) -{ - void *p; - unsigned long l; - -# ifdef M_TRIM_THRESHOLD - /* Optional. Reduces probability of false positives */ - malloc_trim(0); -# endif - /* Crude attempt to find where "free memory" starts, - * sans fragmentation. */ - p = malloc(240); - l = (unsigned long)p; - free(p); - p = malloc(3400); - if (l < (unsigned long)p) l = (unsigned long)p; - free(p); - - -# if 0 /* debug */ - { - struct mallinfo mi = mallinfo(); - printf("top alloc:0x%lx malloced:%d+%d=%d\n", l, - mi.arena, mi.hblkhd, mi.arena + mi.hblkhd); - } -# endif - - if (!G.memleak_value) - G.memleak_value = l; - - l -= G.memleak_value; - if ((long)l < 0) - l = 0; - l /= 1024; - if (l > 127) - l = 127; - - /* Exitcode is "how many kilobytes we leaked since 1st call" */ - return l; -} -#endif - -static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM) -{ - puts(get_cwd(0)); - return EXIT_SUCCESS; -} - -static int FAST_FUNC builtin_source(char **argv) -{ - char *arg_path, *filename; - FILE *input; - save_arg_t sv; - char *args_need_save; -#if ENABLE_HUSH_FUNCTIONS - smallint sv_flg; -#endif - - argv = skip_dash_dash(argv); - filename = argv[0]; - if (!filename) { - /* bash says: "bash: .: filename argument required" */ - return 2; /* bash compat */ - } - arg_path = NULL; - if (!strchr(filename, '/')) { - arg_path = find_in_path(filename); - if (arg_path) - filename = arg_path; - } - input = remember_FILE(fopen_or_warn(filename, "r")); - free(arg_path); - if (!input) { - /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ - /* POSIX: non-interactive shell should abort here, - * not merely fail. So far no one complained :) - */ - return EXIT_FAILURE; - } - -#if ENABLE_HUSH_FUNCTIONS - sv_flg = G_flag_return_in_progress; - /* "we are inside sourced file, ok to use return" */ - G_flag_return_in_progress = -1; -#endif - args_need_save = argv[1]; /* used as a boolean variable */ - if (args_need_save) - save_and_replace_G_args(&sv, argv); - - /* "false; . ./empty_line; echo Zero:$?" should print 0 */ - G.last_exitcode = 0; - parse_and_run_file(input); - fclose_and_forget(input); - - if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */ - restore_G_args(&sv, argv); -#if ENABLE_HUSH_FUNCTIONS - G_flag_return_in_progress = sv_flg; -#endif - - return G.last_exitcode; -} - -#if ENABLE_HUSH_UMASK -static int FAST_FUNC builtin_umask(char **argv) -{ - int rc; - mode_t mask; - - rc = 1; - mask = umask(0); - argv = skip_dash_dash(argv); - if (argv[0]) { - mode_t old_mask = mask; - - /* numeric umasks are taken as-is */ - /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ - if (!isdigit(argv[0][0])) - mask ^= 0777; - mask = bb_parse_mode(argv[0], mask); - if (!isdigit(argv[0][0])) - mask ^= 0777; - if ((unsigned)mask > 0777) { - mask = old_mask; - /* bash messages: - * bash: umask: 'q': invalid symbolic mode operator - * bash: umask: 999: octal number out of range - */ - bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); - rc = 0; - } - } else { - /* Mimic bash */ - printf("%04o\n", (unsigned) mask); - /* fall through and restore mask which we set to 0 */ - } - umask(mask); - - return !rc; /* rc != 0 - success */ -} -#endif - #if ENABLE_HUSH_KILL static int FAST_FUNC builtin_kill(char **argv) { @@ -9984,3 +9939,46 @@ static int FAST_FUNC builtin_return(char **argv) return rc; } #endif + +#if ENABLE_HUSH_MEMLEAK +static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM) +{ + void *p; + unsigned long l; + +# ifdef M_TRIM_THRESHOLD + /* Optional. Reduces probability of false positives */ + malloc_trim(0); +# endif + /* Crude attempt to find where "free memory" starts, + * sans fragmentation. */ + p = malloc(240); + l = (unsigned long)p; + free(p); + p = malloc(3400); + if (l < (unsigned long)p) l = (unsigned long)p; + free(p); + + +# if 0 /* debug */ + { + struct mallinfo mi = mallinfo(); + printf("top alloc:0x%lx malloced:%d+%d=%d\n", l, + mi.arena, mi.hblkhd, mi.arena + mi.hblkhd); + } +# endif + + if (!G.memleak_value) + G.memleak_value = l; + + l -= G.memleak_value; + if ((long)l < 0) + l = 0; + l /= 1024; + if (l > 127) + l = 127; + + /* Exitcode is "how many kilobytes we leaked since 1st call" */ + return l; +} +#endif -- cgit v1.2.3-55-g6feb From 80f806cac9b418c07b149a683a4d1d989507d4d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Jan 2017 16:51:10 +0100 Subject: hush: shorten output of "help" builtin text data bss dec hex filename 891272 485 6856 898613 db635 busybox_old 891232 485 6856 898573 db60d busybox_unstripped Signed-off-by: Denys Vlasenko --- shell/hush.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index 7cce89183..ecef099ac 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -995,13 +995,13 @@ struct built_in_command { }; static const struct built_in_command bltins1[] = { - BLTIN("." , builtin_source , "Run commands in a file"), + BLTIN("." , builtin_source , "Run commands in file"), BLTIN(":" , builtin_true , NULL), #if ENABLE_HUSH_JOB - BLTIN("bg" , builtin_fg_bg , "Resume a job in the background"), + BLTIN("bg" , builtin_fg_bg , "Resume job in background"), #endif #if ENABLE_HUSH_LOOPS - BLTIN("break" , builtin_break , "Exit from a loop"), + BLTIN("break" , builtin_break , "Exit loop"), #endif BLTIN("cd" , builtin_cd , "Change directory"), #if ENABLE_HUSH_LOOPS @@ -1009,18 +1009,18 @@ static const struct built_in_command bltins1[] = { #endif BLTIN("eval" , builtin_eval , "Construct and run shell command"), BLTIN("exec" , builtin_exec , "Execute command, don't return to shell"), - BLTIN("exit" , builtin_exit , "Exit"), + BLTIN("exit" , builtin_exit , NULL), #if ENABLE_HUSH_EXPORT BLTIN("export" , builtin_export , "Set environment variables"), #endif #if ENABLE_HUSH_JOB - BLTIN("fg" , builtin_fg_bg , "Bring job into the foreground"), + BLTIN("fg" , builtin_fg_bg , "Bring job into foreground"), #endif #if ENABLE_HUSH_HELP BLTIN("help" , builtin_help , NULL), #endif #if MAX_HISTORY && ENABLE_FEATURE_EDITING - BLTIN("history" , builtin_history , "Show command history"), + BLTIN("history" , builtin_history , "Show history"), #endif #if ENABLE_HUSH_JOB BLTIN("jobs" , builtin_jobs , "List jobs"), @@ -1038,14 +1038,14 @@ static const struct built_in_command bltins1[] = { BLTIN("read" , builtin_read , "Input into variable"), #endif #if ENABLE_HUSH_FUNCTIONS - BLTIN("return" , builtin_return , "Return from a function"), + BLTIN("return" , builtin_return , "Return from function"), #endif #if ENABLE_HUSH_SET - BLTIN("set" , builtin_set , "Set/unset positional parameters"), + BLTIN("set" , builtin_set , "Set positional parameters"), #endif BLTIN("shift" , builtin_shift , "Shift positional parameters"), #if ENABLE_HUSH_BASH_COMPAT - BLTIN("source" , builtin_source , "Run commands in a file"), + BLTIN("source" , builtin_source , NULL), #endif #if ENABLE_HUSH_TRAP BLTIN("trap" , builtin_trap , "Trap signals"), @@ -1067,6 +1067,9 @@ static const struct built_in_command bltins1[] = { BLTIN("wait" , builtin_wait , "Wait for process"), #endif }; +/* These builtins won't be used if we are on NOMMU and need to re-exec + * (it's cheaper to run an external program in this case): + */ static const struct built_in_command bltins2[] = { #if ENABLE_HUSH_TEST BLTIN("[" , builtin_test , NULL), -- cgit v1.2.3-55-g6feb From c5891fe1af821dae83a8b1df088462b6989d089b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 10:38:52 +0100 Subject: more: hardcode FEATURE_USE_TERMIOS=y in this applet; code shrink function old new delta get_wh - 27 +27 tcsetattr_tty_TCSANOW - 18 +18 gotsig 35 27 -8 more_main 835 759 -76 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 0/2 up/down: 45/-84) Total: -39 bytes Signed-off-by: Denys Vlasenko --- util-linux/more.c | 106 +++++++++++++++++++++++++----------------------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/util-linux/more.c b/util-linux/more.c index 934b30f8a..7fa60bdba 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -38,32 +38,34 @@ #include "libbb.h" #include "common_bufsiz.h" -/* Support for FEATURE_USE_TERMIOS */ - struct globals { - int cin_fileno; + int tty_fileno; + unsigned terminal_width; + unsigned terminal_height; struct termios initial_settings; struct termios new_settings; } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) -#define initial_settings (G.initial_settings) -#define new_settings (G.new_settings ) -#define cin_fileno (G.cin_fileno ) #define INIT_G() do { setup_common_bufsiz(); } while (0) -#define setTermSettings(fd, argp) \ -do { \ - if (ENABLE_FEATURE_USE_TERMIOS) \ - tcsetattr(fd, TCSANOW, argp); \ -} while (0) -#define getTermSettings(fd, argp) tcgetattr(fd, argp) +static void get_wh(void) +{ + /* never returns w, h <= 1 */ + get_terminal_width_height(G.tty_fileno, &G.terminal_width, &G.terminal_height); + G.terminal_height -= 1; +} + +static void tcsetattr_tty_TCSANOW(struct termios *settings) +{ + tcsetattr(G.tty_fileno, TCSANOW, settings); +} static void gotsig(int sig UNUSED_PARAM) { /* bb_putchar_stderr doesn't use stdio buffering, * therefore it is safe in signal handler */ bb_putchar_stderr('\n'); - setTermSettings(cin_fileno, &initial_settings); + tcsetattr_tty_TCSANOW(&G.initial_settings); _exit(EXIT_FAILURE); } @@ -73,22 +75,16 @@ int more_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int more_main(int argc UNUSED_PARAM, char **argv) { int c = c; /* for compiler */ - int lines; int input = 0; int spaces = 0; int please_display_more_prompt; - struct stat st; - FILE *file; - FILE *cin; - int len; - unsigned terminal_width; - unsigned terminal_height; + FILE *tty; INIT_G(); /* Parse options */ /* Accepted but ignored: */ - /* -d Display help instead of ringing bell is pressed */ + /* -d Display help instead of ringing bell */ /* -f Count logical lines (IOW: long lines are not folded) */ /* -l Do not pause after any line containing a ^L (form feed) */ /* -s Squeeze blank lines into one */ @@ -100,26 +96,25 @@ int more_main(int argc UNUSED_PARAM, char **argv) * is not a tty and turns into cat. This makes sense. */ if (!isatty(STDOUT_FILENO)) return bb_cat(argv); - cin = fopen_for_read(CURRENT_TTY); - if (!cin) + tty = fopen_for_read(CURRENT_TTY); + if (!tty) return bb_cat(argv); - if (ENABLE_FEATURE_USE_TERMIOS) { - cin_fileno = fileno(cin); - getTermSettings(cin_fileno, &initial_settings); - new_settings = initial_settings; - new_settings.c_lflag &= ~(ICANON | ECHO); - new_settings.c_cc[VMIN] = 1; - new_settings.c_cc[VTIME] = 0; - setTermSettings(cin_fileno, &new_settings); - bb_signals(0 - + (1 << SIGINT) - + (1 << SIGQUIT) - + (1 << SIGTERM) - , gotsig); - } + G.tty_fileno = fileno(tty); + tcgetattr(G.tty_fileno, &G.initial_settings); + G.new_settings = G.initial_settings; + G.new_settings.c_lflag &= ~(ICANON | ECHO); + G.new_settings.c_cc[VMIN] = 1; + G.new_settings.c_cc[VTIME] = 0; + tcsetattr_tty_TCSANOW(&G.new_settings); + bb_signals(BB_FATAL_SIGS, gotsig); do { + struct stat st; + FILE *file; + int len; + int lines; + file = stdin; if (*argv) { file = fopen_or_warn(*argv, "r"); @@ -129,17 +124,20 @@ int more_main(int argc UNUSED_PARAM, char **argv) st.st_size = 0; fstat(fileno(file), &st); - please_display_more_prompt = 0; - /* never returns w, h <= 1 */ - get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height); - terminal_height -= 1; + get_wh(); + please_display_more_prompt = 0; len = 0; lines = 0; - while (spaces || (c = getc(file)) != EOF) { + for (;;) { int wrap; + if (spaces) spaces--; + else { + c = getc(file); + if (c == EOF) break; + } loop_top: if (input != 'r' && please_display_more_prompt) { len = printf("--More-- "); @@ -151,26 +149,26 @@ int more_main(int argc UNUSED_PARAM, char **argv) (int) ((uoff_t)ftello(file) / d), st.st_size); } - fflush_all(); /* * We've just displayed the "--More--" prompt, so now we need * to get input from the user. */ for (;;) { - input = getc(cin); + fflush_all(); + input = getc(tty); input = tolower(input); - if (!ENABLE_FEATURE_USE_TERMIOS) - printf("\033[A"); /* cursor up */ /* Erase the last message */ printf("\r%*s\r", len, ""); + if (input == 'q') + goto end; /* Due to various multibyte escape * sequences, it's not ok to accept * any input as a command to scroll * the screen. We only allow known * commands, else we show help msg. */ - if (input == ' ' || input == '\n' || input == 'q' || input == 'r') + if (input == ' ' || input == '\n' || input == 'r') break; len = printf("(Enter:next line Space:next page Q:quit R:show the rest)"); } @@ -178,15 +176,9 @@ int more_main(int argc UNUSED_PARAM, char **argv) lines = 0; please_display_more_prompt = 0; - if (input == 'q') - goto end; - /* The user may have resized the terminal. * Re-read the dimensions. */ - if (ENABLE_FEATURE_USE_TERMIOS) { - get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height); - terminal_height -= 1; - } + get_wh(); } /* Crudely convert tabs into spaces, which are @@ -206,11 +198,11 @@ int more_main(int argc UNUSED_PARAM, char **argv) * see if any characters have been hit in the _input_ stream. This * allows the user to quit while in the middle of a file. */ - wrap = (++len > terminal_width); + wrap = (++len > G.terminal_width); if (c == '\n' || wrap) { /* Then outputting this character * will move us to a new line. */ - if (++lines >= terminal_height || input == '\n') + if (++lines >= G.terminal_height || input == '\n') please_display_more_prompt = 1; len = 0; } @@ -230,6 +222,6 @@ int more_main(int argc UNUSED_PARAM, char **argv) fflush_all(); } while (*argv && *++argv); end: - setTermSettings(cin_fileno, &initial_settings); + tcsetattr_tty_TCSANOW(&G.initial_settings); return 0; } -- cgit v1.2.3-55-g6feb From 0fd9fb4244a6dd4ba71f81e355261115cd80d2f1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 10:50:08 +0100 Subject: top: FEATURE_USE_TERMIOS shouldn't control reading of screen size It controls whether we take input. Signed-off-by: Denys Vlasenko --- procps/top.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/procps/top.c b/procps/top.c index 71207bac1..491acb574 100644 --- a/procps/top.c +++ b/procps/top.c @@ -726,7 +726,6 @@ static void clearmems(void) } #if ENABLE_FEATURE_USE_TERMIOS - static void reset_term(void) { if (!OPT_BATCH_MODE) @@ -738,7 +737,6 @@ static void sig_catcher(int sig) reset_term(); kill_myself_with_sig(sig); } - #endif /* FEATURE_USE_TERMIOS */ /* @@ -1165,14 +1163,12 @@ int top_main(int argc UNUSED_PARAM, char **argv) } else { G.lines = 24; /* default */ col = 79; -#if ENABLE_FEATURE_USE_TERMIOS /* We output to stdout, we need size of stdout (not stdin)! */ get_terminal_width_height(STDOUT_FILENO, &col, &G.lines); if (G.lines < 5 || col < 10) { sleep(interval); continue; } -#endif if (col > LINE_BUF_SIZE - 2) col = LINE_BUF_SIZE - 2; } -- cgit v1.2.3-55-g6feb From a8a075acfee7b31c4da00cf3500b67354339e3b9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 10:52:24 +0100 Subject: busybox: stop depending on FEATURE_AUTOWIDTH for applet list Many other appletw don't - they unconditionally use get_terminal_wodth(), and here the amount of code saved by FEATURE_AUTOWIDTH=n is tiny. Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index bf6d4762c..7f0d62060 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -748,11 +748,7 @@ static int busybox_main(char **argv) int col; unsigned output_width; help: - output_width = 80; - if (ENABLE_FEATURE_AUTOWIDTH) { - /* Obtain the terminal width */ - output_width = get_terminal_width(2); - } + output_width = get_terminal_width(2); dup2(1, 2); full_write2_str(bb_banner); /* reuse const string */ -- cgit v1.2.3-55-g6feb From 7d4aec0c3ecb0c10de60070616d9d8fb9b074497 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 14:00:38 +0100 Subject: ash: split bash compatible extensions into separate defines. No code changes Splitting these options makes it self-documenting about what bash-compatible features we have. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- shell/ash.c | 175 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 101 insertions(+), 74 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 866c7de05..02545f565 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -145,15 +145,10 @@ //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o /* - * The following should be set to reflect the type of system you have: - * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * define SYSV if you are running under System V. - * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) - * define DEBUG=2 to compile in and turn on debugging. - * - * When debugging is on (DEBUG is 1 and "set -o debug" was executed), - * debugging info will be written to ./trace and a quit signal - * will generate a core dump. + * DEBUG=1 to compile in debugging ('set -o debug' turns on) + * DEBUG=2 to compile in and turn on debugging. + * When debugging is on ("set -o debug" was executed, or DEBUG=2), + * debugging info is written to ./trace, quit signal generates core dump. */ #define DEBUG 0 /* Tweak debug output verbosity here */ @@ -170,9 +165,30 @@ #include #include #include /* for setting $HOSTNAME */ - #include "busybox.h" /* for applet_names */ +/* So far, all bash compat is controlled by one config option */ +/* Separate defines document which part of code implements what */ +/* function keyword */ +#define BASH_FUNCTION ENABLE_ASH_BASH_COMPAT +#define IF_BASH_FUNCTION IF_ASH_BASH_COMPAT +/* &>file */ +#define BASH_REDIR_OUTPUT ENABLE_ASH_BASH_COMPAT +#define IF_BASH_REDIR_OUTPUT IF_ASH_BASH_COMPAT +/* $'...' */ +#define BASH_DOLLAR_SQUOTE ENABLE_ASH_BASH_COMPAT +#define IF_BASH_DOLLAR_SQUOTE IF_ASH_BASH_COMPAT +#define BASH_PATTERN_SUBST ENABLE_ASH_BASH_COMPAT +#define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT +#define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT +#define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT +/* [[ EXPR ]] */ +#define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST) +#define BASH_SOURCE ENABLE_ASH_BASH_COMPAT +#define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT +#define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT +#define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT + #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 /* Bionic at least up to version 24 has no glob() */ # undef ENABLE_ASH_INTERNAL_GLOB @@ -250,7 +266,7 @@ static const char *const optletters_optnames[] = { "b" "notify", "u" "nounset", "\0" "vi" -#if ENABLE_ASH_BASH_COMPAT +#if BASH_PIPEFAIL ,"\0" "pipefail" #endif #if DEBUG @@ -327,14 +343,14 @@ struct globals_misc { #define bflag optlist[11] #define uflag optlist[12] #define viflag optlist[13] -#if ENABLE_ASH_BASH_COMPAT +#if BASH_PIPEFAIL # define pipefail optlist[14] #else # define pipefail 0 #endif #if DEBUG -# define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT] -# define debug optlist[15 + ENABLE_ASH_BASH_COMPAT] +# define nolog optlist[14 + BASH_PIPEFAIL] +# define debug optlist[15 + BASH_PIPEFAIL] #endif /* trap handler commands */ @@ -655,8 +671,10 @@ out2str(const char *p) #define VSTRIMLEFT 0x8 /* ${var#pattern} */ #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ #define VSLENGTH 0xa /* ${#var} */ -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SUBSTR #define VSSUBSTR 0xc /* ${var:position:length} */ +#endif +#if BASH_PATTERN_SUBST #define VSREPLACE 0xd /* ${var/pattern/replacement} */ #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */ #endif @@ -683,7 +701,7 @@ static const char dolatstr[] ALIGN1 = { #define NDEFUN 14 #define NARG 15 #define NTO 16 -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT #define NTO2 17 #endif #define NCLOBBER 18 @@ -1093,7 +1111,7 @@ shcmd(union node *cmd, FILE *fp) case NTO: s = ">>"+1; dftfd = 1; break; case NCLOBBER: s = ">|"; dftfd = 1; break; case NAPPEND: s = ">>"; dftfd = 1; break; -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif case NTOFD: s = ">&"; dftfd = 1; break; @@ -4455,7 +4473,8 @@ cmdputs(const char *s) static const char vstype[VSTYPE + 1][3] = { "", "}", "-", "+", "?", "=", "%", "%%", "#", "##" - IF_ASH_BASH_COMPAT(, ":", "/", "//") + IF_BASH_SUBSTR(, ":") + IF_BASH_PATTERN_SUBST(, "/", "//") }; const char *p, *str; @@ -4682,7 +4701,7 @@ cmdtxt(union node *n) case NAPPEND: p = ">>"; goto redir; -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif case NTOFD: @@ -5209,7 +5228,7 @@ openredirect(union node *redir) goto ecreate; break; case NTO: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif /* Take care of noclobber mode. */ @@ -5370,7 +5389,7 @@ redirect(union node *redir, int flags) union node *tmp = redir; do { sv_pos++; -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT if (tmp->nfile.type == NTO2) sv_pos++; #endif @@ -5412,7 +5431,7 @@ redirect(union node *redir, int flags) continue; } } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT redirect_more: #endif if (need_to_remember(sv, fd)) { @@ -5465,12 +5484,12 @@ redirect(union node *redir, int flags) } } else if (fd != newfd) { /* move newfd to fd */ dup2_or_raise(newfd, fd); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT if (!(redir->nfile.type == NTO2 && fd == 2)) #endif close(newfd); } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT if (redir->nfile.type == NTO2 && fd == 1) { /* We already redirected it to fd 1, now copy it to 2 */ newfd = 1; @@ -5787,15 +5806,15 @@ static char * rmescapes(char *str, int flag) { static const char qchars[] ALIGN1 = { - IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' }; + IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' }; char *p, *q, *r; unsigned inquotes; unsigned protect_against_glob; unsigned globbing; - IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;) + IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;) - p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash)); + p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash)); if (!p) return str; @@ -5847,7 +5866,7 @@ rmescapes(char *str, int flag) protect_against_glob = 0; goto copy; } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_PATTERN_SUBST else if (*p == '/' && slash) { /* stop handling globbing and mark location of slash */ globbing = slash = 0; @@ -6494,10 +6513,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *loc; char *rmesc, *rmescend; char *str; - IF_ASH_BASH_COMPAT(char *repl = NULL;) - IF_ASH_BASH_COMPAT(int pos, len, orig_len;) + IF_BASH_SUBSTR(int pos, len, orig_len;) int amount, resetloc; - IF_ASH_BASH_COMPAT(int workloc;) + IF_BASH_PATTERN_SUBST(int workloc;) + IF_BASH_PATTERN_SUBST(char *repl = NULL;) int zero; char *(*scan)(char*, char*, char*, char*, int, int); @@ -6522,7 +6541,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, varunset(p, varname, startp, varflags); /* NOTREACHED */ -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SUBSTR case VSSUBSTR: //TODO: support more general format ${v:EXPR:EXPR}, // where EXPR follows $(()) rules @@ -6591,17 +6610,19 @@ subevalvar(char *p, char *varname, int strloc, int subtype, amount = loc - expdest; STADJUST(amount, expdest); return loc; -#endif +#endif /* BASH_SUBSTR */ } resetloc = expdest - (char *)stackblock(); +#if BASH_PATTERN_SUBST /* We'll comeback here if we grow the stack while handling * a VSREPLACE or VSREPLACEALL, since our pointers into the * stack will need rebasing, and we'll need to remove our work * areas each time */ - IF_ASH_BASH_COMPAT(restart:) + restart: +#endif amount = expdest - ((char *)stackblock() + resetloc); STADJUST(-amount, expdest); @@ -6626,11 +6647,11 @@ subevalvar(char *p, char *varname, int strloc, int subtype, * RMESCAPE_SLASH causes preglob to work differently on the pattern * and string. It's only used on the first call. */ - preglob(str, IF_ASH_BASH_COMPAT( + preglob(str, IF_BASH_PATTERN_SUBST( (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? - RMESCAPE_SLASH :) 0); + RMESCAPE_SLASH : ) 0); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_PATTERN_SUBST workloc = expdest - (char *)stackblock(); if (subtype == VSREPLACE || subtype == VSREPLACEALL) { char *idx, *end; @@ -6731,7 +6752,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, STADJUST(-amount, expdest); return startp; } -#endif /* ENABLE_ASH_BASH_COMPAT */ +#endif /* BASH_PATTERN_SUBST */ subtype -= VSTRIMRIGHT; #if DEBUG @@ -6999,8 +7020,10 @@ evalvar(char *p, int flag, struct strlist *var_str_list) case VSTRIMLEFTMAX: case VSTRIMRIGHT: case VSTRIMRIGHTMAX: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SUBSTR case VSSUBSTR: +#endif +#if BASH_PATTERN_SUBST case VSREPLACE: case VSREPLACEALL: #endif @@ -7924,7 +7947,7 @@ enum { TESAC, TFI, TFOR, -#if ENABLE_ASH_BASH_COMPAT +#if BASH_FUNCTION TFUNCTION, #endif TIF, @@ -7962,7 +7985,7 @@ enum { /* 19 */ | (1u << TESAC) /* 20 */ | (1u << TFI) /* 21 */ | (0u << TFOR) -#if ENABLE_ASH_BASH_COMPAT +#if BASH_FUNCTION /* 22 */ | (0u << TFUNCTION) #endif /* 23 */ | (0u << TIF) @@ -8000,7 +8023,7 @@ static const char *const tokname_array[] = { "esac", "fi", "for", -#if ENABLE_ASH_BASH_COMPAT +#if BASH_FUNCTION "function", #endif "if", @@ -8244,7 +8267,7 @@ static const uint8_t nodesize[N_NUMBER] ALIGN1 = { [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)), [NARG ] = SHELL_ALIGN(sizeof(struct narg)), [NTO ] = SHELL_ALIGN(sizeof(struct nfile)), -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)), #endif [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)), @@ -8326,7 +8349,7 @@ calcsize(int funcblocksize, union node *n) funcblocksize = calcsize(funcblocksize, n->narg.next); break; case NTO: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif case NCLOBBER: @@ -8440,7 +8463,7 @@ copynode(union node *n) new->narg.next = copynode(n->narg.next); break; case NTO: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif case NCLOBBER: @@ -8873,14 +8896,14 @@ expredir(union node *n) case NFROMTO: case NFROM: case NTO: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT case NTO2: #endif case NCLOBBER: case NAPPEND: expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); TRACE(("expredir expanded to '%s'\n", fn.list->text)); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT store_expfname: #endif #if 0 @@ -8902,7 +8925,7 @@ expredir(union node *n) expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); if (fn.list == NULL) ash_msg_and_raise_error("redir error"); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT //FIXME: we used expandarg with different args! if (!isdigit_str9(fn.list->text)) { /* >&file, not >&fd */ @@ -9298,7 +9321,7 @@ static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, a #if ENABLE_ASH_PRINTF static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } #endif -#if ENABLE_ASH_TEST +#if ENABLE_ASH_TEST || BASH_TEST2 static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } #endif @@ -9308,9 +9331,9 @@ static const struct builtincmd builtintab[] = { { BUILTIN_SPEC_REG ":" , truecmd }, #if ENABLE_ASH_TEST { BUILTIN_REGULAR "[" , testcmd }, -# if ENABLE_ASH_BASH_COMPAT +#endif +#if BASH_TEST2 { BUILTIN_REGULAR "[[" , testcmd }, -# endif #endif #if ENABLE_ASH_ALIAS { BUILTIN_REG_ASSG "alias" , aliascmd }, @@ -9363,7 +9386,7 @@ static const struct builtincmd builtintab[] = { { BUILTIN_SPEC_REG "return" , returncmd }, { BUILTIN_SPEC_REG "set" , setcmd }, { BUILTIN_SPEC_REG "shift" , shiftcmd }, -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SOURCE { BUILTIN_SPEC_REG "source" , dotcmd }, #endif #if ENABLE_ASH_TEST @@ -9386,7 +9409,7 @@ static const struct builtincmd builtintab[] = { #define COMMANDCMD (builtintab + \ /* . : */ 2 + \ /* [ */ 1 * ENABLE_ASH_TEST + \ - /* [[ */ 1 * ENABLE_ASH_TEST * ENABLE_ASH_BASH_COMPAT + \ + /* [[ */ 1 * BASH_TEST2 + \ /* alias */ 1 * ENABLE_ASH_ALIAS + \ /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ /* break cd cddir */ 3) @@ -11008,10 +11031,10 @@ simplecmd(void) union node *vars, **vpp; union node **rpp, *redir; int savecheckkwd; -#if ENABLE_ASH_BASH_COMPAT +#if BASH_TEST2 smallint double_brackets_flag = 0; - smallint function_flag = 0; #endif + IF_BASH_FUNCTION(smallint function_flag = 0;) args = NULL; app = &args; @@ -11026,12 +11049,14 @@ simplecmd(void) checkkwd = savecheckkwd; t = readtoken(); switch (t) { -#if ENABLE_ASH_BASH_COMPAT +#if BASH_FUNCTION case TFUNCTION: if (peektoken() != TWORD) raise_error_unexpected_syntax(TWORD); function_flag = 1; break; +#endif +#if BASH_TEST2 case TAND: /* "&&" */ case TOR: /* "||" */ if (!double_brackets_flag) { @@ -11045,7 +11070,7 @@ simplecmd(void) n->type = NARG; /*n->narg.next = NULL; - stzalloc did it */ n->narg.text = wordtext; -#if ENABLE_ASH_BASH_COMPAT +#if BASH_TEST2 if (strcmp("[[", wordtext) == 0) double_brackets_flag = 1; else if (strcmp("]]", wordtext) == 0) @@ -11060,7 +11085,7 @@ simplecmd(void) app = &n->narg.next; savecheckkwd = 0; } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_FUNCTION if (function_flag) { checkkwd = CHKNL | CHKKWD; switch (peektoken()) { @@ -11090,7 +11115,7 @@ simplecmd(void) parsefname(); /* read name of redirection file */ break; case TLP: - IF_ASH_BASH_COMPAT(do_func:) + IF_BASH_FUNCTION(do_func:) if (args && app == &args->narg.next && !vars && !redir ) { @@ -11098,7 +11123,7 @@ simplecmd(void) const char *name; /* We have a function */ - if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP) + if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP) raise_error_unexpected_syntax(TRP); name = n->narg.text; if (!goodname(name) @@ -11111,7 +11136,7 @@ simplecmd(void) n->narg.next = parse_command(); return n; } - IF_ASH_BASH_COMPAT(function_flag = 0;) + IF_BASH_FUNCTION(function_flag = 0;) /* fall through */ default: tokpushback = 1; @@ -11292,7 +11317,7 @@ parse_command(void) n1 = list(0); t = TEND; break; - IF_ASH_BASH_COMPAT(case TFUNCTION:) + IF_BASH_FUNCTION(case TFUNCTION:) case TWORD: case TREDIR: tokpushback = 1; @@ -11325,7 +11350,7 @@ parse_command(void) return n1; } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_DOLLAR_SQUOTE static int decode_dollar_squote(void) { @@ -11410,7 +11435,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ int dqvarnest; /* levels of variables expansion within double quotes */ - IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) + IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;) startlinno = g_parsefile->linno; bqlist = NULL; @@ -11445,7 +11470,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) USTPUTC(c, out); break; case CCTL: -#if ENABLE_ASH_BASH_COMPAT +#if BASH_DOLLAR_SQUOTE if (c == '\\' && bash_dollar_squote) { c = decode_dollar_squote(); if (c == '\0') { @@ -11506,7 +11531,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) dblquote = 1; goto quotemark; case CENDQUOTE: - IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) + IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;) if (eofmark != NULL && varnest == 0) { USTPUTC(c, out); } else { @@ -11565,7 +11590,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) break; default: if (varnest == 0) { -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT if (c == '&') { //Can't call pgetc_eatbnl() here, this requires three-deep pungetc() if (pgetc() == '>') @@ -11597,7 +11622,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) len = out - (char *)stackblock(); out = stackblock(); if (eofmark == NULL) { - if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>')) + if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>')) && quotef == 0 ) { if (isdigit_str9(out)) { @@ -11685,7 +11710,7 @@ parseredir: { pungetc(); } } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT else if (c == 0x100 + '>') { /* this flags &> redirection */ np->nfile.fd = 1; pgetc(); /* this is '>', no need to check */ @@ -11751,7 +11776,7 @@ parsesub: { if (c > 255 /* PEOA or PEOF */ || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) ) { -#if ENABLE_ASH_BASH_COMPAT +#if BASH_DOLLAR_SQUOTE if (syntax != DQSYNTAX && c == '\'') bash_dollar_squote = 1; else @@ -11827,7 +11852,7 @@ parsesub: { switch (c) { case ':': c = pgetc_eatbnl(); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SUBSTR /* This check is only needed to not misinterpret * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} * constructs. @@ -11857,7 +11882,7 @@ parsesub: { subtype++; break; } -#if ENABLE_ASH_BASH_COMPAT +#if BASH_PATTERN_SUBST case '/': /* ${v/[/]pattern/repl} */ //TODO: encode pattern and repl separately. @@ -12112,7 +12137,7 @@ xxreadtoken(void) p += xxreadtoken_doubles + 1; } else { pungetc(); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_REDIR_OUTPUT if (c == '&' && cc == '>') /* &> */ break; /* return readtoken1(...) */ #endif @@ -13274,9 +13299,11 @@ init(void) setvareq((char*)defoptindvar, VTEXTFIXED); setvar0("PPID", utoa(getppid())); -#if ENABLE_ASH_BASH_COMPAT +#if BASH_SHLVL_VAR p = lookupvar("SHLVL"); setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); +#endif +#if BASH_HOSTNAME_VAR if (!lookupvar("HOSTNAME")) { struct utsname uts; uname(&uts); -- cgit v1.2.3-55-g6feb From 027d3ab57d6a3a5a872543a6f30e55347d975149 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Wed, 11 Jan 2017 14:18:15 +0100 Subject: hush: split bash compatible extensions into separate defines. No code changes Splitting these options makes it self-documenting about what bash-compatible features we have. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- shell/hush.c | 73 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index ecef099ac..fb0321a2c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -326,6 +326,15 @@ #endif +/* So far, all bash compat is controlled by one config option */ +/* Separate defines document which part of code implements what */ +#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT +#define BASH_SUBSTR ENABLE_HUSH_BASH_COMPAT +#define BASH_TEST2 ENABLE_HUSH_BASH_COMPAT +#define BASH_SOURCE ENABLE_HUSH_BASH_COMPAT +#define BASH_HOSTNAME_VAR ENABLE_HUSH_BASH_COMPAT + + /* Build knobs */ #define LEAK_HUNTING 0 #define BUILD_AS_NOMMU 0 @@ -411,7 +420,7 @@ #define _SPECIAL_VARS_STR "_*@$!?#" #define SPECIAL_VARS_STR ("_*@$!?#" + 1) #define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3) -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_PATTERN_SUBST /* Support / and // replace ops */ /* Note that // is stored as \ in "encoded" string representation */ # define VAR_ENCODED_SUBST_OPS "\\/%#:-=+?" @@ -572,7 +581,7 @@ struct command { smallint cmd_type; /* CMD_xxx */ #define CMD_NORMAL 0 #define CMD_SUBSHELL 1 -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_TEST2 /* used for "[[ EXPR ]]" */ # define CMD_SINGLEWORD_NOGLOB 2 #endif @@ -947,7 +956,7 @@ static int builtin_set(char **argv) FAST_FUNC; #endif static int builtin_shift(char **argv) FAST_FUNC; static int builtin_source(char **argv) FAST_FUNC; -#if ENABLE_HUSH_TEST +#if ENABLE_HUSH_TEST || BASH_TEST2 static int builtin_test(char **argv) FAST_FUNC; #endif #if ENABLE_HUSH_TRAP @@ -1044,7 +1053,7 @@ static const struct built_in_command bltins1[] = { BLTIN("set" , builtin_set , "Set positional parameters"), #endif BLTIN("shift" , builtin_shift , "Shift positional parameters"), -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_SOURCE BLTIN("source" , builtin_source , NULL), #endif #if ENABLE_HUSH_TRAP @@ -2174,7 +2183,7 @@ static void unset_vars(char **strings) free(strings); } -#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_BASH_COMPAT || ENABLE_HUSH_READ +#if BASH_HOSTNAME_VAR || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_READ static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val) { char *var = xasprintf("%s=%s", name, val); @@ -3633,7 +3642,7 @@ static int done_word(o_string *word, struct parse_context *ctx) (ctx->ctx_res_w == RES_SNTX)); return (ctx->ctx_res_w == RES_SNTX); } -# if ENABLE_HUSH_BASH_COMPAT +# if BASH_TEST2 if (strcmp(word->data, "[[") == 0) { command->cmd_type = CMD_SINGLEWORD_NOGLOB; } @@ -4231,7 +4240,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign { int ch; char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG; -# if ENABLE_HUSH_BASH_COMPAT +# if BASH_SUBSTR || BASH_PATTERN_SUBST char end_char2 = end_ch >> 8; # endif end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1); @@ -4242,7 +4251,11 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign syntax_error_unterm_ch(end_ch); return 0; } - if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { + if (ch == end_ch +# if BASH_SUBSTR || BASH_PATTERN_SUBST + || ch == end_char2 +# endif + ) { if (!dbl) break; /* we look for closing )) of $((EXPR)) */ @@ -4395,14 +4408,14 @@ static int parse_dollar(o_string *as_string, /* Eat everything until closing '}' (or ':') */ end_ch = '}'; - if (ENABLE_HUSH_BASH_COMPAT + if (BASH_SUBSTR && ch == ':' && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input)) ) { /* It's ${var:N[:M]} thing */ end_ch = '}' * 0x100 + ':'; } - if (ENABLE_HUSH_BASH_COMPAT + if (BASH_PATTERN_SUBST && ch == '/' ) { /* It's ${var/[/]pattern[/repl]} thing */ @@ -4429,7 +4442,9 @@ static int parse_dollar(o_string *as_string, o_addchr(as_string, last_ch); } - if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) { + if ((BASH_SUBSTR || BASH_PATTERN_SUBST) + && (end_ch & 0xff00) + ) { /* close the first block: */ o_addchr(dest, SPECIAL_VAR_SYMBOL); /* while parsing N from ${var:N[:M]} @@ -4440,7 +4455,7 @@ static int parse_dollar(o_string *as_string, goto again; } /* got '}' */ - if (end_ch == '}' * 0x100 + ':') { + if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') { /* it's ${var:N} - emulate :999999999 */ o_addstr(dest, "999999999"); } /* else: it's ${var/[/]pattern} */ @@ -4515,7 +4530,7 @@ static int parse_dollar(o_string *as_string, } #if BB_MMU -# if ENABLE_HUSH_BASH_COMPAT +# if BASH_PATTERN_SUBST #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ encode_string(dest, input, dquote_end, process_bkslash) # else @@ -4527,7 +4542,7 @@ static int parse_dollar(o_string *as_string, #else /* !MMU */ -# if ENABLE_HUSH_BASH_COMPAT +# if BASH_PATTERN_SUBST /* all parameters are needed, no macro tricks */ # else #define encode_string(as_string, dest, input, dquote_end, process_bkslash) \ @@ -4540,7 +4555,7 @@ static int encode_string(o_string *as_string, int dquote_end, int process_bkslash) { -#if !ENABLE_HUSH_BASH_COMPAT +#if !BASH_PATTERN_SUBST const int process_bkslash = 1; #endif int ch; @@ -5183,7 +5198,7 @@ static struct pipe *parse_stream(char **pstring, /*** Execution routines ***/ /* Expansion can recurse, need forward decls: */ -#if !ENABLE_HUSH_BASH_COMPAT +#if !BASH_PATTERN_SUBST /* only ${var/pattern/repl} (its pattern part) needs additional mode */ #define expand_string_to_string(str, do_unbackslash) \ expand_string_to_string(str) @@ -5304,7 +5319,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha * Returns malloced string. * As an optimization, we return NULL if expansion is not needed. */ -#if !ENABLE_HUSH_BASH_COMPAT +#if !BASH_PATTERN_SUBST /* only ${var/pattern/repl} (its pattern part) needs additional mode */ #define encode_then_expand_string(str, process_bkslash, do_unbackslash) \ encode_then_expand_string(str) @@ -5358,7 +5373,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) } #endif -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_PATTERN_SUBST /* ${var/[/]pattern[/repl]} helpers */ static char *strstr_pattern(char *val, const char *pattern, int *size) { @@ -5410,7 +5425,7 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c debug_printf_varexp("result:'%s'\n", result); return result; } -#endif +#endif /* BASH_PATTERN_SUBST */ /* Helper: * Handles varname... construct. @@ -5458,7 +5473,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha if (exp_op == ':') { exp_op = *exp_word++; //TODO: try ${var:} and ${var:bogus} in non-bash config - if (ENABLE_HUSH_BASH_COMPAT + if (BASH_SUBSTR && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op)) ) { /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */ @@ -5540,7 +5555,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha } } } -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_PATTERN_SUBST else if (exp_op == '/' || exp_op == '\\') { /* It's ${var/[/]pattern[/repl]} thing. * Note that in encoded form it has TWO parts: @@ -5587,9 +5602,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha free(repl); } } -#endif +#endif /* BASH_PATTERN_SUBST */ else if (exp_op == ':') { -#if ENABLE_HUSH_BASH_COMPAT && ENABLE_FEATURE_SH_MATH +#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH /* It's ${var:N[:M]} bashism. * Note that in encoded form it has TWO parts: * var:NM @@ -5625,7 +5640,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha } debug_printf_varexp("val:'%s'\n", val); } else -#endif +#endif /* HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH */ { die_if_script("malformed ${%s:...}", var); val = NULL; @@ -5915,7 +5930,7 @@ static char **expand_strvec_to_strvec(char **argv) return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS); } -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_TEST2 static char **expand_strvec_to_strvec_singleword_noglob(char **argv) { return expand_variables(argv, EXP_FLAG_SINGLEWORD); @@ -5930,7 +5945,7 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv) */ static char *expand_string_to_string(const char *str, int do_unbackslash) { -#if !ENABLE_HUSH_BASH_COMPAT +#if !BASH_PATTERN_SUBST const int do_unbackslash = 1; #endif char *argv[2], **list; @@ -7652,7 +7667,7 @@ static NOINLINE int run_pipe(struct pipe *pi) } /* Expand the rest into (possibly) many strings each */ -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_TEST2 if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); } else @@ -8408,7 +8423,7 @@ int hush_main(int argc, char **argv) /* Export PWD */ set_pwd_var(/*exp:*/ 1); -#if ENABLE_HUSH_BASH_COMPAT +#if BASH_HOSTNAME_VAR /* Set (but not export) HOSTNAME unless already set */ if (!get_local_var_value("HOSTNAME")) { struct utsname uts; @@ -8816,7 +8831,7 @@ static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char * return applet_main_func(argc, argv - argc); } #endif -#if ENABLE_HUSH_TEST +#if ENABLE_HUSH_TEST || BASH_TEST2 static int FAST_FUNC builtin_test(char **argv) { return run_applet_main(argv, test_main); -- cgit v1.2.3-55-g6feb From 8944c67b1f61ca6a51a485772d5d1e6a8ff3d83d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 14:22:00 +0100 Subject: hush: reinstate [[ builtin Mike deleted it: commit 39456a18a104b228de240b265bd943251219849d Author: Mike Frysinger Date: Sat Mar 28 12:21:57 2009 +0000 stop lying about [[ test support probably because it was not properly ifdefed around, and was enabled even when bash compat is off. I just tested it - it works: $ [ *.diff = z.diff ]; echo $? 0 $ [[ *.diff = z.diff ]]; echo $? 1 Of course, not all numerous bash tricks of [[ ]] are implemented... function old new delta bltins2 60 72 +12 Signed-off-by: Denys Vlasenko --- shell/hush.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shell/hush.c b/shell/hush.c index fb0321a2c..d90c1485a 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1083,6 +1083,9 @@ static const struct built_in_command bltins2[] = { #if ENABLE_HUSH_TEST BLTIN("[" , builtin_test , NULL), #endif +#if BASH_TEST2 + BLTIN("[[" , builtin_test , NULL), +#endif #if ENABLE_HUSH_ECHO BLTIN("echo" , builtin_echo , NULL), #endif -- cgit v1.2.3-55-g6feb From 01ccdd1d3c5221789f1ac62ced12b7984d910705 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 16:17:59 +0100 Subject: libbb: consolidate the code to set termios unbuffered mode function old new delta set_termios_to_raw - 116 +116 count_lines 72 74 +2 powertop_main 1458 1430 -28 top_main 943 914 -29 more_main 759 714 -45 fsck_minix_main 2969 2921 -48 conspy_main 1197 1135 -62 rawmode 99 36 -63 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/6 up/down: 118/-275) Total: -157 bytes Signed-off-by: Denys Vlasenko --- editors/vi.c | 15 ++++----------- include/libbb.h | 4 ++++ libbb/lineedit.c | 2 +- libbb/xfuncs.c | 37 +++++++++++++++++++++++++++++++++++++ loginutils/getty.c | 2 +- loginutils/vlock.c | 8 ++++---- miscutils/chat.c | 1 + miscutils/conspy.c | 17 +++++++---------- miscutils/microcom.c | 1 + miscutils/rx.c | 1 + procps/powertop.c | 10 +++------- procps/top.c | 10 ++-------- shell/shell_common.c | 2 +- util-linux/fsck_minix.c | 6 +----- util-linux/more.c | 10 +++------- 15 files changed, 71 insertions(+), 55 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index b56b04bdd..1e5ef44fb 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -354,7 +354,7 @@ struct globals { #if ENABLE_FEATURE_VI_USE_SIGNALS sigjmp_buf restart; // catch_sig() #endif - struct termios term_orig, term_vi; // remember what the cooked mode was + struct termios term_orig; // remember what the cooked mode was #if ENABLE_FEATURE_VI_COLON char *initial_cmds[3]; // currently 2 entries, NULL terminated #endif @@ -462,7 +462,6 @@ struct globals { #define context_end (G.context_end ) #define restart (G.restart ) #define term_orig (G.term_orig ) -#define term_vi (G.term_vi ) #define initial_cmds (G.initial_cmds ) #define readbuffer (G.readbuffer ) #define scr_out_buf (G.scr_out_buf ) @@ -2731,15 +2730,9 @@ static char *swap_context(char *p) // goto new context for '' command make this //----- Set terminal attributes -------------------------------- static void rawmode(void) { - tcgetattr(0, &term_orig); - term_vi = term_orig; - term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG on - allow intr's - term_vi.c_iflag &= (~IXON & ~ICRNL); - term_vi.c_oflag &= (~ONLCR); - term_vi.c_cc[VMIN] = 1; - term_vi.c_cc[VTIME] = 0; - erase_char = term_vi.c_cc[VERASE]; - tcsetattr_stdin_TCSANOW(&term_vi); + // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals + set_termios_to_raw(STDIN_FILENO, &term_orig, TERMIOS_RAW_CRNL); + erase_char = term_orig.c_cc[VERASE]; } static void cookmode(void) diff --git a/include/libbb.h b/include/libbb.h index abdc8c2b8..87f89c76d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1438,6 +1438,10 @@ int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FU int get_terminal_width(int fd) FAST_FUNC; int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC; +#define TERMIOS_CLEAR_ISIG (1 << 0) +#define TERMIOS_RAW_CRNL (1 << 1) +#define TERMIOS_RAW_INPUT (1 << 2) +int set_termios_to_raw(int fd, struct termios *oldterm, int flags) FAST_FUNC; /* NB: "unsigned request" is crucial! "int request" will break some arches! */ int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC; diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 31e392147..2a5d4e704 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2325,7 +2325,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */ /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */ new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG); - /* reads would block only if < 1 char is available */ + /* reads will block only if < 1 char is available */ new_settings.c_cc[VMIN] = 1; /* no timeout (reads block forever) */ new_settings.c_cc[VTIME] = 0; diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 45650edba..98d3531d6 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -311,6 +311,43 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) return tcsetattr(STDIN_FILENO, TCSANOW, tp); } +int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags) +{ +//TODO: lineedit, microcom and less might be adapted to use this too: +// grep for "tcsetattr" + + struct termios newterm; + + tcgetattr(fd, oldterm); + newterm = *oldterm; + + /* Turn off buffered input (ICANON) + * Turn off echoing (ECHO) + * and separate echoing of newline (ECHONL, normally off anyway) + */ + newterm.c_lflag &= ~(ICANON | ECHO | ECHONL); + if (flags & TERMIOS_CLEAR_ISIG) { + /* dont recognize INT/QUIT/SUSP chars */ + newterm.c_lflag &= ~ISIG; + } + /* reads will block only if < 1 char is available */ + newterm.c_cc[VMIN] = 1; + /* no timeout (reads block forever) */ + newterm.c_cc[VTIME] = 0; + if (flags & TERMIOS_RAW_CRNL) { + /* dont convert CR to NL on input */ + newterm.c_iflag &= ~(IXON | ICRNL); + /* dont convert NL to CR on output */ + newterm.c_oflag &= ~(ONLCR); + } + if (flags & TERMIOS_RAW_INPUT) { + /* dont convert anything on input */ + newterm.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL); + } + + return tcsetattr(fd, TCSANOW, &newterm); +} + pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options) { pid_t r; diff --git a/loginutils/getty.c b/loginutils/getty.c index 162c1697e..ba6c784a3 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -316,7 +316,7 @@ static void init_tty_attrs(int speed) /* non-raw output; add CR to each NL */ G.tty_attrs.c_oflag = OPOST | ONLCR; - /* reads would block only if < 1 char is available */ + /* reads will block only if < 1 char is available */ G.tty_attrs.c_cc[VMIN] = 1; /* no timeout (reads block forever) */ G.tty_attrs.c_cc[VTIME] = 0; diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 52ae607c9..5ba6a8780 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c @@ -105,12 +105,12 @@ int vlock_main(int argc UNUSED_PARAM, char **argv) ioctl(STDIN_FILENO, VT_SETMODE, &vtm); #endif +//TODO: use set_termios_to_raw() tcgetattr(STDIN_FILENO, &oterm); term = oterm; - term.c_iflag &= ~BRKINT; - term.c_iflag |= IGNBRK; - term.c_lflag &= ~ISIG; - term.c_lflag &= ~(ECHO | ECHOCTL); + term.c_iflag |= IGNBRK; /* ignore serial break (why? VTs don't have breaks, right?) */ + term.c_iflag &= ~BRKINT; /* redundant? "dont translate break to SIGINT" */ + term.c_lflag &= ~(ISIG | ECHO | ECHOCTL); /* ignore ^C ^Z, echo off */ tcsetattr_stdin_TCSANOW(&term); while (1) { diff --git a/miscutils/chat.c b/miscutils/chat.c index dc85f82fb..8df194534 100644 --- a/miscutils/chat.c +++ b/miscutils/chat.c @@ -213,6 +213,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv) , signal_handler); #if ENABLE_FEATURE_CHAT_TTY_HIFI +//TODO: use set_termios_to_raw() tcgetattr(STDIN_FILENO, &tio); tio0 = tio; cfmakeraw(&tio); diff --git a/miscutils/conspy.c b/miscutils/conspy.c index d9d09d482..1f0278b47 100644 --- a/miscutils/conspy.c +++ b/miscutils/conspy.c @@ -363,7 +363,6 @@ int conspy_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int conspy_main(int argc UNUSED_PARAM, char **argv) { char tty_name[sizeof(DEV_TTY "NN")]; - struct termios termbuf; unsigned opts; unsigned ttynum; int poll_timeout_ms; @@ -414,16 +413,14 @@ int conspy_main(int argc UNUSED_PARAM, char **argv) bb_signals(BB_FATAL_SIGS, cleanup); - // All characters must be passed through to us unaltered G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY); - tcgetattr(G.kbd_fd, &G.term_orig); - termbuf = G.term_orig; - termbuf.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL); - //termbuf.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n - termbuf.c_lflag &= ~(ISIG|ICANON|ECHO); - termbuf.c_cc[VMIN] = 1; - termbuf.c_cc[VTIME] = 0; - tcsetattr(G.kbd_fd, TCSANOW, &termbuf); + + // All characters must be passed through to us unaltered + set_termios_to_raw(G.kbd_fd, &G.term_orig, 0 + | TERMIOS_CLEAR_ISIG // no signals on ^C ^Z etc + | TERMIOS_RAW_INPUT // turn off all input conversions + ); + //Note: termios.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n poll_timeout_ms = 250; while (1) { diff --git a/miscutils/microcom.c b/miscutils/microcom.c index 04605d883..5a4bbefa9 100644 --- a/miscutils/microcom.c +++ b/miscutils/microcom.c @@ -33,6 +33,7 @@ // set raw tty mode static void xget1(int fd, struct termios *t, struct termios *oldt) { +//TODO: use set_termios_to_raw() tcgetattr(fd, oldt); *t = *oldt; cfmakeraw(t); diff --git a/miscutils/rx.c b/miscutils/rx.c index 660f66a89..36fc20a72 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c @@ -263,6 +263,7 @@ int rx_main(int argc UNUSED_PARAM, char **argv) termios_err = tcgetattr(read_fd, &tty); if (termios_err == 0) { +//TODO: use set_termios_to_raw() orig_tty = tty; cfmakeraw(&tty); tcsetattr(read_fd, TCSAFLUSH, &tty); diff --git a/procps/powertop.c b/procps/powertop.c index ce85f4191..ee806161f 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -683,7 +683,6 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) ullong cur_duration[MAX_CSTATE_COUNT]; char cstate_lines[MAX_CSTATE_COUNT + 2][64]; #if ENABLE_FEATURE_USE_TERMIOS - struct termios new_settings; struct pollfd pfd[1]; pfd[0].fd = 0; @@ -707,14 +706,11 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) puts("Collecting data for "DEFAULT_SLEEP_STR" seconds"); #if ENABLE_FEATURE_USE_TERMIOS - tcgetattr(0, (void *)&G.init_settings); - memcpy(&new_settings, &G.init_settings, sizeof(new_settings)); - /* Turn on unbuffered input, turn off echoing */ - new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); + /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */ + set_termios_to_raw(STDIN_FILENO, &G.init_settings, TERMIOS_CLEAR_ISIG); + bb_signals(BB_FATAL_SIGS, sig_handler); /* So we don't forget to reset term settings */ atexit(reset_term); - bb_signals(BB_FATAL_SIGS, sig_handler); - tcsetattr_stdin_TCSANOW(&new_settings); #endif /* Collect initial data */ diff --git a/procps/top.c b/procps/top.c index 491acb574..91bb8a883 100644 --- a/procps/top.c +++ b/procps/top.c @@ -1089,9 +1089,6 @@ int top_main(int argc UNUSED_PARAM, char **argv) unsigned interval; char *str_interval, *str_iterations; unsigned scan_mask = TOP_MASK; -#if ENABLE_FEATURE_USE_TERMIOS - struct termios new_settings; -#endif INIT_G(); @@ -1141,11 +1138,8 @@ int top_main(int argc UNUSED_PARAM, char **argv) } #if ENABLE_FEATURE_USE_TERMIOS else { - tcgetattr(0, (void *) &initial_settings); - memcpy(&new_settings, &initial_settings, sizeof(new_settings)); - /* unbuffered input, turn off echo */ - new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); - tcsetattr_stdin_TCSANOW(&new_settings); + /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */ + set_termios_to_raw(STDIN_FILENO, &initial_settings, TERMIOS_CLEAR_ISIG); } bb_signals(BB_FATAL_SIGS, sig_catcher); diff --git a/shell/shell_common.c b/shell/shell_common.c index 98d862744..549b17ca1 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -143,7 +143,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val), // Setting it to more than 1 breaks poll(): // it blocks even if there's data. !?? //tty.c_cc[VMIN] = nchars < 256 ? nchars : 255; - /* reads would block only if < 1 char is available */ + /* reads will block only if < 1 char is available */ tty.c_cc[VMIN] = 1; /* no timeout (reads block forever) */ tty.c_cc[VTIME] = 0; diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c index 0eaac17c0..2ab7530ea 100644 --- a/util-linux/fsck_minix.c +++ b/util-linux/fsck_minix.c @@ -1226,7 +1226,6 @@ void check2(void); int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int fsck_minix_main(int argc UNUSED_PARAM, char **argv) { - struct termios tmp; int retcode = 0; xfunc_error_retval = 8; @@ -1271,10 +1270,7 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv) read_tables(); if (OPT_manual) { - tcgetattr(0, &sv_termios); - tmp = sv_termios; - tmp.c_lflag &= ~(ICANON | ECHO); - tcsetattr_stdin_TCSANOW(&tmp); + set_termios_to_raw(STDIN_FILENO, &sv_termios, 0); termios_set = 1; } diff --git a/util-linux/more.c b/util-linux/more.c index 7fa60bdba..debad81bd 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -43,7 +43,6 @@ struct globals { unsigned terminal_width; unsigned terminal_height; struct termios initial_settings; - struct termios new_settings; } FIX_ALIASING; #define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { setup_common_bufsiz(); } while (0) @@ -101,12 +100,9 @@ int more_main(int argc UNUSED_PARAM, char **argv) return bb_cat(argv); G.tty_fileno = fileno(tty); - tcgetattr(G.tty_fileno, &G.initial_settings); - G.new_settings = G.initial_settings; - G.new_settings.c_lflag &= ~(ICANON | ECHO); - G.new_settings.c_cc[VMIN] = 1; - G.new_settings.c_cc[VTIME] = 0; - tcsetattr_tty_TCSANOW(&G.new_settings); + + /* Turn on unbuffered input; turn off echoing */ + set_termios_to_raw(G.tty_fileno, &G.initial_settings, 0); bb_signals(BB_FATAL_SIGS, gotsig); do { -- cgit v1.2.3-55-g6feb From 6c1f348fa792a33d5a98e68c139df65c2d4c1628 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 16:27:12 +0100 Subject: Move FEATURE_USE_TERMIOS config option to two applets which use it No code changes Signed-off-by: Denys Vlasenko --- Config.in | 9 --------- configs/TEST_nommu_defconfig | 1 - configs/TEST_noprintf_defconfig | 1 - configs/TEST_rh9_defconfig | 1 - configs/android2_defconfig | 1 - configs/android_502_defconfig | 1 - configs/android_defconfig | 1 - configs/android_ndk_defconfig | 1 - configs/cygwin_defconfig | 1 - configs/freebsd_defconfig | 1 - procps/powertop.c | 18 +++++++++++++----- procps/top.c | 28 ++++++++++++++++++---------- 12 files changed, 31 insertions(+), 33 deletions(-) diff --git a/Config.in b/Config.in index db1587169..ec302ffdf 100644 --- a/Config.in +++ b/Config.in @@ -61,15 +61,6 @@ config FEATURE_AUTOWIDTH If you leave this disabled, your utilities will be especially primitive and will be unable to determine the current screen width. -#fixme: delete, create suboptions for applets which use this -config FEATURE_USE_TERMIOS - bool "Use termios for one-stroke input" - default y - help - This option allows utilities such as 'top' to accept keyboard - commands. Without this option, they simply refresh display - after a fixed period. - config SHOW_USAGE bool "Show applet usage messages" default y diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index d7a9cfe25..37f3df019 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -524,7 +524,6 @@ CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y CONFIG_MKSWAP=y CONFIG_FEATURE_MKSWAP_UUID=y CONFIG_MORE=y -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_VOLUMEID=y CONFIG_FEATURE_VOLUMEID_EXT=y CONFIG_FEATURE_VOLUMEID_BTRFS=y diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig index adb6b7036..b03f6250e 100644 --- a/configs/TEST_noprintf_defconfig +++ b/configs/TEST_noprintf_defconfig @@ -527,7 +527,6 @@ CONFIG_FDISK_SUPPORT_LARGE_DISKS=y # CONFIG_MKSWAP is not set # CONFIG_FEATURE_MKSWAP_UUID is not set # CONFIG_MORE is not set -# CONFIG_FEATURE_USE_TERMIOS is not set CONFIG_VOLUMEID=y # CONFIG_FEATURE_VOLUMEID_EXT is not set # CONFIG_FEATURE_VOLUMEID_BTRFS is not set diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 0d72cdac9..3fc137787 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig @@ -540,7 +540,6 @@ CONFIG_FEATURE_MDEV_LOAD_FIRMWARE=y CONFIG_MKSWAP=y CONFIG_FEATURE_MKSWAP_UUID=y CONFIG_MORE=y -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_VOLUMEID=y CONFIG_FEATURE_VOLUMEID_EXT=y CONFIG_FEATURE_VOLUMEID_BTRFS=y diff --git a/configs/android2_defconfig b/configs/android2_defconfig index 866a87989..1846bb764 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig @@ -94,7 +94,6 @@ CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y # CONFIG_FEATURE_EDITING is not set CONFIG_FEATURE_EDITING_MAX_LEN=0 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 8d8dd250f..2cf4cd86c 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig @@ -174,7 +174,6 @@ CONFIG_MD5_SMALL=1 CONFIG_SHA3_SMALL=1 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/configs/android_defconfig b/configs/android_defconfig index 1eaab9eae..8316b2efb 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig @@ -112,7 +112,6 @@ CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y # CONFIG_FEATURE_EDITING is not set CONFIG_FEATURE_EDITING_MAX_LEN=0 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index dc9d21ce5..d8b994ed4 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig @@ -102,7 +102,6 @@ CONFIG_MD5_SMALL=1 CONFIG_SHA3_SMALL=1 # CONFIG_FEATURE_FAST_TOP is not set # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y # CONFIG_FEATURE_EDITING is not set CONFIG_FEATURE_EDITING_MAX_LEN=0 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig index 37e3e210f..352ed90ad 100644 --- a/configs/cygwin_defconfig +++ b/configs/cygwin_defconfig @@ -94,7 +94,6 @@ CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 CONFIG_FEATURE_FAST_TOP=y # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig index 90e0a8bda..b19a9fd49 100644 --- a/configs/freebsd_defconfig +++ b/configs/freebsd_defconfig @@ -93,7 +93,6 @@ CONFIG_PASSWORD_MINLEN=6 CONFIG_MD5_SMALL=1 CONFIG_FEATURE_FAST_TOP=y # CONFIG_FEATURE_ETC_NETWORKS is not set -CONFIG_FEATURE_USE_TERMIOS=y CONFIG_FEATURE_EDITING=y CONFIG_FEATURE_EDITING_MAX_LEN=1024 # CONFIG_FEATURE_EDITING_VI is not set diff --git a/procps/powertop.c b/procps/powertop.c index ee806161f..413806836 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -18,6 +18,14 @@ //config: default y //config: help //config: Analyze power consumption on Intel-based laptops +//config: +//config:config FEATURE_POWERTOP_INTERACTIVE +//config: bool "Accept keyboard commands" +//config: default y +//config: depends on POWERTOP +//config: help +//config: Without this, powertop will only refresh display every 10 seconds. +//config: No keyboard commands will work, only ^C to terminate. // XXX This should be configurable #define ENABLE_FEATURE_POWERTOP_PROCIRQ 1 @@ -82,7 +90,7 @@ struct globals { ullong last_usage[MAX_CSTATE_COUNT]; ullong start_duration[MAX_CSTATE_COUNT]; ullong last_duration[MAX_CSTATE_COUNT]; -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_POWERTOP_INTERACTIVE struct termios init_settings; #endif }; @@ -91,7 +99,7 @@ struct globals { SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_POWERTOP_INTERACTIVE static void reset_term(void) { tcsetattr_stdin_TCSANOW(&G.init_settings); @@ -682,7 +690,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) ullong cur_usage[MAX_CSTATE_COUNT]; ullong cur_duration[MAX_CSTATE_COUNT]; char cstate_lines[MAX_CSTATE_COUNT + 2][64]; -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_POWERTOP_INTERACTIVE struct pollfd pfd[1]; pfd[0].fd = 0; @@ -705,7 +713,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) puts("Collecting data for "DEFAULT_SLEEP_STR" seconds"); -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_POWERTOP_INTERACTIVE /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */ set_termios_to_raw(STDIN_FILENO, &G.init_settings, TERMIOS_CLEAR_ISIG); bb_signals(BB_FATAL_SIGS, sig_handler); @@ -735,7 +743,7 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) int i; G.cant_enable_timer_stats |= start_timer(); /* 1 on error */ -#if !ENABLE_FEATURE_USE_TERMIOS +#if !ENABLE_FEATURE_POWERTOP_INTERACTIVE sleep(DEFAULT_SLEEP); #else if (safe_poll(pfd, 1, DEFAULT_SLEEP * 1000) > 0) { diff --git a/procps/top.c b/procps/top.c index 91bb8a883..ff2fddeea 100644 --- a/procps/top.c +++ b/procps/top.c @@ -56,6 +56,14 @@ //config: The top program provides a dynamic real-time view of a running //config: system. //config: +//config:config FEATURE_TOP_INTERACTIVE +//config: bool "Accept keyboard commands" +//config: default y +//config: depends on TOP +//config: help +//config: Without this, top will only refresh display every 5 seconds. +//config: No keyboard commands will work, only ^C to terminate. +//config: //config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE //config: bool "Show CPU per-process usage percentage" //config: default y @@ -158,7 +166,7 @@ struct globals { smallint smp_cpu_info; /* one/many cpu info lines? */ #endif unsigned lines; /* screen height */ -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE struct termios initial_settings; int scroll_ofs; #define G_scroll_ofs G.scroll_ofs @@ -181,7 +189,7 @@ struct globals { jiffy_counts_t *cpu_jif, *cpu_prev_jif; int num_cpus; #endif -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE char kbd_input[KEYCODE_BUFFER_SIZE]; #endif char line_buf[80]; @@ -220,7 +228,7 @@ enum { #define OPT_BATCH_MODE (option_mask32 & OPT_b) -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE static int pid_sort(top_status_t *P, top_status_t *Q) { /* Buggy wrt pids with high bit set */ @@ -725,7 +733,7 @@ static void clearmems(void) top = NULL; } -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE static void reset_term(void) { if (!OPT_BATCH_MODE) @@ -737,7 +745,7 @@ static void sig_catcher(int sig) reset_term(); kill_myself_with_sig(sig); } -#endif /* FEATURE_USE_TERMIOS */ +#endif /* FEATURE_TOP_INTERACTIVE */ /* * TOPMEM support @@ -892,7 +900,7 @@ enum { EXIT_MASK = (unsigned)-1, }; -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE static unsigned handle_input(unsigned scan_mask, unsigned interval) { if (option_mask32 & OPT_EOF) { @@ -1041,7 +1049,7 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) //usage: "\n""Read the status of all processes from /proc each SECONDS" //usage: "\n""and display a screenful of them." //usage: "\n" -//usage: IF_FEATURE_USE_TERMIOS( +//usage: IF_FEATURE_TOP_INTERACTIVE( //usage: "Keys:" //usage: "\n"" N/M" //usage: IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE("/P") @@ -1136,7 +1144,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) if (OPT_BATCH_MODE) { option_mask32 |= OPT_EOF; } -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE else { /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */ set_termios_to_raw(STDIN_FILENO, &initial_settings, TERMIOS_CLEAR_ISIG); @@ -1237,7 +1245,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) clearmems(); if (iterations >= 0 && !--iterations) break; -#if !ENABLE_FEATURE_USE_TERMIOS +#if !ENABLE_FEATURE_TOP_INTERACTIVE sleep(interval); #else scan_mask = handle_input(scan_mask, interval); @@ -1245,7 +1253,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) } /* end of "while (not Q)" */ bb_putchar('\n'); -#if ENABLE_FEATURE_USE_TERMIOS +#if ENABLE_FEATURE_TOP_INTERACTIVE reset_term(); #endif if (ENABLE_FEATURE_CLEAN_UP) { -- cgit v1.2.3-55-g6feb From ed15dde60a72dce888df10295a916b199346929d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 16:35:52 +0100 Subject: Move FEATURE_AUTOWIDTH config option to two applets which use it No code changes Signed-off-by: Denys Vlasenko --- Config.in | 11 ----------- configs/TEST_nommu_defconfig | 5 ----- configs/TEST_noprintf_defconfig | 1 - configs/TEST_rh9_defconfig | 5 ----- configs/android2_defconfig | 5 ----- configs/android_502_defconfig | 5 ----- configs/android_defconfig | 5 ----- configs/android_ndk_defconfig | 5 ----- configs/cygwin_defconfig | 5 ----- configs/freebsd_defconfig | 5 ----- coreutils/ls.c | 27 ++++++++++++++++----------- networking/telnet.c | 15 ++++++++++----- 12 files changed, 26 insertions(+), 68 deletions(-) diff --git a/Config.in b/Config.in index ec302ffdf..cfb3aa0ee 100644 --- a/Config.in +++ b/Config.in @@ -50,17 +50,6 @@ config USE_PORTABLE_CODE compiler other than gcc. If you do use gcc, this option may needlessly increase code size. -#fixme: delete, create suboptions for applets which use this -config FEATURE_AUTOWIDTH - bool "Calculate terminal & column widths" - default y - help - This option allows utilities such as 'ls', 'telnet' etc - to determine the width of the screen, which can allow them to - display additional text or avoid wrapping text onto the next line. - If you leave this disabled, your utilities will be especially - primitive and will be unable to determine the current screen width. - config SHOW_USAGE bool "Show applet usage messages" default y diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index 37f3df019..b7d9a35c2 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -265,11 +265,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/TEST_noprintf_defconfig b/configs/TEST_noprintf_defconfig index b03f6250e..3f85ee1df 100644 --- a/configs/TEST_noprintf_defconfig +++ b/configs/TEST_noprintf_defconfig @@ -277,7 +277,6 @@ CONFIG_TRUE=y # CONFIG_WHOAMI is not set # CONFIG_YES is not set # CONFIG_FEATURE_PRESERVE_HARDLINKS is not set -# CONFIG_FEATURE_AUTOWIDTH is not set # CONFIG_FEATURE_HUMAN_READABLE is not set # CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 3fc137787..99deb67fe 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig @@ -276,11 +276,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/android2_defconfig b/configs/android2_defconfig index 1846bb764..b079fa759 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig @@ -288,11 +288,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 2cf4cd86c..4273d3382 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig @@ -389,11 +389,6 @@ CONFIG_FEATURE_VERBOSE=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/android_defconfig b/configs/android_defconfig index 8316b2efb..b9489c456 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig @@ -311,11 +311,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index d8b994ed4..caf22e57b 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig @@ -315,11 +315,6 @@ CONFIG_FEATURE_VERBOSE=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/cygwin_defconfig b/configs/cygwin_defconfig index 352ed90ad..6bfc973ef 100644 --- a/configs/cygwin_defconfig +++ b/configs/cygwin_defconfig @@ -288,11 +288,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/configs/freebsd_defconfig b/configs/freebsd_defconfig index b19a9fd49..e3d04aedc 100644 --- a/configs/freebsd_defconfig +++ b/configs/freebsd_defconfig @@ -286,11 +286,6 @@ CONFIG_YES=y # CONFIG_FEATURE_PRESERVE_HARDLINKS=y -# -# Common options for ls, more and telnet -# -CONFIG_FEATURE_AUTOWIDTH=y - # # Common options for df, du, ls # diff --git a/coreutils/ls.c b/coreutils/ls.c index 531eb85b5..13df77410 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -48,6 +48,11 @@ //config: default y //config: depends on LS //config: +//config:config FEATURE_LS_WIDTH +//config: bool "Enable -w WIDTH and window size autodetection" +//config: default y +//config: depends on LS +//config: //config:config FEATURE_LS_SORTFILES //config: bool "Sort the file names" //config: default y @@ -101,7 +106,7 @@ //usage: IF_FEATURE_LS_SORTFILES("rSXv") //usage: IF_FEATURE_LS_TIMESTAMPS("ctu") //usage: IF_SELINUX("kKZ") "]" -//usage: IF_FEATURE_AUTOWIDTH(" [-w WIDTH]") " [FILE]..." +//usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..." //usage:#define ls_full_usage "\n\n" //usage: "List directory contents\n" //usage: "\n -1 One column output" @@ -147,7 +152,7 @@ //usage: "\n -K List security context in long format" //usage: "\n -Z List security context and permission" //usage: ) -//usage: IF_FEATURE_AUTOWIDTH( +//usage: IF_FEATURE_LS_WIDTH( //usage: "\n -w N Assume the terminal is N columns wide" //usage: ) //usage: IF_FEATURE_LS_COLOR( @@ -263,7 +268,7 @@ static const char ls_options[] ALIGN1 = IF_SELINUX("KZ") /* 2, 26 */ IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ - IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ + IF_FEATURE_LS_WIDTH("T:w:") /* 2, 31 */ /* with --color, we use all 32 bits */; enum { //OPT_C = (1 << 0), @@ -298,7 +303,7 @@ enum { OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, OPTBIT_w, /* 30 */ - OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, + OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS, @@ -316,8 +321,8 @@ enum { OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, - OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_AUTOWIDTH, - OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_AUTOWIDTH, + OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH, + OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH, OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR, }; @@ -417,7 +422,7 @@ struct globals { #endif smallint exit_code; unsigned all_fmt; -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_LS_WIDTH unsigned terminal_width; # define G_terminal_width (G.terminal_width) #else @@ -433,7 +438,7 @@ struct globals { setup_common_bufsiz(); \ /* we have to zero it out because of NOEXEC */ \ memset(&G, 0, sizeof(G)); \ - IF_FEATURE_AUTOWIDTH(G_terminal_width = TERMINAL_WIDTH;) \ + IF_FEATURE_LS_WIDTH(G_terminal_width = TERMINAL_WIDTH;) \ IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ } while (0) @@ -1167,7 +1172,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_FEATURE_LS_SORTFILES) G.all_fmt = SORT_NAME; -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_LS_WIDTH /* obtain the terminal width */ G_terminal_width = get_terminal_width(STDIN_FILENO); /* go one less... */ @@ -1190,9 +1195,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv) ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */ IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ /* -w NUM: */ - IF_FEATURE_AUTOWIDTH(":w+"); + IF_FEATURE_LS_WIDTH(":w+"); opt = getopt32(argv, ls_options - IF_FEATURE_AUTOWIDTH(, NULL, &G_terminal_width) + IF_FEATURE_LS_WIDTH(, NULL, &G_terminal_width) IF_FEATURE_LS_COLOR(, &color_opt) ); for (i = 0; opt_flags[i] != (1U << 31); i++) { diff --git a/networking/telnet.c b/networking/telnet.c index f520fe1dd..a70f74762 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -45,6 +45,11 @@ //config: remote host you are connecting to. This is useful when you need to //config: log into a machine without telling the username (autologin). This //config: option enables `-a' and `-l USER' arguments. +//config: +//config:config FEATURE_TELNET_WIDTH +//config: bool "Enable window size autodetection" +//config: default y +//config: depends on TELNET //applet:IF_TELNET(APPLET(telnet, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -128,7 +133,7 @@ struct globals { #if ENABLE_FEATURE_TELNET_AUTOLOGIN const char *autologin; #endif -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_TELNET_WIDTH unsigned win_width, win_height; #endif /* same buffer used both for network and console read/write */ @@ -401,7 +406,7 @@ static void put_iac_subopt_autologin(void) } #endif -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_TELNET_WIDTH static void put_iac_naws(byte c, int x, int y) { if (G.iaclen + 9 > IACBUFSIZE) @@ -538,7 +543,7 @@ static void to_new_environ(void) } #endif -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_TELNET_WIDTH static void to_naws(void) { /* Tell server we will do NAWS */ @@ -561,7 +566,7 @@ static void telopt(byte c) case TELOPT_NEW_ENVIRON: to_new_environ(); break; #endif -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_TELNET_WIDTH case TELOPT_NAWS: to_naws(); put_iac_naws(c, G.win_width, G.win_height); @@ -623,7 +628,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) INIT_G(); -#if ENABLE_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_TELNET_WIDTH get_terminal_width_height(0, &G.win_width, &G.win_height); #endif -- cgit v1.2.3-55-g6feb From 4c179373e07fbc1d8fc8e53c7096fce9ee4b08b6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 18:44:15 +0100 Subject: ash: 16-bit ->nprocs field is a pain for many CPUs function old new delta getoptscmd 527 540 +13 getjob 280 286 +6 makejob 278 282 +4 forkchild 602 600 -2 waitcmd 208 205 -3 showjob 382 379 -3 getstatus 83 80 -3 dowait 408 405 -3 freejob 93 89 -4 fg_bgcmd 290 286 -4 forkshell 260 255 -5 killcmd 224 218 -6 jobno 17 11 -6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/10 up/down: 23/-39) Total: -16 bytes Signed-off-by: Denys Vlasenko --- shell/ash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 02545f565..bfdd94047 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3392,12 +3392,13 @@ struct job { #if JOBS int stopstatus; /* status of a stopped job */ #endif - uint32_t - nprocs: 16, /* number of processes */ - state: 8, + unsigned nprocs; /* number of processes */ + #define JOBRUNNING 0 /* at least one proc running */ #define JOBSTOPPED 1 /* all procs are stopped */ #define JOBDONE 2 /* all procs are completed */ + unsigned + state: 8, #if JOBS sigint: 1, /* job was killed by SIGINT */ jobctl: 1, /* job running under job control */ -- cgit v1.2.3-55-g6feb From 098b713c7b5b22fc60b606be97da431eaedc6639 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 19:59:03 +0100 Subject: ash: commented-out possible fix for 7694 bash has a feature: it restores termios after a successful wait for a foreground job which had at least one stopped or sigkilled member. The probable rationale is that SIGSTOP and SIGKILL can preclude task from properly restoring tty state. Should we do this too? A reproducer: ^Z an interactive python: $ python Python 2.7.12 (...) >>> ^Z { python leaves tty in -icanon -echo state. We do survive that... } [1]+ Stopped python { ...however, next program (python no.2) does not survive it well: } $ python Python 2.7.12 (...) >>> Traceback (most recent call last): { above, I typed "qwerty", but -echo state is still in effect } File "", line 1, in NameError: name 'qwerty' is not defined The implementation is modeled on bash code and seems to work. However, I'm not sure we should do this. For one: what if I'd fg the stopped python instead? It'll be confused by "restored" tty state. Signed-off-by: Denys Vlasenko --- shell/ash.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index bfdd94047..d8f41327b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3579,6 +3579,72 @@ static struct job *curjob; //lots /* number of presumed living untracked jobs */ static int jobless; //4 +#if 0 +/* Bash has a feature: it restores termios after a successful wait for + * a foreground job which had at least one stopped or sigkilled member. + * The probable rationale is that SIGSTOP and SIGKILL can preclude task from + * properly restoring tty state. Should we do this too? + * A reproducer: ^Z an interactive python: + * + * # python + * Python 2.7.12 (...) + * >>> ^Z + * { python leaves tty in -icanon -echo state. We do survive that... } + * [1]+ Stopped python + * { ...however, next program (python #2) does not survive it well: } + * # python + * Python 2.7.12 (...) + * >>> Traceback (most recent call last): + * { above, I typed "qwerty", but -echo state is still in effect } + * File "", line 1, in + * NameError: name 'qwerty' is not defined + * + * The implementation below is modeled on bash code and seems to work. + * However, I'm not sure we should do this. For one: what if I'd fg + * the stopped python instead? It'll be confused by "restored" tty state. + */ +static struct termios shell_tty_info; +static void +get_tty_state(void) +{ + if (rootshell && ttyfd >= 0) + tcgetattr(ttyfd, &shell_tty_info); +} +static void +set_tty_state(void) +{ + /* if (rootshell) - caller ensures this */ + if (ttyfd >= 0) + tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info); +} +static int +job_signal_status(struct job *jp) +{ + int status; + unsigned i; + struct procstat *ps = jp->ps; + for (i = 0; i < jp->nprocs; i++) { + status = ps[i].ps_status; + if (WIFSIGNALED(status) || WIFSTOPPED(status)) + return status; + } + return 0; +} +static void +restore_tty_if_stopped_or_signaled(struct job *jp) +{ +//TODO: check what happens if we come from waitforjob() in expbackq() + if (rootshell) { + int s = job_signal_status(jp); + if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */ + set_tty_state(); + } +} +#else +# define get_tty_state() ((void)0) +# define restore_tty_if_stopped_or_signaled(jp) ((void)0) +#endif + static void set_curjob(struct job *jp, unsigned mode) { @@ -3910,8 +3976,10 @@ restartjob(struct job *jp, int mode) goto out; jp->state = JOBRUNNING; pgid = jp->ps[0].ps_pid; - if (mode == FORK_FG) + if (mode == FORK_FG) { + get_tty_state(); xtcsetpgrp(ttyfd, pgid); + } killpg(pgid, SIGCONT); ps = jp->ps; i = jp->nprocs; @@ -4445,7 +4513,7 @@ makejob(/*union node *node,*/ int nprocs) memset(jp, 0, sizeof(*jp)); #if JOBS /* jp->jobctl is a bitfield. - * "jp->jobctl |= jobctl" likely to give awful code */ + * "jp->jobctl |= doing_jobctl" likely to give awful code */ if (doing_jobctl) jp->jobctl = 1; #endif @@ -5040,6 +5108,8 @@ waitforjob(struct job *jp) #if JOBS if (jp->jobctl) { xtcsetpgrp(ttyfd, rootpid); + restore_tty_if_stopped_or_signaled(jp); + /* * This is truly gross. * If we're doing job control, then we did a TIOCSPGRP which @@ -8852,13 +8922,15 @@ static int evalsubshell(union node *n, int flags) { struct job *jp; - int backgnd = (n->type == NBACKGND); + int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */ int status; expredir(n->nredir.redirect); if (!backgnd && (flags & EV_EXIT) && !may_have_traps) goto nofork; INT_OFF; + if (backgnd == FORK_FG) + get_tty_state(); jp = makejob(/*n,*/ 1); if (forkshell(jp, n, backgnd) == 0) { /* child */ @@ -8873,7 +8945,7 @@ evalsubshell(union node *n, int flags) } /* parent */ status = 0; - if (!backgnd) + if (backgnd == FORK_FG) status = waitforjob(jp); INT_ON; return status; @@ -8965,6 +9037,8 @@ evalpipe(union node *n, int flags) pipelen++; flags |= EV_EXIT; INT_OFF; + if (n->npipe.pipe_backgnd == 0) + get_tty_state(); jp = makejob(/*n,*/ pipelen); prevfd = -1; for (lp = n->npipe.cmdlist; lp; lp = lp->next) { @@ -9647,6 +9721,7 @@ evalcommand(union node *cmd, int flags) if (!(flags & EV_EXIT) || may_have_traps) { /* No, forking off a child is necessary */ INT_OFF; + get_tty_state(); jp = makejob(/*cmd,*/ 1); if (forkshell(jp, cmd, FORK_FG) != 0) { /* parent */ -- cgit v1.2.3-55-g6feb From a6f8651911716d1d1624712eb19e4f3608767c7e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Jan 2017 20:16:45 +0100 Subject: wget: fix for brain-damaged HTTP servers. Closes 9471 write(3, "GET / HTTP/1.1\r\nUser-Agent: Wget\r\nConnection: close\r\n\r\n", 74) = 74 shutdown(3, SHUT_WR) = 0 alarm(900) = 900 read(3, "", 1024) = 0 write(2, "wget: error getting response\n", 29) = 29 exit(1) The peer simply does not return anything. It closes its connection. Probably it detects wget closing its writing end: shutdown(3, SHUT_WR). The point it, closing write side of the socket is _valid_ for HTTP. wget sent the full request, it won't be sending anything more: it will only receive the response, and that's it. Signed-off-by: Denys Vlasenko --- networking/wget.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index c82086878..d5a92a950 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -137,6 +137,8 @@ #endif +#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER) + struct host_info { char *allocated; const char *path; @@ -147,7 +149,7 @@ struct host_info { }; static const char P_FTP[] ALIGN1 = "ftp"; static const char P_HTTP[] ALIGN1 = "http"; -#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER +#if SSL_SUPPORTED static const char P_HTTPS[] ALIGN1 = "https"; #endif @@ -448,7 +450,7 @@ static void parse_url(const char *src_url, struct host_info *h) if (strcmp(url, P_FTP) == 0) { h->port = bb_lookup_port(P_FTP, "tcp", 21); } else -#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER +#if SSL_SUPPORTED if (strcmp(url, P_HTTPS) == 0) { h->port = bb_lookup_port(P_HTTPS, "tcp", 443); h->protocol = P_HTTPS; @@ -1089,12 +1091,17 @@ static void download_one_url(const char *url) } fflush(sfp); - /* If we use SSL helper, keeping our end of the socket open for writing - * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF) - * even after child closes its copy of the fd. - * This helps: - */ - shutdown(fileno(sfp), SHUT_WR); + +#if SSL_SUPPORTED + if (target.protocol == P_HTTPS) { + /* If we use SSL helper, keeping our end of the socket open for writing + * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF) + * even after child closes its copy of the fd. + * This helps: + */ + shutdown(fileno(sfp), SHUT_WR); + } +#endif /* * Retrieve HTTP response line and check for "200" status code. -- cgit v1.2.3-55-g6feb From ceff6b0ea9d8084b439e7d80f42c073d3bdda58d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 14 Jan 2017 12:49:32 +0100 Subject: tls: work-in-progress TLS1.2 test applet function old new delta tls_main - 733 +733 dump - 230 +230 xread_tls_block - 180 +180 get_der_len - 76 +76 enter_der_item - 70 +70 skip_der_item - 56 +56 get24be - 24 +24 tls_error_die - 19 +19 packed_usage 31010 31027 +17 applet_names 2549 2553 +4 applet_main 1472 1476 +4 applet_suid 92 93 +1 applet_install_loc 184 185 +1 ------------------------------------------------------------------------------ (add/remove: 9/0 grow/shrink: 5/0 up/down: 1415/0) Total: 1415 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 643 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 643 insertions(+) create mode 100644 networking/tls.c diff --git a/networking/tls.c b/networking/tls.c new file mode 100644 index 000000000..983ed507d --- /dev/null +++ b/networking/tls.c @@ -0,0 +1,643 @@ +/* + * Licensed under GPLv2, see file LICENSE in this source tree. + * + * Copyright (C) 2017 Denys Vlasenko + */ +//config:config TLS +//config: bool "tls (debugging)" +//config: default n + +//applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_TLS) += tls.o +////kbuild:lib-$(CONFIG_TLS) += tls_ciphers.o +////kbuild:lib-$(CONFIG_TLS) += tls_aes.o +////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o + +//usage:#define tls_trivial_usage +//usage: "HOST[:PORT]" +//usage:#define tls_full_usage "\n\n" + +#include "libbb.h" +//#include "tls_cryptoapi.h" +//#include "tls_ciphers.h" + +#if 1 +# define dbg(...) fprintf(stderr, __VA_ARGS__) +#else +# define dbg(...) ((void)0) +#endif + +#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 +#define RECORD_TYPE_ALERT 21 +#define RECORD_TYPE_HANDSHAKE 22 +#define RECORD_TYPE_APPLICATION_DATA 23 + +#define HANDSHAKE_HELLO_REQUEST 0 +#define HANDSHAKE_CLIENT_HELLO 1 +#define HANDSHAKE_SERVER_HELLO 2 +#define HANDSHAKE_HELLO_VERIFY_REQUEST 3 +#define HANDSHAKE_NEW_SESSION_TICKET 4 +#define HANDSHAKE_CERTIFICATE 11 +#define HANDSHAKE_SERVER_KEY_EXCHANGE 12 +#define HANDSHAKE_CERTIFICATE_REQUEST 13 +#define HANDSHAKE_SERVER_HELLO_DONE 14 +#define HANDSHAKE_CERTIFICATE_VERIFY 15 +#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 +#define HANDSHAKE_FINISHED 20 + +#define SSL_NULL_WITH_NULL_NULL 0x0000 +#define SSL_RSA_WITH_NULL_MD5 0x0001 +#define SSL_RSA_WITH_NULL_SHA 0x0002 +#define SSL_RSA_WITH_RC4_128_MD5 0x0004 +#define SSL_RSA_WITH_RC4_128_SHA 0x0005 +#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ +#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF + +#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */ +#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */ +#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */ +#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */ +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */ +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */ +#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */ +#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */ +#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */ +#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */ +#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */ +#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */ +#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */ +#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */ +#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */ +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */ +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */ +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */ +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */ +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */ +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ + +#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ +#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */ +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */ +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */ +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */ +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */ +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */ +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ + +//Tested against kernel.org: +//TLS 1.1 +//#define TLS_MAJ 3 +//#define TLS_MIN 2 +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE +//TLS 1.2 +#define TLS_MAJ 3 +#define TLS_MIN 3 +//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE +// All GCMs: +//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE +#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE +//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE +// (tested b/c this one doesn't req server certs... no luck) +//test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported + +struct transport_hdr { + uint8_t type; + uint8_t proto_maj, proto_min; + uint8_t len16_hi, len16_lo; +}; + +typedef struct tls_state { + int fd; + + uint8_t *pubkey; + int pubkey_len; + + int insize; + int tail; + // RFC 5246 + // |6.2.1. Fragmentation + // | The record layer fragments information blocks into TLSPlaintext + // | records carrying data in chunks of 2^14 bytes or less. Client + // | message boundaries are not preserved in the record layer (i.e., + // | multiple client messages of the same ContentType MAY be coalesced + // | into a single TLSPlaintext record, or a single message MAY be + // | fragmented across several records) + // |... + // | length + // | The length (in bytes) of the following TLSPlaintext.fragment. + // | The length MUST NOT exceed 2^14. + // |... + // | 6.2.2. Record Compression and Decompression + // |... + // | Compression must be lossless and may not increase the content length + // | by more than 1024 bytes. If the decompression function encounters a + // | TLSCompressed.fragment that would decompress to a length in excess of + // | 2^14 bytes, it MUST report a fatal decompression failure error. + // |... + // | length + // | The length (in bytes) of the following TLSCompressed.fragment. + // | The length MUST NOT exceed 2^14 + 1024. + // + // Since our buffer also contains 5-byte headers, make it a bit bigger: + uint8_t inbuf[18*1024]; +} tls_state_t; + +static +tls_state_t *new_tls_state(void) +{ + tls_state_t *tls = xzalloc(sizeof(*tls)); + tls->fd = -1; + return tls; +} + +static unsigned get24be(const uint8_t *p) +{ + return 0x100*(0x100*p[0] + p[1]) + p[2]; +} + +static void dump(const void *vp, int len) +{ + char hexbuf[32 * 1024 + 4]; + const uint8_t *p = vp; + + while (len > 0) { + unsigned xhdr_len; + if (len < 5) { + bin2hex(hexbuf, (void*)p, len)[0] = '\0'; + dbg("< |%s|\n", hexbuf); + return; + } + xhdr_len = 0x100*p[3] + p[4]; + dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len); + p += 5; + len -= 5; + if (len >= 4 && p[-5] == RECORD_TYPE_HANDSHAKE) { + unsigned len24 = get24be(p + 1); + dbg(" type:%u len24:%u", p[0], len24); + } + if (xhdr_len > len) + xhdr_len = len; + bin2hex(hexbuf, (void*)p, xhdr_len)[0] = '\0'; + dbg(" |%s|\n", hexbuf); + p += xhdr_len; + len -= xhdr_len; + } +} + +static void tls_error_die(tls_state_t *tls) +{ + dump(tls->inbuf, tls->insize + tls->tail); + xfunc_die(); +} + +static int xread_tls_block(tls_state_t *tls) +{ + int len; + int total; + int target; + + dbg("insize:%u tail:%u\n", tls->insize, tls->tail); + memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); + errno = 0; + total = tls->tail; + target = sizeof(tls->inbuf); + for (;;) { + if (total >= sizeof(struct transport_hdr) && target == sizeof(tls->inbuf)) { + struct transport_hdr *xhdr = (void*)tls->inbuf; + target = sizeof(*xhdr) + (0x100 * xhdr->len16_hi + xhdr->len16_lo); + } + /* if total >= target, we have a full packet (and possibly more)... */ + if (target - total <= 0) + break; + len = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); + if (len <= 0) + bb_perror_msg_and_die("short read"); + total += len; + } + tls->tail = -(target - total); + tls->insize = target; + target -= sizeof(struct transport_hdr); + dbg("got block len:%u\n", target); + return target; +} + +static void send_client_hello(tls_state_t *tls) +{ + struct client_hello { + struct transport_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t proto_maj, proto_min; + uint8_t rand32[32]; + uint8_t session_id_len; + /* uint8_t session_id[]; */ + uint8_t cipherid_len16_hi, cipherid_len16_lo; + uint8_t cipherid[2 * 1]; /* actually variable */ + uint8_t comprtypes_len; + uint8_t comprtypes[1]; /* actually variable */ + }; + struct client_hello hello; + + memset(&hello, 0, sizeof(hello)); + hello.xhdr.type = RECORD_TYPE_HANDSHAKE; + hello.xhdr.proto_maj = TLS_MAJ; + hello.xhdr.proto_min = TLS_MIN; + hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; + hello.xhdr.len16_lo = (sizeof(hello) - sizeof(hello.xhdr)); + hello.type = HANDSHAKE_CLIENT_HELLO; + hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; + hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); + hello.proto_maj = TLS_MAJ; + hello.proto_min = TLS_MIN; + //fillrand(hello.rand32, sizeof(hello.rand32)); + open_read_close("/dev/urandom", hello.rand32, sizeof(hello.rand32)); + //hello.session_id_len = 0; + //hello.cipherid_len16_hi = 0; + hello.cipherid_len16_lo = 2; + hello.cipherid[0] = CIPHER_ID >> 8; + hello.cipherid[1] = CIPHER_ID & 0xff; + hello.comprtypes_len = 1; + //hello.comprtypes[0] = 0; + + xwrite(tls->fd, &hello, sizeof(hello)); +} + +static void get_server_hello_or_die(tls_state_t *tls) +{ + struct server_hello { + struct transport_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t proto_maj, proto_min; + uint8_t rand32[32]; /* first 4 bytes are unix time in BE format */ + uint8_t session_id_len; + uint8_t session_id[32]; + uint8_t cipherid_hi, cipherid_lo; + uint8_t comprtype; + /* extensions may follow, but only those which client offered in its Hello */ + }; + struct server_hello *hp; + int len; + + len = xread_tls_block(tls); + + hp = (void*)tls->inbuf; + if (len != 74 /* TODO: if we accept extensions, should be < instead of != */ + || hp->xhdr.type != RECORD_TYPE_HANDSHAKE + || hp->xhdr.proto_maj != TLS_MAJ + || hp->xhdr.proto_min != TLS_MIN + ) { + /* example: RECORD_TYPE_ALERT if server can't support our ciphers */ + tls_error_die(tls); + } + dbg("got HANDSHAKE\n"); + // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| + // SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel + if (hp->type != HANDSHAKE_SERVER_HELLO + || hp->len24_hi != 0 + || hp->len24_mid != 0 + || hp->len24_lo != 70 + || hp->proto_maj != TLS_MAJ + || hp->proto_min != TLS_MIN + || hp->session_id_len != 32 + || hp->cipherid_hi != (CIPHER_ID >> 8) + || hp->cipherid_lo != (CIPHER_ID & 0xff) + || hp->comprtype != 0 + ) { + tls_error_die(tls); + } + dbg("got SERVER_HELLO\n"); +} + +static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) +{ + unsigned len; + + if (end - der < 2) + xfunc_die(); +// if ((der[0] & 0x1f) == 0x1f) /* not single-byte item code? */ +// xfunc_die(); + + len = der[1]; /* maybe it's short len */ + if (len >= 0x80) { + /* no */ + if (len != 0x82) { + /* 0x80 is "0 bytes of len", invalid DER: must use short len if can */ + /* 0x81 is "1 byte of len", invalid DER */ + /* >0x82 is "3+ bytes of len", should not happen realistically */ + xfunc_die(); + } + if (end - der < 4) + xfunc_die(); + /* it's "ii 82 xx yy" */ + len = 0x100*der[2] + der[3]; + if (len < 0x80) + xfunc_die(); /* invalid DER: must use short len if can */ + + der += 2; /* skip [code]+[82]+[2byte_len] */ + } + der += 2; /* skip [code]+[1byte_len] */ + + if (end - der < len) + xfunc_die(); + *bodyp = der; + + return len; +} + +static uint8_t *enter_der_item(uint8_t *der, uint8_t **endp) +{ + uint8_t *new_der; + unsigned len = get_der_len(&new_der, der, *endp); + dbg("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]); + /* Move "end" position to cover only this item */ + *endp = new_der + len; + return new_der; +} + +static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) +{ + uint8_t *new_der; + unsigned len = get_der_len(&new_der, der, end); + /* Skip body */ + new_der += len; + dbg("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]); + return new_der; +} + +static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) +{ +/* Example: partial decode of kernel.org certificate in DER format. + * SEQ 0x05ac/1452 bytes (Certificate): 308205ac + * SEQ 0x0494/1172 bytes (tbsCertificate): 30820494 + * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0] 3 bytes: a003 + * INTEGER (version): 0201 02 + * INTEGER 0x11 bytes (serialNumber): 0211 00 9f85bf664b0cddafca508679501b2be4 + * //^^^^^^note: matrixSSL also allows [ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2] = 0x82 type + * SEQ 0x0d bytes (signatureAlgo): 300d + * OID 9 bytes: 0609 2a864886f70d01010b (OID_SHA256_RSA_SIG 42.134.72.134.247.13.1.1.11) + * NULL: 0500 + * SEQ 0x5f bytes (issuer): 305f + * SET 11 bytes: 310b + * SEQ 9 bytes: 3009 + * OID 3 bytes: 0603 550406 + * Printable string "FR": 1302 4652 + * SET 14 bytes: 310e + * SEQ 12 bytes: 300c + * OID 3 bytes: 0603 550408 + * Printable string "Paris": 1305 5061726973 + * SET 14 bytes: 310e + * SEQ 12 bytes: 300c + * OID 3 bytes: 0603 550407 + * Printable string "Paris": 1305 5061726973 + * SET 14 bytes: 310e + * SEQ 12 bytes: 300c + * OID 3 bytes: 0603 55040a + * Printable string "Gandi": 1305 47616e6469 + * SET 32 bytes: 3120 + * SEQ 30 bytes: 301e + * OID 3 bytes: 0603 550403 + * Printable string "Gandi Standard SSL CA 2": 1317 + * 47616e6469205374616e646172642053534c2043412032 + * SEQ 30 bytes (validity): 301e + * TIME "161011000000Z": 170d 3136313031313030303030305a + * TIME "191011235959Z": 170d 3139313031313233353935395a + * SEQ 0x5b/91 bytes (subject): 305b //I did not decode this + * 3121301f060355040b1318446f6d61696e20436f + * 6e74726f6c2056616c6964617465643121301f06 + * 0355040b1318506f73697469766553534c204d75 + * 6c74692d446f6d61696e31133011060355040313 + * 0a6b65726e656c2e6f7267 + * SEQ 0x01a2/418 bytes (subjectPublicKeyInfo): 308201a2 + * SEQ 13 bytes (algorithm): 300d + * OID 9 bytes: 0609 2a864886f70d010101 (OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1) + * NULL: 0500 + * BITSTRING 0x018f/399 bytes (publicKey): 0382018f + * ????: 00 + * //after the zero byte, it appears key itself uses DER encoding: + * SEQ 0x018a/394 bytes: 3082018a + * INTEGER 0x0181/385 bytes (modulus): 02820181 + * 00b1ab2fc727a3bef76780c9349bf3 + * ...24 more blocks of 15 bytes each... + * 90e895291c6bc8693b65 + * INTEGER 3 bytes (exponent): 0203 010001 + * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0x3] 0x01e5 bytes (X509v3 extensions): a38201e5 + * SEQ 0x01e1 bytes: 308201e1 + * ... + * Certificate is a DER-encoded data structure. Each DER element has a length, + * which makes it easy to skip over large compound elements of any complexity + * without parsing them. + * + * Certificate is a sequence of three elements: + * tbsCertificate (SEQ) + * signatureAlgorithm (AlgorithmIdentifier) + * signatureValue (BIT STRING) + * + * In turn, tbsCertificate is a sequence of: + * version + * serialNumber + * signatureAlgo (AlgorithmIdentifier) + * issuer (Name, has complex structure) + * validity (Validity, SEQ of two Times) + * subject (Name) + * subjectPublicKeyInfo (SEQ) + * ... + * + * subjectPublicKeyInfo is a sequence of: + * algorithm (AlgorithmIdentifier) + * publicKey (BIT STRING) + * + * Essentially, we want subjectPublicKeyInfo.publicKey + */ + uint8_t *end = der + len; + + /* enter "Certificate" item: [der, end) will be only Cert */ + der = enter_der_item(der, &end); + + /* enter "tbsCertificate" item: [der, end) will be only tbsCert */ + der = enter_der_item(der, &end); + + /* skip up to subjectPublicKeyInfo */ + der = skip_der_item(der, end); /* version */ + der = skip_der_item(der, end); /* serialNumber */ + der = skip_der_item(der, end); /* signatureAlgo */ + der = skip_der_item(der, end); /* issuer */ + der = skip_der_item(der, end); /* validity */ + der = skip_der_item(der, end); /* subject */ + + /* enter "subjectPublicKeyInfo" */ + der = enter_der_item(der, &end); + + /* skip "subjectPublicKeyInfo.algorithm" */ + der = skip_der_item(der, end); + /* enter "subjectPublicKeyInfo.publicKey" */ +// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ + der = enter_der_item(der, &end); + + /* return a copy */ + *key_len = end - der; + dbg("copying key bytes:%u, first:0x%02x\n", *key_len, der[0]); + return xmemdup(der, *key_len); +} + +static void get_server_cert_or_die(tls_state_t *tls) +{ + struct transport_hdr *xhdr; + uint8_t *certbuf; + int len, len1; + + len = xread_tls_block(tls); + xhdr = (void*)tls->inbuf; + if (len < sizeof(*xhdr) + 10 + || xhdr->type != RECORD_TYPE_HANDSHAKE + || xhdr->proto_maj != TLS_MAJ + || xhdr->proto_min != TLS_MIN + ) { + tls_error_die(tls); + } + dbg("got HANDSHAKE\n"); + certbuf = (void*)(xhdr + 1); + if (certbuf[0] != HANDSHAKE_CERTIFICATE) + tls_error_die(tls); + dbg("got CERTIFICATE\n"); + // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... (4392 bytes) + // Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text + len1 = get24be(certbuf + 1); + if (len1 > len - 4) tls_error_die(tls); + len = len1; + + len1 = get24be(certbuf + 4); + if (len1 > len - 3) tls_error_die(tls); + len = len1; + + len1 = get24be(certbuf + 7); + if (len1 > len - 3) tls_error_die(tls); + len = len1; + + if (len) + tls->pubkey = find_key_in_der_cert(&tls->pubkey_len, certbuf + 10, len); +} + +static void tls_handshake(tls_state_t *tls) +{ + // Client RFC 5246 Server + // (*) - optional messages, not always sent + // + // ClientHello -------> + // ServerHello + // Certificate* + // ServerKeyExchange* + // CertificateRequest* + // <------- ServerHelloDone + // Certificate* + // ClientKeyExchange + // CertificateVerify* + // [ChangeCipherSpec] + // Finished -------> + // [ChangeCipherSpec] + // <------- Finished + // Application Data <------> Application Data + int len; + + send_client_hello(tls); +#if 0 /* dump */ + for (;;) { + uint8_t buf[16*1024]; + sleep(2); + len = recv(tls->fd, buf, sizeof(buf), 0); //MSG_DONTWAIT); + if (len < 0) { + if (errno == EAGAIN) + continue; + bb_perror_msg_and_die("recv"); + } + if (len == 0) + break; + dump(buf, len); + } +#endif + + get_server_hello_or_die(tls); + + //RFC 5246 + // The server MUST send a Certificate message whenever the agreed- + // upon key exchange method uses certificates for authentication + // (this includes all key exchange methods defined in this document + // except DH_anon). This message will always immediately follow the + // ServerHello message. + // + // IOW: in practice, Certificate *always* follows. + // (for example, kernel.org does not even accept DH_anon cipher id) + get_server_cert_or_die(tls); + + len = xread_tls_block(tls); + /* Next handshake type is not predetermined */ + switch (tls->inbuf[5]) { + case HANDSHAKE_SERVER_KEY_EXCHANGE: + //0c 0001c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... 459 bytes + //SvKey len^^^ + dbg("got SERVER_KEY_EXCHANGE\n"); + len = xread_tls_block(tls); + break; + case HANDSHAKE_CERTIFICATE_REQUEST: + dbg("got CERTIFICATE_REQUEST\n"); + len = xread_tls_block(tls); + break; + case HANDSHAKE_SERVER_HELLO_DONE: + // 0e 000000 (len:0) + dbg("got SERVER_HELLO_DONE\n"); + break; + default: + tls_error_die(tls); + } +} + +int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tls_main(int argc UNUSED_PARAM, char **argv) +{ + tls_state_t *tls; + len_and_sockaddr *lsa; + int fd; + + // INIT_G(); + // getopt32(argv, "myopts") + + if (!argv[1]) + bb_show_usage(); + + lsa = xhost2sockaddr(argv[1], 443); + fd = xconnect_stream(lsa); + + tls = new_tls_state(); + tls->fd = fd; + tls_handshake(tls); + + return EXIT_SUCCESS; +} -- cgit v1.2.3-55-g6feb From b1003f7019827d4d2581cc447e293294a1d8e5ae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 14 Jan 2017 13:57:16 +0100 Subject: tls: a bit more work $ ./busybox tls kernel.org insize:0 tail:0 got block len:74 got HANDSHAKE got SERVER_HELLO insize:79 tail:4406 got block len:4392 got HANDSHAKE got CERTIFICATE entered der @0x8f7e723:0x30 len:1452 inner_byte @0x8f7e727:0x30 entered der @0x8f7e727:0x30 len:1172 inner_byte @0x8f7e72b:0xa0 skipped der 0xa0, next byte 0x02 skipped der 0x02, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 entered der @0x8f7e830:0x30 len:418 inner_byte @0x8f7e834:0x30 skipped der 0x30, next byte 0x03 entered der @0x8f7e843:0x03 len:399 inner_byte @0x8f7e847:0x00 copying key bytes:399, first:0x00 insize:4397 tail:9 got block len:4 got SERVER_HELLO_DONE Now need to teach it to send ClientKeyExchange... Signed-off-by: Denys Vlasenko --- networking/tls.c | 72 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 983ed507d..3b6347ecc 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -128,7 +128,7 @@ // (tested b/c this one doesn't req server certs... no luck) //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported -struct transport_hdr { +struct record_hdr { uint8_t type; uint8_t proto_maj, proto_min; uint8_t len16_hi, len16_lo; @@ -140,8 +140,6 @@ typedef struct tls_state { uint8_t *pubkey; int pubkey_len; - int insize; - int tail; // RFC 5246 // |6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext @@ -167,6 +165,8 @@ typedef struct tls_state { // | The length MUST NOT exceed 2^14 + 1024. // // Since our buffer also contains 5-byte headers, make it a bit bigger: + int insize; + int tail; uint8_t inbuf[18*1024]; } tls_state_t; @@ -220,6 +220,7 @@ static void tls_error_die(tls_state_t *tls) static int xread_tls_block(tls_state_t *tls) { + struct record_hdr *xhdr; int len; int total; int target; @@ -230,21 +231,28 @@ static int xread_tls_block(tls_state_t *tls) total = tls->tail; target = sizeof(tls->inbuf); for (;;) { - if (total >= sizeof(struct transport_hdr) && target == sizeof(tls->inbuf)) { - struct transport_hdr *xhdr = (void*)tls->inbuf; + if (total >= sizeof(*xhdr) && target == sizeof(tls->inbuf)) { + xhdr = (void*)tls->inbuf; target = sizeof(*xhdr) + (0x100 * xhdr->len16_hi + xhdr->len16_lo); + if (target >= sizeof(tls->inbuf)) { + /* malformed input (too long): yell and die */ + tls->tail = 0; + tls->insize = total; + tls_error_die(tls); + } + // can also check type/proto_maj/proto_min here } /* if total >= target, we have a full packet (and possibly more)... */ - if (target - total <= 0) + if (total - target >= 0) break; len = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); if (len <= 0) bb_perror_msg_and_die("short read"); total += len; } - tls->tail = -(target - total); + tls->tail = total - target; tls->insize = target; - target -= sizeof(struct transport_hdr); + target -= sizeof(*xhdr); dbg("got block len:%u\n", target); return target; } @@ -252,7 +260,7 @@ static int xread_tls_block(tls_state_t *tls) static void send_client_hello(tls_state_t *tls) { struct client_hello { - struct transport_hdr xhdr; + struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; uint8_t proto_maj, proto_min; @@ -270,18 +278,18 @@ static void send_client_hello(tls_state_t *tls) hello.xhdr.type = RECORD_TYPE_HANDSHAKE; hello.xhdr.proto_maj = TLS_MAJ; hello.xhdr.proto_min = TLS_MIN; - hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; + //zero: hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; hello.xhdr.len16_lo = (sizeof(hello) - sizeof(hello.xhdr)); hello.type = HANDSHAKE_CLIENT_HELLO; - hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; + //hello.len24_hi = 0; + //zero: hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); hello.proto_maj = TLS_MAJ; hello.proto_min = TLS_MIN; - //fillrand(hello.rand32, sizeof(hello.rand32)); open_read_close("/dev/urandom", hello.rand32, sizeof(hello.rand32)); //hello.session_id_len = 0; //hello.cipherid_len16_hi = 0; - hello.cipherid_len16_lo = 2; + hello.cipherid_len16_lo = 2 * 1; hello.cipherid[0] = CIPHER_ID >> 8; hello.cipherid[1] = CIPHER_ID & 0xff; hello.comprtypes_len = 1; @@ -293,7 +301,7 @@ static void send_client_hello(tls_state_t *tls) static void get_server_hello_or_die(tls_state_t *tls) { struct server_hello { - struct transport_hdr xhdr; + struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; uint8_t proto_maj, proto_min; @@ -319,8 +327,9 @@ static void get_server_hello_or_die(tls_state_t *tls) tls_error_die(tls); } dbg("got HANDSHAKE\n"); - // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| - // SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel + // 74 bytes: + // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| + //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel if (hp->type != HANDSHAKE_SERVER_HELLO || hp->len24_hi != 0 || hp->len24_mid != 0 @@ -359,8 +368,8 @@ static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) xfunc_die(); /* it's "ii 82 xx yy" */ len = 0x100*der[2] + der[3]; - if (len < 0x80) - xfunc_die(); /* invalid DER: must use short len if can */ +// if (len < 0x80) +// xfunc_die(); /* invalid DER: must use short len if can */ der += 2; /* skip [code]+[82]+[2byte_len] */ } @@ -395,7 +404,9 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) { -/* Example: partial decode of kernel.org certificate in DER format. +/* Certificate is a DER-encoded data structure. Each DER element has a length, + * which makes it easy to skip over large compound elements of any complexity + * without parsing them. Example: partial decode of kernel.org certificate: * SEQ 0x05ac/1452 bytes (Certificate): 308205ac * SEQ 0x0494/1172 bytes (tbsCertificate): 30820494 * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0] 3 bytes: a003 @@ -425,8 +436,7 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) * SET 32 bytes: 3120 * SEQ 30 bytes: 301e * OID 3 bytes: 0603 550403 - * Printable string "Gandi Standard SSL CA 2": 1317 - * 47616e6469205374616e646172642053534c2043412032 + * Printable string "Gandi Standard SSL CA 2": 1317 47616e6469205374616e646172642053534c2043412032 * SEQ 30 bytes (validity): 301e * TIME "161011000000Z": 170d 3136313031313030303030305a * TIME "191011235959Z": 170d 3139313031313233353935395a @@ -452,10 +462,6 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0x3] 0x01e5 bytes (X509v3 extensions): a38201e5 * SEQ 0x01e1 bytes: 308201e1 * ... - * Certificate is a DER-encoded data structure. Each DER element has a length, - * which makes it easy to skip over large compound elements of any complexity - * without parsing them. - * * Certificate is a sequence of three elements: * tbsCertificate (SEQ) * signatureAlgorithm (AlgorithmIdentifier) @@ -475,7 +481,7 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) * algorithm (AlgorithmIdentifier) * publicKey (BIT STRING) * - * Essentially, we want subjectPublicKeyInfo.publicKey + * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey */ uint8_t *end = der + len; @@ -510,7 +516,7 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) static void get_server_cert_or_die(tls_state_t *tls) { - struct transport_hdr *xhdr; + struct record_hdr *xhdr; uint8_t *certbuf; int len, len1; @@ -528,16 +534,15 @@ static void get_server_cert_or_die(tls_state_t *tls) if (certbuf[0] != HANDSHAKE_CERTIFICATE) tls_error_die(tls); dbg("got CERTIFICATE\n"); - // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... (4392 bytes) - // Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text + // 4392 bytes: + // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... + //Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text len1 = get24be(certbuf + 1); if (len1 > len - 4) tls_error_die(tls); len = len1; - len1 = get24be(certbuf + 4); if (len1 > len - 3) tls_error_die(tls); len = len1; - len1 = get24be(certbuf + 7); if (len1 > len - 3) tls_error_die(tls); len = len1; @@ -601,8 +606,9 @@ static void tls_handshake(tls_state_t *tls) /* Next handshake type is not predetermined */ switch (tls->inbuf[5]) { case HANDSHAKE_SERVER_KEY_EXCHANGE: - //0c 0001c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... 459 bytes - //SvKey len^^^ + // 459 bytes: + // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... + //SvKey len=455^ dbg("got SERVER_KEY_EXCHANGE\n"); len = xread_tls_block(tls); break; -- cgit v1.2.3-55-g6feb From 2a17d1fc9bdcbc97d48dd08a9fa4941da25187fd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 14 Jan 2017 22:38:25 +0100 Subject: tls: DER length byte 0x81 is actually valid Signed-off-by: Denys Vlasenko --- networking/tls.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 3b6347ecc..69c81b558 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -348,7 +348,7 @@ static void get_server_hello_or_die(tls_state_t *tls) static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) { - unsigned len; + unsigned len, len1; if (end - der < 2) xfunc_die(); @@ -358,24 +358,29 @@ static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) len = der[1]; /* maybe it's short len */ if (len >= 0x80) { /* no */ - if (len != 0x82) { + if (end - der < (int)(len - 0x7e)) /* need 3 or 4 bytes for 81, 82 */ + xfunc_die(); + + len1 = der[2]; + if (len == 0x81) { + /* it's "ii 81 xx" */ + } else if (len == 0x82) { + /* it's "ii 82 xx yy" */ + len1 = 0x100*len1 + der[3]; + der += 1; /* skip [yy] */ + } else { /* 0x80 is "0 bytes of len", invalid DER: must use short len if can */ - /* 0x81 is "1 byte of len", invalid DER */ /* >0x82 is "3+ bytes of len", should not happen realistically */ xfunc_die(); } - if (end - der < 4) - xfunc_die(); - /* it's "ii 82 xx yy" */ - len = 0x100*der[2] + der[3]; + der += 1; /* skip [xx] */ + len = len1; // if (len < 0x80) // xfunc_die(); /* invalid DER: must use short len if can */ - - der += 2; /* skip [code]+[82]+[2byte_len] */ } - der += 2; /* skip [code]+[1byte_len] */ + der += 2; /* skip [code]+[1byte] */ - if (end - der < len) + if (end - der < (int)len) xfunc_die(); *bodyp = der; -- cgit v1.2.3-55-g6feb From 11d0096516c0d5395729caba5dfd940a10a6e20c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 00:12:42 +0100 Subject: tls: format and send CLIENT_KEY_EXCHANGE $ ./busybox tls kernel.org insize:0 tail:0 got block len:74 got HANDSHAKE got SERVER_HELLO insize:79 tail:4265 got block len:4392 got HANDSHAKE got CERTIFICATE entered der @0x8b217a7:0x30 len:1452 inner_byte @0x8b217ab:0x30 entered der @0x8b217ab:0x30 len:1172 inner_byte @0x8b217af:0xa0 skipped der 0xa0, next byte 0x02 skipped der 0x02, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 skipped der 0x30, next byte 0x30 entered der @0x8b218b4:0x30 len:418 inner_byte @0x8b218b8:0x30 skipped der 0x30, next byte 0x03 entered der @0x8b218c7:0x03 len:399 inner_byte @0x8b218cb:0x00 key bytes:399, first:0x00 entered der @0x8b218cc:0x30 len:394 inner_byte @0x8b218d0:0x02 binary bytes:385, first:0x00 skipped der 0x02, next byte 0x02 binary bytes:3, first:0x01 server_rsa_pub_key.size:384 insize:4397 tail:9 got block len:4 got SERVER_HELLO_DONE insize:9 tail:0 ^C Next step: send CHANGE_CIPHER_SPEC... and actually implement it. Signed-off-by: Denys Vlasenko --- networking/tls.c | 225 ++- networking/tls.h | 73 + networking/tls_pstm.c | 2254 +++++++++++++++++++++++++++++++ networking/tls_pstm.h | 238 ++++ networking/tls_pstm_montgomery_reduce.c | 423 ++++++ networking/tls_pstm_mul_comba.c | 777 +++++++++++ networking/tls_pstm_sqr_comba.c | 1107 +++++++++++++++ networking/tls_rsa.c | 203 +++ networking/tls_rsa.h | 18 + 9 files changed, 5281 insertions(+), 37 deletions(-) create mode 100644 networking/tls.h create mode 100644 networking/tls_pstm.c create mode 100644 networking/tls_pstm.h create mode 100644 networking/tls_pstm_montgomery_reduce.c create mode 100644 networking/tls_pstm_mul_comba.c create mode 100644 networking/tls_pstm_sqr_comba.c create mode 100644 networking/tls_rsa.c create mode 100644 networking/tls_rsa.h diff --git a/networking/tls.c b/networking/tls.c index 69c81b558..b0a4f7e75 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1,7 +1,7 @@ /* - * Licensed under GPLv2, see file LICENSE in this source tree. - * * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TLS //config: bool "tls (debugging)" @@ -10,6 +10,11 @@ //applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_TLS) += tls.o +//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o +//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o +//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o +//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o +//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o ////kbuild:lib-$(CONFIG_TLS) += tls_ciphers.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o @@ -18,9 +23,7 @@ //usage: "HOST[:PORT]" //usage:#define tls_full_usage "\n\n" -#include "libbb.h" -//#include "tls_cryptoapi.h" -//#include "tls_ciphers.h" +#include "tls.h" #if 1 # define dbg(...) fprintf(stderr, __VA_ARGS__) @@ -28,23 +31,26 @@ # define dbg(...) ((void)0) #endif -#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 -#define RECORD_TYPE_ALERT 21 -#define RECORD_TYPE_HANDSHAKE 22 -#define RECORD_TYPE_APPLICATION_DATA 23 - -#define HANDSHAKE_HELLO_REQUEST 0 -#define HANDSHAKE_CLIENT_HELLO 1 -#define HANDSHAKE_SERVER_HELLO 2 -#define HANDSHAKE_HELLO_VERIFY_REQUEST 3 -#define HANDSHAKE_NEW_SESSION_TICKET 4 -#define HANDSHAKE_CERTIFICATE 11 -#define HANDSHAKE_SERVER_KEY_EXCHANGE 12 -#define HANDSHAKE_CERTIFICATE_REQUEST 13 -#define HANDSHAKE_SERVER_HELLO_DONE 14 -#define HANDSHAKE_CERTIFICATE_VERIFY 15 -#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 -#define HANDSHAKE_FINISHED 20 +#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 +#define RECORD_TYPE_ALERT 21 +#define RECORD_TYPE_HANDSHAKE 22 +#define RECORD_TYPE_APPLICATION_DATA 23 + +#define HANDSHAKE_HELLO_REQUEST 0 +#define HANDSHAKE_CLIENT_HELLO 1 +#define HANDSHAKE_SERVER_HELLO 2 +#define HANDSHAKE_HELLO_VERIFY_REQUEST 3 +#define HANDSHAKE_NEW_SESSION_TICKET 4 +#define HANDSHAKE_CERTIFICATE 11 +#define HANDSHAKE_SERVER_KEY_EXCHANGE 12 +#define HANDSHAKE_CERTIFICATE_REQUEST 13 +#define HANDSHAKE_SERVER_HELLO_DONE 14 +#define HANDSHAKE_CERTIFICATE_VERIFY 15 +#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 +#define HANDSHAKE_FINISHED 20 + +#define SSL_HS_RANDOM_SIZE 32 +#define SSL_HS_RSA_PREMASTER_SIZE 48 #define SSL_NULL_WITH_NULL_NULL 0x0000 #define SSL_RSA_WITH_NULL_MD5 0x0001 @@ -112,6 +118,7 @@ //TLS 1.2 #define TLS_MAJ 3 #define TLS_MIN 3 +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE // All GCMs: //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE @@ -123,9 +130,9 @@ //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE -#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE +#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE -// (tested b/c this one doesn't req server certs... no luck) +//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported struct record_hdr { @@ -137,8 +144,7 @@ struct record_hdr { typedef struct tls_state { int fd; - uint8_t *pubkey; - int pubkey_len; + psRsaKey_t server_rsa_pub_key; // RFC 5246 // |6.2.1. Fragmentation @@ -170,6 +176,12 @@ typedef struct tls_state { uint8_t inbuf[18*1024]; } tls_state_t; +void tls_get_random(void *buf, unsigned len) +{ + if (len != open_read_close("/dev/urandom", buf, len)) + xfunc_die(); +} + static tls_state_t *new_tls_state(void) { @@ -286,7 +298,7 @@ static void send_client_hello(tls_state_t *tls) hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); hello.proto_maj = TLS_MAJ; hello.proto_min = TLS_MIN; - open_read_close("/dev/urandom", hello.rand32, sizeof(hello.rand32)); + tls_get_random(hello.rand32, sizeof(hello.rand32)); //hello.session_id_len = 0; //hello.cipherid_len16_hi = 0; hello.cipherid_len16_lo = 2 * 1; @@ -407,7 +419,18 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) return new_der; } -static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) +static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) +{ + uint8_t *bin_ptr; + unsigned len = get_der_len(&bin_ptr, der, end); + + dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); + pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); + pstm_read_unsigned_bin(pstm_n, bin_ptr, len); + //return bin + len; +} + +static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) { /* Certificate is a DER-encoded data structure. Each DER element has a length, * which makes it easy to skip over large compound elements of any complexity @@ -504,19 +527,43 @@ static void *find_key_in_der_cert(int *key_len, uint8_t *der, int len) der = skip_der_item(der, end); /* validity */ der = skip_der_item(der, end); /* subject */ - /* enter "subjectPublicKeyInfo" */ + /* enter subjectPublicKeyInfo */ der = enter_der_item(der, &end); - - /* skip "subjectPublicKeyInfo.algorithm" */ + { /* check subjectPublicKeyInfo.algorithm */ + static const uint8_t expected[] = { + 0x30,0x0d, // SEQ 13 bytes + 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1 + //0x05,0x00, // NULL + }; + if (memcmp(der, expected, sizeof(expected)) != 0) + bb_error_msg_and_die("not RSA key"); + } + /* skip subjectPublicKeyInfo.algorithm */ der = skip_der_item(der, end); - /* enter "subjectPublicKeyInfo.publicKey" */ + /* enter subjectPublicKeyInfo.publicKey */ // die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */ der = enter_der_item(der, &end); - /* return a copy */ - *key_len = end - der; - dbg("copying key bytes:%u, first:0x%02x\n", *key_len, der[0]); - return xmemdup(der, *key_len); + /* parse RSA key: */ +//based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note + dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]); + if (end - der < 14) xfunc_die(); + /* example format: + * ignore bits: 00 + * SEQ 0x018a/394 bytes: 3082018a + * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX + * INTEGER 3 bytes (exponent): 0203 010001 + */ + if (*der != 0) /* "ignore bits", should be 0 */ + xfunc_die(); + der++; + der = enter_der_item(der, &end); /* enter SEQ */ + //memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); + der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ + der = skip_der_item(der, end); + der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ + tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N); + dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } static void get_server_cert_or_die(tls_state_t *tls) @@ -553,7 +600,107 @@ static void get_server_cert_or_die(tls_state_t *tls) len = len1; if (len) - tls->pubkey = find_key_in_der_cert(&tls->pubkey_len, certbuf + 10, len); + find_key_in_der_cert(tls, certbuf + 10, len); +} + +static void send_client_key_exchange(tls_state_t *tls) +{ +#if 0 //matrixssl code snippets: + int32 csRsaEncryptPub(psPool_t *pool, psPubKey_t *key, + unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, + void *data) + { + psAssert(key->type == PS_RSA); + return psRsaEncryptPub(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen, + data); + } +... + /* pkaAfter.user is buffer len */ + if ((rc = csRsaEncryptPub(pka->pool, &ssl->sec.cert->publicKey, + ssl->sec.premaster, ssl->sec.premasterSize, pka->outbuf, + pka->user, pka->data)) < 0) { + if (rc == PS_PENDING) { + /* For these ClientKeyExchange paths, we do want to come + back through nowDoCkePka for a double pass so each + case can manage its own pkaAfter and to make sure + psX509FreeCert and sslCreateKeys() are hit below. */ + return rc; + } + psTraceIntInfo("csRsaEncryptPub in CKE failed %d\n", rc); + return MATRIXSSL_ERROR; + } + /* RSA closed the pool on second pass */ + pka->pool = NULL; + clearPkaAfter(ssl); +... +#ifdef USE_RSA_CIPHER_SUITE +/* + Standard RSA suite +*/ + ssl->sec.premasterSize = SSL_HS_RSA_PREMASTER_SIZE; + ssl->sec.premaster = psMalloc(ssl->hsPool, + SSL_HS_RSA_PREMASTER_SIZE); + if (ssl->sec.premaster == NULL) { + return SSL_MEM_ERROR; + } + + ssl->sec.premaster[0] = ssl->reqMajVer; + ssl->sec.premaster[1] = ssl->reqMinVer; + if (matrixCryptoGetPrngData(ssl->sec.premaster + 2, + SSL_HS_RSA_PREMASTER_SIZE - 2, ssl->userPtr) < 0) { + return MATRIXSSL_ERROR; + } + + /* Shedule RSA encryption. Put tmp pool under control of After */ + pkaAfter->type = PKA_AFTER_RSA_ENCRYPT; + pkaAfter->outbuf = c; + pkaAfter->data = pkiData; + pkaAfter->pool = pkiPool; + pkaAfter->user = (uint32)(end - c); /* Available space */ + + c += keyLen; +#endif +#endif // 0 + + struct client_key_exchange { + struct record_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t keylen16_hi, keylen16_lo; /* exist for RSA, but not for some other key types */ +//had a bug when had no keylen: we: +//write(3, "\x16\x03\x03\x01\x84\x10\x00\x01\x80\xXX\xXX\xXX\xXX\xXX\xXX...", 393) = 393 +//openssl: +//write to 0xe9a090 [0xf9ac20] (395 bytes => 395 (0x18B)) +//0000 - 16 03 03 01 86 10 00 01 -82 01 80 xx xx xx xx xx + uint8_t key[384]; // size?? + }; + struct client_key_exchange record; + uint8_t premaster[SSL_HS_RSA_PREMASTER_SIZE]; + + memset(&record, 0, sizeof(record)); + record.xhdr.type = RECORD_TYPE_HANDSHAKE; + record.xhdr.proto_maj = TLS_MAJ; + record.xhdr.proto_min = TLS_MIN; + record.xhdr.len16_hi = (sizeof(record) - sizeof(record.xhdr)) >> 8; + record.xhdr.len16_lo = (sizeof(record) - sizeof(record.xhdr)) & 0xff; + record.type = HANDSHAKE_CLIENT_KEY_EXCHANGE; + //record.len24_hi = 0; + record.len24_mid = (sizeof(record) - sizeof(record.xhdr) - 4) >> 8; + record.len24_lo = (sizeof(record) - sizeof(record.xhdr) - 4) & 0xff; + record.keylen16_hi = (sizeof(record) - sizeof(record.xhdr) - 6) >> 8; + record.keylen16_lo = (sizeof(record) - sizeof(record.xhdr) - 6) & 0xff; + + tls_get_random(premaster, sizeof(premaster)); + premaster[0] = TLS_MAJ; + premaster[1] = TLS_MIN; + psRsaEncryptPub(/*pool:*/ NULL, + /* psRsaKey_t* */ &tls->server_rsa_pub_key, + premaster, /*inlen:*/ sizeof(premaster), + record.key, sizeof(record.key), + data_param_ignored + ); + + xwrite(tls->fd, &record, sizeof(record)); } static void tls_handshake(tls_state_t *tls) @@ -614,6 +761,8 @@ static void tls_handshake(tls_state_t *tls) // 459 bytes: // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... //SvKey len=455^ + // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: + // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... dbg("got SERVER_KEY_EXCHANGE\n"); len = xread_tls_block(tls); break; @@ -624,6 +773,8 @@ static void tls_handshake(tls_state_t *tls) case HANDSHAKE_SERVER_HELLO_DONE: // 0e 000000 (len:0) dbg("got SERVER_HELLO_DONE\n"); + send_client_key_exchange(tls); + len = xread_tls_block(tls); break; default: tls_error_die(tls); diff --git a/networking/tls.h b/networking/tls.h new file mode 100644 index 000000000..20317ecc3 --- /dev/null +++ b/networking/tls.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "libbb.h" + +/* config tweaks */ +#define HAVE_NATIVE_INT64 1 +#undef DISABLE_PSTM +#undef USE_1024_KEY_SPEED_OPTIMIZATIONS +#undef USE_2048_KEY_SPEED_OPTIMIZATIONS +//TODO: enable to use asm: +//#if defined(__GNUC__) && defined(__i386__) -> #define PSTM_32BIT and PSTM_X86 +//#if defined(__GNUC__) && defined(__x86_64__) -> #define PSTM_64BIT and PSTM_X86_64 +//ARM and MIPS also have these + + +#define PS_SUCCESS 0 +#define PS_FAILURE -1 +#define PS_ARG_FAIL -6 /* Failure due to bad function param */ +#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */ +#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */ +#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */ + +#define PS_TRUE 1 +#define PS_FALSE 0 + +#if BB_BIG_ENDIAN +# define ENDIAN_BIG 1 +# undef ENDIAN_LITTLE +//#???? ENDIAN_32BITWORD +// controls only STORE32L, which we don't use +#else +# define ENDIAN_LITTLE 1 +# undef ENDIAN_BIG +#endif + +typedef uint64_t uint64; +typedef int64_t int64; +typedef uint32_t uint32; +typedef int32_t int32; +typedef uint16_t uint16; +typedef int16_t int16; + +//FIXME +typedef char psPool_t; + +//#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM +#define PS_EXPTMOD_WINSIZE 3 +//#ifdef PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED +//#define PS_EXPTMOD_WINSIZE 5 + +#define PUBKEY_TYPE 0x01 +#define PRIVKEY_TYPE 0x02 + +void tls_get_random(void *buf, unsigned len); + +#define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) + +#define psFree(p, pool) free(p) +#define psTraceCrypto(msg) bb_error_msg_and_die(msg) + +/* Secure zerofill */ +#define memset_s(A,B,C,D) memset((A),(C),(D)) +/* Constant time memory comparison */ +#define memcmpct(s1, s2, len) memcmp((s1), (s2), (len)) +#undef min +#define min(x, y) ((x) < (y) ? (x) : (y)) + + +#include "tls_pstm.h" +#include "tls_rsa.h" diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c new file mode 100644 index 000000000..0d797f87f --- /dev/null +++ b/networking/tls_pstm.c @@ -0,0 +1,2254 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +/** + * @file pstm.c + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * Multiprecision number implementation. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +///bbox +//#include "../cryptoApi.h" +#ifndef DISABLE_PSTM + +static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c); + +/******************************************************************************/ +/* + init an pstm_int for a given size + */ +int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) +{ +// uint16 x; + +/* + alloc mem + */ + a->dp = xzalloc(sizeof (pstm_digit) * size); + a->pool = pool; + a->used = 0; + a->alloc = (int16)size; + a->sign = PSTM_ZPOS; +/* + zero the digits + */ +///bbox +// for (x = 0; x < size; x++) { +// a->dp[x] = 0; +// } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Init a new pstm_int. +*/ +int32 pstm_init(psPool_t *pool, pstm_int * a) +{ +// int32 i; +/* + allocate memory required and clear it + */ + a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT); +/* + set the digits to zero + */ +///bbox +// for (i = 0; i < PSTM_DEFAULT_INIT; i++) { +// a->dp[i] = 0; +// } +/* + set the used to zero, allocated digits to the default precision and sign + to positive + */ + a->pool = pool; + a->used = 0; + a->alloc = PSTM_DEFAULT_INIT; + a->sign = PSTM_ZPOS; + + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Grow as required + */ +int32 pstm_grow(pstm_int * a, int16 size) +{ + int16 i; + pstm_digit *tmp; + +/* + If the alloc size is smaller alloc more ram. + */ + if (a->alloc < size) { +/* + Reallocate the array a->dp + + We store the return in a temporary variable in case the operation + failed we don't want to overwrite the dp member of a. +*/ + tmp = xrealloc(a->dp, sizeof (pstm_digit) * size); +/* + reallocation succeeded so set a->dp + */ + a->dp = tmp; +/* + zero excess digits + */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + copy, b = a (b must be pre-allocated) + */ +int32 pstm_copy(pstm_int * a, pstm_int * b) +{ + int32 res, n; + +/* + If dst == src do nothing + */ + if (a == b) { + return PSTM_OKAY; + } +/* + Grow dest + */ + if (b->alloc < a->used) { + if ((res = pstm_grow (b, a->used)) != PSTM_OKAY) { + return res; + } + } +/* + Zero b and copy the parameters over + */ + { + register pstm_digit *tmpa, *tmpb; + + /* pointer aliases */ + /* source */ + tmpa = a->dp; + + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } +/* + copy used count and sign + */ + b->used = a->used; + b->sign = a->sign; + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Trim unused digits + + This is used to ensure that leading zero digits are trimed and the + leading "used" digit will be non-zero. Typically very fast. Also fixes + the sign if there are no more leading digits +*/ +void pstm_clamp(pstm_int * a) +{ +/* decrease used while the most significant digit is zero. */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } +/* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = PSTM_ZPOS; + } +} + +/******************************************************************************/ +/* + clear one (frees). + */ +void pstm_clear(pstm_int * a) +{ + int32 i; +/* + only do anything if a hasn't been freed previously + */ + if (a != NULL && a->dp != NULL) { +/* + first zero the digits + */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + + psFree (a->dp, a->pool); +/* + reset members to make debugging easier + */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = PSTM_ZPOS; + } +} + +/******************************************************************************/ +/* + clear many (frees). + */ +void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, + pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, + pstm_int *mp6, pstm_int *mp7) +{ + int32 n; /* Number of ok inits */ + + pstm_int *tempArray[9]; + + tempArray[0] = mp0; + tempArray[1] = mp1; + tempArray[2] = mp2; + tempArray[3] = mp3; + tempArray[4] = mp4; + tempArray[5] = mp5; + tempArray[6] = mp6; + tempArray[7] = mp7; + tempArray[8] = NULL; + + for (n = 0; tempArray[n] != NULL; n++) { + if ((tempArray[n] != NULL) && (tempArray[n]->dp != NULL)) { + pstm_clear(tempArray[n]); + } + } +} + +/******************************************************************************/ +/* + Set to zero. + */ +void pstm_zero(pstm_int * a) +{ + int32 n; + pstm_digit *tmp; + + a->sign = PSTM_ZPOS; + a->used = 0; + + tmp = a->dp; + for (n = 0; n < a->alloc; n++) { + *tmp++ = 0; + } +} + + +/******************************************************************************/ +/* + Compare maginitude of two ints (unsigned). + */ +int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) +{ + int16 n; + pstm_digit *tmpa, *tmpb; + +/* + compare based on # of non-zero digits + */ + if (a->used > b->used) { + return PSTM_GT; + } + + if (a->used < b->used) { + return PSTM_LT; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + +/* + compare based on digits + */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return PSTM_GT; + } + if (*tmpa < *tmpb) { + return PSTM_LT; + } + } + return PSTM_EQ; +} + +/******************************************************************************/ +/* + Compare two ints (signed) + */ +int32 pstm_cmp(pstm_int * a, pstm_int * b) +{ +/* + compare based on sign + */ + if (a->sign != b->sign) { + if (a->sign == PSTM_NEG) { + return PSTM_LT; + } else { + return PSTM_GT; + } + } +/* + compare digits + */ + if (a->sign == PSTM_NEG) { + /* if negative compare opposite direction */ + return pstm_cmp_mag(b, a); + } else { + return pstm_cmp_mag(a, b); + } +} + +/******************************************************************************/ +/* + pstm_ints can be initialized more precisely when they will populated + using pstm_read_unsigned_bin since the length of the byte stream is known +*/ +int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len) +{ + int32 size; +/* + Need to set this based on how many words max it will take to store the bin. + The magic + 2: + 1 to round up for the remainder of this integer math + 1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8 +*/ + size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT)) + / DIGIT_BIT) + 2; + return pstm_init_size(pool, a, size); +} + + +/******************************************************************************/ +/* + Reads a unsigned char array into pstm_int format. User should have + called pstm_init_for_read_unsigned_bin first. There is some grow logic + here if the default pstm_init was used but we don't really want to hit it. +*/ +int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) +{ + /* zero the int */ + pstm_zero (a); + +/* + If we know the endianness of this architecture, and we're using + 32-bit pstm_digits, we can optimize this +*/ +#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT) + /* But not for both simultaneously */ +#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG) +#error Both ENDIAN_LITTLE and ENDIAN_BIG defined. +#endif + { + unsigned char *pd; + if ((unsigned)c > (PSTM_MAX_SIZE * sizeof(pstm_digit))) { + uint32 excess = c - (PSTM_MAX_SIZE * sizeof(pstm_digit)); + c -= excess; + b += excess; + } + a->used = (int16)((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit)); + if (a->alloc < a->used) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PSTM_MEM; + } + } + pd = (unsigned char *)a->dp; + /* read the bytes in */ +#ifdef ENDIAN_BIG + { + /* Use Duff's device to unroll the loop. */ + int32 idx = (c - 1) & ~3; + switch (c % 4) { + case 0: do { pd[idx+0] = *b++; + case 3: pd[idx+1] = *b++; + case 2: pd[idx+2] = *b++; + case 1: pd[idx+3] = *b++; + idx -= 4; + } while ((c -= 4) > 0); + } + } +#else + for (c -= 1; c >= 0; c -= 1) { + pd[c] = *b++; + } +#endif + } +#else + /* Big enough based on the len? */ + a->used = (((c / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT)) + / DIGIT_BIT) + 2; + + if (a->alloc < a->used) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PSTM_MEM; + } + } + /* read the bytes in */ + for (; c > 0; c--) { + if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + a->dp[0] |= *b++; + a->used += 1; + } +#endif + + pstm_clamp (a); + return PS_SUCCESS; +} + +/******************************************************************************/ +/* +*/ +int16 pstm_count_bits (pstm_int * a) +{ + int16 r; + pstm_digit q; + + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((pstm_digit) 0)) { + ++r; + q >>= ((pstm_digit) 1); + } + return r; +} + +/******************************************************************************/ +int32 pstm_unsigned_bin_size(pstm_int *a) +{ + int32 size = pstm_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + +/******************************************************************************/ +void pstm_set(pstm_int *a, pstm_digit b) +{ + pstm_zero(a); + a->dp[0] = b; + a->used = a->dp[0] ? 1 : 0; +} + +/******************************************************************************/ +/* + Right shift +*/ +void pstm_rshd(pstm_int *a, int16 x) +{ + int16 y; + + /* too many digits just zero and return */ + if (x >= a->used) { + pstm_zero(a); + return; + } + + /* shift */ + for (y = 0; y < a->used - x; y++) { + a->dp[y] = a->dp[y+x]; + } + + /* zero rest */ + for (; y < a->used; y++) { + a->dp[y] = 0; + } + + /* decrement count */ + a->used -= x; + pstm_clamp(a); +} + +/******************************************************************************/ +/* + Shift left a certain amount of digits. + */ +int32 pstm_lshd(pstm_int * a, int16 b) +{ + int16 x; + int32 res; + +/* + If its less than zero return. + */ + if (b <= 0) { + return PSTM_OKAY; + } +/* + Grow to fit the new digits. + */ + if (a->alloc < a->used + b) { + if ((res = pstm_grow (a, a->used + b)) != PSTM_OKAY) { + return res; + } + } + + { + register pstm_digit *top, *bottom; +/* + Increment the used by the shift amount then copy upwards. + */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; +/* + This is implemented using a sliding window except the window goes the + other way around. Copying from the bottom to the top. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + computes a = 2**b +*/ +int32 pstm_2expt(pstm_int *a, int16 b) +{ + int16 z; + + /* zero a as per default */ + pstm_zero (a); + + if (b < 0) { + return PSTM_OKAY; + } + + z = b / DIGIT_BIT; + if (z >= PSTM_MAX_SIZE) { + return PS_LIMIT_FAIL; + } + + /* set the used count of where the bit will go */ + a->used = z + 1; + + if (a->used > a->alloc) { + if (pstm_grow(a, a->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + /* put the single bit in its place */ + a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + +*/ +int32 pstm_mul_2(pstm_int * a, pstm_int * b) +{ + int32 res; + int16 x, oldused; + +/* + grow to accomodate result + */ + if (b->alloc < a->used + 1) { + if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) { + return res; + } + } + oldused = b->used; + b->used = a->used; + + { + register pstm_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { +/* + get what will be the *next* carry bit from the + MSB of the current digit +*/ + rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1)); +/* + now shift up this digit, add in the carry [from the previous] +*/ + *tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r); +/* + copy the carry that would be from the source + digit into the next iteration +*/ + r = rr; + } + + /* new leading digit? */ + if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } +/* + now zero any excess digits on the destination that we didn't write to +*/ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + unsigned subtraction ||a|| >= ||b|| ALWAYS! +*/ +int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) +{ + int16 oldbused, oldused; + int32 x; + pstm_word t; + + if (b->used > a->used) { + return PS_LIMIT_FAIL; + } + if (c->alloc < a->used) { + if ((x = pstm_grow (c, a->used)) != PSTM_OKAY) { + return x; + } + } + oldused = c->used; + oldbused = b->used; + c->used = a->used; + t = 0; + + for (x = 0; x < oldbused; x++) { + t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t); + c->dp[x] = (pstm_digit)t; + t = (t >> DIGIT_BIT)&1; + } + for (; x < a->used; x++) { + t = ((pstm_word)a->dp[x]) - t; + c->dp[x] = (pstm_digit)t; + t = (t >> DIGIT_BIT); + } + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + unsigned addition +*/ +static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) +{ + int16 x, y, oldused; + register pstm_word t, adp, bdp; + + y = a->used; + if (b->used > y) { + y = b->used; + } + oldused = c->used; + c->used = y; + + if (c->used > c->alloc) { + if (pstm_grow(c, c->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + t = 0; + for (x = 0; x < y; x++) { + if (a->used < x) { + adp = 0; + } else { + adp = (pstm_word)a->dp[x]; + } + if (b->used < x) { + bdp = 0; + } else { + bdp = (pstm_word)b->dp[x]; + } + t += (adp) + (bdp); + c->dp[x] = (pstm_digit)t; + t >>= DIGIT_BIT; + } + if (t != 0 && x < PSTM_MAX_SIZE) { + if (c->used == c->alloc) { + if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + c->dp[c->used++] = (pstm_digit)t; + ++x; + } + + c->used = x; + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + + +/******************************************************************************/ +/* + +*/ +int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) +{ + int32 res; + int16 sa, sb; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { +/* + subtract a negative from a positive, OR a positive from a negative. + For both, ADD their magnitudes, and use the sign of the first number. + */ + c->sign = sa; + if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { +/* + subtract a positive from a positive, OR a negative from a negative. + First, take the difference between their magnitudes, then... + */ + if (pstm_cmp_mag (a, b) != PSTM_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { + /* The result has the _opposite_ sign from the first number. */ + c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS; + /* The second has a larger magnitude */ + if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) { + return res; + } + } + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + c = a - b +*/ +int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) +{ + pstm_int tmp; + int32 res; + + if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + pstm_set(&tmp, b); + res = pstm_sub(a, &tmp, c); + pstm_clear(&tmp); + return res; +} + +/******************************************************************************/ +/* + setups the montgomery reduction +*/ +int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho) +{ + pstm_digit x, b; + +/* + fast inversion mod 2**k + Based on the fact that + XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + => 2*X*A - X*X*A*A = 1 + => 2*(1) - (1) = 1 + */ + b = a->dp[0]; + + if ((b & 1) == 0) { + psTraceCrypto("pstm_montogomery_setup failure\n"); + return PS_ARG_FAIL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#ifdef PSTM_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + /* rho = -1/m mod b */ + *rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) - + ((pstm_word)x)); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + * computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) +{ + int32 x; + int16 bits; + + /* how many bits of last digit does b use */ + bits = pstm_count_bits (b) % DIGIT_BIT; + if (!bits) bits = DIGIT_BIT; + + /* compute A = B^(n-1) * 2^(bits-1) */ + if (b->used > 1) { + if ((x = pstm_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != + PSTM_OKAY) { + return x; + } + } else { + pstm_set(a, 1); + bits = 1; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int32)DIGIT_BIT; x++) { + if (pstm_mul_2 (a, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (pstm_cmp_mag (a, b) != PSTM_LT) { + if (s_pstm_sub (a, b, a) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + } + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + c = a * 2**d +*/ +static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c) +{ + pstm_digit carry, carrytmp, shift; + int16 x; + + /* copy it */ + if (pstm_copy(a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* handle whole digits */ + if (b >= DIGIT_BIT) { + if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + b %= DIGIT_BIT; + + /* shift the digits */ + if (b != 0) { + carry = 0; + shift = DIGIT_BIT - b; + for (x = 0; x < c->used; x++) { + carrytmp = c->dp[x] >> shift; + c->dp[x] = (c->dp[x] << b) + carry; + carry = carrytmp; + } + /* store last carry if room */ + if (carry && x < PSTM_MAX_SIZE) { + if (c->used == c->alloc) { + if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + c->dp[c->used++] = carry; + } + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + c = a mod 2**d +*/ +static int32 pstm_mod_2d(pstm_int *a, int16 b, pstm_int *c) +{ + int16 x; + + /* zero if count less than or equal to zero */ + if (b <= 0) { + pstm_zero(c); + return PSTM_OKAY; + } + + /* get copy of input */ + if (pstm_copy(a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* if 2**d is larger than we just return */ + if (b >= (DIGIT_BIT * a->used)) { + return PSTM_OKAY; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) + { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b); + pstm_clamp (c); + return PSTM_OKAY; +} + + +/******************************************************************************/ +/* + c = a * b +*/ +int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c) +{ + pstm_word w; + int32 res; + int16 x, oldused; + + if (c->alloc < a->used + 1) { + if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) { + return res; + } + } + oldused = c->used; + c->used = a->used; + c->sign = a->sign; + w = 0; + for (x = 0; x < a->used; x++) { + w = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w; + c->dp[x] = (pstm_digit)w; + w = w >> DIGIT_BIT; + } + if (w != 0 && (a->used != PSTM_MAX_SIZE)) { + c->dp[c->used++] = (pstm_digit)w; + ++x; + } + for (; x < oldused; x++) { + c->dp[x] = 0; + } + pstm_clamp(c); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + c = a / 2**b +*/ +int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c, + pstm_int *d) +{ + pstm_digit D, r, rr; + int32 res; + int16 x; + pstm_int t; + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + if (pstm_copy (a, c) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (d != NULL) { + pstm_zero (d); + } + return PSTM_OKAY; + } + + /* get the remainder */ + if (d != NULL) { + if (pstm_init(pool, &t) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + if (pstm_mod_2d (a, b, &t) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_DONE; + } + } + + /* copy */ + if (pstm_copy(a, c) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_DONE; + } + + /* shift by as many digits in the bit count */ + if (b >= (int32)DIGIT_BIT) { + pstm_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (pstm_digit) (b % DIGIT_BIT); + if (D != 0) { + register pstm_digit *tmpc, mask, shift; + + /* mask */ + mask = (((pstm_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from previous */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word above */ + r = rr; + } + } + pstm_clamp (c); + + res = PSTM_OKAY; +LBL_DONE: + if (d != NULL) { + if (pstm_copy(&t, d) != PSTM_OKAY) { + res = PS_MEM_FAIL; + } + pstm_clear(&t); + } + return res; +} + +/******************************************************************************/ +/* + b = a/2 +*/ +int32 pstm_div_2(pstm_int * a, pstm_int * b) +{ + int16 x, oldused; + + if (b->alloc < a->used) { + if (pstm_grow(b, a->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + oldused = b->used; + b->used = a->used; + { + register pstm_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + pstm_clamp (b); + return PSTM_OKAY; +} + +/******************************************************************************/ +/* + Creates "a" then copies b into it + */ +int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int16 toSqr) +{ + int16 x; + int32 res; + + if (a == b) { + return PSTM_OKAY; + } + x = b->alloc; + + if (toSqr) { +/* + Smart-size: Increasing size of a if b->used is roughly half + of b->alloc because usage has shown that a lot of these copies + go on to be squared and need these extra digits +*/ + if ((b->used * 2) + 2 >= x) { + x = (b->used * 2) + 3; + } + } + if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) { + return res; + } + return pstm_copy(b, a); +} + +/******************************************************************************/ +/* + With some compilers, we have seen issues linking with the builtin + 64 bit division routine. The issues with either manifest in a failure + to find 'udivdi3' at link time, or a runtime invalid instruction fault + during an RSA operation. + The routine below divides a 64 bit unsigned int by a 32 bit unsigned int + explicitly, rather than using the division operation + The 64 bit result is placed in the 'numerator' parameter + The 32 bit mod (remainder) of the division is the return parameter + Based on implementations by: + Copyright (C) 2003 Bernardo Innocenti + Copyright (C) 1999 Hewlett-Packard Co + Copyright (C) 1999 David Mosberger-Tang +*/ +#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT) +static uint32 psDiv64(uint64 *numerator, uint32 denominator) +{ + uint64 rem = *numerator; + uint64 b = denominator; + uint64 res = 0; + uint64 d = 1; + uint32 high = rem >> 32; + + if (high >= denominator) { + high /= denominator; + res = (uint64) high << 32; + rem -= (uint64) (high * denominator) << 32; + } + while ((int64)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *numerator = res; + return rem; +} +#endif /* USE_MATRIX_DIV64 */ + +#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT) +typedef unsigned long uint128 __attribute__ ((mode(TI))); +static uint64 psDiv128(uint128 *numerator, uint64 denominator) +{ + uint128 rem = *numerator; + uint128 b = denominator; + uint128 res = 0; + uint128 d = 1; + uint64 high = rem >> 64; + + if (high >= denominator) { + high /= denominator; + res = (uint128) high << 64; + rem -= (uint128) (high * denominator) << 64; + } + while ((uint128)b > 0 && b < rem) { + b = b+b; + d = d+d; + } + do { + if (rem >= b) { + rem -= b; + res += d; + } + b >>= 1; + d >>= 1; + } while (d); + *numerator = res; + return rem; +} +#endif /* USE_MATRIX_DIV128 */ + +/******************************************************************************/ +/* + a/b => cb + d == a +*/ +int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, + pstm_int *d) +{ + pstm_int q, x, y, t1, t2; + int32 res; + int16 n, t, i, norm, neg; + + /* is divisor zero ? */ + if (pstm_iszero (b) == 1) { + return PS_LIMIT_FAIL; + } + + /* if a < b then q=0, r = a */ + if (pstm_cmp_mag (a, b) == PSTM_LT) { + if (d != NULL) { + if (pstm_copy(a, d) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (c != NULL) { + pstm_zero (c); + } + return PSTM_OKAY; + } +/* + Smart-size inits +*/ + if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) { + return res; + } + if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) { + goto LBL_T1; + } + if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) { + goto LBL_T2; + } +/* + Used to be an init_copy on b but pstm_grow was always hit with triple size +*/ + if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) { + goto LBL_X; + } + if ((res = pstm_copy(b, &y)) != PSTM_OKAY) { + goto LBL_Y; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG; + x.sign = y.sign = PSTM_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = pstm_count_bits(&y) % DIGIT_BIT; + if (norm < (int32)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) { + goto LBL_Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + if ((res = pstm_init_size(pool, &q, n - t + 1)) != PSTM_OKAY) { + goto LBL_Y; + } + q.used = n - t + 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */ + goto LBL_Q; + } + + while (pstm_cmp (&x, &y) != PSTM_LT) { + ++(q.dp[n - t]); + if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + } + + /* reset y by shifting it back down */ + pstm_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1); + } else { + pstm_word tmp; + tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT); + tmp |= ((pstm_word) x.dp[i - 1]); +#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT) + psDiv64(&tmp, y.dp[t]); +#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT) + psDiv128(&tmp, y.dp[t]); +#else + tmp /= ((pstm_word) y.dp[t]); +#endif /* USE_MATRIX_DIV64 */ + q.dp[i - t - 1] = (pstm_digit) (tmp); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1); + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1); + + /* find left hand */ + pstm_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (pstm_cmp_mag(&t1, &t2) == PSTM_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + + if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) { + goto LBL_Q; + } + + if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == PSTM_NEG) { + if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) { + goto LBL_Q; + } + if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) { + goto LBL_Q; + } + if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) { + goto LBL_Q; + } + q.dp[i - t - 1] = q.dp[i - t - 1] - 1; + } + } +/* + now q is the quotient and x is the remainder (which we have to normalize) +*/ + /* get sign before writing to c */ + x.sign = x.used == 0 ? PSTM_ZPOS : a->sign; + + if (c != NULL) { + pstm_clamp (&q); + if (pstm_copy (&q, c) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_Q; + } + c->sign = neg; + } + + if (d != NULL) { + if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) { + goto LBL_Q; + } +/* + the following is a kludge, essentially we were seeing the right + remainder but with excess digits that should have been zero + */ + for (i = b->used; i < x.used; i++) { + x.dp[i] = 0; + } + pstm_clamp(&x); + if (pstm_copy (&x, d) != PSTM_OKAY) { + res = PS_MEM_FAIL; + goto LBL_Q; + } + } + + res = PSTM_OKAY; + +LBL_Q:pstm_clear (&q); +LBL_Y:pstm_clear (&y); +LBL_X:pstm_clear (&x); +LBL_T2:pstm_clear (&t2); +LBL_T1:pstm_clear (&t1); + + return res; +} + +/******************************************************************************/ +/* + Swap the elements of two integers, for cases where you can't simply swap + the pstm_int pointers around +*/ +void pstm_exch(pstm_int * a, pstm_int * b) +{ + pstm_int t; + + t = *a; + *a = *b; + *b = t; +} + +/******************************************************************************/ +/* + c = a mod b, 0 <= c < b +*/ +int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) +{ + pstm_int t; + int32 err; +/* + Smart-size +*/ + if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) { + return err; + } + if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) { + pstm_clear (&t); + return err; + } + if (t.sign != b->sign) { + err = pstm_add(&t, b, c); + } else { + pstm_exch (&t, c); + } + pstm_clear (&t); + return err; +} + +/******************************************************************************/ +/* + d = a * b (mod c) +*/ +int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, + pstm_int *d) +{ + int32 res; + int16 size; + pstm_int tmp; + +/* + Smart-size pstm_inits. d is an output that is influenced by this local 't' + so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow + in RSA operations +*/ + size = a->used + b->used + 1; + if ((a == d) && (size < a->alloc)) { + size = a->alloc; + } + if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) { + return res; + } + if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) { + pstm_clear(&tmp); + return res; + } + res = pstm_mod(pool, &tmp, c, d); + pstm_clear(&tmp); + return res; +} + +/******************************************************************************/ +/* + * y = g**x (mod b) + * Some restrictions... x must be positive and < b + */ +int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, + pstm_int *Y) +{ + pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */ + pstm_digit buf, mp; + pstm_digit *paD; + int32 err, bitbuf; + int16 bitcpy, bitcnt, mode, digidx, x, y, winsize; + uint32 paDlen; + + /* set window size from what user set as optimization */ + x = pstm_count_bits(X); + if (x < 50) { + winsize = 2; + } else { + winsize = PS_EXPTMOD_WINSIZE; + } + + /* now setup montgomery */ + if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) { + return err; + } + + /* setup result */ + if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) { + return err; + } +/* + create M table + The M table contains powers of the input base, e.g. M[x] = G^x mod P + The first half of the table is not computed though except for M[0] and M[1] + */ + /* now we need R mod m */ + if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) { + goto LBL_RES; + } +/* + init M array + init first cell + */ + if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) { + goto LBL_RES; + } + + /* now set M[1] to G * R mod m */ + if (pstm_cmp_mag(P, G) != PSTM_GT) { + /* G > P so we reduce it first */ + if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } + } else { + if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } + } + if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) { + goto LBL_M; + } +/* + Pre-allocated digit. Used for mul, sqr, AND reduce +*/ + paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit); + paD = xzalloc(paDlen); +/* + compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times + */ + if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) { + err = PS_MEM_FAIL; + goto LBL_PAD; + } + for (x = 0; x < (winsize - 1); x++) { + if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)], + &M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) { + goto LBL_PAD; + } + if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp, + paD, paDlen)) != PSTM_OKAY) { + goto LBL_PAD; + } + } +/* + now init the second half of the array +*/ + for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) { + if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1)) + != PSTM_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + pstm_clear(&M[y]); + } + goto LBL_PAD; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int32)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (pstm_digit)1; +/* + If the bit is zero and mode == 0 then we ignore it. + These represent the leading zero bits before the first 1 bit + in the exponent. Technically this opt is not required but it + does lower the # of trivial squaring/reductions used +*/ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and mul square first */ + for (x = 0; x < winsize; x++) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + } + + /* then multiply */ + if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen)) + != PSTM_OKAY) { + goto LBL_MARRAY; + } + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, + paDlen)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + } + } + } +/* + Fix up result if Montgomery reduction is used recall that any value in a + Montgomery system is actually multiplied by R mod n. So we have to reduce + one more time to cancel out the factor of R. +*/ + if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) != + PSTM_OKAY) { + goto LBL_MARRAY; + } + /* swap res with Y */ + if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) { + goto LBL_MARRAY; + } + err = PSTM_OKAY; +LBL_MARRAY: + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + pstm_clear(&M[x]); + } +LBL_PAD:psFree(paD, pool); +LBL_M: pstm_clear(&M[1]); +LBL_RES:pstm_clear(&res); + return err; +} + +/******************************************************************************/ +/* + +*/ +int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) +{ + int32 res; + int16 sa, sb; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative, add their mags, copy the sign */ + c->sign = sa; + if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) { + return res; + } + } else { +/* + one positive, the other negative + subtract the one with the greater magnitude from the one of the lesser + magnitude. The result gets the sign of the one with the greater mag. + */ + if (pstm_cmp_mag (a, b) == PSTM_LT) { + c->sign = sb; + if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) { + return res; + } + } else { + c->sign = sa; + if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) { + return res; + } + } + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + reverse an array, used for radix code +*/ +static void pstm_reverse (unsigned char *s, int16 len) +{ + int32 ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} +/******************************************************************************/ +/* + No reverse. Useful in some of the EIP-154 PKA stuff where special byte + order seems to come into play more often +*/ +int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b) +{ + int32 res; + int16 x; + pstm_int t = { 0 }; + + if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { + return res; + } + + x = 0; + while (pstm_iszero (&t) == 0) { + b[x++] = (unsigned char) (t.dp[0] & 255); + if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) { + pstm_clear(&t); + return res; + } + } + pstm_clear(&t); + return PS_SUCCESS; +} +/******************************************************************************/ +/* + +*/ +int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) +{ + int32 res; + int16 x; + pstm_int t = { 0 }; + + if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) { + return res; + } + + x = 0; + while (pstm_iszero (&t) == 0) { + b[x++] = (unsigned char) (t.dp[0] & 255); + if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) { + pstm_clear(&t); + return res; + } + } + pstm_reverse (b, x); + pstm_clear(&t); + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + compare against a single digit +*/ +int32 pstm_cmp_d(pstm_int *a, pstm_digit b) +{ + /* compare based on sign */ + if ((b && a->used == 0) || a->sign == PSTM_NEG) { + return PSTM_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return PSTM_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return PSTM_GT; + } else if (a->dp[0] < b) { + return PSTM_LT; + } else { + return PSTM_EQ; + } +} + +/* + Need invmod for ECC and also private key loading for hardware crypto + in cases where dQ > dP. The values must be switched and a new qP must be + calculated using this function +*/ +static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b, + pstm_int * c) +{ + pstm_int x, y, u, v, A, B, C, D; + int32 res; + + /* b cannot be negative */ + if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) { + return PS_LIMIT_FAIL; + } + + /* init temps */ + if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + + /* x = a, y = b */ + if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) { + goto LBL_X; + } + + if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) { + goto LBL_X; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) { + res = PS_FAILURE; + goto LBL_Y; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) { + goto LBL_U; + } + + if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) { + goto LBL_V; + } + + if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) { + goto LBL_A; + } + pstm_set (&A, 1); + pstm_set (&D, 1); + + if ((res = pstm_init(pool, &B)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_init(pool, &C)) != PSTM_OKAY) { + goto LBL_B; + } + +top: + /* 4. while u is even do */ + while (pstm_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) { + goto LBL_C; + } + + /* 4.2 if A or B is odd then */ + if (pstm_isodd (&A) == 1 || pstm_isodd (&B) == 1) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = pstm_add (&A, &y, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } + /* A = A/2, B = B/2 */ + if ((res = pstm_div_2 (&A, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* 5. while v is even do */ + while (pstm_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) { + goto LBL_C; + } + + /* 5.2 if C or D is odd then */ + if (pstm_isodd (&C) == 1 || pstm_isodd (&D) == 1) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = pstm_add (&C, &y, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + /* C = C/2, D = D/2 */ + if ((res = pstm_div_2 (&C, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* 6. if u >= v then */ + if (pstm_cmp (&u, &v) != PSTM_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&A, &C, &A)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) { + goto LBL_C; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&C, &A, &C)) != PSTM_OKAY) { + goto LBL_C; + } + if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* if not zero goto step 4 */ + if (pstm_iszero (&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (pstm_cmp_d (&v, 1) != PSTM_EQ) { + res = PS_FAILURE; + goto LBL_C; + } + + /* if its too low */ + while (pstm_cmp_d(&C, 0) == PSTM_LT) { + if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* too big */ + while (pstm_cmp_mag(&C, b) != PSTM_LT) { + if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) { + goto LBL_C; + } + } + + /* C is now the inverse */ + if ((res = pstm_copy(&C, c)) != PSTM_OKAY) { + goto LBL_C; + } + res = PSTM_OKAY; + +LBL_C: pstm_clear(&C); +LBL_D: pstm_clear(&D); +LBL_B: pstm_clear(&B); +LBL_A: pstm_clear(&A); +LBL_V: pstm_clear(&v); +LBL_U: pstm_clear(&u); +LBL_Y: pstm_clear(&y); +LBL_X: pstm_clear(&x); + + return res; +} + +/* c = 1/a (mod b) for odd b only */ +int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) +{ + pstm_int x, y, u, v, B, D; + int32 res; + uint16 neg, sanity; + + /* 2. [modified] b must be odd */ + if (pstm_iseven (b) == 1) { + return pstm_invmod_slow(pool, a,b,c); + } + + /* x == modulus, y == value to invert */ + if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) { + return res; + } + + if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) { + goto LBL_X; + } + + /* we need y = |a| */ + pstm_abs(a, &y); + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) { + goto LBL_Y; + } + if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) { + goto LBL_U; + } + if ((res = pstm_init(pool, &B)) != PSTM_OKAY) { + goto LBL_V; + } + if ((res = pstm_init(pool, &D)) != PSTM_OKAY) { + goto LBL_B; + } + + pstm_set (&D, 1); + + sanity = 0; +top: + /* 4. while u is even do */ + while (pstm_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) { + goto LBL_D; + } + + /* 4.2 if B is odd then */ + if (pstm_isodd (&B) == 1) { + if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } + /* B = B/2 */ + if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* 5. while v is even do */ + while (pstm_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) { + goto LBL_D; + } + /* 5.2 if D is odd then */ + if (pstm_isodd (&D) == 1) { + /* D = (D-x)/2 */ + if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + /* D = D/2 */ + if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* 6. if u >= v then */ + if (pstm_cmp (&u, &v) != PSTM_LT) { + /* u = u - v, B = B - D */ + if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) { + goto LBL_D; + } + } else { + /* v - v - u, D = D - B */ + if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) { + goto LBL_D; + } + if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + + /* if not zero goto step 4 */ + if (sanity++ > 1000) { + res = PS_LIMIT_FAIL; + goto LBL_D; + } + if (pstm_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (pstm_cmp_d (&v, 1) != PSTM_EQ) { + res = PS_FAILURE; + goto LBL_D; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == PSTM_NEG) { + if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) { + goto LBL_D; + } + } + if ((res = pstm_copy (&D, c)) != PSTM_OKAY) { + goto LBL_D; + } + c->sign = neg; + res = PSTM_OKAY; + +LBL_D: pstm_clear(&D); +LBL_B: pstm_clear(&B); +LBL_V: pstm_clear(&v); +LBL_U: pstm_clear(&u); +LBL_Y: pstm_clear(&y); +LBL_X: pstm_clear(&x); + return res; +} +#endif /* !DISABLE_PSTM */ +/******************************************************************************/ diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h new file mode 100644 index 000000000..1affc1b69 --- /dev/null +++ b/networking/tls_pstm.h @@ -0,0 +1,238 @@ +/** + * @file pstm.h + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * multiple-precision integer library. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PSTMATH +#define _h_PSTMATH +#ifndef DISABLE_PSTM + +/* Define this here to avoid including circular limits.h on some platforms */ +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +/******************************************************************************/ +/* + If native 64 bit integers are not supported, we do not support 32x32->64 + in hardware, so we must set the 16 bit flag to produce 16x16->32 products. +*/ +#ifndef HAVE_NATIVE_INT64 + #define PSTM_16BIT +#endif /* ! HAVE_NATIVE_INT64 */ + +/******************************************************************************/ +/* + Some default configurations. + + pstm_word should be the largest value the processor can hold as the product + of a multiplication. Most platforms support a 32x32->64 MAC instruction, + so 64bits is the default pstm_word size. + pstm_digit should be half the size of pstm_word + */ +#ifdef PSTM_8BIT +/* 8-bit digits, 16-bit word products */ + typedef unsigned char pstm_digit; + typedef unsigned short pstm_word; + #define DIGIT_BIT 8 + +#elif defined(PSTM_16BIT) +/* 16-bit digits, 32-bit word products */ + typedef unsigned short pstm_digit; + typedef unsigned long pstm_word; + #define DIGIT_BIT 16 + +#elif defined(PSTM_64BIT) +/* 64-bit digits, 128-bit word products */ + #ifndef __GNUC__ + #error "64bit digits requires GCC" + #endif + typedef unsigned long pstm_digit; + typedef unsigned long pstm_word __attribute__ ((mode(TI))); + #define DIGIT_BIT 64 + +#else +/* This is the default case, 32-bit digits, 64-bit word products */ + typedef uint32 pstm_digit; + typedef uint64 pstm_word; + #define DIGIT_BIT 32 + #define PSTM_32BIT +#endif /* digit and word size */ + +#define PSTM_MASK (pstm_digit)(-1) +#define PSTM_DIGIT_MAX PSTM_MASK + +/******************************************************************************/ +/* + equalities + */ +#define PSTM_LT -1 /* less than */ +#define PSTM_EQ 0 /* equal to */ +#define PSTM_GT 1 /* greater than */ + +#define PSTM_ZPOS 0 /* positive integer */ +#define PSTM_NEG 1 /* negative */ + +#define PSTM_OKAY PS_SUCCESS +#define PSTM_MEM PS_MEM_FAIL + +/******************************************************************************/ +/* + Various build options + */ +#define PSTM_DEFAULT_INIT 64 /* default (64) digits of allocation */ +#define PSTM_MAX_SIZE 4096 + +typedef struct { + int16 used, alloc, sign; + pstm_digit *dp; + psPool_t *pool; +} pstm_int; + +/******************************************************************************/ +/* + Operations on large integers + */ +#define pstm_iszero(a) (((a)->used == 0) ? PS_TRUE : PS_FALSE) +#define pstm_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? PS_TRUE : PS_FALSE) +#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE) +#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; } + +extern void pstm_set(pstm_int *a, pstm_digit b); + +extern void pstm_zero(pstm_int * a); + +extern int32 pstm_init(psPool_t *pool, pstm_int * a); + +extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size); + +extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, + int16 toSqr); + +extern int16 pstm_count_bits (pstm_int * a); + +extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, + uint32 len); + +extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c); + +extern int32 pstm_unsigned_bin_size(pstm_int *a); + +extern int32 pstm_copy(pstm_int * a, pstm_int * b); + +extern void pstm_exch(pstm_int * a, pstm_int * b); + +extern void pstm_clear(pstm_int * a); + +extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, + pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6, + pstm_int *mp7); + +extern int32 pstm_grow(pstm_int * a, int16 size); + +extern void pstm_clamp(pstm_int * a); + +extern int32 pstm_cmp(pstm_int * a, pstm_int * b); + +extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b); + +extern void pstm_rshd(pstm_int *a, int16 x); + +extern int32 pstm_lshd(pstm_int * a, int16 b); + +extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, + pstm_int *d); + +extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c, + pstm_int *d); + +extern int32 pstm_div_2(pstm_int * a, pstm_int * b); + +extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); + +extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); + +extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c); + +extern int32 pstm_mul_2(pstm_int * a, pstm_int * b); + +extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c); + +extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, + pstm_int *d); + +extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, + pstm_int *Y); + +extern int32 pstm_2expt(pstm_int *a, int16 b); + +extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c); + +extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, + unsigned char *b); + +extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, + unsigned char *b); + +extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho); + +///bbox: pool unused +#define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \ + pstm_montgomery_reduce( a, m, mp, paD, paDlen) +extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, + pstm_digit mp, pstm_digit *paD, uint32 paDlen); + +#define pstm_mul_comba(pool, A, B, C, paD, paDlen) \ + pstm_mul_comba( A, B, C, paD, paDlen) +extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, + pstm_int *C, pstm_digit *paD, uint32 paDlen); + +///bbox: pool unused +#define pstm_sqr_comba(pool, A, B, paD, paDlen) \ + pstm_sqr_comba( A, B, paD, paDlen) +extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, + pstm_digit *paD, uint32 paDlen); + +extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b); + +extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); + +extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c); + +extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b, + pstm_int * c); + +#else /* DISABLE_PSTM */ + typedef int32 pstm_int; +#endif /* !DISABLE_PSTM */ +#endif /* _h_PSTMATH */ + diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c new file mode 100644 index 000000000..c231c4ddf --- /dev/null +++ b/networking/tls_pstm_montgomery_reduce.c @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +/** + * @file pstm_montgomery_reduce.c + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * Multiprecision Montgomery Reduction. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +///bbox +//#include "../cryptoApi.h" +#ifndef DISABLE_PSTM + +/******************************************************************************/ + +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +asm( \ + "movl %5,%%eax \n\t" \ + "mull %4 \n\t" \ + "addl %1,%%eax \n\t" \ + "adcl $0,%%edx \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl $0,%%edx \n\t" \ + "movl %%edx,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ +: "%eax", "%edx", "%cc") + +#define PROPCARRY \ +asm( \ + "addl %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbl %%al,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy) \ +: "%eax", "%cc") + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#define INNERMUL \ +asm( \ + "movq %5,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %1,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rdx,%1 \n\t" \ + :"=g"(_c[LO]), "=r"(cy) \ + :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ + : "%rax", "%rdx", "cc") + +#define INNERMUL8 \ +asm( \ + "movq 0(%5),%%rax \n\t" \ + "movq 0(%2),%%r10 \n\t" \ + "movq 0x8(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x8(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x10(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x10(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x8(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x18(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x18(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x10(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x20(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x20(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x18(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x28(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x28(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x20(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x30(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x30(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x28(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x38(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x38(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x30(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x38(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + :"=r"(_c), "=r"(cy) \ + : "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\ + : "%rax", "%rdx", "%r10", "%r11", "cc") + +#define PROPCARRY \ +asm( \ + "addq %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbq %%al,%1 \n\t" \ + :"=g"(_c[LO]), "=r"(cy) \ + :"0"(_c[LO]), "1"(cy) \ + : "%rax", "cc") + +/******************************************************************************/ +#elif defined(PSTM_ARM) + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#ifdef __thumb2__ +//#pragma message ("Using 32 bit ARM Thumb2 Assembly Optimizations") +#define INNERMUL \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ + :"r0","%cc"); +#define PROPCARRY \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"m"(_c[0])\ + :"r0","%cc"); +#else /* Non-Thumb2 code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") +#define INNERMUL \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\ + :"r0","%cc"); +#define PROPCARRY \ +asm( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"0"(cy),"m"(_c[0])\ + :"r0","%cc"); +#endif /* __thumb2__ */ + + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ +mu = c[x] * mp + +#define INNERMUL \ +asm( \ + " multu %3,%4 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu $12,$12,%0 \n\t" \ + " sltu $10,$12,%0 \n\t" \ + " addu $13,$13,$10 \n\t" \ + " lw $10,%1 \n\t" \ + " addu $12,$12,$10 \n\t" \ + " sltu $10,$12,$10 \n\t" \ + " addu %0,$13,$10 \n\t" \ + " sw $12,%1 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"r"(cy),"r"(mu),"r"(tmpm[0]),"r"(_c[0])\ + :"$10","$12","$13")\ +; ++tmpm; + +#define PROPCARRY \ +asm( \ + " lw $10,%1 \n\t" \ + " addu $10,$10,%0 \n\t" \ + " sw $10,%1 \n\t" \ + " sltu %0,$10,%0 \n\t" \ + :"=r"(cy),"=m"(_c[0])\ + :"r"(cy),"r"(_c[0])\ + :"$10"); + + +/******************************************************************************/ +#else + +/* ISO C code */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ + do { pstm_word t; \ + t = ((pstm_word)_c[0] + (pstm_word)cy) + \ + (((pstm_word)mu) * ((pstm_word)*tmpm++)); \ + _c[0] = (pstm_digit)t; \ + cy = (pstm_digit)(t >> DIGIT_BIT); \ + } while (0) + +#define PROPCARRY \ + do { pstm_digit t = _c[0] += cy; cy = (t < cy); } while (0) + +#endif + +/******************************************************************************/ + +#define LO 0 + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, + pstm_digit mp, pstm_digit *paD, uint32 paDlen) +{ + pstm_digit *c, *_c, *tmpm, mu; + int32 oldused, x, y; + int16 pa; + + pa = m->used; + if (pa > a->alloc) { + /* Sanity test for bad numbers. This will confirm no buffer overruns */ + return PS_LIMIT_FAIL; + } + + if (paD && paDlen >= (uint32)2*pa+1) { + c = paD; + memset(c, 0x0, paDlen); + } else { + c = xzalloc(2*pa+1); + } + /* copy the input */ + oldused = a->used; + for (x = 0; x < oldused; x++) { + c[x] = a->dp[x]; + } + + MONT_START; + + for (x = 0; x < pa; x++) { + pstm_digit cy = 0; + /* get Mu for this round */ + LOOP_START; + _c = c + x; + tmpm = m->dp; + y = 0; +#ifdef PSTM_X86_64 + for (; y < (pa & ~7); y += 8) { + INNERMUL8; + _c += 8; + tmpm += 8; + } +#endif /* PSTM_X86_64 */ + for (; y < pa; y++) { + INNERMUL; + ++_c; + } + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + } + + /* now copy out */ + _c = c + pa; + tmpm = a->dp; + for (x = 0; x < pa+1; x++) { + *tmpm++ = *_c++; + } + + for (; x < oldused; x++) { + *tmpm++ = 0; + } + + MONT_FINI; + + a->used = pa+1; + pstm_clamp(a); + + /* reuse x as return code */ + x = PSTM_OKAY; + + /* if A >= m then A = A - m */ + if (pstm_cmp_mag (a, m) != PSTM_LT) { + if (s_pstm_sub (a, m, a) != PSTM_OKAY) { + x = PS_MEM_FAIL; + } + } + if (paDlen < (uint32)2*pa+1) { + psFree(c, pool); + } + return x; +} + +#endif /* !DISABLE_PSTM */ +/******************************************************************************/ diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c new file mode 100644 index 000000000..6e051baeb --- /dev/null +++ b/networking/tls_pstm_mul_comba.c @@ -0,0 +1,777 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +/** + * @file pstm_mul_comba.c + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * Multiprecision multiplication with Comba technique. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +///bbox +//#include "../cryptoApi.h" +#ifndef DISABLE_PSTM + +/******************************************************************************/ +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ + x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ + x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ +x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ +x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +asm ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +/******************************************************************************/ +#elif defined(PSTM_ARM) +/* ARM code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") + +#define COMBA_START + +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +asm( \ + " UMULL r0,r1,%6,%7 \n\t" \ + " ADDS %0,%0,r0 \n\t" \ + " ADCS %1,%1,r1 \n\t" \ + " ADC %2,%2,#0 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 code */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") + +#define COMBA_START + +#define COMBA_CLEAR \ +c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13"); + +/******************************************************************************/ +#else + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ + do { pstm_word t; \ + t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \ + t = (pstm_word)c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#endif + +/******************************************************************************/ +/* generic PxQ multiplier */ +///bbox: pool unused +#define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \ + pstm_mul_comba_gen( A, B, C, paD, paDlen) +static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, + pstm_int *C, pstm_digit *paD, uint32 paDlen) +{ + int16 paDfail, pa; + int32 ix, iy, iz, tx, ty; + pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst; + + COMBA_START; + COMBA_CLEAR; + + paDfail = 0; + /* get size of output and trim */ + pa = A->used + B->used; + +/* + If c is not large enough grow it and continue +*/ + if (C->alloc < pa) { + if (pstm_grow(C, pa) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (paD != NULL) { + if (paDlen < (sizeof(pstm_digit) * pa)) { + paDfail = 1; /* have a paD but it's not large enough */ + dst = xzalloc(sizeof(pstm_digit) * pa); + } else { + dst = paD; + memset(dst, 0x0, paDlen); + } + } else { + dst = xzalloc(sizeof(pstm_digit) * pa); + } + + for (ix = 0; ix < pa; ix++) { + /* get offsets into the two bignums */ + ty = min(ix, B->used-1); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = B->dp + ty; +/* + This is the number of times the loop will iterate, essentially it's + while (tx++ < a->used && ty-- >= 0) { ... } +*/ + iy = min(A->used-tx, ty+1); + + /* execute loop */ + COMBA_FORWARD; + for (iz = 0; iz < iy; ++iz) { + MULADD(*tmpx++, *tmpy--); + } + + /* store term */ + COMBA_STORE(dst[ix]); + } + COMBA_FINI; +/* + setup dest + */ + iy = C->used; + C->used = pa; + C->sign = A->sign ^ B->sign; + { + pstm_digit *tmpc; + tmpc = C->dp; + for (ix = 0; ix < pa; ix++) { + *tmpc++ = dst[ix]; + } +/* + clear unused digits [that existed in the old copy of c] + */ + for (; ix < iy; ix++) { + *tmpc++ = 0; + } + } + pstm_clamp(C); + + if ((paD == NULL) || (paDfail == 1)) { + psFree(dst, pool); + } + + return PS_SUCCESS; +} + +/******************************************************************************/ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS +static int32 pstm_mul_comba16(pstm_int *A, pstm_int *B, pstm_int *C) +{ + pstm_digit c0, c1, c2, at[32]; + + if (C->alloc < 32) { + if (pstm_grow(C, 32) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + memcpy(at, A->dp, 16 * sizeof(pstm_digit)); + memcpy(at+16, B->dp, 16 * sizeof(pstm_digit)); + + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[16]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[14], at[31]); MULADD(at[15], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[15], at[31]); + COMBA_STORE(C->dp[30]); + COMBA_STORE2(C->dp[31]); + C->used = 32; + C->sign = A->sign ^ B->sign; + pstm_clamp(C); + COMBA_FINI; + return PSTM_OKAY; +} +#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */ + + +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS +static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C) +{ + pstm_digit c0, c1, c2, at[64]; + int32 out_size; + + if (C->alloc < 64) { + if (pstm_grow(C, 64) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + + out_size = A->used + B->used; + memcpy(at, A->dp, 32 * sizeof(pstm_digit)); + memcpy(at+32, B->dp, 32 * sizeof(pstm_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[32]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]); + COMBA_STORE(C->dp[38]); + + /* early out at 40 digits, 40*32==1280, or two 640 bit operands */ + if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 39 */ + COMBA_FORWARD; + MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]); + COMBA_STORE(C->dp[46]); + + /* early out at 48 digits, 48*32==1536, or two 768 bit operands */ + if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 47 */ + COMBA_FORWARD; + MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); + COMBA_STORE(C->dp[54]); + + /* early out at 56 digits, 56*32==1792, or two 896 bit operands */ + if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; pstm_clamp(C); COMBA_FINI; return PSTM_OKAY; } + + /* 55 */ + COMBA_FORWARD; + MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[30], at[63]); MULADD(at[31], at[62]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[31], at[63]); + COMBA_STORE(C->dp[62]); + COMBA_STORE2(C->dp[63]); + C->used = 64; + C->sign = A->sign ^ B->sign; + pstm_clamp(C); + COMBA_FINI; + return PSTM_OKAY; +} +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + +/******************************************************************************/ + +int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C, + pstm_digit *paD, uint32 paDlen) +{ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS + if (A->used == 16 && B->used == 16) { + return pstm_mul_comba16(A, B, C); + } else { +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32 && B->used == 32) { + return pstm_mul_comba32(A, B, C); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen); + } +#else +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32 && B->used == 32) { + return pstm_mul_comba32(A, B, C); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen); +#endif +} + +#endif /* !DISABLE_PSTM */ +/******************************************************************************/ diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c new file mode 100644 index 000000000..98186d31f --- /dev/null +++ b/networking/tls_pstm_sqr_comba.c @@ -0,0 +1,1107 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +/** + * @file pstm_sqr_comba.c + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * Multiprecision Squaring with Comba technique. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +///bbox +//#include "../cryptoApi.h" +#ifndef DISABLE_PSTM + +/******************************************************************************/ +#if defined(PSTM_X86) +/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */ +#if !defined(__GNUC__) || !defined(__i386__) +#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor" +#endif +//#pragma message ("Using 32 bit x86 Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %%eax \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc"); + +#define SQRADD2(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc"); + +#define SQRADDSC(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "movl %%eax,%0 \n\t" \ + "movl %%edx,%1 \n\t" \ + "xorl %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); + +#define SQRADDAC(i, j) \ +asm( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc"); + +#define SQRADDDB \ +asm( \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_X86_64) +/* x86-64 optimized */ +#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT) +#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor" +#endif +//#pragma message ("Using 64 bit x86_64 Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %%rax \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc"); + +#define SQRADD2(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDSC(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "movq %%rax,%0 \n\t" \ + "movq %%rdx,%1 \n\t" \ + "xorq %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDAC(i, j) \ +asm( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDDB \ +asm( \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); + +/******************************************************************************/ +#elif defined(PSTM_ARM) +/* ARM code */ +//#pragma message ("Using 32 bit ARM Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +asm( \ +" UMULL r0,r1,%6,%6 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +asm( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +#define SQRADDSC(i, j) \ +asm( \ +" UMULL %0,%1,%6,%7 \n\t" \ +" SUB %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc"); + +#define SQRADDAC(i, j) \ +asm( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc"); + +#define SQRADDDB \ +asm( \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc"); + +/******************************************************************************/ +#elif defined(PSTM_MIPS) +/* MIPS32 */ +//#pragma message ("Using 32 bit MIPS Assembly Optimizations") + +#define COMBA_START + +#define CLEAR_CARRY \ +c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ +x = c0; + +#define COMBA_STORE2(x) \ +x = c1; + +#define CARRY_FORWARD \ +do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +asm( \ + " multu %6,%6 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15"); + +#define SQRADDSC(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo %0 \n\t" \ + " mfhi %1 \n\t" \ + " xor %2,%2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc"); + +#define SQRADDAC(i, j) \ +asm( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14"); + +#define SQRADDDB \ +asm( \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11"); + +#else +/******************************************************************************/ +#define PSTM_ISO +/* ISO C portable code */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ + do { pstm_word t; \ + t = c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \ + t = c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)i) * ((pstm_word)j); \ + tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \ + tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \ + c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \ + tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \ + tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \ + c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \ + } while (0); + +#define SQRADDSC(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)i) * ((pstm_word)j); \ + sc0 = (pstm_digit)t; sc1 = (pstm_digit)(t >> DIGIT_BIT); sc2 = 0; \ + } while (0); + +#define SQRADDAC(i, j) \ + do { pstm_word t; \ + t = ((pstm_word)sc0) + ((pstm_word)i) * ((pstm_word)j); \ + sc0 = (pstm_digit)t; \ + t = ((pstm_word)sc1) + (t >> DIGIT_BIT); sc1 = (pstm_digit)t; \ + sc2 += (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#define SQRADDDB \ + do { pstm_word t; \ + t = ((pstm_word)sc0) + ((pstm_word)sc0) + ((pstm_word)c0); \ + c0 = (pstm_digit)t; \ + t = ((pstm_word)sc1) + ((pstm_word)sc1) + c1 + (t >> DIGIT_BIT); \ + c1 = (pstm_digit)t; \ + c2 = c2 + sc2 + sc2 + (pstm_digit)(t >> DIGIT_BIT); \ + } while (0); + +#endif /* ISO_C */ + +/******************************************************************************/ +/* + Non-unrolled comba squarer + */ +///bbox: pool unused +#define pstm_sqr_comba_gen(pool, A, B, paD, paDlen) \ + pstm_sqr_comba_gen( A, B, paD, paDlen) +static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, + pstm_digit *paD, uint32 paDlen) +{ + int16 paDfail, pa; + int32 ix, iz; + pstm_digit c0, c1, c2, *dst; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + paDfail = 0; + /* get size of output and trim */ + pa = A->used + A->used; + + /* number of output digits to produce */ + COMBA_START; + CLEAR_CARRY; +/* + If b is not large enough grow it and continue +*/ + if (B->alloc < pa) { + if (pstm_grow(B, pa) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + if (paD != NULL) { + if (paDlen < (sizeof(pstm_digit) * pa)) { + paDfail = 1; /* have a paD, but it's not big enough */ + dst = xzalloc(sizeof(pstm_digit) * pa); + } else { + dst = paD; + memset(dst, 0x0, paDlen); + } + } else { + dst = xzalloc(sizeof(pstm_digit) * pa); + } + + for (ix = 0; ix < pa; ix++) { + int32 tx, ty, iy; + pstm_digit *tmpy, *tmpx; + + /* get offsets into the two bignums */ + ty = min(A->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = A->dp + ty; + +/* + This is the number of times the loop will iterate, + while (tx++ < a->used && ty-- >= 0) { ... } +*/ + iy = min(A->used-tx, ty+1); + +/* + now for squaring tx can never equal ty. We halve the distance since + they approach at a rate of 2x and we have to round because odd cases + need to be executed +*/ + iy = min(iy, (ty-tx+1)>>1); + + /* forward carries */ + CARRY_FORWARD; + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + SQRADD2(*tmpx++, *tmpy--); + } + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + SQRADD(A->dp[ix>>1], A->dp[ix>>1]); + } + + /* store it */ + COMBA_STORE(dst[ix]); + } + + COMBA_FINI; +/* + setup dest + */ + iz = B->used; + B->used = pa; + { + pstm_digit *tmpc; + tmpc = B->dp; + for (ix = 0; ix < pa; ix++) { + *tmpc++ = dst[ix]; + } + /* clear unused digits (that existed in the old copy of c) */ + for (; ix < iz; ix++) { + *tmpc++ = 0; + } + } + pstm_clamp(B); + + if ((paD == NULL) || paDfail == 1) { + psFree(dst, pool); + } + return PS_SUCCESS; +} + +/******************************************************************************/ +/* + Unrolled Comba loop for 1024 bit keys + */ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS +static int32 pstm_sqr_comba16(pstm_int *A, pstm_int *B) +{ + pstm_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + if (B->alloc < 32) { + if (pstm_grow(B, 32) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + a = A->dp; + sc0 = sc1 = sc2 = 0; + + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]); + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADD2(a[14], a[15]); + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + COMBA_STORE2(b[31]); + COMBA_FINI; + + B->used = 32; + B->sign = PSTM_ZPOS; + memcpy(B->dp, b, 32 * sizeof(pstm_digit)); + pstm_clamp(B); + return PSTM_OKAY; +} +#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */ + + +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS +static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B) +{ + pstm_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2; +#ifdef PSTM_ISO + pstm_word tt; +#endif + + if (B->alloc < 64) { + if (pstm_grow(B, 64) != PSTM_OKAY) { + return PS_MEM_FAIL; + } + } + sc0 = sc1 = sc2 = 0; + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]); + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADD2(a[30], a[31]); + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + COMBA_STORE2(b[63]); + COMBA_FINI; + + B->used = 64; + B->sign = PSTM_ZPOS; + memcpy(B->dp, b, 64 * sizeof(pstm_digit)); + pstm_clamp(B); + return PSTM_OKAY; +} +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + +/******************************************************************************/ +/* + */ +int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD, + uint32 paDlen) +{ +#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS + if (A->used == 16) { + return pstm_sqr_comba16(A, B); + } else { +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32) { + return pstm_sqr_comba32(A, B); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_sqr_comba_gen(pool, A, B, paD, paDlen); + } +#else +#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS + if (A->used == 32) { + return pstm_sqr_comba32(A, B); + } +#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */ + return pstm_sqr_comba_gen(pool, A, B, paD, paDlen); +#endif +} + +#endif /* DISABLE_PSTM */ +/******************************************************************************/ diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c new file mode 100644 index 000000000..058b09cee --- /dev/null +++ b/networking/tls_rsa.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \ + pkcs1Pad(in, inlen, out, outlen, cryptType) +static ///bbox +int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, + uint32 outlen, int32 cryptType, void *userPtr) +{ + unsigned char *c; + int32 randomLen; + + randomLen = outlen - 3 - inlen; + if (randomLen < 8) { + psTraceCrypto("pkcs1Pad failure\n"); + return PS_LIMIT_FAIL; + } + c = out; + *c = 0x00; + c++; + *c = (unsigned char)cryptType; + c++; + if (cryptType == PUBKEY_TYPE) { + while (randomLen-- > 0) { + *c++ = 0xFF; + } + } else { + if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) { + return PS_PLATFORM_FAIL; + } +/* + SECURITY: Read through the random data and change all 0x0 to 0x01. + This is per spec that no random bytes should be 0 +*/ + while (randomLen-- > 0) { + if (*c == 0x0) { + *c = 0x01; + } + c++; + } + } + *c = 0x00; + c++; + memcpy(c, in, inlen); + + return outlen; +} + +#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \ + psRsaCrypt(pool, in, inlen, out, outlen, key, type) +static ///bbox +int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen, + unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type, + void *data) +{ + pstm_int tmp, tmpa, tmpb; + int32 res; + uint32 x; + + if (in == NULL || out == NULL || outlen == NULL || key == NULL) { + psTraceCrypto("NULL parameter error in psRsaCrypt\n"); + return PS_ARG_FAIL; + } + + tmp.dp = tmpa.dp = tmpb.dp = NULL; + + /* Init and copy into tmp */ + if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit)) + != PS_SUCCESS) { + return PS_FAILURE; + } + if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){ + pstm_clear(&tmp); + return PS_FAILURE; + } + /* Sanity check on the input */ + if (pstm_cmp(&key->N, &tmp) == PSTM_LT) { + res = PS_LIMIT_FAIL; + goto done; + } + if (type == PRIVKEY_TYPE) { + if (key->optimized) { + if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) { + res = PS_FAILURE; + goto done; + } + if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) { + pstm_clear(&tmpa); + res = PS_FAILURE; + goto done; + } + if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) != + PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_exptmod dP, p\n"); + goto error; + } + if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) != + PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n"); + goto error; + } + if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: sub tmpb, tmp\n"); + goto error; + } + if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_mulmod qP, p\n"); + goto error; + } + if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0) + != PS_SUCCESS){ + psTraceCrypto("decrypt error: pstm_mul q \n"); + goto error; + } + if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) { + psTraceCrypto("decrypt error: pstm_add tmp \n"); + goto error; + } + } else { + if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) != + PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_exptmod\n"); + goto error; + } + } + } else if (type == PUBKEY_TYPE) { + if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_exptmod\n"); + goto error; + } + } else { + psTraceCrypto("psRsaCrypt error: invalid type param\n"); + goto error; + } + /* Read it back */ + x = pstm_unsigned_bin_size(&key->N); + + if ((uint32)x > *outlen) { + res = -1; + psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n"); + goto done; + } + /* We want the encrypted value to always be the key size. Pad with 0x0 */ + while ((uint32)x < (unsigned long)key->size) { + *out++ = 0x0; + x++; + } + + *outlen = x; + /* Convert it */ + memset(out, 0x0, x); + + if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp))) + != PS_SUCCESS) { + psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n"); + goto error; + } + /* Clean up and return */ + res = PS_SUCCESS; + goto done; +error: + res = PS_FAILURE; +done: + if (type == PRIVKEY_TYPE && key->optimized) { + pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL); + } + pstm_clear(&tmp); + return res; +} + +int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint32 inlen, + unsigned char *out, uint32 outlen, void *data) +{ + int32 err; + uint32 size; + + size = key->size; + if (outlen < size) { + psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); + return PS_ARG_FAIL; + } + + if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data)) + < PS_SUCCESS) { + psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n"); + return err; + } + if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key, + PUBKEY_TYPE, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaEncryptPub\n"); + return err; + } + if (outlen != size) { + psTraceCrypto("Encrypted size error in psRsaEncryptPub\n"); + return PS_FAILURE; + } + return size; +} diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h new file mode 100644 index 000000000..3281087c7 --- /dev/null +++ b/networking/tls_rsa.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + +typedef struct { + pstm_int e, d, N, qP, dP, dQ, p, q; + uint32 size; /* Size of the key in bytes */ + int32 optimized; /* 1 for optimized */ + psPool_t *pool; +} psRsaKey_t; + +#define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \ + psRsaEncryptPub(pool, key, in, inlen, out, outlen) +int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, + unsigned char *in, uint32 inlen, + unsigned char *out, uint32 outlen, void *data); -- cgit v1.2.3-55-g6feb From f78ad0938b76112aed0317d2e7d1ecbf469c3731 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 00:18:22 +0100 Subject: whitespace fix Signed-off-by: Denys Vlasenko --- networking/tls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index b0a4f7e75..79afe58b0 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -421,8 +421,8 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) { - uint8_t *bin_ptr; - unsigned len = get_der_len(&bin_ptr, der, end); + uint8_t *bin_ptr; + unsigned len = get_der_len(&bin_ptr, der, end); dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); -- cgit v1.2.3-55-g6feb From c5540d61f6b411967fc3e30f1eb1e8af5077c2e5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 02:17:03 +0100 Subject: tls: send CHANGE_CIPHER_SPEC To "actually implement it" will take more work... Signed-off-by: Denys Vlasenko --- networking/tls.c | 82 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 79afe58b0..71e5ac3a5 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -269,6 +269,23 @@ static int xread_tls_block(tls_state_t *tls) return target; } +static int xread_tls_handshake_block(tls_state_t *tls, int min_len) +{ + struct record_hdr *xhdr; + int len = xread_tls_block(tls); + + xhdr = (void*)tls->inbuf; + if (len < min_len + || xhdr->type != RECORD_TYPE_HANDSHAKE + || xhdr->proto_maj != TLS_MAJ + || xhdr->proto_min != TLS_MIN + ) { + tls_error_die(tls); + } + dbg("got HANDSHAKE\n"); + return len; +} + static void send_client_hello(tls_state_t *tls) { struct client_hello { @@ -296,8 +313,8 @@ static void send_client_hello(tls_state_t *tls) //hello.len24_hi = 0; //zero: hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); - hello.proto_maj = TLS_MAJ; - hello.proto_min = TLS_MIN; + hello.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ + hello.proto_min = TLS_MIN; /* can be higher than one in record headers */ tls_get_random(hello.rand32, sizeof(hello.rand32)); //hello.session_id_len = 0; //hello.cipherid_len16_hi = 0; @@ -325,20 +342,10 @@ static void get_server_hello_or_die(tls_state_t *tls) /* extensions may follow, but only those which client offered in its Hello */ }; struct server_hello *hp; - int len; - len = xread_tls_block(tls); + xread_tls_handshake_block(tls, 74); hp = (void*)tls->inbuf; - if (len != 74 /* TODO: if we accept extensions, should be < instead of != */ - || hp->xhdr.type != RECORD_TYPE_HANDSHAKE - || hp->xhdr.proto_maj != TLS_MAJ - || hp->xhdr.proto_min != TLS_MIN - ) { - /* example: RECORD_TYPE_ALERT if server can't support our ciphers */ - tls_error_die(tls); - } - dbg("got HANDSHAKE\n"); // 74 bytes: // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel @@ -572,16 +579,9 @@ static void get_server_cert_or_die(tls_state_t *tls) uint8_t *certbuf; int len, len1; - len = xread_tls_block(tls); + len = xread_tls_handshake_block(tls, 10); + xhdr = (void*)tls->inbuf; - if (len < sizeof(*xhdr) + 10 - || xhdr->type != RECORD_TYPE_HANDSHAKE - || xhdr->proto_maj != TLS_MAJ - || xhdr->proto_min != TLS_MIN - ) { - tls_error_die(tls); - } - dbg("got HANDSHAKE\n"); certbuf = (void*)(xhdr + 1); if (certbuf[0] != HANDSHAKE_CERTIFICATE) tls_error_die(tls); @@ -703,6 +703,15 @@ static void send_client_key_exchange(tls_state_t *tls) xwrite(tls->fd, &record, sizeof(record)); } +static void send_change_cipher_spec(tls_state_t *tls) +{ + static const uint8_t rec[] = { + RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, + 01 + }; + xwrite(tls->fd, rec, sizeof(rec)); +} + static void tls_handshake(tls_state_t *tls) { // Client RFC 5246 Server @@ -754,29 +763,28 @@ static void tls_handshake(tls_state_t *tls) // (for example, kernel.org does not even accept DH_anon cipher id) get_server_cert_or_die(tls); - len = xread_tls_block(tls); - /* Next handshake type is not predetermined */ - switch (tls->inbuf[5]) { - case HANDSHAKE_SERVER_KEY_EXCHANGE: + len = xread_tls_handshake_block(tls, 4); + if (tls->inbuf[5] == HANDSHAKE_SERVER_KEY_EXCHANGE) { // 459 bytes: // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... //SvKey len=455^ // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... - dbg("got SERVER_KEY_EXCHANGE\n"); - len = xread_tls_block(tls); - break; - case HANDSHAKE_CERTIFICATE_REQUEST: - dbg("got CERTIFICATE_REQUEST\n"); - len = xread_tls_block(tls); - break; - case HANDSHAKE_SERVER_HELLO_DONE: + dbg("got SERVER_KEY_EXCHANGE len:%u\n", len); +//need to save it + xread_tls_handshake_block(tls, 4); + } +// if (tls->inbuf[5] == HANDSHAKE_CERTIFICATE_REQUEST) { +// dbg("got CERTIFICATE_REQUEST\n"); +// xread_tls_handshake_block(tls, 4); +// } + if (tls->inbuf[5] == HANDSHAKE_SERVER_HELLO_DONE) { // 0e 000000 (len:0) dbg("got SERVER_HELLO_DONE\n"); send_client_key_exchange(tls); - len = xread_tls_block(tls); - break; - default: + send_change_cipher_spec(tls); +//we now should be able to send encrypted... as soon as we grok AES. + } else { tls_error_die(tls); } } -- cgit v1.2.3-55-g6feb From 3f8ecd933a610c6f3b5d02e184c7faf205ad95d3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 14:16:51 +0100 Subject: tls: rearrange code, add/improve comments, fix whitespace, no real changes here Signed-off-by: Denys Vlasenko --- networking/tls.c | 362 ++++++++++++++++++-------------- networking/tls_pstm.c | 14 +- networking/tls_pstm.h | 9 + networking/tls_pstm_montgomery_reduce.c | 6 +- networking/tls_pstm_mul_comba.c | 8 +- networking/tls_pstm_sqr_comba.c | 8 +- networking/tls_rsa.c | 122 ++++++----- networking/tls_rsa.h | 2 + 8 files changed, 304 insertions(+), 227 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 71e5ac3a5..44c9da195 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -286,85 +286,6 @@ static int xread_tls_handshake_block(tls_state_t *tls, int min_len) return len; } -static void send_client_hello(tls_state_t *tls) -{ - struct client_hello { - struct record_hdr xhdr; - uint8_t type; - uint8_t len24_hi, len24_mid, len24_lo; - uint8_t proto_maj, proto_min; - uint8_t rand32[32]; - uint8_t session_id_len; - /* uint8_t session_id[]; */ - uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * 1]; /* actually variable */ - uint8_t comprtypes_len; - uint8_t comprtypes[1]; /* actually variable */ - }; - struct client_hello hello; - - memset(&hello, 0, sizeof(hello)); - hello.xhdr.type = RECORD_TYPE_HANDSHAKE; - hello.xhdr.proto_maj = TLS_MAJ; - hello.xhdr.proto_min = TLS_MIN; - //zero: hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; - hello.xhdr.len16_lo = (sizeof(hello) - sizeof(hello.xhdr)); - hello.type = HANDSHAKE_CLIENT_HELLO; - //hello.len24_hi = 0; - //zero: hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; - hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); - hello.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ - hello.proto_min = TLS_MIN; /* can be higher than one in record headers */ - tls_get_random(hello.rand32, sizeof(hello.rand32)); - //hello.session_id_len = 0; - //hello.cipherid_len16_hi = 0; - hello.cipherid_len16_lo = 2 * 1; - hello.cipherid[0] = CIPHER_ID >> 8; - hello.cipherid[1] = CIPHER_ID & 0xff; - hello.comprtypes_len = 1; - //hello.comprtypes[0] = 0; - - xwrite(tls->fd, &hello, sizeof(hello)); -} - -static void get_server_hello_or_die(tls_state_t *tls) -{ - struct server_hello { - struct record_hdr xhdr; - uint8_t type; - uint8_t len24_hi, len24_mid, len24_lo; - uint8_t proto_maj, proto_min; - uint8_t rand32[32]; /* first 4 bytes are unix time in BE format */ - uint8_t session_id_len; - uint8_t session_id[32]; - uint8_t cipherid_hi, cipherid_lo; - uint8_t comprtype; - /* extensions may follow, but only those which client offered in its Hello */ - }; - struct server_hello *hp; - - xread_tls_handshake_block(tls, 74); - - hp = (void*)tls->inbuf; - // 74 bytes: - // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| - //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel - if (hp->type != HANDSHAKE_SERVER_HELLO - || hp->len24_hi != 0 - || hp->len24_mid != 0 - || hp->len24_lo != 70 - || hp->proto_maj != TLS_MAJ - || hp->proto_min != TLS_MIN - || hp->session_id_len != 32 - || hp->cipherid_hi != (CIPHER_ID >> 8) - || hp->cipherid_lo != (CIPHER_ID & 0xff) - || hp->comprtype != 0 - ) { - tls_error_die(tls); - } - dbg("got SERVER_HELLO\n"); -} - static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) { unsigned len, len1; @@ -573,7 +494,104 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } -static void get_server_cert_or_die(tls_state_t *tls) +/* + * TLS Handshake routines + */ +static void send_client_hello(tls_state_t *tls) +{ + struct client_hello { + struct record_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t proto_maj, proto_min; + uint8_t rand32[32]; + uint8_t session_id_len; + /* uint8_t session_id[]; */ + uint8_t cipherid_len16_hi, cipherid_len16_lo; + uint8_t cipherid[2 * 1]; /* actually variable */ + uint8_t comprtypes_len; + uint8_t comprtypes[1]; /* actually variable */ + }; + struct client_hello hello; + + memset(&hello, 0, sizeof(hello)); + hello.xhdr.type = RECORD_TYPE_HANDSHAKE; + hello.xhdr.proto_maj = TLS_MAJ; + hello.xhdr.proto_min = TLS_MIN; + //zero: hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; + hello.xhdr.len16_lo = (sizeof(hello) - sizeof(hello.xhdr)); + hello.type = HANDSHAKE_CLIENT_HELLO; + //hello.len24_hi = 0; + //zero: hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; + hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); + hello.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ + hello.proto_min = TLS_MIN; /* can be higher than one in record headers */ + tls_get_random(hello.rand32, sizeof(hello.rand32)); + //hello.session_id_len = 0; + //hello.cipherid_len16_hi = 0; + hello.cipherid_len16_lo = 2 * 1; + hello.cipherid[0] = CIPHER_ID >> 8; + hello.cipherid[1] = CIPHER_ID & 0xff; + hello.comprtypes_len = 1; + //hello.comprtypes[0] = 0; + + xwrite(tls->fd, &hello, sizeof(hello)); +#if 0 /* dump */ + for (;;) { + uint8_t buf[16*1024]; + sleep(2); + len = recv(tls->fd, buf, sizeof(buf), 0); //MSG_DONTWAIT); + if (len < 0) { + if (errno == EAGAIN) + continue; + bb_perror_msg_and_die("recv"); + } + if (len == 0) + break; + dump(buf, len); + } +#endif +} + +static void get_server_hello(tls_state_t *tls) +{ + struct server_hello { + struct record_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t proto_maj, proto_min; + uint8_t rand32[32]; /* first 4 bytes are unix time in BE format */ + uint8_t session_id_len; + uint8_t session_id[32]; + uint8_t cipherid_hi, cipherid_lo; + uint8_t comprtype; + /* extensions may follow, but only those which client offered in its Hello */ + }; + struct server_hello *hp; + + xread_tls_handshake_block(tls, 74); + + hp = (void*)tls->inbuf; + // 74 bytes: + // 02 000046 03|03 58|78|cf|c1 50|a5|49|ee|7e|29|48|71|fe|97|fa|e8|2d|19|87|72|90|84|9d|37|a3|f0|cb|6f|5f|e3|3c|2f |20 |d8|1a|78|96|52|d6|91|01|24|b3|d6|5b|b7|d0|6c|b3|e1|78|4e|3c|95|de|74|a0|ba|eb|a7|3a|ff|bd|a2|bf |00|9c |00| + //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel + if (hp->type != HANDSHAKE_SERVER_HELLO + || hp->len24_hi != 0 + || hp->len24_mid != 0 + || hp->len24_lo != 70 + || hp->proto_maj != TLS_MAJ + || hp->proto_min != TLS_MIN + || hp->session_id_len != 32 + || hp->cipherid_hi != (CIPHER_ID >> 8) + || hp->cipherid_lo != (CIPHER_ID & 0xff) + || hp->comprtype != 0 + ) { + tls_error_die(tls); + } + dbg("got SERVER_HELLO\n"); +} + +static void get_server_cert(tls_state_t *tls) { struct record_hdr *xhdr; uint8_t *certbuf; @@ -605,63 +623,6 @@ static void get_server_cert_or_die(tls_state_t *tls) static void send_client_key_exchange(tls_state_t *tls) { -#if 0 //matrixssl code snippets: - int32 csRsaEncryptPub(psPool_t *pool, psPubKey_t *key, - unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, - void *data) - { - psAssert(key->type == PS_RSA); - return psRsaEncryptPub(pool, (psRsaKey_t*)key->key, in, inlen, out, outlen, - data); - } -... - /* pkaAfter.user is buffer len */ - if ((rc = csRsaEncryptPub(pka->pool, &ssl->sec.cert->publicKey, - ssl->sec.premaster, ssl->sec.premasterSize, pka->outbuf, - pka->user, pka->data)) < 0) { - if (rc == PS_PENDING) { - /* For these ClientKeyExchange paths, we do want to come - back through nowDoCkePka for a double pass so each - case can manage its own pkaAfter and to make sure - psX509FreeCert and sslCreateKeys() are hit below. */ - return rc; - } - psTraceIntInfo("csRsaEncryptPub in CKE failed %d\n", rc); - return MATRIXSSL_ERROR; - } - /* RSA closed the pool on second pass */ - pka->pool = NULL; - clearPkaAfter(ssl); -... -#ifdef USE_RSA_CIPHER_SUITE -/* - Standard RSA suite -*/ - ssl->sec.premasterSize = SSL_HS_RSA_PREMASTER_SIZE; - ssl->sec.premaster = psMalloc(ssl->hsPool, - SSL_HS_RSA_PREMASTER_SIZE); - if (ssl->sec.premaster == NULL) { - return SSL_MEM_ERROR; - } - - ssl->sec.premaster[0] = ssl->reqMajVer; - ssl->sec.premaster[1] = ssl->reqMinVer; - if (matrixCryptoGetPrngData(ssl->sec.premaster + 2, - SSL_HS_RSA_PREMASTER_SIZE - 2, ssl->userPtr) < 0) { - return MATRIXSSL_ERROR; - } - - /* Shedule RSA encryption. Put tmp pool under control of After */ - pkaAfter->type = PKA_AFTER_RSA_ENCRYPT; - pkaAfter->outbuf = c; - pkaAfter->data = pkiData; - pkaAfter->pool = pkiPool; - pkaAfter->user = (uint32)(end - c); /* Available space */ - - c += keyLen; -#endif -#endif // 0 - struct client_key_exchange { struct record_hdr xhdr; uint8_t type; @@ -675,7 +636,7 @@ static void send_client_key_exchange(tls_state_t *tls) uint8_t key[384]; // size?? }; struct client_key_exchange record; - uint8_t premaster[SSL_HS_RSA_PREMASTER_SIZE]; + uint8_t rsa_premaster[SSL_HS_RSA_PREMASTER_SIZE]; memset(&record, 0, sizeof(record)); record.xhdr.type = RECORD_TYPE_HANDSHAKE; @@ -690,12 +651,16 @@ static void send_client_key_exchange(tls_state_t *tls) record.keylen16_hi = (sizeof(record) - sizeof(record.xhdr) - 6) >> 8; record.keylen16_lo = (sizeof(record) - sizeof(record.xhdr) - 6) & 0xff; - tls_get_random(premaster, sizeof(premaster)); - premaster[0] = TLS_MAJ; - premaster[1] = TLS_MIN; + tls_get_random(rsa_premaster, sizeof(rsa_premaster)); +// RFC 5246 +// "Note: The version number in the PreMasterSecret is the version +// offered by the client in the ClientHello.client_version, not the +// version negotiated for the connection." + rsa_premaster[0] = TLS_MAJ; + rsa_premaster[1] = TLS_MIN; psRsaEncryptPub(/*pool:*/ NULL, /* psRsaKey_t* */ &tls->server_rsa_pub_key, - premaster, /*inlen:*/ sizeof(premaster), + rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), record.key, sizeof(record.key), data_param_ignored ); @@ -712,6 +677,88 @@ static void send_change_cipher_spec(tls_state_t *tls) xwrite(tls->fd, rec, sizeof(rec)); } +static void send_client_finished(tls_state_t *tls) +{ +// RFC 5246 on pseudorandom function (PRF): +// +// 5. HMAC and the Pseudorandom Function +//... +// In this section, we define one PRF, based on HMAC. This PRF with the +// SHA-256 hash function is used for all cipher suites defined in this +// document and in TLS documents published prior to this document when +// TLS 1.2 is negotiated. +//... +// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + +// HMAC_hash(secret, A(2) + seed) + +// HMAC_hash(secret, A(3) + seed) + ... +// where + indicates concatenation. +// A() is defined as: +// A(0) = seed +// A(i) = HMAC_hash(secret, A(i-1)) +// P_hash can be iterated as many times as necessary to produce the +// required quantity of data. For example, if P_SHA256 is being used to +// create 80 bytes of data, it will have to be iterated three times +// (through A(3)), creating 96 bytes of output data; the last 16 bytes +// of the final iteration will then be discarded, leaving 80 bytes of +// output data. +// +// TLS's PRF is created by applying P_hash to the secret as: +// +// PRF(secret, label, seed) = P_(secret, label + seed) +// +// The label is an ASCII string. + + tls->fd = 0; + +// 7.4.9. Finished +// A Finished message is always sent immediately after a change +// cipher spec message to verify that the key exchange and +// authentication processes were successful. It is essential that a +// change cipher spec message be received between the other handshake +// messages and the Finished message. +//... +// The Finished message is the first one protected with the just +// negotiated algorithms, keys, and secrets. Recipients of Finished +// messages MUST verify that the contents are correct. Once a side +// has sent its Finished message and received and validated the +// Finished message from its peer, it may begin to send and receive +// application data over the connection. +//... +// struct { +// opaque verify_data[verify_data_length]; +// } Finished; +// +// verify_data +// PRF(master_secret, finished_label, Hash(handshake_messages)) +// [0..verify_data_length-1]; +// +// finished_label +// For Finished messages sent by the client, the string +// "client finished". For Finished messages sent by the server, +// the string "server finished". +// +// Hash denotes a Hash of the handshake messages. For the PRF +// defined in Section 5, the Hash MUST be the Hash used as the basis +// for the PRF. Any cipher suite which defines a different PRF MUST +// also define the Hash to use in the Finished computation. +// +// In previous versions of TLS, the verify_data was always 12 octets +// long. In the current version of TLS, it depends on the cipher +// suite. Any cipher suite which does not explicitly specify +// verify_data_length has a verify_data_length equal to 12. This +// includes all existing cipher suites. +} + +static void get_change_cipher_spec(tls_state_t *tls) +{ + tls->fd = 0; +} + +static void get_server_finished(tls_state_t *tls) +{ + tls->fd = 0; +} + static void tls_handshake(tls_state_t *tls) { // Client RFC 5246 Server @@ -734,23 +781,7 @@ static void tls_handshake(tls_state_t *tls) int len; send_client_hello(tls); -#if 0 /* dump */ - for (;;) { - uint8_t buf[16*1024]; - sleep(2); - len = recv(tls->fd, buf, sizeof(buf), 0); //MSG_DONTWAIT); - if (len < 0) { - if (errno == EAGAIN) - continue; - bb_perror_msg_and_die("recv"); - } - if (len == 0) - break; - dump(buf, len); - } -#endif - - get_server_hello_or_die(tls); + get_server_hello(tls); //RFC 5246 // The server MUST send a Certificate message whenever the agreed- @@ -761,7 +792,7 @@ static void tls_handshake(tls_state_t *tls) // // IOW: in practice, Certificate *always* follows. // (for example, kernel.org does not even accept DH_anon cipher id) - get_server_cert_or_die(tls); + get_server_cert(tls); len = xread_tls_handshake_block(tls, 4); if (tls->inbuf[5] == HANDSHAKE_SERVER_KEY_EXCHANGE) { @@ -776,6 +807,13 @@ static void tls_handshake(tls_state_t *tls) } // if (tls->inbuf[5] == HANDSHAKE_CERTIFICATE_REQUEST) { // dbg("got CERTIFICATE_REQUEST\n"); +//RFC 5246: (in response to this,) "If no suitable certificate is available, +// the client MUST send a certificate message containing no +// certificates. That is, the certificate_list structure has a +// length of zero. ... +// Client certificates are sent using the Certificate structure +// defined in Section 7.4.2." +// (i.e. the same format as server certs) // xread_tls_handshake_block(tls, 4); // } if (tls->inbuf[5] == HANDSHAKE_SERVER_HELLO_DONE) { @@ -784,6 +822,10 @@ static void tls_handshake(tls_state_t *tls) send_client_key_exchange(tls); send_change_cipher_spec(tls); //we now should be able to send encrypted... as soon as we grok AES. + send_client_finished(tls); + get_change_cipher_spec(tls); + get_server_finished(tls); +//we now should receive encrypted, and application data can be sent/received } else { tls_error_die(tls); } diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c index 0d797f87f..f802baa15 100644 --- a/networking/tls_pstm.c +++ b/networking/tls_pstm.c @@ -5,6 +5,10 @@ */ #include "tls.h" +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. + * Changes are flagged with ///bbox + */ + /** * @file pstm.c * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) @@ -51,12 +55,13 @@ static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c); */ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) { +///bbox // uint16 x; /* alloc mem */ - a->dp = xzalloc(sizeof (pstm_digit) * size); + a->dp = xzalloc(sizeof (pstm_digit) * size);///bbox a->pool = pool; a->used = 0; a->alloc = (int16)size; @@ -77,11 +82,12 @@ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) */ int32 pstm_init(psPool_t *pool, pstm_int * a) { +///bbox // int32 i; /* allocate memory required and clear it */ - a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT); + a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);///bbox /* set the digits to zero */ @@ -120,7 +126,7 @@ int32 pstm_grow(pstm_int * a, int16 size) We store the return in a temporary variable in case the operation failed we don't want to overwrite the dp member of a. */ - tmp = xrealloc(a->dp, sizeof (pstm_digit) * size); + tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);///bbox /* reallocation succeeded so set a->dp */ @@ -1616,7 +1622,7 @@ int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, Pre-allocated digit. Used for mul, sqr, AND reduce */ paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit); - paD = xzalloc(paDlen); + paD = xzalloc(paDlen);///bbox /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h index 1affc1b69..de03e3f92 100644 --- a/networking/tls_pstm.h +++ b/networking/tls_pstm.h @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. + * Changes are flagged with ///bbox + */ + /** * @file pstm.h * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c index c231c4ddf..e9ae81c53 100644 --- a/networking/tls_pstm_montgomery_reduce.c +++ b/networking/tls_pstm_montgomery_reduce.c @@ -5,6 +5,10 @@ */ #include "tls.h" +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. + * Changes are flagged with ///bbox + */ + /** * @file pstm_montgomery_reduce.c * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) @@ -353,7 +357,7 @@ int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, c = paD; memset(c, 0x0, paDlen); } else { - c = xzalloc(2*pa+1); + c = xzalloc(2*pa+1);///bbox } /* copy the input */ oldused = a->used; diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c index 6e051baeb..7967231df 100644 --- a/networking/tls_pstm_mul_comba.c +++ b/networking/tls_pstm_mul_comba.c @@ -5,6 +5,10 @@ */ #include "tls.h" +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. + * Changes are flagged with ///bbox + */ + /** * @file pstm_mul_comba.c * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) @@ -246,13 +250,13 @@ static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, if (paD != NULL) { if (paDlen < (sizeof(pstm_digit) * pa)) { paDfail = 1; /* have a paD but it's not large enough */ - dst = xzalloc(sizeof(pstm_digit) * pa); + dst = xzalloc(sizeof(pstm_digit) * pa);///bbox } else { dst = paD; memset(dst, 0x0, paDlen); } } else { - dst = xzalloc(sizeof(pstm_digit) * pa); + dst = xzalloc(sizeof(pstm_digit) * pa);///bbox } for (ix = 0; ix < pa; ix++) { diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c index 98186d31f..378e0647b 100644 --- a/networking/tls_pstm_sqr_comba.c +++ b/networking/tls_pstm_sqr_comba.c @@ -5,6 +5,10 @@ */ #include "tls.h" +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. + * Changes are flagged with ///bbox + */ + /** * @file pstm_sqr_comba.c * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) @@ -466,13 +470,13 @@ static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, if (paD != NULL) { if (paDlen < (sizeof(pstm_digit) * pa)) { paDfail = 1; /* have a paD, but it's not big enough */ - dst = xzalloc(sizeof(pstm_digit) * pa); + dst = xzalloc(sizeof(pstm_digit) * pa);///bbox } else { dst = paD; memset(dst, 0x0, paDlen); } } else { - dst = xzalloc(sizeof(pstm_digit) * pa); + dst = xzalloc(sizeof(pstm_digit) * pa);///bbox } for (ix = 0; ix < pa; ix++) { diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c index 058b09cee..3114435dd 100644 --- a/networking/tls_rsa.c +++ b/networking/tls_rsa.c @@ -5,49 +5,55 @@ */ #include "tls.h" +/* The code below is taken from parts of + * matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c + * matrixssl-3-7-2b-open/crypto/pubkey/rsa.c + * and (so far) almost not modified. Changes are flagged with ///bbox + */ + #define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \ pkcs1Pad(in, inlen, out, outlen, cryptType) static ///bbox int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, - uint32 outlen, int32 cryptType, void *userPtr) + uint32 outlen, int32 cryptType, void *userPtr) { - unsigned char *c; - int32 randomLen; + unsigned char *c; + int32 randomLen; - randomLen = outlen - 3 - inlen; - if (randomLen < 8) { - psTraceCrypto("pkcs1Pad failure\n"); - return PS_LIMIT_FAIL; - } - c = out; - *c = 0x00; - c++; - *c = (unsigned char)cryptType; - c++; - if (cryptType == PUBKEY_TYPE) { - while (randomLen-- > 0) { - *c++ = 0xFF; - } - } else { - if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) { - return PS_PLATFORM_FAIL; - } + randomLen = outlen - 3 - inlen; + if (randomLen < 8) { + psTraceCrypto("pkcs1Pad failure\n"); + return PS_LIMIT_FAIL; + } + c = out; + *c = 0x00; + c++; + *c = (unsigned char)cryptType; + c++; + if (cryptType == PUBKEY_TYPE) { + while (randomLen-- > 0) { + *c++ = 0xFF; + } + } else { + if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) { + return PS_PLATFORM_FAIL; + } /* - SECURITY: Read through the random data and change all 0x0 to 0x01. - This is per spec that no random bytes should be 0 + SECURITY: Read through the random data and change all 0x0 to 0x01. + This is per spec that no random bytes should be 0 */ - while (randomLen-- > 0) { - if (*c == 0x0) { - *c = 0x01; - } - c++; - } - } - *c = 0x00; - c++; - memcpy(c, in, inlen); + while (randomLen-- > 0) { + if (*c == 0x0) { + *c = 0x01; + } + c++; + } + } + *c = 0x00; + c++; + memcpy(c, in, inlen); - return outlen; + return outlen; } #define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \ @@ -173,31 +179,31 @@ done: } int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, - unsigned char *in, uint32 inlen, - unsigned char *out, uint32 outlen, void *data) + unsigned char *in, uint32 inlen, + unsigned char *out, uint32 outlen, void *data) { - int32 err; - uint32 size; + int32 err; + uint32 size; - size = key->size; - if (outlen < size) { - psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); - return PS_ARG_FAIL; - } + size = key->size; + if (outlen < size) { + psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); + return PS_ARG_FAIL; + } - if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data)) - < PS_SUCCESS) { - psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n"); - return err; - } - if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key, - PUBKEY_TYPE, data)) < PS_SUCCESS) { - psTraceCrypto("Error performing psRsaEncryptPub\n"); - return err; - } - if (outlen != size) { - psTraceCrypto("Encrypted size error in psRsaEncryptPub\n"); - return PS_FAILURE; - } - return size; + if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data)) + < PS_SUCCESS) { + psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n"); + return err; + } + if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key, + PUBKEY_TYPE, data)) < PS_SUCCESS) { + psTraceCrypto("Error performing psRsaEncryptPub\n"); + return err; + } + if (outlen != size) { + psTraceCrypto("Encrypted size error in psRsaEncryptPub\n"); + return PS_FAILURE; + } + return size; } diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h index 3281087c7..93f469e83 100644 --- a/networking/tls_rsa.h +++ b/networking/tls_rsa.h @@ -2,6 +2,8 @@ * Copyright (C) 2017 Denys Vlasenko * * Licensed under GPLv2, see file LICENSE in this source tree. + * + * Selected few declarations for RSA. */ typedef struct { -- cgit v1.2.3-55-g6feb From b8935d00b0a60be24ee9073349c2a185cebbacd4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 20:16:27 +0100 Subject: sha512: use larger constant table only if sha512 is in fact selected function old new delta sha_K 640 256 -384 Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 112 +++++++++++++++++++++++++++++-------------------- make_single_applets.sh | 5 ++- 2 files changed, 70 insertions(+), 47 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index 7e7d8da2f..d325584d7 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -9,6 +9,8 @@ #include "libbb.h" +#define NEED_SHA512 (ENABLE_SHA512SUM || ENABLE_USE_BB_CRYPT_SHA) + /* gcc 4.2.1 optimizes rotr64 better with inline than with macro * (for rotX32, there is no difference). Why? My guess is that * macro requires clever common subexpression elimination heuristics @@ -564,48 +566,59 @@ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) * are the most significant half of first 64 elements * of the same array. */ -static const uint64_t sha_K[80] = { - 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, - 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, - 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, - 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, - 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, - 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, - 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, - 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, - 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, - 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, - 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, - 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, - 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, - 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, - 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, - 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, - 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, - 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, - 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, - 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, - 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, - 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, - 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, - 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, - 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, - 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, - 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, - 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, - 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, - 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, - 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, - 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, - 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, /* [64]+ are used for sha512 only */ - 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, - 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, - 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, - 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, - 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, - 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, - 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +#undef K +#if NEED_SHA512 +typedef uint64_t sha_K_int; +# define K(v) v +#else +typedef uint32_t sha_K_int; +# define K(v) (uint32_t)(v >> 32) +#endif +static const sha_K_int sha_K[] = { + K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL), + K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL), + K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL), + K(0x923f82a4af194f9bULL), K(0xab1c5ed5da6d8118ULL), + K(0xd807aa98a3030242ULL), K(0x12835b0145706fbeULL), + K(0x243185be4ee4b28cULL), K(0x550c7dc3d5ffb4e2ULL), + K(0x72be5d74f27b896fULL), K(0x80deb1fe3b1696b1ULL), + K(0x9bdc06a725c71235ULL), K(0xc19bf174cf692694ULL), + K(0xe49b69c19ef14ad2ULL), K(0xefbe4786384f25e3ULL), + K(0x0fc19dc68b8cd5b5ULL), K(0x240ca1cc77ac9c65ULL), + K(0x2de92c6f592b0275ULL), K(0x4a7484aa6ea6e483ULL), + K(0x5cb0a9dcbd41fbd4ULL), K(0x76f988da831153b5ULL), + K(0x983e5152ee66dfabULL), K(0xa831c66d2db43210ULL), + K(0xb00327c898fb213fULL), K(0xbf597fc7beef0ee4ULL), + K(0xc6e00bf33da88fc2ULL), K(0xd5a79147930aa725ULL), + K(0x06ca6351e003826fULL), K(0x142929670a0e6e70ULL), + K(0x27b70a8546d22ffcULL), K(0x2e1b21385c26c926ULL), + K(0x4d2c6dfc5ac42aedULL), K(0x53380d139d95b3dfULL), + K(0x650a73548baf63deULL), K(0x766a0abb3c77b2a8ULL), + K(0x81c2c92e47edaee6ULL), K(0x92722c851482353bULL), + K(0xa2bfe8a14cf10364ULL), K(0xa81a664bbc423001ULL), + K(0xc24b8b70d0f89791ULL), K(0xc76c51a30654be30ULL), + K(0xd192e819d6ef5218ULL), K(0xd69906245565a910ULL), + K(0xf40e35855771202aULL), K(0x106aa07032bbd1b8ULL), + K(0x19a4c116b8d2d0c8ULL), K(0x1e376c085141ab53ULL), + K(0x2748774cdf8eeb99ULL), K(0x34b0bcb5e19b48a8ULL), + K(0x391c0cb3c5c95a63ULL), K(0x4ed8aa4ae3418acbULL), + K(0x5b9cca4f7763e373ULL), K(0x682e6ff3d6b2b8a3ULL), + K(0x748f82ee5defb2fcULL), K(0x78a5636f43172f60ULL), + K(0x84c87814a1f0ab72ULL), K(0x8cc702081a6439ecULL), + K(0x90befffa23631e28ULL), K(0xa4506cebde82bde9ULL), + K(0xbef9a3f7b2c67915ULL), K(0xc67178f2e372532bULL), +#if NEED_SHA512 /* [64]+ are used for sha512 only */ + K(0xca273eceea26619cULL), K(0xd186b8c721c0c207ULL), + K(0xeada7dd6cde0eb1eULL), K(0xf57d4f7fee6ed178ULL), + K(0x06f067aa72176fbaULL), K(0x0a637dc5a2c898a6ULL), + K(0x113f9804bef90daeULL), K(0x1b710b35131c471bULL), + K(0x28db77f523047d84ULL), K(0x32caab7b40c72493ULL), + K(0x3c9ebe0a15c9bebcULL), K(0x431d67c49c100d4cULL), + K(0x4cc5d4becb3e42b6ULL), K(0x597f299cfc657e2aULL), + K(0x5fcb6fab3ad6faecULL), K(0x6c44198c4a475817ULL), +#endif }; +#undef K #undef Ch #undef Maj @@ -649,7 +662,7 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx) * (I hope compiler is clever enough to just fetch * upper half) */ - uint32_t K_t = sha_K[t] >> 32; + uint32_t K_t = NEED_SHA512 ? (sha_K[t] >> 32) : sha_K[t]; uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t]; uint32_t T2 = S0(a) + Maj(a, b, c); h = g; @@ -679,6 +692,7 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx) ctx->hash[7] += h; } +#if NEED_SHA512 static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx) { unsigned t; @@ -740,7 +754,7 @@ static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx) ctx->hash[6] += g; ctx->hash[7] += h; } - +#endif /* NEED_SHA512 */ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx) { @@ -765,6 +779,7 @@ static const uint32_t init256[] = { 0x1f83d9ab, 0x5be0cd19, }; +#if NEED_SHA512 static const uint32_t init512_lo[] = { 0, 0, @@ -777,6 +792,7 @@ static const uint32_t init512_lo[] = { 0xfb41bd6b, 0x137e2179, }; +#endif /* NEED_SHA512 */ /* Initialize structure containing state of computation. (FIPS 180-2:5.3.2) */ @@ -787,6 +803,7 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) ctx->process_block = sha256_process_block64; } +#if NEED_SHA512 /* Initialize structure containing state of computation. (FIPS 180-2:5.3.3) */ void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) @@ -810,7 +827,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) ctx->total64[0] += len; if (ctx->total64[0] < len) ctx->total64[1]++; -#if 0 +# if 0 remaining = 128 - bufpos; /* Hash whole blocks */ @@ -825,7 +842,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) /* Save last, partial blosk */ memcpy(ctx->wbuffer + bufpos, buffer, len); -#else +# else while (1) { remaining = 128 - bufpos; if (remaining > len) @@ -843,8 +860,9 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) sha512_process_block128(ctx); /*bufpos = 0; - already is */ } -#endif +# endif } +#endif /* NEED_SHA512 */ /* Used also for sha256 */ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) @@ -864,6 +882,7 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size); } +#if NEED_SHA512 void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) { unsigned bufpos = ctx->total64[0] & 127; @@ -897,6 +916,7 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) } memcpy(resbuf, ctx->hash, sizeof(ctx->hash)); } +#endif /* NEED_SHA512 */ /* diff --git a/make_single_applets.sh b/make_single_applets.sh index 03a5c324f..8ad7a7406 100755 --- a/make_single_applets.sh +++ b/make_single_applets.sh @@ -30,9 +30,12 @@ done trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT + # Turn on each applet individually and build single-applet executable +# (give config names on command line to build only those) +test $# = 0 && set -- $apps fail=0 -for app in $apps; do +for app; do # Only if it was indeed originally enabled... { echo "$cfg" | grep -q "^CONFIG_${app}=y\$"; } || continue -- cgit v1.2.3-55-g6feb From 16e7f697f8064a4e5fc2f8e181fe6a7b9602b1b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 20:59:32 +0100 Subject: libbb: eliminate redundant variable in sha_crypt function old new delta sha_crypt 1136 1130 -6 Signed-off-by: Denys Vlasenko --- libbb/pw_encrypt_sha.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c index 8aeaacad6..72e37e485 100644 --- a/libbb/pw_encrypt_sha.c +++ b/libbb/pw_encrypt_sha.c @@ -47,16 +47,17 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) unsigned cnt; unsigned rounds; char *cp; - char is_sha512; /* Analyze salt, construct already known part of result */ cnt = strlen(salt_data) + 1 + 43 + 1; - is_sha512 = salt_data[1]; - if (is_sha512 == '6') + _32or64 = 32; + if (salt_data[1] == '6') { /* sha512 */ + _32or64 *= 2; /*64*/ cnt += 43; + } result = resptr = xzalloc(cnt); /* will provide NUL terminator */ *resptr++ = '$'; - *resptr++ = is_sha512; + *resptr++ = salt_data[1]; *resptr++ = '$'; rounds = ROUNDS_DEFAULT; salt_data += 3; @@ -93,12 +94,10 @@ sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) sha_begin = (void*)sha256_begin; sha_hash = (void*)sha256_hash; sha_end = (void*)sha256_end; - _32or64 = 32; - if (is_sha512 == '6') { + if (_32or64 != 32) { sha_begin = (void*)sha512_begin; sha_hash = (void*)sha512_hash; sha_end = (void*)sha512_end; - _32or64 = 64; } /* Add KEY, SALT. */ @@ -200,7 +199,7 @@ do { \ unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ resptr = to64(resptr, w, N); \ } while (0) - if (is_sha512 == '5') { + if (_32or64 == 32) { /* sha256 */ unsigned i = 0; while (1) { unsigned j = i + 10; -- cgit v1.2.3-55-g6feb From 6c73aaff38819533c55aecc53487d53521915e91 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 15 Jan 2017 21:48:31 +0100 Subject: cryptpw: support "rounds=NNNNNNN$" thing in salts Signed-off-by: Denys Vlasenko --- loginutils/cryptpw.c | 6 ++++-- testsuite/cryptpw.tests | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100755 testsuite/cryptpw.tests diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index 9f5f40686..d630231c6 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -35,7 +35,7 @@ //usage: "[OPTIONS] [PASSWORD] [SALT]" /* We do support -s, we just don't mention it */ //usage:#define cryptpw_full_usage "\n\n" -//usage: "Crypt PASSWORD using crypt(3)\n" +//usage: "Print crypt(3) hashed PASSWORD\n" //usage: IF_LONG_OPTS( //usage: "\n -P,--password-fd=N Read password from fd N" /* //usage: "\n -s,--stdin Use stdin; like -P0" */ @@ -92,7 +92,8 @@ to cryptpw. -a option (alias for -m) came from cryptpw. int cryptpw_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int cryptpw_main(int argc UNUSED_PARAM, char **argv) { - char salt[MAX_PW_SALT_LEN]; + /* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */ + char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")]; char *salt_ptr; char *password; const char *opt_m, *opt_S; @@ -122,6 +123,7 @@ int cryptpw_main(int argc UNUSED_PARAM, char **argv) salt_ptr = crypt_make_pw_salt(salt, opt_m); if (opt_S) + /* put user's data after the "$N$" prefix */ safe_strncpy(salt_ptr, opt_S, sizeof(salt) - (sizeof("$N$")-1)); xmove_fd(fd, STDIN_FILENO); diff --git a/testsuite/cryptpw.tests b/testsuite/cryptpw.tests new file mode 100755 index 000000000..8ec476c9f --- /dev/null +++ b/testsuite/cryptpw.tests @@ -0,0 +1,28 @@ +#!/bin/sh + +# Copyright 2017 by Denys Vlasenko +# Licensed under GPLv2, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "description" "command" "result" "infile" "stdin" + +optional USE_BB_CRYPT_SHA +testing "cryptpw sha256" \ + "cryptpw -m sha256 QWErty '123456789012345678901234567890'" \ + '$5$1234567890123456$5DxfOCmU4vRhtzfsbdK.6wSGMwwVbac7ZkWwusb8Si7\n' "" "" + +testing "cryptpw sha256 rounds=99999" \ + "cryptpw -m sha256 QWErty 'rounds=99999\$123456789012345678901234567890'" \ + '$5$rounds=99999$1234567890123456$aYellycJGZM6AKyVzaQsSrDBdTixubtMnM6J.MN0xM8\n' "" "" + +testing "cryptpw sha512" \ + "cryptpw -m sha512 QWErty '123456789012345678901234567890'" \ + '$6$1234567890123456$KB7QqxFyqmJSWyQYcCuGeFukgz1bPQoipWZf7.9L7z3k8UNTXa6UikbKcUGDc2ANn7DOGmDaroxDgpK16w/RE0\n' "" "" + +testing "cryptpw sha512 rounds=99999" \ + "cryptpw -m sha512 QWErty 'rounds=99999\$123456789012345678901234567890'" \ + '$6$rounds=99999$1234567890123456$BfF6gD6ZjUmwawH5QaAglYAxtU./yvsz0fcQ464l49aMI2DZW3j5ri28CrxK7riPWNpLuUpfaIdY751SBYKUH.\n' "" "" +SKIP= + +exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From 936e83e694b3225dbcc14fc99ca8053e2518ab35 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Jan 2017 04:25:01 +0100 Subject: tls: add sha256 hmac and prf code Signed-off-by: Denys Vlasenko --- networking/tls.c | 256 ++++++++++++++++++++++++++++++++++++++++++++------- networking/tls.h | 2 +- networking/tls_rsa.c | 2 +- 3 files changed, 225 insertions(+), 35 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 44c9da195..9bc75f824 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -146,6 +146,11 @@ typedef struct tls_state { psRsaKey_t server_rsa_pub_key; + sha256_ctx_t handshake_sha256_ctx; + + uint8_t client_and_server_rand32[2 * 32]; + uint8_t master_secret[48]; + // RFC 5246 // |6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext @@ -187,9 +192,18 @@ tls_state_t *new_tls_state(void) { tls_state_t *tls = xzalloc(sizeof(*tls)); tls->fd = -1; + sha256_begin(&tls->handshake_sha256_ctx); return tls; } +static void xwrite_and_hash(tls_state_t *tls, const void *buf, unsigned size) +{ + xwrite(tls->fd, buf, size); + /* hash does not include record headers */ + if (size > 5) + sha256_hash(&tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); +} + static unsigned get24be(const uint8_t *p) { return 0x100*(0x100*p[0] + p[1]) + p[2]; @@ -494,6 +508,156 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } +enum { + SHA256_INSIZE = 64, + SHA256_OUTSIZE = 32, +}; + +static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned size) +{ + sha256_ctx_t ctx; + sha256_begin(&ctx); + sha256_hash(&ctx, data, size); + sha256_end(&ctx, out); +} + +// RFC 2104: HMAC(key, text) based on a hash H (say, sha256) is: +// ipad = [0x36 x INSIZE] +// opad = [0x5c x INSIZE] +// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text)) +// +// H(key XOR opad) and H(key XOR ipad) can be precomputed +// if we often need HMAC hmac with the same key. +// +// text is often given in disjoint pieces. +static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE], + sha256_ctx_t *hashed_key_xor_ipad, + sha256_ctx_t *hashed_key_xor_opad, + va_list va) +{ + uint8_t *text; + + /* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ + /* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ + + /* calculate out = H((key XOR ipad) + text) */ + while ((text = va_arg(va, uint8_t*)) != NULL) { + unsigned text_size = va_arg(va, unsigned); + sha256_hash(hashed_key_xor_ipad, text, text_size); + } + sha256_end(hashed_key_xor_ipad, out); + + /* out = H((key XOR opad) + out) */ + sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE); + sha256_end(hashed_key_xor_opad, out); +} + +static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...) +{ + sha256_ctx_t hashed_key_xor_ipad; + sha256_ctx_t hashed_key_xor_opad; + uint8_t key_xor_ipad[SHA256_INSIZE]; + uint8_t key_xor_opad[SHA256_INSIZE]; + uint8_t tempkey[SHA256_OUTSIZE]; + va_list va; + int i; + + va_start(va, key_size); + + // "The authentication key can be of any length up to INSIZE, the + // block length of the hash function. Applications that use keys longer + // than INSIZE bytes will first hash the key using H and then use the + // resultant OUTSIZE byte string as the actual key to HMAC." + if (key_size > SHA256_INSIZE) { + hash_sha256(tempkey, key, key_size); + key = tempkey; + key_size = SHA256_OUTSIZE; + } + + for (i = 0; i < key_size; i++) { + key_xor_ipad[i] = key[i] ^ 0x36; + key_xor_opad[i] = key[i] ^ 0x5c; + } + for (; i < SHA256_INSIZE; i++) { + key_xor_ipad[i] = 0x36; + key_xor_opad[i] = 0x5c; + } + sha256_begin(&hashed_key_xor_ipad); + sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE); + sha256_begin(&hashed_key_xor_opad); + sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE); + + hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); + va_end(va); +} + +// RFC 5246: +// 5. HMAC and the Pseudorandom Function +//... +// In this section, we define one PRF, based on HMAC. This PRF with the +// SHA-256 hash function is used for all cipher suites defined in this +// document and in TLS documents published prior to this document when +// TLS 1.2 is negotiated. +//... +// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + +// HMAC_hash(secret, A(2) + seed) + +// HMAC_hash(secret, A(3) + seed) + ... +// where + indicates concatenation. +// A() is defined as: +// A(0) = seed +// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed) +// A(i) = HMAC_hash(secret, A(i-1)) +// P_hash can be iterated as many times as necessary to produce the +// required quantity of data. For example, if P_SHA256 is being used to +// create 80 bytes of data, it will have to be iterated three times +// (through A(3)), creating 96 bytes of output data; the last 16 bytes +// of the final iteration will then be discarded, leaving 80 bytes of +// output data. +// +// TLS's PRF is created by applying P_hash to the secret as: +// +// PRF(secret, label, seed) = P_(secret, label + seed) +// +// The label is an ASCII string. +static void tls_prf_hmac_sha256( + uint8_t *outbuf, unsigned outbuf_size, + uint8_t *secret, unsigned secret_size, + const char *label, + uint8_t *seed, unsigned seed_size) +{ + uint8_t a[SHA256_OUTSIZE]; + uint8_t *out_p = outbuf; + unsigned label_size = strlen(label); + + /* In P_hash() calculation, "seed" is "label + seed": */ +#define SEED label, label_size, seed, seed_size +#define SECRET secret, secret_size +#define A a, (int)(sizeof(a)) + + /* A(1) = HMAC_hash(secret, seed) */ + hmac_sha256(a, SECRET, SEED, NULL); + + for(;;) { + /* HMAC_hash(secret, A(1) + seed) */ + if (outbuf_size <= SHA256_OUTSIZE) { + /* Last, possibly incomplete, block */ + /* (use a[] as temp buffer) */ + hmac_sha256(a, SECRET, A, SEED, NULL); + memcpy(out_p, a, outbuf_size); + return; + } + /* Not last block. Store directly to result buffer */ + hmac_sha256(out_p, SECRET, A, SEED, NULL); + out_p += SHA256_OUTSIZE; + outbuf_size -= SHA256_OUTSIZE; + /* A(2) = HMAC_hash(secret, A(1)) */ + hmac_sha256(a, SECRET, A, NULL); + } +#undef A +#undef SECRET +#undef SEED +} + /* * TLS Handshake routines */ @@ -535,7 +699,9 @@ static void send_client_hello(tls_state_t *tls) hello.comprtypes_len = 1; //hello.comprtypes[0] = 0; - xwrite(tls->fd, &hello, sizeof(hello)); + xwrite_and_hash(tls, &hello, sizeof(hello)); + memcpy(tls->client_and_server_rand32, hello.rand32, sizeof(hello.rand32)); + #if 0 /* dump */ for (;;) { uint8_t buf[16*1024]; @@ -589,6 +755,7 @@ static void get_server_hello(tls_state_t *tls) tls_error_die(tls); } dbg("got SERVER_HELLO\n"); + memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); } static void get_server_cert(tls_state_t *tls) @@ -665,7 +832,23 @@ static void send_client_key_exchange(tls_state_t *tls) data_param_ignored ); - xwrite(tls->fd, &record, sizeof(record)); + xwrite_and_hash(tls, &record, sizeof(record)); + +// RFC 5246 +// For all key exchange methods, the same algorithm is used to convert +// the pre_master_secret into the master_secret. The pre_master_secret +// should be deleted from memory once the master_secret has been +// computed. +// master_secret = PRF(pre_master_secret, "master secret", +// ClientHello.random + ServerHello.random) +// [0..47]; +// The master secret is always exactly 48 bytes in length. The length +// of the premaster secret will vary depending on key exchange method. + tls_prf_hmac_sha256(tls->master_secret, sizeof(tls->master_secret), + rsa_premaster, sizeof(rsa_premaster), + "master secret", + tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) + ); } static void send_change_cipher_spec(tls_state_t *tls) @@ -674,42 +857,12 @@ static void send_change_cipher_spec(tls_state_t *tls) RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, 01 }; + /* Not "xwrite_and_hash": this is not a handshake message */ xwrite(tls->fd, rec, sizeof(rec)); } static void send_client_finished(tls_state_t *tls) { -// RFC 5246 on pseudorandom function (PRF): -// -// 5. HMAC and the Pseudorandom Function -//... -// In this section, we define one PRF, based on HMAC. This PRF with the -// SHA-256 hash function is used for all cipher suites defined in this -// document and in TLS documents published prior to this document when -// TLS 1.2 is negotiated. -//... -// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + -// HMAC_hash(secret, A(2) + seed) + -// HMAC_hash(secret, A(3) + seed) + ... -// where + indicates concatenation. -// A() is defined as: -// A(0) = seed -// A(i) = HMAC_hash(secret, A(i-1)) -// P_hash can be iterated as many times as necessary to produce the -// required quantity of data. For example, if P_SHA256 is being used to -// create 80 bytes of data, it will have to be iterated three times -// (through A(3)), creating 96 bytes of output data; the last 16 bytes -// of the final iteration will then be discarded, leaving 80 bytes of -// output data. -// -// TLS's PRF is created by applying P_hash to the secret as: -// -// PRF(secret, label, seed) = P_(secret, label + seed) -// -// The label is an ASCII string. - - tls->fd = 0; - // 7.4.9. Finished // A Finished message is always sent immediately after a change // cipher spec message to verify that the key exchange and @@ -747,6 +900,39 @@ static void send_client_finished(tls_state_t *tls) // suite. Any cipher suite which does not explicitly specify // verify_data_length has a verify_data_length equal to 12. This // includes all existing cipher suites. + struct client_finished { + struct record_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t prf_result[12]; + }; + struct client_finished record; + uint8_t handshake_hash[SHA256_OUTSIZE]; + sha256_ctx_t ctx; + + memset(&record, 0, sizeof(record)); + record.xhdr.type = RECORD_TYPE_HANDSHAKE; + record.xhdr.proto_maj = TLS_MAJ; + record.xhdr.proto_min = TLS_MIN; + record.xhdr.len16_hi = (sizeof(record) - sizeof(record.xhdr)) >> 8; + record.xhdr.len16_lo = (sizeof(record) - sizeof(record.xhdr)) & 0xff; + record.type = HANDSHAKE_FINISHED; + //record.len24_hi = 0; + record.len24_mid = (sizeof(record) - sizeof(record.xhdr) - 4) >> 8; + record.len24_lo = (sizeof(record) - sizeof(record.xhdr) - 4) & 0xff; +//FIXME ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code is repeatable + + ctx = tls->handshake_sha256_ctx; /* struct copy */ + sha256_end(&ctx, handshake_hash); + tls_prf_hmac_sha256(record.prf_result, sizeof(record.prf_result), + tls->master_secret, sizeof(tls->master_secret), + "client finished", + handshake_hash, sizeof(handshake_hash) + ); + +//(1) TODO: well, this should be encrypted on send, really. +//(2) do we really need to also hash it? + xwrite_and_hash(tls, &record, sizeof(record)); } static void get_change_cipher_spec(tls_state_t *tls) @@ -831,6 +1017,10 @@ static void tls_handshake(tls_state_t *tls) } } +// To run a test server using openssl: +// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 +// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' + int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tls_main(int argc UNUSED_PARAM, char **argv) { diff --git a/networking/tls.h b/networking/tls.h index 20317ecc3..3a8a3d826 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -59,7 +59,7 @@ void tls_get_random(void *buf, unsigned len); #define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS) #define psFree(p, pool) free(p) -#define psTraceCrypto(msg) bb_error_msg_and_die(msg) +#define psTraceCrypto(...) bb_error_msg_and_die(__VA_ARGS__) /* Secure zerofill */ #define memset_s(A,B,C,D) memset((A),(C),(D)) diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c index 3114435dd..df711865c 100644 --- a/networking/tls_rsa.c +++ b/networking/tls_rsa.c @@ -187,7 +187,7 @@ int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, size = key->size; if (outlen < size) { - psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); + psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub: outlen:%d < size:%d", outlen, size); return PS_ARG_FAIL; } -- cgit v1.2.3-55-g6feb From 4e08a123b0f8c7d2c66583e84759b0974e791ee9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Jan 2017 17:31:05 +0100 Subject: Assorted warning fixes and added a comment, no code changes Signed-off-by: Denys Vlasenko --- networking/wget.c | 3 +++ procps/ps.c | 8 +++++++- procps/pstree.c | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/networking/wget.c b/networking/wget.c index d5a92a950..5da6481c1 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -1092,6 +1092,9 @@ static void download_one_url(const char *url) fflush(sfp); +/* Tried doing this unconditionally. + * Cloudflare and nginx/1.11.5 are shocked to see SHUT_WR on non-HTTPS. + */ #if SSL_SUPPORTED if (target.protocol == P_HTTPS) { /* If we use SSL helper, keeping our end of the socket open for writing diff --git a/procps/ps.c b/procps/ps.c index 1d380590d..e8b122c5a 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -608,7 +608,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv) procps_status_t *p; llist_t* opt_o = NULL; char default_o[sizeof(DEFAULT_O_STR)]; +#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS int opt; +#endif enum { OPT_Z = (1 << 0), OPT_o = (1 << 1), @@ -638,7 +640,11 @@ int ps_main(int argc UNUSED_PARAM, char **argv) * procps v3.2.7 supports -T and shows tids as SPID column, * it also supports -L where it shows tids as LWP column. */ - opt = getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o); +#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS + opt = +#endif + getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o); + if (opt_o) { do { parse_o(llist_pop(&opt_o)); diff --git a/procps/pstree.c b/procps/pstree.c index c5fb83688..f97e99639 100644 --- a/procps/pstree.c +++ b/procps/pstree.c @@ -357,7 +357,9 @@ static void handle_thread(const char *comm, pid_t pid, pid_t ppid, uid_t uid) static void mread_proc(void) { procps_status_t *p = NULL; +#if ENABLE_FEATURE_SHOW_THREADS pid_t parent = 0; +#endif int flags = PSSCAN_COMM | PSSCAN_PID | PSSCAN_PPID | PSSCAN_UIDGID | PSSCAN_TASKS; while ((p = procps_scan(p, flags)) != NULL) { @@ -368,7 +370,9 @@ static void mread_proc(void) #endif { add_proc(p->comm, p->pid, p->ppid, p->uid/*, 0*/); +#if ENABLE_FEATURE_SHOW_THREADS parent = p->pid; +#endif } } } -- cgit v1.2.3-55-g6feb From 9a6897a48a3bd23dacfe8f23016d2f8083c2308b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Jan 2017 23:26:33 +0100 Subject: tls: format FINISHED message properly for unencrypted, but sha256 signed mode Now it at least looks correct, but unfortunately "openssl s_server" says my hash is wrong. Signed-off-by: Denys Vlasenko --- networking/tls.c | 506 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 480 insertions(+), 26 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 9bc75f824..562874aa6 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -60,6 +60,8 @@ #define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */ #define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */ #define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */ +#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */ + #define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF #define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */ @@ -99,6 +101,7 @@ #define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ #define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ +// RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" #define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ #define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ #define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */ @@ -130,11 +133,17 @@ //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE -#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? +//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? +#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) //test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported +enum { + SHA256_INSIZE = 64, + SHA256_OUTSIZE = 32, +}; + struct record_hdr { uint8_t type; uint8_t proto_maj, proto_min; @@ -151,6 +160,17 @@ typedef struct tls_state { uint8_t client_and_server_rand32[2 * 32]; uint8_t master_secret[48]; + uint8_t encrypt_on_write; + uint8_t client_write_MAC_key[SHA256_OUTSIZE]; +// RFC 5246 +// sequence number +// Each connection state contains a sequence number, which is +// maintained separately for read and write states. The sequence +// number MUST be set to zero whenever a connection state is made the +// active state. Sequence numbers are of type uint64 and may not +// exceed 2^64-1. + uint64_t write_seq64_be; + // RFC 5246 // |6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext @@ -196,11 +216,81 @@ tls_state_t *new_tls_state(void) return tls; } -static void xwrite_and_hash(tls_state_t *tls, const void *buf, unsigned size) +static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...); + +static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size) { +// rfc5246 +// 6.2.3.1. Null or Standard Stream Cipher +// +// Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) +// convert TLSCompressed.fragment structures to and from stream +// TLSCiphertext.fragment structures. +// +// stream-ciphered struct { +// opaque content[TLSCompressed.length]; +// opaque MAC[SecurityParameters.mac_length]; +// } GenericStreamCipher; +// +// The MAC is generated as: +// +// MAC(MAC_write_key, seq_num + +// TLSCompressed.type + +// TLSCompressed.version + +// TLSCompressed.length + +// TLSCompressed.fragment); +// +// where "+" denotes concatenation. +// +// seq_num +// The sequence number for this record. +// +// MAC +// The MAC algorithm specified by SecurityParameters.mac_algorithm. +// +// Note that the MAC is computed before encryption. The stream cipher +// encrypts the entire block, including the MAC. +//... +// Appendix C. Cipher Suite Definitions +//... +// Key IV Block +// Cipher Type Material Size Size +// ------------ ------ -------- ---- ----- +// NULL Stream 0 0 N/A +// RC4_128 Stream 16 0 N/A +// 3DES_EDE_CBC Block 24 8 8 +// AES_128_CBC Block 16 16 16 +// AES_256_CBC Block 32 16 16 +// +// MAC Algorithm mac_length mac_key_length +// -------- ----------- ---------- -------------- +// NULL N/A 0 0 +// MD5 HMAC-MD5 16 16 +// SHA HMAC-SHA1 20 20 +// SHA256 HMAC-SHA256 32 32 + + uint8_t mac_hash[SHA256_OUTSIZE]; + struct record_hdr *xhdr = buf; + + if (tls->encrypt_on_write) { + hmac_sha256(mac_hash, + tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), + &tls->write_seq64_be, sizeof(tls->write_seq64_be), + buf, size, + NULL); + tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + xhdr->len16_lo += SHA256_OUTSIZE; +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME + } + xwrite(tls->fd, buf, size); - /* hash does not include record headers */ - if (size > 5) + if (tls->encrypt_on_write) { + xwrite(tls->fd, mac_hash, sizeof(mac_hash)); + xhdr->len16_lo -= SHA256_OUTSIZE; + } + + /* Handshake hash does not include record headers */ + if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) sha256_hash(&tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); } @@ -311,22 +401,23 @@ static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) len = der[1]; /* maybe it's short len */ if (len >= 0x80) { - /* no */ - if (end - der < (int)(len - 0x7e)) /* need 3 or 4 bytes for 81, 82 */ - xfunc_die(); + /* no, it's long */ - len1 = der[2]; - if (len == 0x81) { - /* it's "ii 81 xx" */ - } else if (len == 0x82) { - /* it's "ii 82 xx yy" */ - len1 = 0x100*len1 + der[3]; - der += 1; /* skip [yy] */ - } else { + if (len == 0x80 || end - der < (int)(len - 0x7e)) { /* 0x80 is "0 bytes of len", invalid DER: must use short len if can */ + /* need 3 or 4 bytes for 81, 82 */ + xfunc_die(); + } + + len1 = der[2]; /* if (len == 0x81) it's "ii 81 xx", fetch xx */ + if (len > 0x82) { /* >0x82 is "3+ bytes of len", should not happen realistically */ xfunc_die(); } + if (len == 0x82) { /* it's "ii 82 xx yy" */ + len1 = 0x100*len1 + der[3]; + der += 1; /* skip [yy] */ + } der += 1; /* skip [xx] */ len = len1; // if (len < 0x80) @@ -508,11 +599,6 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } -enum { - SHA256_INSIZE = 64, - SHA256_OUTSIZE = 32, -}; - static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned size) { sha256_ctx_t ctx; @@ -734,6 +820,7 @@ static void get_server_hello(tls_state_t *tls) /* extensions may follow, but only those which client offered in its Hello */ }; struct server_hello *hp; + uint8_t *cipherid; xread_tls_handshake_block(tls, 74); @@ -744,16 +831,34 @@ static void get_server_hello(tls_state_t *tls) if (hp->type != HANDSHAKE_SERVER_HELLO || hp->len24_hi != 0 || hp->len24_mid != 0 - || hp->len24_lo != 70 + /* hp->len24_lo checked later */ || hp->proto_maj != TLS_MAJ || hp->proto_min != TLS_MIN - || hp->session_id_len != 32 - || hp->cipherid_hi != (CIPHER_ID >> 8) - || hp->cipherid_lo != (CIPHER_ID & 0xff) - || hp->comprtype != 0 ) { tls_error_die(tls); } + + cipherid = &hp->cipherid_hi; + if (hp->session_id_len != 32) { + if (hp->session_id_len != 0) + tls_error_die(tls); + + // session_id_len == 0: no session id + // "The server + // may return an empty session_id to indicate that the session will + // not be cached and therefore cannot be resumed." + cipherid -= 32; + hp->len24_lo += 32; /* what len would be if session id would be present */ + } + + if (hp->len24_lo < 70 + || cipherid[0] != (CIPHER_ID >> 8) + || cipherid[1] != (CIPHER_ID & 0xff) + || cipherid[2] != 0 /* comprtype */ + ) { + tls_error_die(tls); + } + dbg("got SERVER_HELLO\n"); memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); } @@ -844,11 +949,59 @@ static void send_client_key_exchange(tls_state_t *tls) // [0..47]; // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. - tls_prf_hmac_sha256(tls->master_secret, sizeof(tls->master_secret), + tls_prf_hmac_sha256( + tls->master_secret, sizeof(tls->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) ); + +// RFC 5246 +// 6.3. Key Calculation +// +// The Record Protocol requires an algorithm to generate keys required +// by the current connection state (see Appendix A.6) from the security +// parameters provided by the handshake protocol. +// +// The master secret is expanded into a sequence of secure bytes, which +// is then split to a client write MAC key, a server write MAC key, a +// client write encryption key, and a server write encryption key. Each +// of these is generated from the byte sequence in that order. Unused +// values are empty. Some AEAD ciphers may additionally require a +// client write IV and a server write IV (see Section 6.2.3.3). +// +// When keys and MAC keys are generated, the master secret is used as an +// entropy source. +// +// To generate the key material, compute +// +// key_block = PRF(SecurityParameters.master_secret, +// "key expansion", +// SecurityParameters.server_random + +// SecurityParameters.client_random); +// +// until enough output has been generated. Then, the key_block is +// partitioned as follows: +// +// client_write_MAC_key[SecurityParameters.mac_key_length] +// server_write_MAC_key[SecurityParameters.mac_key_length] +// client_write_key[SecurityParameters.enc_key_length] +// server_write_key[SecurityParameters.enc_key_length] +// client_write_IV[SecurityParameters.fixed_iv_length] +// server_write_IV[SecurityParameters.fixed_iv_length] + { + uint8_t tmp64[64]; + /* make server_rand32 + client_rand32 */ + memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); + memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); + + tls_prf_hmac_sha256( + tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), + tls->master_secret, sizeof(tls->master_secret), + "key expansion", + tmp64, 64 + ); + } } static void send_change_cipher_spec(tls_state_t *tls) @@ -859,6 +1012,9 @@ static void send_change_cipher_spec(tls_state_t *tls) }; /* Not "xwrite_and_hash": this is not a handshake message */ xwrite(tls->fd, rec, sizeof(rec)); + + tls->write_seq64_be = 0; + tls->encrypt_on_write = 1; } static void send_client_finished(tls_state_t *tls) @@ -932,7 +1088,38 @@ static void send_client_finished(tls_state_t *tls) //(1) TODO: well, this should be encrypted on send, really. //(2) do we really need to also hash it? + xwrite_and_hash(tls, &record, sizeof(record)); + +//s_client does this: +// +//write to 0x1d750b0 [0x1e74620] (6 bytes => 6 (0x6)) +//0000 - 14 03 03 00 01 01 ...... >> CHANGE_CIPHER_SPEC +// +//write to 0x1d750b0 [0x1e74620] (53 bytes => 53 (0x35)) +//0000 - 16 03 03 0030 14 00000c [ed b9 e1 33 36 0b 76 ....0.......36.v >> FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] +//0010 - c0 d1 d4 0b a3|73 ec a8-fa b5 cb 12 b6 4c 2a b1 .....s.......L*. +//0020 - fb 42 7f 73 0d 06 1c 87-56 f0 db df e6 6a 25 aa .B.s....V....j%. +//0030 - fc 42 38 cb 0b] .B8.. + +//we do this (as seen by s_server): +// +//read from 0x26b7650 [0x26ac383] (5 bytes => 5 (0x5)) +//0000 - 14 03 03 00 01 ..... +//read from 0x26b7650 [0x26ac388] (1 bytes => 1 (0x1)) +//0000 - 01 . << CHANGE_CIPHER_SPEC +//read from 0x26b7650 [0x26ac383] (5 bytes => 5 (0x5)) +//0000 - 16 03 03 0030 ....0 +//read from 0x26b7650 [0x26ac388] (48 bytes => 48 (0x30)) +//0000 - 14 00000c [d1 6f 08 c3-ef ec 26 7c 17 76 ac 1c| .....o....&|.v.. << FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] +//0010 - 0b 27 ae 1c 59 f8 cb af-de 25 25 7e 50 51 da dd .'..Y....%%~PQ.. +//0020 - c2 9e d6 27 96 0b 72 05-63 54 89 00 0e d7 b1 10] ...'..r.cT...... +// +//write to 0x26b7650 [0x26b4d90] (7 bytes => 7 (0x7)) +//0000 - 15 03 03 00 02 02 33 ......3 +//ERROR +//140684206577528:error:1408C095:SSL routines:ssl3_get_finished:digest check failed:s3_both.c:273: +//140684206577528:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:656: } static void get_change_cipher_spec(tls_state_t *tls) @@ -1043,3 +1230,270 @@ int tls_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } + +//TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise + +/* Unencryped SHA256 example: + * $ openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' + * $ openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL + * $ openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 + * s_client says: + +write to 0x1d750b0 [0x1e6f153] (99 bytes => 99 (0x63)) +0000 - 16 03 01 005e 01 00005a 0303 [4d ef 5c 82 3e ....^...Z..M.\.> >> ClHello +0010 - bf a6 ee f1 1e 04 d1 5c-99 20 86 13 e9 0a cf 58 .......\. .....X +0020 - 75 b1 bd 7a e6 d6 44 f3-d3 a1 52] 00 0004 003b u..z..D...R....; 003b = TLS_RSA_WITH_NULL_SHA256 +0030 - 00ff TLS_EMPTY_RENEGOTIATION_INFO_SCSV + 0100 compr=none + 002d, 0023 0000, 000d 0020 [00 1e .....-.#..... .. extlen, SessionTicketTLS 0 bytes, SignatureAlgorithms 32 bytes +0040 - 06 01 06 02 06 03 05 01-05 02 05 03 04 01 04 02 ................ +0050 - 04 03 03 01 03 02 03 03-02 01 02 02 02 03] 000f ................ Heart Beat 1 byte +0060 - 0001 01 ... + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 16 03 03 00 3a ....: +read from 0x1d750b0 [0x1e6ac08] (58 bytes => 58 (0x3A)) +0000 - 02 000036 0303 [f2 61-ae c8 58 e3 51 42 32 93 ...6...a..X.QB2. << SvHello +0010 - c5 62 e4 f5 06 93 81 65-aa f7 df 74 af 7c 98 b4 .b.....e...t.|.. +0020 - 3e a7 35 c3 25 69] 00,003b,00.................. >.5.%i..;....... - no session id! "The server + may return an empty session_id to indicate that the session will + not be cached and therefore cannot be resumed." + 003b = TLS_RSA_WITH_NULL_SHA256 accepted, 00 - no compr + 000e ff01 0001 extlen, 0xff01=RenegotiationInfo 1 byte +0030 - 00, 0023 0000, SessionTicketTLS 0 bytes + 000f 0001 01 ..#....... Heart Beat 1 byte + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 16 03 03 04 0b ..... +read from 0x1d750b0 [0x1e6ac08] (1035 bytes => 1035 (0x40B)) +0000 - 0b 00 04 07 00 04 04 00-04 01 30 82 03 fd 30 82 ..........0...0. << Cert +0010 - 02 65 a0 03 02 01 02 02-09 00 d9 d9 8d b8 94 ad .e.............. +0020 - 2e 2b 30 0d 06 09 2a 86-48 86 f7 0d 01 01 0b 05 .+0...*.H....... +0030 - 00 30 14 31 12 30 10 06-03 55 04 03 0c 09 6c 6f .0.1.0...U....lo +0040 - 63 61 6c 68 6f 73 74 30-20 17 0d 31 37 30 31 31 calhost0 ..17011 +0050 - 36 30 33 30 39 34 36 5a-18 0f 32 32 39 30 31 30 6030946Z..229010 +0060 - 33 31 30 33 30 39 34 36-5a 30 14 31 12 30 10 06 31030946Z0.1.0.. +0070 - 03 55 04 03 0c 09 6c 6f-63 61 6c 68 6f 73 74 30 .U....localhost0 +0080 - 82 01 a2 30 0d 06 09 2a-86 48 86 f7 0d 01 01 01 ...0...*.H...... +0090 - 05 00 03 82 01 8f 00 30-82 01 8a 02 82 01 81 00 .......0........ +00a0 - f5 a8 66 54 af fd 33 9e-fb 1d 2d d7 33 ff b9 99 ..fT..3...-.3... +00b0 - 21 16 8a 65 75 1c 39 9d-0a c3 fc 8c 6d 63 de 7b !..eu.9.....mc.{ +00c0 - d8 1e d8 20 a1 a9 d5 ab-2a 8e d1 4f b8 9a f4 f7 ... ....*..O.... +00d0 - 91 0d db 70 a8 59 d3 0d-8f 6f bb 51 a4 5c f1 c1 ...p.Y...o.Q.\.. +00e0 - ce 1e b5 58 3a 46 1b 2a-1f 7c 75 87 b4 9f ed d3 ...X:F.*.|u..... +00f0 - 3d 9a cf a4 5b 96 5b 25-cf f5 33 1c c8 7a 8a 37 =...[.[%..3..z.7 +0100 - 69 2f 63 8c f9 a4 a5 40-06 c9 63 cf fd 35 5d d3 i/c....@..c..5]. +0110 - 8e e3 17 2f 8a ab 5e fd-6c 7e 5b 03 bb b6 3c e3 .../..^.l~[...<. +0120 - 32 01 99 72 45 a7 a3 c3-11 d8 6c dc 50 a6 75 01 2..rE.....l.P.u. +0130 - a2 81 85 56 5e be eb 8c-ad 44 05 cf 47 e0 3e 8b ...V^....D..G.>. +0140 - cd 6e 08 11 ee 5e 94 39-5d 8c a2 e3 b0 03 7f c2 .n...^.9]....... +0150 - f8 99 35 0b d1 c2 3c 37-49 a8 bb 70 8e e2 a6 c8 ..5...<7I..p.... +0160 - 5b 7d f5 d1 dc 6e ef fb-83 f7 4c ef 8c 85 e3 b9 [}...n....L..... +0170 - fd 51 18 70 7e a5 03 b7-6d e5 c6 c2 d1 4d e2 16 .Q.p~...m....M.. +0180 - 42 c8 21 25 2a 27 af c4-4a c2 f0 b6 2f 72 46 33 B.!%*'..J.../rF3 +0190 - b1 89 d8 95 7a 9d 52 db-75 ae f4 a0 97 32 8c 5f ....z.R.u....2._ +01a0 - 97 e7 5d 12 15 3f 85 8f-d1 9c ca a0 fd 59 cd c5 ..]..?.......Y.. +01b0 - 25 70 d3 97 62 04 af cb-19 1b 6e 24 c9 82 b8 25 %p..b.....n$...% +01c0 - c3 5c bd d7 ee 08 17 6f-ea 99 24 2f c7 05 a8 40 .\.....o..$/...@ +01d0 - 24 d5 74 7b 5b 65 c5 ec-97 63 de d1 46 d2 c4 09 $.t{[e...c..F... +01e0 - c2 22 23 99 ce 13 03 6f-b4 08 7f 3e 00 c6 fe 91 ."#....o...>.... +01f0 - bc c8 ba b2 32 c2 42 9d-89 de 04 d0 36 27 9e 8c ....2.B.....6'.. +0200 - ad 79 3e d6 84 38 db cd-57 ad 68 05 85 0b 13 59 .y>..8..W.h....Y +0210 - 11 5a 2b a4 d0 5f c3 ee-1a 02 69 d4 c5 bf 19 b5 .Z+.._....i..... +0220 - 02 03 01 00 01 a3 50 30-4e 30 1d 06 03 55 1d 0e ......P0N0...U.. +0230 - 04 16 04 14 08 87 29 ce-04 09 7f 11 33 80 ba 30 ......).....3..0 +0240 - b2 77 84 b4 73 6e 82 94-30 1f 06 03 55 1d 23 04 .w..sn..0...U.#. +0250 - 18 30 16 80 14 08 87 29-ce 04 09 7f 11 33 80 ba .0.....).....3.. +0260 - 30 b2 77 84 b4 73 6e 82-94 30 0c 06 03 55 1d 13 0.w..sn..0...U.. +0270 - 04 05 30 03 01 01 ff 30-0d 06 09 2a 86 48 86 f7 ..0....0...*.H.. +0280 - 0d 01 01 0b 05 00 03 82-01 81 00 22 c4 a8 6f 0a ..........."..o. +0290 - 40 a0 c4 92 ae 83 86 9c-42 f8 0a a8 c7 72 d2 5d @.......B....r.] +02a0 - de 78 f2 5a 38 e0 e6 0b-3c df af dd 6c 44 a9 0a .x.Z8...<...lD.. +02b0 - 81 f3 0e 49 e5 07 da 40-0f 85 73 db d6 86 87 6a ...I...@..s....j +02c0 - b9 29 75 6a a9 dd fc 16-81 dc eb 25 3a c7 dc 3f .)uj.......%:..? +02d0 - c8 a3 2d bb 49 3e 08 72-e9 03 e6 2f ee 1e 17 9a ..-.I>.r.../.... +02e0 - 9c f6 fd 3c 73 cf e4 2c-5d f1 a8 1c 93 f7 1d f7 ......I<.%B'.{8.. +0390 - 3a 87 6f db 79 7a 54 c1-a3 6a 54 01 17 92 04 24 :.o.yzT..jT....$ +03a0 - 6c 66 1d 47 45 4e 3a af-fe 45 1d 2c 23 81 f6 cc lf.GEN:..E.,#... +03b0 - e1 0d 89 81 90 b6 3b 7d-49 8d 0f d5 d8 f6 d8 0c ......;}I....... +03c0 - 7e 47 1e fb b7 a0 7a 66-7a 1e f2 ba 4e 28 ed 36 ~G....zfz...N(.6 +03d0 - 6b b6 2b e5 9c 57 0e ba-df 44 1b 4d 5e a2 9e 3f k.+..W...D.M^..? +03e0 - 29 18 b6 7c 26 ea 6a d5-0d f1 e9 42 fa 08 0d 44 )..|&.j....B...D +03f0 - 11 8a cd c5 a3 0a 22 43-d5 13 f9 a5 8a 06 f9 00 ......"C........ +0400 - 3c f7 86 4e e8 a5 d8 5b-92 37 f5 <..N...[.7. +depth=0 CN = localhost +verify error:num=18:self signed certificate +verify return:1 +depth=0 CN = localhost +verify return:1 + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 16 03 03 00 04 ..... + +read from 0x1d750b0 [0x1e6ac08] (4 bytes => 4 (0x4)) << SvDone +0000 - 0e . +0004 - + +write to 0x1d750b0 [0x1e74620] (395 bytes => 395 (0x18B)) >> ClDone +0000 - 16 03 03 01 86 10 00 01-82 01 80 88 f0 87 5d b0 ..............]. +0010 - ea df 3b 4d e2 35 f3 99-e6 d4 29 87 36 86 ea 30 ..;M.5....).6..0 +0020 - 38 80 c7 37 66 7f 5b e7-23 38 7e 87 24 66 82 81 8..7f.[.#8~.$f.. +0030 - e4 ba 6c 2a 0c 92 a8 b9-39 c1 55 16 32 88 14 cd ..l*....9.U.2... +0040 - 95 8c 82 49 a1 c7 f9 9b-e5 8f f6 5e 7e ee 91 b3 ...I.......^~... +0050 - 2c 92 e7 a3 02 f8 9f 56-04 45 39 df a7 d6 1a 16 ,......V.E9..... +0060 - 67 5c a4 f8 87 8a c4 c8-6c 6f c6 f0 9b c9 b4 87 g\......lo...... +0070 - 36 43 c1 67 9f b3 aa 11-34 b0 c2 fc 1f d9 e1 ff 6C.g....4....... +0080 - fb e1 89 db 91 58 ec cc-aa 16 19 9a 91 74 e2 46 .....X.......t.F +0090 - 22 a7 a7 f7 9e 3c 97 82-2c e4 21 b3 fa ef ba 3f "....<..,.!....? +00a0 - 57 48 e4 b2 84 b7 c2 81-92 a9 f1 03 68 f4 e6 0c WH..........h... +00b0 - fd 54 87 f5 e9 a0 5d e6-5f 0e bd 80 86 27 ab 0e .T....]._....'.. +00c0 - cf 92 4f bd fc 24 b9 54-72 5f 58 df 6b 2b 1d 97 ..O..$.Tr_X.k+.. +00d0 - 00 60 fe 95 b0 aa d6 c7-c1 3a f9 2e 7c 92 a9 6d .`.......:..|..m +00e0 - 28 a3 ef 3e c1 e6 2d 2d-e8 db 81 ea 51 02 3f 64 (..>..--....Q.?d +00f0 - a8 66 14 c1 4b 17 1f 55-c6 5b 3b 38 c3 6a 61 a8 .f..K..U.[;8.ja. +0100 - f7 ad 65 7d cb 14 6d b3-0f 76 19 25 8e ed bd 53 ..e}..m..v.%...S +0110 - 35 a9 a1 34 00 9d 07 81-84 51 35 e0 83 83 e3 a6 5..4.....Q5..... +0120 - c7 77 4c 61 e4 78 9c cb-f5 92 4e d6 dd c4 c2 2b .wLa.x....N....+ +0130 - 75 9e 72 a6 7f 81 6a 1c-fc 4a 51 91 81 b4 cc 33 u.r...j..JQ....3 +0140 - 1c 8b 0a b6 94 8b 16 1b-86 2f 31 5e 31 e1 57 14 ........./1^1.W. +0150 - 2e b5 09 5d cf 6f ea b2-94 e9 5c cc b9 fc 24 a0 ...].o....\...$. +0160 - b7 f1 f4 9d 95 46 4f 08-5c 45 c6 2f 9f 7d 76 09 .....FO.\E./.}v. +0170 - 6a af 50 2c 89 76 82 5f-e8 34 d8 4b 84 b6 34 18 j.P,.v._.4.K..4. +0180 - 85 95 4a 3f 0f 28 88 3a-71 32 90 ..J?.(.:q2. + +write to 0x1d750b0 [0x1e74620] (6 bytes => 6 (0x6)) +0000 - 14 03 03 00 01 01 ...... >> CHANGE_CIPHER_SPEC + +write to 0x1d750b0 [0x1e74620] (53 bytes => 53 (0x35)) +0000 - 16 03 03 0030 14 00000c [ed b9 e1 33 36 0b 76 ....0.......36.v >> FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] +0010 - c0 d1 d4 0b a3|73 ec a8-fa b5 cb 12 b6 4c 2a b1 .....s.......L*. +0020 - fb 42 7f 73 0d 06 1c 87-56 f0 db df e6 6a 25 aa .B.s....V....j%. +0030 - fc 42 38 cb 0b] .B8.. + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 16 03 03 00 aa ..... +read from 0x1d750b0 [0x1e6ac08] (170 bytes => 170 (0xAA)) +0000 - 04 00 00 a6 00 00 1c 20-00 a0 dd f4 52 01 54 8d ....... ....R.T. << NEW_SESSION_TICKET +0010 - f8 a6 f9 2d 7d 19 20 5b-14 44 d3 2d 7b f2 ca e8 ...-}. [.D.-{... +0020 - 01 4e 94 7b fe 12 59 3a-00 2e 7e cf 74 43 7a f7 .N.{..Y:..~.tCz. +0030 - 9e cc 70 80 70 7c e3 a5-c6 9d 85 2c 36 19 4c 5c ..p.p|.....,6.L\ +0040 - ba 3b c3 e5 69 dc f3 a4-47 38 11 c9 7d 1a b0 6e .;..i...G8..}..n +0050 - d8 49 a0 a8 e4 de 70 a8-d0 6b e4 7a b7 65 25 df .I....p..k.z.e%. +0060 - 1b 5f 64 0f 89 69 02 72-fe eb d3 7a af 51 78 0e ._d..i.r...z.Qx. +0070 - de 17 06 a5 f0 47 9d e0-04 d4 b1 1e be 7e ed bd .....G.......~.. +0080 - 27 8f 5d e8 ac f6 45 aa-e0 12 93 41 5f a8 4b b9 '.]...E....A_.K. +0090 - bd 43 8f a1 23 51 af 92-77 8f 38 23 3e 2e c2 f0 .C..#Q..w.8#>... +00a0 - a3 74 fa 83 94 ce 19 8a-5b 5b .t......[[ + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 14 03 03 00 01 ..... << CHANGE_CIPHER_SPEC +read from 0x1d750b0 [0x1e6ac08] (1 bytes => 1 (0x1)) +0000 - 01 . + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 16 03 03 00 30 ....0 +read from 0x1d750b0 [0x1e6ac08] (48 bytes => 48 (0x30)) +0000 - 14 00000c [06 86 0d 5c-92 0b 63 04 cc b4 f0 00 .......\..c..... << FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] +0010 -|49 d6 dd 56 73 e3 d2 e8-22 d6 bd 61 b2 b3 af f0 I..Vs..."..a.... +0020 - f5 00 8a 80 82 04 33 a7-50 8e ae 3b 4c 8c cf 4a] ......3.P..;L..J +--- +Certificate chain + 0 s:/CN=localhost + i:/CN=localhost +--- +Server certificate +-----BEGIN CERTIFICATE----- +MIID/TCCAmWgAwIBAgIJANnZjbiUrS4rMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAgFw0xNzAxMTYwMzA5NDZaGA8yMjkwMTAzMTAzMDk0Nlow +FDESMBAGA1UEAwwJbG9jYWxob3N0MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB +igKCAYEA9ahmVK/9M577HS3XM/+5mSEWimV1HDmdCsP8jG1j3nvYHtggoanVqyqO +0U+4mvT3kQ3bcKhZ0w2Pb7tRpFzxwc4etVg6RhsqH3x1h7Sf7dM9ms+kW5ZbJc/1 +MxzIeoo3aS9jjPmkpUAGyWPP/TVd047jFy+Kq179bH5bA7u2POMyAZlyRaejwxHY +bNxQpnUBooGFVl6+64ytRAXPR+A+i81uCBHuXpQ5XYyi47ADf8L4mTUL0cI8N0mo +u3CO4qbIW3310dxu7/uD90zvjIXjuf1RGHB+pQO3beXGwtFN4hZCyCElKievxErC +8LYvckYzsYnYlXqdUtt1rvSglzKMX5fnXRIVP4WP0ZzKoP1ZzcUlcNOXYgSvyxkb +biTJgrglw1y91+4IF2/qmSQvxwWoQCTVdHtbZcXsl2Pe0UbSxAnCIiOZzhMDb7QI +fz4Axv6RvMi6sjLCQp2J3gTQNieejK15PtaEONvNV61oBYULE1kRWiuk0F/D7hoC +adTFvxm1AgMBAAGjUDBOMB0GA1UdDgQWBBQIhynOBAl/ETOAujCyd4S0c26ClDAf +BgNVHSMEGDAWgBQIhynOBAl/ETOAujCyd4S0c26ClDAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBCwUAA4IBgQAixKhvCkCgxJKug4acQvgKqMdy0l3eePJaOODmCzzf +r91sRKkKgfMOSeUH2kAPhXPb1oaHarkpdWqp3fwWgdzrJTrH3D/Ioy27ST4IcukD +5i/uHheanPb9PHPP5Cxd8agck/cd966ylr+6vdBdP07TVF6BR3KhNTnb+qdUlvQf +5V7IgPgfc+UJFK7lSsLzclzYUm7Y0uneSBRW/DLOaaNooen1eOithKjDRRo6fVTb +486EnrHXYI6y5xWEjqUPxFPkuXHnRpP3rwC9PTaaTo/r4RgGVElKeZ89253W51e3 +dd0mrLeGGfD5tl41NqRap7AziJ5/yfM+zALOSTwOJUInv3s429g6h2/beXpUwaNq +VAEXkgQkbGYdR0VOOq/+RR0sI4H2zOENiYGQtjt9SY0P1dj22Ax+Rx77t6B6Znoe +8rpOKO02a7Yr5ZxXDrrfRBtNXqKePykYtnwm6mrVDfHpQvoIDUQRis3FowoiQ9UT ++aWKBvkAPPeGTuil2FuSN/U= +-----END CERTIFICATE----- +subject=/CN=localhost +issuer=/CN=localhost +--- +No client certificate CA names sent +--- +SSL handshake has read 1346 bytes and written 553 bytes +--- +New, TLSv1/SSLv3, Cipher is NULL-SHA256 +Server public key is 3072 bit +Secure Renegotiation IS supported +Compression: NONE +Expansion: NONE +No ALPN negotiated +SSL-Session: + Protocol : TLSv1.2 + Cipher : NULL-SHA256 + Session-ID: 5D62B36950F3DEB571707CD1B815E9E275041B9DB70D7F3E25C4A6535B13B616 + Session-ID-ctx: + Master-Key: 4D08108C59417E0A41656636C51BA5B83F4EFFF9F4C860987B47B31250E5D1816D00940DBCCC196C2D99C8462C889DF1 + Key-Arg : None + Krb5 Principal: None + PSK identity: None + PSK identity hint: None + TLS session ticket lifetime hint: 7200 (seconds) + TLS session ticket: + 0000 - dd f4 52 01 54 8d f8 a6-f9 2d 7d 19 20 5b 14 44 ..R.T....-}. [.D + 0010 - d3 2d 7b f2 ca e8 01 4e-94 7b fe 12 59 3a 00 2e .-{....N.{..Y:.. + 0020 - 7e cf 74 43 7a f7 9e cc-70 80 70 7c e3 a5 c6 9d ~.tCz...p.p|.... + 0030 - 85 2c 36 19 4c 5c ba 3b-c3 e5 69 dc f3 a4 47 38 .,6.L\.;..i...G8 + 0040 - 11 c9 7d 1a b0 6e d8 49-a0 a8 e4 de 70 a8 d0 6b ..}..n.I....p..k + 0050 - e4 7a b7 65 25 df 1b 5f-64 0f 89 69 02 72 fe eb .z.e%.._d..i.r.. + 0060 - d3 7a af 51 78 0e de 17-06 a5 f0 47 9d e0 04 d4 .z.Qx......G.... + 0070 - b1 1e be 7e ed bd 27 8f-5d e8 ac f6 45 aa e0 12 ...~..'.]...E... + 0080 - 93 41 5f a8 4b b9 bd 43-8f a1 23 51 af 92 77 8f .A_.K..C..#Q..w. + 0090 - 38 23 3e 2e c2 f0 a3 74-fa 83 94 ce 19 8a 5b 5b 8#>....t......[[ + + Start Time: 1484574330 + Timeout : 7200 (sec) + Verify return code: 18 (self signed certificate) +--- +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 17 03 03 00 21 ....! +read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) +0000 - 0a 74 5b 50 02 13 75 a4-27 0a 40 b1 53 74 52 14 .t[P..u.'.@.StR. +0010 - e7 1e 6a 6c c1 60 2e 93-7e a5 d9 43 1d 8e f6 08 ..jl.`..~..C.... +0020 - 69 i + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 17 03 03 00 21 ....! +read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) +0000 - 0a 1b ce 44 98 4f 81 c5-28 7a cc 79 62 db d2 86 ...D.O..(z.yb... +0010 - 6a 55 a4 c7 73 49 ef 3e-bd 03 99 76 df 65 2a a1 jU..sI.>...v.e*. +0020 - b6 . + +read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) +0000 - 17 03 03 00 21 ....! +read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) +0000 - 0a 67 66 34 ba 68 36 3c-ad 0a c1 f5 c0 5a 50 fe .gf4.h6<.....ZP. +0010 - 68 cd 04 65 e9 de 6e 98-f9 e2 41 1e 0b 9b 84 06 h..e..n...A..... +0020 - 64 d +*/ -- cgit v1.2.3-55-g6feb From e2cb3b990f9c832d69691f2a869df8c9ac73d46a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jan 2017 16:53:36 +0100 Subject: tls: make our send_client_finished() pass server check sha256 hash should be calculated over incoming handshake packets too! Signed-off-by: Denys Vlasenko --- networking/tls.c | 420 ++++++++++++++++++++++++------------------------------- 1 file changed, 180 insertions(+), 240 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 562874aa6..60afd30b4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -25,7 +25,9 @@ #include "tls.h" -#if 1 +#define TLS_DEBUG 2 + +#if TLS_DEBUG # define dbg(...) fprintf(stderr, __VA_ARGS__) #else # define dbg(...) ((void)0) @@ -201,12 +203,87 @@ typedef struct tls_state { uint8_t inbuf[18*1024]; } tls_state_t; + +static unsigned get24be(const uint8_t *p) +{ + return 0x100*(0x100*p[0] + p[1]) + p[2]; +} + +#if TLS_DEBUG +static void dump_hex(const char *fmt, const void *vp, int len) +{ + char hexbuf[32 * 1024 + 4]; + const uint8_t *p = vp; + + bin2hex(hexbuf, (void*)p, len)[0] = '\0'; + dbg(fmt, hexbuf); +} + +static void dump_tls_record(const void *vp, int len) +{ + const uint8_t *p = vp; + + while (len > 0) { + unsigned xhdr_len; + if (len < 5) { + dump_hex("< |%s|\n", p, len); + return; + } + xhdr_len = 0x100*p[3] + p[4]; + dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len); + p += 5; + len -= 5; + if (len >= 4 && p[-5] == RECORD_TYPE_HANDSHAKE) { + unsigned len24 = get24be(p + 1); + dbg(" type:%u len24:%u", p[0], len24); + } + if (xhdr_len > len) + xhdr_len = len; + dump_hex(" |%s|\n", p, xhdr_len); + p += xhdr_len; + len -= xhdr_len; + } +} +#endif + void tls_get_random(void *buf, unsigned len) { if (len != open_read_close("/dev/urandom", buf, len)) xfunc_die(); } +//TODO rename this to sha256_hash, and sha256_hash -> sha256_update +static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned size) +{ + sha256_ctx_t ctx; + sha256_begin(&ctx); + sha256_hash(&ctx, data, size); + sha256_end(&ctx, out); +} + +#if TLS_DEBUG >= 2 +/* Nondestructively see the current hash value */ +static void sha256_peek(sha256_ctx_t *ctx, void *buffer) +{ + sha256_ctx_t ctx_copy = *ctx; + sha256_end(&ctx_copy, buffer); +} + +static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) +{ + uint8_t h[SHA256_OUTSIZE]; + + sha256_hash(ctx, buffer, len); + dump_hex(fmt, buffer, len); + dbg(" (%u) ", (int)len); + sha256_peek(ctx, h); + dump_hex("%s\n", h, SHA256_OUTSIZE); +} +#else +# define sha256_hash_dbg(fmt, ctx, buffer, len) \ + sha256_hash(ctx, buffer, len) +#endif /* not TLS_DEBUG >= 2 */ + static tls_state_t *new_tls_state(void) { @@ -284,53 +361,22 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size } xwrite(tls->fd, buf, size); + dbg("wrote %u bytes\n", size); if (tls->encrypt_on_write) { xwrite(tls->fd, mac_hash, sizeof(mac_hash)); + dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); xhdr->len16_lo -= SHA256_OUTSIZE; } /* Handshake hash does not include record headers */ - if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) - sha256_hash(&tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); -} - -static unsigned get24be(const uint8_t *p) -{ - return 0x100*(0x100*p[0] + p[1]) + p[2]; -} - -static void dump(const void *vp, int len) -{ - char hexbuf[32 * 1024 + 4]; - const uint8_t *p = vp; - - while (len > 0) { - unsigned xhdr_len; - if (len < 5) { - bin2hex(hexbuf, (void*)p, len)[0] = '\0'; - dbg("< |%s|\n", hexbuf); - return; - } - xhdr_len = 0x100*p[3] + p[4]; - dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len); - p += 5; - len -= 5; - if (len >= 4 && p[-5] == RECORD_TYPE_HANDSHAKE) { - unsigned len24 = get24be(p + 1); - dbg(" type:%u len24:%u", p[0], len24); - } - if (xhdr_len > len) - xhdr_len = len; - bin2hex(hexbuf, (void*)p, xhdr_len)[0] = '\0'; - dbg(" |%s|\n", hexbuf); - p += xhdr_len; - len -= xhdr_len; + if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { + sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); } } static void tls_error_die(tls_state_t *tls) { - dump(tls->inbuf, tls->insize + tls->tail); + dump_tls_record(tls->inbuf, tls->insize + tls->tail); xfunc_die(); } @@ -369,6 +415,14 @@ static int xread_tls_block(tls_state_t *tls) tls->tail = total - target; tls->insize = target; target -= sizeof(*xhdr); + + /* RFC 5246 is not saying it explicitly, but sha256 hash + * in our FINISHED packet must include hashes of incoming packets too! + */ + if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { + sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target); + } + dbg("got block len:%u\n", target); return target; } @@ -591,7 +645,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) xfunc_die(); der++; der = enter_der_item(der, &end); /* enter SEQ */ - //memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); + /* memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); - already is */ der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ der = skip_der_item(der, end); der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ @@ -599,14 +653,6 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } -static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned size) -{ - sha256_ctx_t ctx; - sha256_begin(&ctx); - sha256_hash(&ctx, data, size); - sha256_end(&ctx, out); -} - // RFC 2104: HMAC(key, text) based on a hash H (say, sha256) is: // ipad = [0x36 x INSIZE] // opad = [0x5c x INSIZE] @@ -722,6 +768,7 @@ static void tls_prf_hmac_sha256( /* A(1) = HMAC_hash(secret, seed) */ hmac_sha256(a, SECRET, SEED, NULL); +//TODO: convert hmac_sha256 to precomputed for(;;) { /* HMAC_hash(secret, A(1) + seed) */ @@ -785,24 +832,10 @@ static void send_client_hello(tls_state_t *tls) hello.comprtypes_len = 1; //hello.comprtypes[0] = 0; + //dbg (make it repeatable): memset(hello.rand32, 0x11, sizeof(hello.rand32)); + dbg(">> HANDSHAKE_CLIENT_HELLO\n"); xwrite_and_hash(tls, &hello, sizeof(hello)); memcpy(tls->client_and_server_rand32, hello.rand32, sizeof(hello.rand32)); - -#if 0 /* dump */ - for (;;) { - uint8_t buf[16*1024]; - sleep(2); - len = recv(tls->fd, buf, sizeof(buf), 0); //MSG_DONTWAIT); - if (len < 0) { - if (errno == EAGAIN) - continue; - bb_perror_msg_and_die("recv"); - } - if (len == 0) - break; - dump(buf, len); - } -#endif } static void get_server_hello(tls_state_t *tls) @@ -905,23 +938,17 @@ static void send_client_key_exchange(tls_state_t *tls) //openssl: //write to 0xe9a090 [0xf9ac20] (395 bytes => 395 (0x18B)) //0000 - 16 03 03 01 86 10 00 01 -82 01 80 xx xx xx xx xx - uint8_t key[384]; // size?? + uint8_t key[4 * 1024]; // size?? }; struct client_key_exchange record; uint8_t rsa_premaster[SSL_HS_RSA_PREMASTER_SIZE]; + int len; memset(&record, 0, sizeof(record)); record.xhdr.type = RECORD_TYPE_HANDSHAKE; record.xhdr.proto_maj = TLS_MAJ; record.xhdr.proto_min = TLS_MIN; - record.xhdr.len16_hi = (sizeof(record) - sizeof(record.xhdr)) >> 8; - record.xhdr.len16_lo = (sizeof(record) - sizeof(record.xhdr)) & 0xff; record.type = HANDSHAKE_CLIENT_KEY_EXCHANGE; - //record.len24_hi = 0; - record.len24_mid = (sizeof(record) - sizeof(record.xhdr) - 4) >> 8; - record.len24_lo = (sizeof(record) - sizeof(record.xhdr) - 4) & 0xff; - record.keylen16_hi = (sizeof(record) - sizeof(record.xhdr) - 6) >> 8; - record.keylen16_lo = (sizeof(record) - sizeof(record.xhdr) - 6) & 0xff; tls_get_random(rsa_premaster, sizeof(rsa_premaster)); // RFC 5246 @@ -930,78 +957,92 @@ static void send_client_key_exchange(tls_state_t *tls) // version negotiated for the connection." rsa_premaster[0] = TLS_MAJ; rsa_premaster[1] = TLS_MIN; - psRsaEncryptPub(/*pool:*/ NULL, + len = psRsaEncryptPub(/*pool:*/ NULL, /* psRsaKey_t* */ &tls->server_rsa_pub_key, rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), record.key, sizeof(record.key), data_param_ignored ); + record.keylen16_hi = len >> 8; + record.keylen16_lo = len & 0xff; + len += 2; + //record.len24_hi = 0; + record.len24_mid = len >> 8; + record.len24_lo = len & 0xff; + len += 4; + record.xhdr.len16_hi = len >> 8; + record.xhdr.len16_lo = len & 0xff; - xwrite_and_hash(tls, &record, sizeof(record)); + dbg(">> HANDSHAKE_CLIENT_KEY_EXCHANGE\n"); + xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len); -// RFC 5246 -// For all key exchange methods, the same algorithm is used to convert -// the pre_master_secret into the master_secret. The pre_master_secret -// should be deleted from memory once the master_secret has been -// computed. -// master_secret = PRF(pre_master_secret, "master secret", -// ClientHello.random + ServerHello.random) -// [0..47]; -// The master secret is always exactly 48 bytes in length. The length -// of the premaster secret will vary depending on key exchange method. + // RFC 5246 + // For all key exchange methods, the same algorithm is used to convert + // the pre_master_secret into the master_secret. The pre_master_secret + // should be deleted from memory once the master_secret has been + // computed. + // master_secret = PRF(pre_master_secret, "master secret", + // ClientHello.random + ServerHello.random) + // [0..47]; + // The master secret is always exactly 48 bytes in length. The length + // of the premaster secret will vary depending on key exchange method. tls_prf_hmac_sha256( tls->master_secret, sizeof(tls->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) ); + dump_hex("master secret:%s\n", tls->master_secret, sizeof(tls->master_secret)); -// RFC 5246 -// 6.3. Key Calculation -// -// The Record Protocol requires an algorithm to generate keys required -// by the current connection state (see Appendix A.6) from the security -// parameters provided by the handshake protocol. -// -// The master secret is expanded into a sequence of secure bytes, which -// is then split to a client write MAC key, a server write MAC key, a -// client write encryption key, and a server write encryption key. Each -// of these is generated from the byte sequence in that order. Unused -// values are empty. Some AEAD ciphers may additionally require a -// client write IV and a server write IV (see Section 6.2.3.3). -// -// When keys and MAC keys are generated, the master secret is used as an -// entropy source. -// -// To generate the key material, compute -// -// key_block = PRF(SecurityParameters.master_secret, -// "key expansion", -// SecurityParameters.server_random + -// SecurityParameters.client_random); -// -// until enough output has been generated. Then, the key_block is -// partitioned as follows: -// -// client_write_MAC_key[SecurityParameters.mac_key_length] -// server_write_MAC_key[SecurityParameters.mac_key_length] -// client_write_key[SecurityParameters.enc_key_length] -// server_write_key[SecurityParameters.enc_key_length] -// client_write_IV[SecurityParameters.fixed_iv_length] -// server_write_IV[SecurityParameters.fixed_iv_length] - { - uint8_t tmp64[64]; - /* make server_rand32 + client_rand32 */ - memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); - memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); - - tls_prf_hmac_sha256( - tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), - tls->master_secret, sizeof(tls->master_secret), - "key expansion", - tmp64, 64 - ); - } + // RFC 5246 + // 6.3. Key Calculation + // + // The Record Protocol requires an algorithm to generate keys required + // by the current connection state (see Appendix A.6) from the security + // parameters provided by the handshake protocol. + // + // The master secret is expanded into a sequence of secure bytes, which + // is then split to a client write MAC key, a server write MAC key, a + // client write encryption key, and a server write encryption key. Each + // of these is generated from the byte sequence in that order. Unused + // values are empty. Some AEAD ciphers may additionally require a + // client write IV and a server write IV (see Section 6.2.3.3). + // + // When keys and MAC keys are generated, the master secret is used as an + // entropy source. + // + // To generate the key material, compute + // + // key_block = PRF(SecurityParameters.master_secret, + // "key expansion", + // SecurityParameters.server_random + + // SecurityParameters.client_random); + // + // until enough output has been generated. Then, the key_block is + // partitioned as follows: + // + // client_write_MAC_key[SecurityParameters.mac_key_length] + // server_write_MAC_key[SecurityParameters.mac_key_length] + // client_write_key[SecurityParameters.enc_key_length] + // server_write_key[SecurityParameters.enc_key_length] + // client_write_IV[SecurityParameters.fixed_iv_length] + // server_write_IV[SecurityParameters.fixed_iv_length] + { + uint8_t tmp64[64]; + /* make server_rand32 + client_rand32 */ + memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); + memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); + + tls_prf_hmac_sha256( + tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), + tls->master_secret, sizeof(tls->master_secret), + "key expansion", + tmp64, 64 + ); + dump_hex("client_write_MAC_key:%s\n", + tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key) + ); + } } static void send_change_cipher_spec(tls_state_t *tls) @@ -1011,14 +1052,13 @@ static void send_change_cipher_spec(tls_state_t *tls) 01 }; /* Not "xwrite_and_hash": this is not a handshake message */ + dbg(">> CHANGE_CIPHER_SPEC\n"); xwrite(tls->fd, rec, sizeof(rec)); tls->write_seq64_be = 0; tls->encrypt_on_write = 1; } -static void send_client_finished(tls_state_t *tls) -{ // 7.4.9. Finished // A Finished message is always sent immediately after a change // cipher spec message to verify that the key exchange and @@ -1056,6 +1096,8 @@ static void send_client_finished(tls_state_t *tls) // suite. Any cipher suite which does not explicitly specify // verify_data_length has a verify_data_length equal to 12. This // includes all existing cipher suites. +static void send_client_finished(tls_state_t *tls) +{ struct client_finished { struct record_hdr xhdr; uint8_t type; @@ -1085,41 +1127,16 @@ static void send_client_finished(tls_state_t *tls) "client finished", handshake_hash, sizeof(handshake_hash) ); + dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); + dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); + dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); + dump_hex("=> digest: %s\n", record.prf_result, sizeof(record.prf_result)); //(1) TODO: well, this should be encrypted on send, really. //(2) do we really need to also hash it? + dbg(">> HANDSHAKE_FINISHED\n"); xwrite_and_hash(tls, &record, sizeof(record)); - -//s_client does this: -// -//write to 0x1d750b0 [0x1e74620] (6 bytes => 6 (0x6)) -//0000 - 14 03 03 00 01 01 ...... >> CHANGE_CIPHER_SPEC -// -//write to 0x1d750b0 [0x1e74620] (53 bytes => 53 (0x35)) -//0000 - 16 03 03 0030 14 00000c [ed b9 e1 33 36 0b 76 ....0.......36.v >> FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] -//0010 - c0 d1 d4 0b a3|73 ec a8-fa b5 cb 12 b6 4c 2a b1 .....s.......L*. -//0020 - fb 42 7f 73 0d 06 1c 87-56 f0 db df e6 6a 25 aa .B.s....V....j%. -//0030 - fc 42 38 cb 0b] .B8.. - -//we do this (as seen by s_server): -// -//read from 0x26b7650 [0x26ac383] (5 bytes => 5 (0x5)) -//0000 - 14 03 03 00 01 ..... -//read from 0x26b7650 [0x26ac388] (1 bytes => 1 (0x1)) -//0000 - 01 . << CHANGE_CIPHER_SPEC -//read from 0x26b7650 [0x26ac383] (5 bytes => 5 (0x5)) -//0000 - 16 03 03 0030 ....0 -//read from 0x26b7650 [0x26ac388] (48 bytes => 48 (0x30)) -//0000 - 14 00000c [d1 6f 08 c3-ef ec 26 7c 17 76 ac 1c| .....o....&|.v.. << FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] -//0010 - 0b 27 ae 1c 59 f8 cb af-de 25 25 7e 50 51 da dd .'..Y....%%~PQ.. -//0020 - c2 9e d6 27 96 0b 72 05-63 54 89 00 0e d7 b1 10] ...'..r.cT...... -// -//write to 0x26b7650 [0x26b4d90] (7 bytes => 7 (0x7)) -//0000 - 15 03 03 00 02 02 33 ......3 -//ERROR -//140684206577528:error:1408C095:SSL routines:ssl3_get_finished:digest check failed:s3_both.c:273: -//140684206577528:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:656: } static void get_change_cipher_spec(tls_state_t *tls) @@ -1196,6 +1213,7 @@ static void tls_handshake(tls_state_t *tls) send_change_cipher_spec(tls); //we now should be able to send encrypted... as soon as we grok AES. send_client_finished(tls); + get_change_cipher_spec(tls); get_server_finished(tls); //we now should receive encrypted, and application data can be sent/received @@ -1271,64 +1289,7 @@ read from 0x1d750b0 [0x1e6ac08] (1035 bytes => 1035 (0x40B)) 0020 - 2e 2b 30 0d 06 09 2a 86-48 86 f7 0d 01 01 0b 05 .+0...*.H....... 0030 - 00 30 14 31 12 30 10 06-03 55 04 03 0c 09 6c 6f .0.1.0...U....lo 0040 - 63 61 6c 68 6f 73 74 30-20 17 0d 31 37 30 31 31 calhost0 ..17011 -0050 - 36 30 33 30 39 34 36 5a-18 0f 32 32 39 30 31 30 6030946Z..229010 -0060 - 33 31 30 33 30 39 34 36-5a 30 14 31 12 30 10 06 31030946Z0.1.0.. -0070 - 03 55 04 03 0c 09 6c 6f-63 61 6c 68 6f 73 74 30 .U....localhost0 -0080 - 82 01 a2 30 0d 06 09 2a-86 48 86 f7 0d 01 01 01 ...0...*.H...... -0090 - 05 00 03 82 01 8f 00 30-82 01 8a 02 82 01 81 00 .......0........ -00a0 - f5 a8 66 54 af fd 33 9e-fb 1d 2d d7 33 ff b9 99 ..fT..3...-.3... -00b0 - 21 16 8a 65 75 1c 39 9d-0a c3 fc 8c 6d 63 de 7b !..eu.9.....mc.{ -00c0 - d8 1e d8 20 a1 a9 d5 ab-2a 8e d1 4f b8 9a f4 f7 ... ....*..O.... -00d0 - 91 0d db 70 a8 59 d3 0d-8f 6f bb 51 a4 5c f1 c1 ...p.Y...o.Q.\.. -00e0 - ce 1e b5 58 3a 46 1b 2a-1f 7c 75 87 b4 9f ed d3 ...X:F.*.|u..... -00f0 - 3d 9a cf a4 5b 96 5b 25-cf f5 33 1c c8 7a 8a 37 =...[.[%..3..z.7 -0100 - 69 2f 63 8c f9 a4 a5 40-06 c9 63 cf fd 35 5d d3 i/c....@..c..5]. -0110 - 8e e3 17 2f 8a ab 5e fd-6c 7e 5b 03 bb b6 3c e3 .../..^.l~[...<. -0120 - 32 01 99 72 45 a7 a3 c3-11 d8 6c dc 50 a6 75 01 2..rE.....l.P.u. -0130 - a2 81 85 56 5e be eb 8c-ad 44 05 cf 47 e0 3e 8b ...V^....D..G.>. -0140 - cd 6e 08 11 ee 5e 94 39-5d 8c a2 e3 b0 03 7f c2 .n...^.9]....... -0150 - f8 99 35 0b d1 c2 3c 37-49 a8 bb 70 8e e2 a6 c8 ..5...<7I..p.... -0160 - 5b 7d f5 d1 dc 6e ef fb-83 f7 4c ef 8c 85 e3 b9 [}...n....L..... -0170 - fd 51 18 70 7e a5 03 b7-6d e5 c6 c2 d1 4d e2 16 .Q.p~...m....M.. -0180 - 42 c8 21 25 2a 27 af c4-4a c2 f0 b6 2f 72 46 33 B.!%*'..J.../rF3 -0190 - b1 89 d8 95 7a 9d 52 db-75 ae f4 a0 97 32 8c 5f ....z.R.u....2._ -01a0 - 97 e7 5d 12 15 3f 85 8f-d1 9c ca a0 fd 59 cd c5 ..]..?.......Y.. -01b0 - 25 70 d3 97 62 04 af cb-19 1b 6e 24 c9 82 b8 25 %p..b.....n$...% -01c0 - c3 5c bd d7 ee 08 17 6f-ea 99 24 2f c7 05 a8 40 .\.....o..$/...@ -01d0 - 24 d5 74 7b 5b 65 c5 ec-97 63 de d1 46 d2 c4 09 $.t{[e...c..F... -01e0 - c2 22 23 99 ce 13 03 6f-b4 08 7f 3e 00 c6 fe 91 ."#....o...>.... -01f0 - bc c8 ba b2 32 c2 42 9d-89 de 04 d0 36 27 9e 8c ....2.B.....6'.. -0200 - ad 79 3e d6 84 38 db cd-57 ad 68 05 85 0b 13 59 .y>..8..W.h....Y -0210 - 11 5a 2b a4 d0 5f c3 ee-1a 02 69 d4 c5 bf 19 b5 .Z+.._....i..... -0220 - 02 03 01 00 01 a3 50 30-4e 30 1d 06 03 55 1d 0e ......P0N0...U.. -0230 - 04 16 04 14 08 87 29 ce-04 09 7f 11 33 80 ba 30 ......).....3..0 -0240 - b2 77 84 b4 73 6e 82 94-30 1f 06 03 55 1d 23 04 .w..sn..0...U.#. -0250 - 18 30 16 80 14 08 87 29-ce 04 09 7f 11 33 80 ba .0.....).....3.. -0260 - 30 b2 77 84 b4 73 6e 82-94 30 0c 06 03 55 1d 13 0.w..sn..0...U.. -0270 - 04 05 30 03 01 01 ff 30-0d 06 09 2a 86 48 86 f7 ..0....0...*.H.. -0280 - 0d 01 01 0b 05 00 03 82-01 81 00 22 c4 a8 6f 0a ..........."..o. -0290 - 40 a0 c4 92 ae 83 86 9c-42 f8 0a a8 c7 72 d2 5d @.......B....r.] -02a0 - de 78 f2 5a 38 e0 e6 0b-3c df af dd 6c 44 a9 0a .x.Z8...<...lD.. -02b0 - 81 f3 0e 49 e5 07 da 40-0f 85 73 db d6 86 87 6a ...I...@..s....j -02c0 - b9 29 75 6a a9 dd fc 16-81 dc eb 25 3a c7 dc 3f .)uj.......%:..? -02d0 - c8 a3 2d bb 49 3e 08 72-e9 03 e6 2f ee 1e 17 9a ..-.I>.r.../.... -02e0 - 9c f6 fd 3c 73 cf e4 2c-5d f1 a8 1c 93 f7 1d f7 ......I<.%B'.{8.. -0390 - 3a 87 6f db 79 7a 54 c1-a3 6a 54 01 17 92 04 24 :.o.yzT..jT....$ -03a0 - 6c 66 1d 47 45 4e 3a af-fe 45 1d 2c 23 81 f6 cc lf.GEN:..E.,#... -03b0 - e1 0d 89 81 90 b6 3b 7d-49 8d 0f d5 d8 f6 d8 0c ......;}I....... -03c0 - 7e 47 1e fb b7 a0 7a 66-7a 1e f2 ba 4e 28 ed 36 ~G....zfz...N(.6 -03d0 - 6b b6 2b e5 9c 57 0e ba-df 44 1b 4d 5e a2 9e 3f k.+..W...D.M^..? -03e0 - 29 18 b6 7c 26 ea 6a d5-0d f1 e9 42 fa 08 0d 44 )..|&.j....B...D +..."......."......."......."......."......."......."......."......."..... 03f0 - 11 8a cd c5 a3 0a 22 43-d5 13 f9 a5 8a 06 f9 00 ......"C........ 0400 - 3c f7 86 4e e8 a5 d8 5b-92 37 f5 <..N...[.7. depth=0 CN = localhost @@ -1413,28 +1374,7 @@ Certificate chain --- Server certificate -----BEGIN CERTIFICATE----- -MIID/TCCAmWgAwIBAgIJANnZjbiUrS4rMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV -BAMMCWxvY2FsaG9zdDAgFw0xNzAxMTYwMzA5NDZaGA8yMjkwMTAzMTAzMDk0Nlow -FDESMBAGA1UEAwwJbG9jYWxob3N0MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB -igKCAYEA9ahmVK/9M577HS3XM/+5mSEWimV1HDmdCsP8jG1j3nvYHtggoanVqyqO -0U+4mvT3kQ3bcKhZ0w2Pb7tRpFzxwc4etVg6RhsqH3x1h7Sf7dM9ms+kW5ZbJc/1 -MxzIeoo3aS9jjPmkpUAGyWPP/TVd047jFy+Kq179bH5bA7u2POMyAZlyRaejwxHY -bNxQpnUBooGFVl6+64ytRAXPR+A+i81uCBHuXpQ5XYyi47ADf8L4mTUL0cI8N0mo -u3CO4qbIW3310dxu7/uD90zvjIXjuf1RGHB+pQO3beXGwtFN4hZCyCElKievxErC -8LYvckYzsYnYlXqdUtt1rvSglzKMX5fnXRIVP4WP0ZzKoP1ZzcUlcNOXYgSvyxkb -biTJgrglw1y91+4IF2/qmSQvxwWoQCTVdHtbZcXsl2Pe0UbSxAnCIiOZzhMDb7QI -fz4Axv6RvMi6sjLCQp2J3gTQNieejK15PtaEONvNV61oBYULE1kRWiuk0F/D7hoC -adTFvxm1AgMBAAGjUDBOMB0GA1UdDgQWBBQIhynOBAl/ETOAujCyd4S0c26ClDAf -BgNVHSMEGDAWgBQIhynOBAl/ETOAujCyd4S0c26ClDAMBgNVHRMEBTADAQH/MA0G -CSqGSIb3DQEBCwUAA4IBgQAixKhvCkCgxJKug4acQvgKqMdy0l3eePJaOODmCzzf -r91sRKkKgfMOSeUH2kAPhXPb1oaHarkpdWqp3fwWgdzrJTrH3D/Ioy27ST4IcukD -5i/uHheanPb9PHPP5Cxd8agck/cd966ylr+6vdBdP07TVF6BR3KhNTnb+qdUlvQf -5V7IgPgfc+UJFK7lSsLzclzYUm7Y0uneSBRW/DLOaaNooen1eOithKjDRRo6fVTb -486EnrHXYI6y5xWEjqUPxFPkuXHnRpP3rwC9PTaaTo/r4RgGVElKeZ89253W51e3 -dd0mrLeGGfD5tl41NqRap7AziJ5/yfM+zALOSTwOJUInv3s429g6h2/beXpUwaNq -VAEXkgQkbGYdR0VOOq/+RR0sI4H2zOENiYGQtjt9SY0P1dj22Ax+Rx77t6B6Znoe -8rpOKO02a7Yr5ZxXDrrfRBtNXqKePykYtnwm6mrVDfHpQvoIDUQRis3FowoiQ9UT -+aWKBvkAPPeGTuil2FuSN/U= +..."......."......."......."......."......."......."......."......."..... -----END CERTIFICATE----- subject=/CN=localhost issuer=/CN=localhost -- cgit v1.2.3-55-g6feb From fe0588df3b12a084cd01118e1c06767a815a9998 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jan 2017 17:04:24 +0100 Subject: tls: rearrange function order, improve comments Signed-off-by: Denys Vlasenko --- networking/tls.c | 341 +++++++++++++++++++++++++++---------------------------- 1 file changed, 170 insertions(+), 171 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 60afd30b4..81820e9a1 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -284,6 +284,145 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff sha256_hash(ctx, buffer, len) #endif /* not TLS_DEBUG >= 2 */ +// RFC 2104 +// HMAC(key, text) based on a hash H (say, sha256) is: +// ipad = [0x36 x INSIZE] +// opad = [0x5c x INSIZE] +// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text)) +// +// H(key XOR opad) and H(key XOR ipad) can be precomputed +// if we often need HMAC hmac with the same key. +// +// text is often given in disjoint pieces. +static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE], + sha256_ctx_t *hashed_key_xor_ipad, + sha256_ctx_t *hashed_key_xor_opad, + va_list va) +{ + uint8_t *text; + + /* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ + /* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ + + /* calculate out = H((key XOR ipad) + text) */ + while ((text = va_arg(va, uint8_t*)) != NULL) { + unsigned text_size = va_arg(va, unsigned); + sha256_hash(hashed_key_xor_ipad, text, text_size); + } + sha256_end(hashed_key_xor_ipad, out); + + /* out = H((key XOR opad) + out) */ + sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE); + sha256_end(hashed_key_xor_opad, out); +} + +static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...) +{ + sha256_ctx_t hashed_key_xor_ipad; + sha256_ctx_t hashed_key_xor_opad; + uint8_t key_xor_ipad[SHA256_INSIZE]; + uint8_t key_xor_opad[SHA256_INSIZE]; + uint8_t tempkey[SHA256_OUTSIZE]; + va_list va; + int i; + + va_start(va, key_size); + + // "The authentication key can be of any length up to INSIZE, the + // block length of the hash function. Applications that use keys longer + // than INSIZE bytes will first hash the key using H and then use the + // resultant OUTSIZE byte string as the actual key to HMAC." + if (key_size > SHA256_INSIZE) { + hash_sha256(tempkey, key, key_size); + key = tempkey; + key_size = SHA256_OUTSIZE; + } + + for (i = 0; i < key_size; i++) { + key_xor_ipad[i] = key[i] ^ 0x36; + key_xor_opad[i] = key[i] ^ 0x5c; + } + for (; i < SHA256_INSIZE; i++) { + key_xor_ipad[i] = 0x36; + key_xor_opad[i] = 0x5c; + } + sha256_begin(&hashed_key_xor_ipad); + sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE); + sha256_begin(&hashed_key_xor_opad); + sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE); + + hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); + va_end(va); +} + +// RFC 5246: +// 5. HMAC and the Pseudorandom Function +//... +// In this section, we define one PRF, based on HMAC. This PRF with the +// SHA-256 hash function is used for all cipher suites defined in this +// document and in TLS documents published prior to this document when +// TLS 1.2 is negotiated. +//... +// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + +// HMAC_hash(secret, A(2) + seed) + +// HMAC_hash(secret, A(3) + seed) + ... +// where + indicates concatenation. +// A() is defined as: +// A(0) = seed +// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed) +// A(i) = HMAC_hash(secret, A(i-1)) +// P_hash can be iterated as many times as necessary to produce the +// required quantity of data. For example, if P_SHA256 is being used to +// create 80 bytes of data, it will have to be iterated three times +// (through A(3)), creating 96 bytes of output data; the last 16 bytes +// of the final iteration will then be discarded, leaving 80 bytes of +// output data. +// +// TLS's PRF is created by applying P_hash to the secret as: +// +// PRF(secret, label, seed) = P_(secret, label + seed) +// +// The label is an ASCII string. +static void tls_prf_hmac_sha256( + uint8_t *outbuf, unsigned outbuf_size, + uint8_t *secret, unsigned secret_size, + const char *label, + uint8_t *seed, unsigned seed_size) +{ + uint8_t a[SHA256_OUTSIZE]; + uint8_t *out_p = outbuf; + unsigned label_size = strlen(label); + + /* In P_hash() calculation, "seed" is "label + seed": */ +#define SEED label, label_size, seed, seed_size +#define SECRET secret, secret_size +#define A a, (int)(sizeof(a)) + + /* A(1) = HMAC_hash(secret, seed) */ + hmac_sha256(a, SECRET, SEED, NULL); +//TODO: convert hmac_sha256 to precomputed + + for(;;) { + /* HMAC_hash(secret, A(1) + seed) */ + if (outbuf_size <= SHA256_OUTSIZE) { + /* Last, possibly incomplete, block */ + /* (use a[] as temp buffer) */ + hmac_sha256(a, SECRET, A, SEED, NULL); + memcpy(out_p, a, outbuf_size); + return; + } + /* Not last block. Store directly to result buffer */ + hmac_sha256(out_p, SECRET, A, SEED, NULL); + out_p += SHA256_OUTSIZE; + outbuf_size -= SHA256_OUTSIZE; + /* A(2) = HMAC_hash(secret, A(1)) */ + hmac_sha256(a, SECRET, A, NULL); + } +#undef A +#undef SECRET +#undef SEED +} + static tls_state_t *new_tls_state(void) { @@ -293,11 +432,13 @@ tls_state_t *new_tls_state(void) return tls; } -static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...); - -static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size) +static void tls_error_die(tls_state_t *tls) { -// rfc5246 + dump_tls_record(tls->inbuf, tls->insize + tls->tail); + xfunc_die(); +} + +// RFC 5246 // 6.2.3.1. Null or Standard Stream Cipher // // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) @@ -310,18 +451,14 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size // } GenericStreamCipher; // // The MAC is generated as: -// // MAC(MAC_write_key, seq_num + // TLSCompressed.type + // TLSCompressed.version + // TLSCompressed.length + // TLSCompressed.fragment); -// // where "+" denotes concatenation. -// // seq_num // The sequence number for this record. -// // MAC // The MAC algorithm specified by SecurityParameters.mac_algorithm. // @@ -345,23 +482,26 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size // MD5 HMAC-MD5 16 16 // SHA HMAC-SHA1 20 20 // SHA256 HMAC-SHA256 32 32 - +static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size) +{ uint8_t mac_hash[SHA256_OUTSIZE]; struct record_hdr *xhdr = buf; if (tls->encrypt_on_write) { +//TODO: convert hmac_sha256 to precomputed hmac_sha256(mac_hash, tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), &tls->write_seq64_be, sizeof(tls->write_seq64_be), buf, size, NULL); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + /* Temporarily change for writing */ xhdr->len16_lo += SHA256_OUTSIZE; -//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FIXME } xwrite(tls->fd, buf, size); dbg("wrote %u bytes\n", size); + if (tls->encrypt_on_write) { xwrite(tls->fd, mac_hash, sizeof(mac_hash)); dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); @@ -374,12 +514,6 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size } } -static void tls_error_die(tls_state_t *tls) -{ - dump_tls_record(tls->inbuf, tls->insize + tls->tail); - xfunc_die(); -} - static int xread_tls_block(tls_state_t *tls) { struct record_hdr *xhdr; @@ -417,7 +551,7 @@ static int xread_tls_block(tls_state_t *tls) target -= sizeof(*xhdr); /* RFC 5246 is not saying it explicitly, but sha256 hash - * in our FINISHED packet must include hashes of incoming packets too! + * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target); @@ -427,23 +561,9 @@ static int xread_tls_block(tls_state_t *tls) return target; } -static int xread_tls_handshake_block(tls_state_t *tls, int min_len) -{ - struct record_hdr *xhdr; - int len = xread_tls_block(tls); - - xhdr = (void*)tls->inbuf; - if (len < min_len - || xhdr->type != RECORD_TYPE_HANDSHAKE - || xhdr->proto_maj != TLS_MAJ - || xhdr->proto_min != TLS_MIN - ) { - tls_error_die(tls); - } - dbg("got HANDSHAKE\n"); - return len; -} - +/* + * DER parsing routines + */ static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end) { unsigned len, len1; @@ -653,147 +773,26 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); } -// RFC 2104: HMAC(key, text) based on a hash H (say, sha256) is: -// ipad = [0x36 x INSIZE] -// opad = [0x5c x INSIZE] -// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text)) -// -// H(key XOR opad) and H(key XOR ipad) can be precomputed -// if we often need HMAC hmac with the same key. -// -// text is often given in disjoint pieces. -static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE], - sha256_ctx_t *hashed_key_xor_ipad, - sha256_ctx_t *hashed_key_xor_opad, - va_list va) -{ - uint8_t *text; - - /* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ - /* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ - - /* calculate out = H((key XOR ipad) + text) */ - while ((text = va_arg(va, uint8_t*)) != NULL) { - unsigned text_size = va_arg(va, unsigned); - sha256_hash(hashed_key_xor_ipad, text, text_size); - } - sha256_end(hashed_key_xor_ipad, out); - - /* out = H((key XOR opad) + out) */ - sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE); - sha256_end(hashed_key_xor_opad, out); -} - -static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...) -{ - sha256_ctx_t hashed_key_xor_ipad; - sha256_ctx_t hashed_key_xor_opad; - uint8_t key_xor_ipad[SHA256_INSIZE]; - uint8_t key_xor_opad[SHA256_INSIZE]; - uint8_t tempkey[SHA256_OUTSIZE]; - va_list va; - int i; - - va_start(va, key_size); - - // "The authentication key can be of any length up to INSIZE, the - // block length of the hash function. Applications that use keys longer - // than INSIZE bytes will first hash the key using H and then use the - // resultant OUTSIZE byte string as the actual key to HMAC." - if (key_size > SHA256_INSIZE) { - hash_sha256(tempkey, key, key_size); - key = tempkey; - key_size = SHA256_OUTSIZE; - } - - for (i = 0; i < key_size; i++) { - key_xor_ipad[i] = key[i] ^ 0x36; - key_xor_opad[i] = key[i] ^ 0x5c; - } - for (; i < SHA256_INSIZE; i++) { - key_xor_ipad[i] = 0x36; - key_xor_opad[i] = 0x5c; - } - sha256_begin(&hashed_key_xor_ipad); - sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE); - sha256_begin(&hashed_key_xor_opad); - sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE); - - hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); - va_end(va); -} - -// RFC 5246: -// 5. HMAC and the Pseudorandom Function -//... -// In this section, we define one PRF, based on HMAC. This PRF with the -// SHA-256 hash function is used for all cipher suites defined in this -// document and in TLS documents published prior to this document when -// TLS 1.2 is negotiated. -//... -// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + -// HMAC_hash(secret, A(2) + seed) + -// HMAC_hash(secret, A(3) + seed) + ... -// where + indicates concatenation. -// A() is defined as: -// A(0) = seed -// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed) -// A(i) = HMAC_hash(secret, A(i-1)) -// P_hash can be iterated as many times as necessary to produce the -// required quantity of data. For example, if P_SHA256 is being used to -// create 80 bytes of data, it will have to be iterated three times -// (through A(3)), creating 96 bytes of output data; the last 16 bytes -// of the final iteration will then be discarded, leaving 80 bytes of -// output data. -// -// TLS's PRF is created by applying P_hash to the secret as: -// -// PRF(secret, label, seed) = P_(secret, label + seed) -// -// The label is an ASCII string. -static void tls_prf_hmac_sha256( - uint8_t *outbuf, unsigned outbuf_size, - uint8_t *secret, unsigned secret_size, - const char *label, - uint8_t *seed, unsigned seed_size) +/* + * TLS Handshake routines + */ +static int xread_tls_handshake_block(tls_state_t *tls, int min_len) { - uint8_t a[SHA256_OUTSIZE]; - uint8_t *out_p = outbuf; - unsigned label_size = strlen(label); - - /* In P_hash() calculation, "seed" is "label + seed": */ -#define SEED label, label_size, seed, seed_size -#define SECRET secret, secret_size -#define A a, (int)(sizeof(a)) - - /* A(1) = HMAC_hash(secret, seed) */ - hmac_sha256(a, SECRET, SEED, NULL); -//TODO: convert hmac_sha256 to precomputed + struct record_hdr *xhdr; + int len = xread_tls_block(tls); - for(;;) { - /* HMAC_hash(secret, A(1) + seed) */ - if (outbuf_size <= SHA256_OUTSIZE) { - /* Last, possibly incomplete, block */ - /* (use a[] as temp buffer) */ - hmac_sha256(a, SECRET, A, SEED, NULL); - memcpy(out_p, a, outbuf_size); - return; - } - /* Not last block. Store directly to result buffer */ - hmac_sha256(out_p, SECRET, A, SEED, NULL); - out_p += SHA256_OUTSIZE; - outbuf_size -= SHA256_OUTSIZE; - /* A(2) = HMAC_hash(secret, A(1)) */ - hmac_sha256(a, SECRET, A, NULL); + xhdr = (void*)tls->inbuf; + if (len < min_len + || xhdr->type != RECORD_TYPE_HANDSHAKE + || xhdr->proto_maj != TLS_MAJ + || xhdr->proto_min != TLS_MIN + ) { + tls_error_die(tls); } -#undef A -#undef SECRET -#undef SEED + dbg("got HANDSHAKE\n"); + return len; } -/* - * TLS Handshake routines - */ static void send_client_hello(tls_state_t *tls) { struct client_hello { @@ -1055,7 +1054,7 @@ static void send_change_cipher_spec(tls_state_t *tls) dbg(">> CHANGE_CIPHER_SPEC\n"); xwrite(tls->fd, rec, sizeof(rec)); - tls->write_seq64_be = 0; + /* tls->write_seq64_be = 0; - already is */ tls->encrypt_on_write = 1; } -- cgit v1.2.3-55-g6feb From e69d78c0385525a8e77002bebf47c4dcceaee1f4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jan 2017 17:24:11 +0100 Subject: tls: process CHANGE_CIPHER_SPEC and FINISHED from server Successfully finishes handshake with test servers using NULL-SHA256 cipher. The "only" thing remaining before there is a chance this can actually work with real servers is AES encrypt/decrypt. Signed-off-by: Denys Vlasenko --- networking/tls.c | 60 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 81820e9a1..3df2015a0 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -163,6 +163,7 @@ typedef struct tls_state { uint8_t master_secret[48]; uint8_t encrypt_on_write; + uint8_t decrypt_on_read; uint8_t client_write_MAC_key[SHA256_OUTSIZE]; // RFC 5246 // sequence number @@ -1044,15 +1045,16 @@ static void send_client_key_exchange(tls_state_t *tls) } } +static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { + RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, + 01 +}; + static void send_change_cipher_spec(tls_state_t *tls) { - static const uint8_t rec[] = { - RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01, - 01 - }; /* Not "xwrite_and_hash": this is not a handshake message */ dbg(">> CHANGE_CIPHER_SPEC\n"); - xwrite(tls->fd, rec, sizeof(rec)); + xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); /* tls->write_seq64_be = 0; - already is */ tls->encrypt_on_write = 1; @@ -1138,16 +1140,6 @@ static void send_client_finished(tls_state_t *tls) xwrite_and_hash(tls, &record, sizeof(record)); } -static void get_change_cipher_spec(tls_state_t *tls) -{ - tls->fd = 0; -} - -static void get_server_finished(tls_state_t *tls) -{ - tls->fd = 0; -} - static void tls_handshake(tls_state_t *tls) { // Client RFC 5246 Server @@ -1205,20 +1197,32 @@ static void tls_handshake(tls_state_t *tls) // (i.e. the same format as server certs) // xread_tls_handshake_block(tls, 4); // } - if (tls->inbuf[5] == HANDSHAKE_SERVER_HELLO_DONE) { - // 0e 000000 (len:0) - dbg("got SERVER_HELLO_DONE\n"); - send_client_key_exchange(tls); - send_change_cipher_spec(tls); -//we now should be able to send encrypted... as soon as we grok AES. - send_client_finished(tls); - - get_change_cipher_spec(tls); - get_server_finished(tls); -//we now should receive encrypted, and application data can be sent/received - } else { + if (tls->inbuf[5] != HANDSHAKE_SERVER_HELLO_DONE) tls_error_die(tls); - } + // 0e 000000 (len:0) + dbg("got SERVER_HELLO_DONE\n"); + + send_client_key_exchange(tls); + + send_change_cipher_spec(tls); + /* we now should send encrypted... as soon as we grok AES. */ + + send_client_finished(tls); + + /* Get CHANGE_CIPHER_SPEC */ + len = xread_tls_block(tls); + if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) + tls_error_die(tls); + dbg("got CHANGE_CIPHER_SPEC\n"); + tls->decrypt_on_read = 1; + /* we now should receive encrypted */ + + /* Get (encrypted) FINISHED from the server */ + len = xread_tls_block(tls); + if (len < 4 || tls->inbuf[5] != HANDSHAKE_FINISHED) + tls_error_die(tls); + dbg("got FINISHED\n"); + /* application data can be sent/received */ } // To run a test server using openssl: -- cgit v1.2.3-55-g6feb From 5d1662ea1c29f53b6ece93806c4cf218f9b9a5ae Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 17 Jan 2017 18:17:27 +0100 Subject: tls: address one easy FIXME, tidy up comments Signed-off-by: Denys Vlasenko --- networking/tls.c | 144 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 3df2015a0..8bcaee9a6 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -262,7 +262,6 @@ static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned sha256_end(&ctx, out); } -#if TLS_DEBUG >= 2 /* Nondestructively see the current hash value */ static void sha256_peek(sha256_ctx_t *ctx, void *buffer) { @@ -270,6 +269,7 @@ static void sha256_peek(sha256_ctx_t *ctx, void *buffer) sha256_end(&ctx_copy, buffer); } +#if TLS_DEBUG >= 2 static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) { uint8_t h[SHA256_OUTSIZE]; @@ -384,7 +384,7 @@ static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_ // PRF(secret, label, seed) = P_(secret, label + seed) // // The label is an ASCII string. -static void tls_prf_hmac_sha256( +static void prf_hmac_sha256( uint8_t *outbuf, unsigned outbuf_size, uint8_t *secret, unsigned secret_size, const char *label, @@ -794,6 +794,35 @@ static int xread_tls_handshake_block(tls_state_t *tls, int min_len) return len; } +static void fill_handshake_record_hdr(struct record_hdr *xhdr, unsigned len) +{ + struct handshake_hdr { + struct record_hdr xhdr; + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + } *h = (void*)xhdr; + + h->xhdr.type = RECORD_TYPE_HANDSHAKE; + h->xhdr.proto_maj = TLS_MAJ; + h->xhdr.proto_min = TLS_MIN; + len -= 5; + h->xhdr.len16_hi = len >> 8; + // can be optimized to do one store instead of four: + // uint32_t v = htonl(0x100*(RECORD_TYPE_HANDSHAKE + 0x100*(TLS_MAJ + 0x100*(TLS_MIN)))) + // | ((len >> 8) << 24); // little-endian specific, don't use in this form + // *(uint32_t *)xhdr = v; + + h->xhdr.len16_lo = len & 0xff; + + len -= 4; + h->len24_hi = len >> 16; + h->len24_mid = len >> 8; + h->len24_lo = len & 0xff; + + memset(h + 1, 0, len); +} + +//TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise static void send_client_hello(tls_state_t *tls) { struct client_hello { @@ -809,33 +838,25 @@ static void send_client_hello(tls_state_t *tls) uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ }; - struct client_hello hello; - - memset(&hello, 0, sizeof(hello)); - hello.xhdr.type = RECORD_TYPE_HANDSHAKE; - hello.xhdr.proto_maj = TLS_MAJ; - hello.xhdr.proto_min = TLS_MIN; - //zero: hello.xhdr.len16_hi = (sizeof(hello) - sizeof(hello.xhdr)) >> 8; - hello.xhdr.len16_lo = (sizeof(hello) - sizeof(hello.xhdr)); - hello.type = HANDSHAKE_CLIENT_HELLO; - //hello.len24_hi = 0; - //zero: hello.len24_mid = (sizeof(hello) - sizeof(hello.xhdr) - 4) >> 8; - hello.len24_lo = (sizeof(hello) - sizeof(hello.xhdr) - 4); - hello.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ - hello.proto_min = TLS_MIN; /* can be higher than one in record headers */ - tls_get_random(hello.rand32, sizeof(hello.rand32)); - //hello.session_id_len = 0; - //hello.cipherid_len16_hi = 0; - hello.cipherid_len16_lo = 2 * 1; - hello.cipherid[0] = CIPHER_ID >> 8; - hello.cipherid[1] = CIPHER_ID & 0xff; - hello.comprtypes_len = 1; - //hello.comprtypes[0] = 0; - - //dbg (make it repeatable): memset(hello.rand32, 0x11, sizeof(hello.rand32)); + struct client_hello record; + + fill_handshake_record_hdr(&record.xhdr, sizeof(record)); + record.type = HANDSHAKE_CLIENT_HELLO; + record.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ + record.proto_min = TLS_MIN; /* can be higher than one in record headers */ + tls_get_random(record.rand32, sizeof(record.rand32)); + /* record.session_id_len = 0; - already is */ + /* record.cipherid_len16_hi = 0; */ + record.cipherid_len16_lo = 2 * 1; + record.cipherid[0] = CIPHER_ID >> 8; + record.cipherid[1] = CIPHER_ID & 0xff; + record.comprtypes_len = 1; + /* record.comprtypes[0] = 0; */ + + //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); dbg(">> HANDSHAKE_CLIENT_HELLO\n"); - xwrite_and_hash(tls, &hello, sizeof(hello)); - memcpy(tls->client_and_server_rand32, hello.rand32, sizeof(hello.rand32)); + xwrite_and_hash(tls, &record, sizeof(record)); + memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32)); } static void get_server_hello(tls_state_t *tls) @@ -892,7 +913,7 @@ static void get_server_hello(tls_state_t *tls) tls_error_die(tls); } - dbg("got SERVER_HELLO\n"); + dbg("<< SERVER_HELLO\n"); memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); } @@ -908,7 +929,7 @@ static void get_server_cert(tls_state_t *tls) certbuf = (void*)(xhdr + 1); if (certbuf[0] != HANDSHAKE_CERTIFICATE) tls_error_die(tls); - dbg("got CERTIFICATE\n"); + dbg("<< CERTIFICATE\n"); // 4392 bytes: // 0b 00|11|24 00|11|21 00|05|b0 30|82|05|ac|30|82|04|94|a0|03|02|01|02|02|11|00|9f|85|bf|66|4b|0c|dd|af|ca|50|86|79|50|1b|2b|e4|30|0d... //Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text @@ -932,29 +953,22 @@ static void send_client_key_exchange(tls_state_t *tls) struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; - uint8_t keylen16_hi, keylen16_lo; /* exist for RSA, but not for some other key types */ -//had a bug when had no keylen: we: -//write(3, "\x16\x03\x03\x01\x84\x10\x00\x01\x80\xXX\xXX\xXX\xXX\xXX\xXX...", 393) = 393 -//openssl: -//write to 0xe9a090 [0xf9ac20] (395 bytes => 395 (0x18B)) -//0000 - 16 03 03 01 86 10 00 01 -82 01 80 xx xx xx xx xx + /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */ + uint8_t keylen16_hi, keylen16_lo; uint8_t key[4 * 1024]; // size?? }; struct client_key_exchange record; uint8_t rsa_premaster[SSL_HS_RSA_PREMASTER_SIZE]; int len; - memset(&record, 0, sizeof(record)); - record.xhdr.type = RECORD_TYPE_HANDSHAKE; - record.xhdr.proto_maj = TLS_MAJ; - record.xhdr.proto_min = TLS_MIN; + fill_handshake_record_hdr(&record.xhdr, sizeof(record) - sizeof(record.key)); record.type = HANDSHAKE_CLIENT_KEY_EXCHANGE; tls_get_random(rsa_premaster, sizeof(rsa_premaster)); -// RFC 5246 -// "Note: The version number in the PreMasterSecret is the version -// offered by the client in the ClientHello.client_version, not the -// version negotiated for the connection." + // RFC 5246 + // "Note: The version number in the PreMasterSecret is the version + // offered by the client in the ClientHello.client_version, not the + // version negotiated for the connection." rsa_premaster[0] = TLS_MAJ; rsa_premaster[1] = TLS_MIN; len = psRsaEncryptPub(/*pool:*/ NULL, @@ -963,10 +977,11 @@ static void send_client_key_exchange(tls_state_t *tls) record.key, sizeof(record.key), data_param_ignored ); + /* length fields need fixing */ record.keylen16_hi = len >> 8; record.keylen16_lo = len & 0xff; len += 2; - //record.len24_hi = 0; + /* record.len24_hi = 0; - already is */ record.len24_mid = len >> 8; record.len24_lo = len & 0xff; len += 4; @@ -986,7 +1001,7 @@ static void send_client_key_exchange(tls_state_t *tls) // [0..47]; // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. - tls_prf_hmac_sha256( + prf_hmac_sha256( tls->master_secret, sizeof(tls->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", @@ -1033,7 +1048,7 @@ static void send_client_key_exchange(tls_state_t *tls) memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); - tls_prf_hmac_sha256( + prf_hmac_sha256( tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), tls->master_secret, sizeof(tls->master_secret), "key expansion", @@ -1107,23 +1122,12 @@ static void send_client_finished(tls_state_t *tls) }; struct client_finished record; uint8_t handshake_hash[SHA256_OUTSIZE]; - sha256_ctx_t ctx; - memset(&record, 0, sizeof(record)); - record.xhdr.type = RECORD_TYPE_HANDSHAKE; - record.xhdr.proto_maj = TLS_MAJ; - record.xhdr.proto_min = TLS_MIN; - record.xhdr.len16_hi = (sizeof(record) - sizeof(record.xhdr)) >> 8; - record.xhdr.len16_lo = (sizeof(record) - sizeof(record.xhdr)) & 0xff; + fill_handshake_record_hdr(&record.xhdr, sizeof(record)); record.type = HANDSHAKE_FINISHED; - //record.len24_hi = 0; - record.len24_mid = (sizeof(record) - sizeof(record.xhdr) - 4) >> 8; - record.len24_lo = (sizeof(record) - sizeof(record.xhdr) - 4) & 0xff; -//FIXME ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this code is repeatable - - ctx = tls->handshake_sha256_ctx; /* struct copy */ - sha256_end(&ctx, handshake_hash); - tls_prf_hmac_sha256(record.prf_result, sizeof(record.prf_result), + + sha256_peek(&tls->handshake_sha256_ctx, handshake_hash); + prf_hmac_sha256(record.prf_result, sizeof(record.prf_result), tls->master_secret, sizeof(tls->master_secret), "client finished", handshake_hash, sizeof(handshake_hash) @@ -1182,12 +1186,13 @@ static void tls_handshake(tls_state_t *tls) //SvKey len=455^ // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes: // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... - dbg("got SERVER_KEY_EXCHANGE len:%u\n", len); -//need to save it + dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); +//probably need to save it xread_tls_handshake_block(tls, 4); } + // if (tls->inbuf[5] == HANDSHAKE_CERTIFICATE_REQUEST) { -// dbg("got CERTIFICATE_REQUEST\n"); +// dbg("<< CERTIFICATE_REQUEST\n"); //RFC 5246: (in response to this,) "If no suitable certificate is available, // the client MUST send a certificate message containing no // certificates. That is, the certificate_list structure has a @@ -1197,10 +1202,11 @@ static void tls_handshake(tls_state_t *tls) // (i.e. the same format as server certs) // xread_tls_handshake_block(tls, 4); // } + if (tls->inbuf[5] != HANDSHAKE_SERVER_HELLO_DONE) tls_error_die(tls); // 0e 000000 (len:0) - dbg("got SERVER_HELLO_DONE\n"); + dbg("<< SERVER_HELLO_DONE\n"); send_client_key_exchange(tls); @@ -1213,7 +1219,7 @@ static void tls_handshake(tls_state_t *tls) len = xread_tls_block(tls); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) tls_error_die(tls); - dbg("got CHANGE_CIPHER_SPEC\n"); + dbg("<< CHANGE_CIPHER_SPEC\n"); tls->decrypt_on_read = 1; /* we now should receive encrypted */ @@ -1221,7 +1227,7 @@ static void tls_handshake(tls_state_t *tls) len = xread_tls_block(tls); if (len < 4 || tls->inbuf[5] != HANDSHAKE_FINISHED) tls_error_die(tls); - dbg("got FINISHED\n"); + dbg("<< FINISHED\n"); /* application data can be sent/received */ } @@ -1252,8 +1258,6 @@ int tls_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } -//TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise - /* Unencryped SHA256 example: * $ openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' * $ openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL -- cgit v1.2.3-55-g6feb From c8ba23bcec94ecbc8ee82053d1b7e299cc839184 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2017 06:45:50 +0100 Subject: tls: massage writing for encryption support; finer-grained debug Signed-off-by: Denys Vlasenko --- networking/tls.c | 69 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 8bcaee9a6..9d1a0fca9 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -25,7 +25,9 @@ #include "tls.h" -#define TLS_DEBUG 2 +#define TLS_DEBUG 1 +#define TLS_DEBUG_HASH 0 +#define TLS_DEBUG_DER 0 #if TLS_DEBUG # define dbg(...) fprintf(stderr, __VA_ARGS__) @@ -33,6 +35,12 @@ # define dbg(...) ((void)0) #endif +#if TLS_DEBUG_DER +# define dbg_der(...) fprintf(stderr, __VA_ARGS__) +#else +# define dbg_der(...) ((void)0) +#endif + #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 #define RECORD_TYPE_ALERT 21 #define RECORD_TYPE_HANDSHAKE 22 @@ -269,7 +277,7 @@ static void sha256_peek(sha256_ctx_t *ctx, void *buffer) sha256_end(&ctx_copy, buffer); } -#if TLS_DEBUG >= 2 +#if TLS_DEBUG_HASH static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) { uint8_t h[SHA256_OUTSIZE]; @@ -283,7 +291,7 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff #else # define sha256_hash_dbg(fmt, ctx, buffer, len) \ sha256_hash(ctx, buffer, len) -#endif /* not TLS_DEBUG >= 2 */ +#endif // RFC 2104 // HMAC(key, text) based on a hash H (say, sha256) is: @@ -424,8 +432,7 @@ static void prf_hmac_sha256( #undef SEED } -static -tls_state_t *new_tls_state(void) +static tls_state_t *new_tls_state(void) { tls_state_t *tls = xzalloc(sizeof(*tls)); tls->fd = -1; @@ -488,31 +495,31 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size uint8_t mac_hash[SHA256_OUTSIZE]; struct record_hdr *xhdr = buf; - if (tls->encrypt_on_write) { + if (!tls->encrypt_on_write) { + xwrite(tls->fd, buf, size); + dbg("wrote %u bytes\n", size); + /* Handshake hash does not include record headers */ + if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { + sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); + } + return; + } + //TODO: convert hmac_sha256 to precomputed - hmac_sha256(mac_hash, + hmac_sha256(mac_hash, tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), &tls->write_seq64_be, sizeof(tls->write_seq64_be), buf, size, - NULL); - tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); - /* Temporarily change for writing */ - xhdr->len16_lo += SHA256_OUTSIZE; - } + NULL); + tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + xhdr->len16_lo += SHA256_OUTSIZE; xwrite(tls->fd, buf, size); + xhdr->len16_lo -= SHA256_OUTSIZE; dbg("wrote %u bytes\n", size); - if (tls->encrypt_on_write) { - xwrite(tls->fd, mac_hash, sizeof(mac_hash)); - dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); - xhdr->len16_lo -= SHA256_OUTSIZE; - } - - /* Handshake hash does not include record headers */ - if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); - } + xwrite(tls->fd, mac_hash, sizeof(mac_hash)); + dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); } static int xread_tls_block(tls_state_t *tls) @@ -611,7 +618,7 @@ static uint8_t *enter_der_item(uint8_t *der, uint8_t **endp) { uint8_t *new_der; unsigned len = get_der_len(&new_der, der, *endp); - dbg("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]); + dbg_der("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]); /* Move "end" position to cover only this item */ *endp = new_der + len; return new_der; @@ -623,7 +630,7 @@ static uint8_t *skip_der_item(uint8_t *der, uint8_t *end) unsigned len = get_der_len(&new_der, der, end); /* Skip body */ new_der += len; - dbg("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]); + dbg_der("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]); return new_der; } @@ -632,7 +639,7 @@ static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end) uint8_t *bin_ptr; unsigned len = get_der_len(&bin_ptr, der, end); - dbg("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); + dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]); pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len); pstm_read_unsigned_bin(pstm_n, bin_ptr, len); //return bin + len; @@ -854,7 +861,7 @@ static void send_client_hello(tls_state_t *tls) /* record.comprtypes[0] = 0; */ //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); - dbg(">> HANDSHAKE_CLIENT_HELLO\n"); + dbg(">> CLIENT_HELLO\n"); xwrite_and_hash(tls, &record, sizeof(record)); memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32)); } @@ -988,7 +995,7 @@ static void send_client_key_exchange(tls_state_t *tls) record.xhdr.len16_hi = len >> 8; record.xhdr.len16_lo = len & 0xff; - dbg(">> HANDSHAKE_CLIENT_KEY_EXCHANGE\n"); + dbg(">> CLIENT_KEY_EXCHANGE\n"); xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len); // RFC 5246 @@ -1114,13 +1121,13 @@ static void send_change_cipher_spec(tls_state_t *tls) // includes all existing cipher suites. static void send_client_finished(tls_state_t *tls) { - struct client_finished { + struct finished { struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; uint8_t prf_result[12]; }; - struct client_finished record; + struct finished record; uint8_t handshake_hash[SHA256_OUTSIZE]; fill_handshake_record_hdr(&record.xhdr, sizeof(record)); @@ -1134,13 +1141,13 @@ static void send_client_finished(tls_state_t *tls) ); dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); - dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); + dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); dump_hex("=> digest: %s\n", record.prf_result, sizeof(record.prf_result)); //(1) TODO: well, this should be encrypted on send, really. //(2) do we really need to also hash it? - dbg(">> HANDSHAKE_FINISHED\n"); + dbg(">> FINISHED\n"); xwrite_and_hash(tls, &record, sizeof(record)); } -- cgit v1.2.3-55-g6feb From b7e9ae6e9f8b1683774e2a69b943cec31c94f5a2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2017 17:20:27 +0100 Subject: tls: added AES code and made it compile. not used yet Signed-off-by: Denys Vlasenko --- networking/tls.c | 3 +- networking/tls.h | 41 +- networking/tls_aes.c | 1718 ++++++++++++++++++++++++++++++++++++++++++++ networking/tls_aes.h | 20 + networking/tls_symmetric.h | 500 +++++++++++++ 5 files changed, 2272 insertions(+), 10 deletions(-) create mode 100644 networking/tls_aes.c create mode 100644 networking/tls_aes.h create mode 100644 networking/tls_symmetric.h diff --git a/networking/tls.c b/networking/tls.c index 9d1a0fca9..4986c991d 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -15,8 +15,7 @@ //kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o //kbuild:lib-$(CONFIG_TLS) += tls_rsa.o -////kbuild:lib-$(CONFIG_TLS) += tls_ciphers.o -////kbuild:lib-$(CONFIG_TLS) += tls_aes.o +//kbuild:lib-$(CONFIG_TLS) += tls_aes.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o //usage:#define tls_trivial_usage diff --git a/networking/tls.h b/networking/tls.h index 3a8a3d826..5a0cb67e9 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -3,17 +3,40 @@ * * Licensed under GPLv2, see file LICENSE in this source tree. */ +/* Interface glue between bbox code and minimally tweaked matrixssl + * code. All C files (matrixssl and bbox (ones which need TLS)) + * include this file, and guaranteed to see a consistent API, + * defines, types, etc. + */ #include "libbb.h" -/* config tweaks */ -#define HAVE_NATIVE_INT64 1 -#undef DISABLE_PSTM + +/* Config tweaks */ +#define HAVE_NATIVE_INT64 #undef USE_1024_KEY_SPEED_OPTIMIZATIONS #undef USE_2048_KEY_SPEED_OPTIMIZATIONS -//TODO: enable to use asm: -//#if defined(__GNUC__) && defined(__i386__) -> #define PSTM_32BIT and PSTM_X86 -//#if defined(__GNUC__) && defined(__x86_64__) -> #define PSTM_64BIT and PSTM_X86_64 -//ARM and MIPS also have these +#define USE_AES +#undef USE_AES_CBC_EXTERNAL +#undef USE_AES_CCM +#undef USE_AES_GCM +#undef USE_3DES +#undef USE_ARC4 +#undef USE_IDEA +#undef USE_RC2 +#undef USE_SEED +/* pstm: multiprecision numbers */ +#undef DISABLE_PSTM +#if defined(__GNUC__) && defined(__i386__) +# define PSTM_32BIT +# define PSTM_X86 +#endif +//test this before enabling: +//#if defined(__GNUC__) && defined(__x86_64__) +//# define PSTM_64BIT +//# define PSTM_X86_64 +//#endif +//#if SOME_COND #define PSTM_MIPS, #define PSTM_32BIT +//#if SOME_COND #define PSTM_ARM, #define PSTM_32BIT #define PS_SUCCESS 0 @@ -65,9 +88,11 @@ void tls_get_random(void *buf, unsigned len); #define memset_s(A,B,C,D) memset((A),(C),(D)) /* Constant time memory comparison */ #define memcmpct(s1, s2, len) memcmp((s1), (s2), (len)) -#undef min +#undef min #define min(x, y) ((x) < (y) ? (x) : (y)) #include "tls_pstm.h" #include "tls_rsa.h" +#include "tls_symmetric.h" +#include "tls_aes.h" diff --git a/networking/tls_aes.c b/networking/tls_aes.c new file mode 100644 index 000000000..661bd8272 --- /dev/null +++ b/networking/tls_aes.c @@ -0,0 +1,1718 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +#include "tls.h" + +/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. + * Changes are flagged with ///bbox + */ + +/** + * @file aes.c + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * AES CBC block cipher implementation. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +///vda +//#include "../cryptoApi.h" + +#ifdef USE_AES +#ifndef USE_AES_CBC_EXTERNAL +/******************************************************************************/ + +/* The precomputed tables for AES */ +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +static const uint32 TE0[] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, + 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, + 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, + 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, + 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, + 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, + 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, + 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, + 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, + 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, + 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, + 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, + 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, + 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, + 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, + 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, + 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, + 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, + 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, + 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, + 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, + 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, + 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, + 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, + 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, + 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, + 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, +}; + +static const uint32 Te4[] = { + 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, + 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, + 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, + 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, + 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, + 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, + 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, + 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, + 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, + 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, + 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, + 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, + 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, + 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, + 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, + 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, + 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, + 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, + 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, + 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, + 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, + 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, + 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, + 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, + 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, + 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, + 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, + 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, + 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, + 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, + 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, + 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, + 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, + 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, + 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, + 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, + 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, + 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, + 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, + 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, + 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, + 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, + 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, + 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, + 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, + 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, + 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, + 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, + 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, + 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, + 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, + 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, + 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, + 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, + 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, + 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, + 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, + 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, + 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, + 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, + 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, + 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, + 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, + 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, +}; + +static const uint32 TD0[] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; + +static const uint32 Td4[] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, + 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL +}; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + +#define Te0(x) TE0[x] +#define Te1(x) ROR(TE0[x], 8) +#define Te2(x) ROR(TE0[x], 16) +#define Te3(x) ROR(TE0[x], 24) + +#define Td0(x) TD0[x] +#define Td1(x) ROR(TD0[x], 8) +#define Td2(x) ROR(TD0[x], 16) +#define Td3(x) ROR(TD0[x], 24) + +#define Te4_0 0x000000FF & Te4 +#define Te4_1 0x0000FF00 & Te4 +#define Te4_2 0x00FF0000 & Te4 +#define Te4_3 0xFF000000 & Te4 + +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] + +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] + +static const uint32 TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const uint32 TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const uint32 TE3[256] = { + + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; + +static const uint32 Te4_0[] = { +0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, +0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, +0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, +0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, +0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, +0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, +0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, +0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, +0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, +0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, +0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, +0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, +0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, +0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, +0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, +0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, +0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, +0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, +0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, +0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, +0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, +0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, +0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, +0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, +0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, +0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, +0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, +0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, +0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, +0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, +0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, +0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL +}; + +static const uint32 Te4_1[] = { +0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, +0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, +0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, +0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, +0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, +0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, +0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, +0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, +0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, +0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, +0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, +0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, +0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, +0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, +0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, +0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, +0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, +0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, +0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, +0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, +0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, +0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, +0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, +0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, +0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, +0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, +0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, +0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, +0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, +0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, +0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, +0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL +}; + +static const uint32 Te4_2[] = { +0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, +0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, +0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, +0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, +0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, +0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, +0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, +0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, +0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, +0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, +0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, +0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, +0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, +0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, +0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, +0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, +0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, +0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, +0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, +0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, +0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, +0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, +0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, +0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, +0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, +0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, +0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, +0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, +0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, +0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, +0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, +0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL +}; + +static const uint32 Te4_3[] = { +0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, +0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, +0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, +0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, +0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, +0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, +0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, +0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, +0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, +0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, +0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, +0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, +0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, +0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, +0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, +0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, +0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, +0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, +0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, +0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, +0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, +0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, +0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, +0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, +0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, +0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, +0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, +0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, +0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, +0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, +0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, +0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL +}; + +static const uint32 TD1[256] = { + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, + 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, + 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, + 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, + 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, + 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, + 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, + 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, + 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, + 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, + 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, + 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, + 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, + 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, + 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, + 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, + 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, + 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, + 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, + 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, + 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, + 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, + 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, + 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, + 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, + 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, + 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, + 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, + 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, + 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, + 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, + 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, + 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; +static const uint32 TD2[256] = { + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, + 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, + 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, + 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, + 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, + 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, + 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, + 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, + 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, + 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, + 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, + 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, + 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, + 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, + 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, + 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, + 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, + 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, + 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, + 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, + 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, + 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, + 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, + 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, + 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, + 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, + 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, + 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, + 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, + 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, + 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, + 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, + 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; +static const uint32 TD3[256] = { + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, + 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, + 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, + 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, + 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, + 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, + 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, + 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, + 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, + 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, + 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, + 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, + 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, + 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, + 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, + 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, + 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, + 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, + 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, + 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, + 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, + 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, + 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, + 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, + 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, + 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, + 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, + 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, + 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, + 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, + 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, + 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, + 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; + +static const uint32 Tks0[] = { +0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, +0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, +0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, +0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, +0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, +0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, +0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, +0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, +0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, +0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, +0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, +0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, +0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, +0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, +0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, +0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, +0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, +0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, +0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, +0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, +0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, +0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, +0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, +0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, +0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, +0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, +0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, +0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, +0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, +0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, +0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, +0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL +}; + +static const uint32 Tks1[] = { +0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, +0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, +0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, +0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, +0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, +0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, +0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, +0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, +0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, +0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, +0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, +0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, +0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, +0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, +0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, +0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, +0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, +0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, +0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, +0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, +0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, +0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, +0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, +0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, +0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, +0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, +0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, +0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, +0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, +0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, +0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, +0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL +}; + +static const uint32 Tks2[] = { +0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, +0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, +0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, +0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, +0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, +0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, +0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, +0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, +0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, +0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, +0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, +0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, +0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, +0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, +0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, +0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, +0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, +0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, +0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, +0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, +0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, +0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, +0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, +0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, +0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, +0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, +0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, +0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, +0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, +0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, +0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, +0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL +}; + +static const uint32 Tks3[] = { +0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, +0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, +0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, +0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, +0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, +0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, +0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, +0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, +0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, +0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, +0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, +0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, +0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, +0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, +0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, +0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, +0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, +0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, +0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, +0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, +0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, +0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, +0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, +0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, +0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, +0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, +0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, +0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, +0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, +0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, +0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, +0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL +}; + +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +static const uint32 rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, AES never uses more than 10 rcon values */ +}; + +#ifdef USE_BURN_STACK +static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey); +static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey); +#endif + +static uint32 setup_mix(uint32 temp) +{ + return (Te4_3[byte(temp, 2)]) ^ + (Te4_2[byte(temp, 1)]) ^ + (Te4_1[byte(temp, 0)]) ^ + (Te4_0[byte(temp, 3)]); +} + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE +static uint32 setup_mix2(uint32 temp) +{ + return Td0(255 & Te4[byte(temp, 3)]) ^ + Td1(255 & Te4[byte(temp, 2)]) ^ + Td2(255 & Te4[byte(temp, 1)]) ^ + Td3(255 & Te4[byte(temp, 0)]); +} +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* + Software implementation of AES CBC APIs + */ +#ifndef USE_AES_CBC_EXTERNAL +int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, + unsigned char *key, uint32 keylen) +{ + int32 x, err; + + if (IV == NULL || key == NULL || ctx == NULL) { + psTraceCrypto("psAesInit arg fail\n"); + return PS_ARG_FAIL; + } + memset(ctx, 0x0, sizeof(psCipherContext_t)); +/* + setup cipher + */ + if ((err = psAesInitKey(key, keylen, &ctx->aes.key)) != PS_SUCCESS) { + return err; + } +/* + copy IV + */ + ctx->aes.blocklen = 16; + for (x = 0; x < ctx->aes.blocklen; x++) { + ctx->aes.IV[x] = IV[x]; + } + return PS_SUCCESS; +} + +int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, + unsigned char *ct, uint32 len) +{ + int32 x; + uint32 i; + unsigned char tmp[MAXBLOCKSIZE]; + + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psAesEncrypt\n"); + return PS_ARG_FAIL; + } + +/* + is blocklen valid? + */ + if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen > + (int32)sizeof(ctx->aes.IV))) { + psTraceCrypto("Bad blocklen in psAesEncrypt\n"); + return PS_LIMIT_FAIL; + } + + for (i = 0; i < len; i += ctx->aes.blocklen) { +/* + xor IV against plaintext + */ + for (x = 0; x < ctx->aes.blocklen; x++) { + tmp[x] = pt[x] ^ ctx->aes.IV[x]; + } +/* + encrypt + */ + psAesEncryptBlock(tmp, ct, &ctx->aes.key); + +/* + store IV [ciphertext] for a future block + */ + for (x = 0; x < ctx->aes.blocklen; x++) { + ctx->aes.IV[x] = ct[x]; + } + ct += ctx->aes.blocklen; + pt += ctx->aes.blocklen; + } + + memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp)); + return len; +} + +int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, + unsigned char *pt, uint32 len) +{ + int32 x; + uint32 i; + unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE]; + + if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { + psTraceCrypto("Bad parameters to psAesDecrypt\n"); + return PS_ARG_FAIL; + } + +/* + is blocklen valid? + */ + if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen > + (int32)sizeof(ctx->aes.IV))) { + psTraceCrypto("Bad blocklen in psAesDecrypt\n"); + return PS_LIMIT_FAIL; + } + for (i = 0; i < len; i += ctx->aes.blocklen) { +/* + decrypt the block from ct into tmp + */ + psAesDecryptBlock(ct, tmp, &ctx->aes.key); +/* + xor IV against the plaintext of the previous step + */ + for (x = 0; x < ctx->aes.blocklen; x++) { +/* + copy CT in case ct == pt + */ + tmp2[x] = ct[x]; +/* + actually decrypt the byte + */ + pt[x] = tmp[x] ^ ctx->aes.IV[x]; + } +/* + replace IV with this current ciphertext + */ + for (x = 0; x < ctx->aes.blocklen; x++) { + ctx->aes.IV[x] = tmp2[x]; + } + ct += ctx->aes.blocklen; + pt += ctx->aes.blocklen; + } + memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp)); + memset_s(tmp2, sizeof(tmp2), 0x0, sizeof(tmp2)); + + return len; +} + +#endif /* USE_AES_CBC_EXTERNAL */ + +/******************************************************************************/ +/* + Initialize the AES (Rijndael) block cipher + + key: The symmetric key you wish to pass + keylen: The key length in bytes + skey: The key in as scheduled by this function. +*/ + +int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey) +{ + int32 i, j; + uint32 temp, *rk, *rrk; + + if (key == NULL || skey == NULL) { + psTraceCrypto("Bad args to psAesInitKey\n"); + return PS_ARG_FAIL; + } + + if (keylen != 16 && keylen != 24 && keylen != 32) { + psTraceCrypto("Invalid AES key length\n"); + ///bbox return CRYPT_INVALID_KEYSIZE; + //unreachable anyway + return PS_ARG_FAIL; + } + + memset(skey, 0x0, sizeof(psAesKey_t)); + skey->Nr = 10 + ((keylen/8)-2)*2; + +/* + setup the forward key + */ + i = 0; + rk = skey->eK; + LOAD32H(rk[0], key ); + LOAD32H(rk[1], key + 4); + LOAD32H(rk[2], key + 8); + LOAD32H(rk[3], key + 12); + if (keylen == 16) { + j = 44; + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + break; + } + rk += 4; + } + } else if (keylen == 24) { + j = 52; + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + for (;;) { + #ifdef _MSC_VER + temp = skey->eK[rk - skey->eK + 5]; + #else + temp = rk[5]; + #endif /* _MSC_VER */ + rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + break; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } else if (keylen == 32) { + j = 60; + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + LOAD32H(rk[6], key + 24); + LOAD32H(rk[7], key + 28); + for (;;) { + #ifdef _MSC_VER + temp = skey->eK[rk - skey->eK + 7]; + #else + temp = rk[7]; + #endif /* _MSC_VER */ + rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + break; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8)); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } else { +/* + this can't happen + */ + return PS_FAILURE; + } + +/* + setup the inverse key now + */ + rk = skey->dK; + rrk = skey->eK + j - 4; + +/* + apply the inverse MixColumn transform to all round keys but + the first and the last: + */ + /* copy first */ + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; rrk -= 3; + + for (i = 1; i < skey->Nr; i++) { + rrk -= 4; + rk += 4; +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + temp = rrk[0]; + rk[0] = setup_mix2(temp); + temp = rrk[1]; + rk[1] = setup_mix2(temp); + temp = rrk[2]; + rk[2] = setup_mix2(temp); + temp = rrk[3]; + rk[3] = setup_mix2(temp); +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + temp = rrk[0]; + rk[0] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[1]; + rk[1] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[2]; + rk[2] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; + temp = rrk[3]; + rk[3] = + Tks0[byte(temp, 3)] ^ + Tks1[byte(temp, 2)] ^ + Tks2[byte(temp, 1)] ^ + Tks3[byte(temp, 0)]; +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + } + + /* copy last */ + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + + return PS_SUCCESS; +} + + +#ifdef USE_BURN_STACK +void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey) +{ + _aes_ecb_encrypt(pt, ct, skey); + psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2); +} +static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey) +#else +void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey) +#endif /* USE_BURN_STACK */ +{ + uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int32 Nr, r; + + if (pt == NULL || ct == NULL || skey == NULL) { + return; + } + + Nr = skey->Nr; + rk = skey->eK; + +/* + map byte array block to cipher state + and add initial round key: + */ + LOAD32H(s0, pt ); s0 ^= rk[0]; + LOAD32H(s1, pt + 4); s1 ^= rk[1]; + LOAD32H(s2, pt + 8); s2 ^= rk[2]; + LOAD32H(s3, pt + 12); s3 ^= rk[3]; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + for (r = 0; ; r++) { + rk += 4; + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[0]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[1]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[2]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* + Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + + t0 = + Te0(byte(s0, 3)) ^ + Te1(byte(s1, 2)) ^ + Te2(byte(s2, 1)) ^ + Te3(byte(s3, 0)) ^ + rk[4]; + t1 = + Te0(byte(s1, 3)) ^ + Te1(byte(s2, 2)) ^ + Te2(byte(s3, 1)) ^ + Te3(byte(s0, 0)) ^ + rk[5]; + t2 = + Te0(byte(s2, 3)) ^ + Te1(byte(s3, 2)) ^ + Te2(byte(s0, 1)) ^ + Te3(byte(s1, 0)) ^ + rk[6]; + t3 = + Te0(byte(s3, 3)) ^ + Te1(byte(s0, 2)) ^ + Te2(byte(s1, 1)) ^ + Te3(byte(s2, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0(byte(t0, 3)) ^ + Te1(byte(t1, 2)) ^ + Te2(byte(t2, 1)) ^ + Te3(byte(t3, 0)) ^ + rk[0]; + s1 = + Te0(byte(t1, 3)) ^ + Te1(byte(t2, 2)) ^ + Te2(byte(t3, 1)) ^ + Te3(byte(t0, 0)) ^ + rk[1]; + s2 = + Te0(byte(t2, 3)) ^ + Te1(byte(t3, 2)) ^ + Te2(byte(t0, 1)) ^ + Te3(byte(t1, 0)) ^ + rk[2]; + s3 = + Te0(byte(t3, 3)) ^ + Te1(byte(t0, 2)) ^ + Te2(byte(t1, 1)) ^ + Te3(byte(t2, 0)) ^ + rk[3]; + } +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* + apply last round and map cipher state to byte array block: + */ + s0 = + (Te4_3[byte(t0, 3)]) ^ + (Te4_2[byte(t1, 2)]) ^ + (Te4_1[byte(t2, 1)]) ^ + (Te4_0[byte(t3, 0)]) ^ + rk[0]; + STORE32H(s0, ct); + s1 = + (Te4_3[byte(t1, 3)]) ^ + (Te4_2[byte(t2, 2)]) ^ + (Te4_1[byte(t3, 1)]) ^ + (Te4_0[byte(t0, 0)]) ^ + rk[1]; + STORE32H(s1, ct+4); + s2 = + (Te4_3[byte(t2, 3)]) ^ + (Te4_2[byte(t3, 2)]) ^ + (Te4_1[byte(t0, 1)]) ^ + (Te4_0[byte(t1, 0)]) ^ + rk[2]; + STORE32H(s2, ct+8); + s3 = + (Te4_3[byte(t3, 3)]) ^ + (Te4_2[byte(t0, 2)]) ^ + (Te4_1[byte(t1, 1)]) ^ + (Te4_0[byte(t2, 0)]) ^ + rk[3]; + STORE32H(s3, ct+12); +} + +#ifdef USE_BURN_STACK +void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey) +{ + _aes_ecb_decrypt(ct, pt, skey); + psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2); +} +static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey) +#else +void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey) +#endif /* USE_BURN_STACK */ +{ + uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; + int32 Nr, r; + + if (pt == NULL || ct == NULL || skey == NULL) { + return; + } + + Nr = skey->Nr; + rk = skey->dK; + +/* + map byte array block to cipher state and add initial round key: + */ + LOAD32H(s0, ct ); s0 ^= rk[0]; + LOAD32H(s1, ct + 4); s1 ^= rk[1]; + LOAD32H(s2, ct + 8); s2 ^= rk[2]; + LOAD32H(s3, ct + 12); s3 ^= rk[3]; + +#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE + for (r = 0; ; r++) { + rk += 4; + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[0]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[1]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[2]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* + Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + + t0 = + Td0(byte(s0, 3)) ^ + Td1(byte(s3, 2)) ^ + Td2(byte(s2, 1)) ^ + Td3(byte(s1, 0)) ^ + rk[4]; + t1 = + Td0(byte(s1, 3)) ^ + Td1(byte(s0, 2)) ^ + Td2(byte(s3, 1)) ^ + Td3(byte(s2, 0)) ^ + rk[5]; + t2 = + Td0(byte(s2, 3)) ^ + Td1(byte(s1, 2)) ^ + Td2(byte(s0, 1)) ^ + Td3(byte(s3, 0)) ^ + rk[6]; + t3 = + Td0(byte(s3, 3)) ^ + Td1(byte(s2, 2)) ^ + Td2(byte(s1, 1)) ^ + Td3(byte(s0, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0(byte(t0, 3)) ^ + Td1(byte(t3, 2)) ^ + Td2(byte(t2, 1)) ^ + Td3(byte(t1, 0)) ^ + rk[0]; + s1 = + Td0(byte(t1, 3)) ^ + Td1(byte(t0, 2)) ^ + Td2(byte(t3, 1)) ^ + Td3(byte(t2, 0)) ^ + rk[1]; + s2 = + Td0(byte(t2, 3)) ^ + Td1(byte(t1, 2)) ^ + Td2(byte(t0, 1)) ^ + Td3(byte(t3, 0)) ^ + rk[2]; + s3 = + Td0(byte(t3, 3)) ^ + Td1(byte(t2, 2)) ^ + Td2(byte(t1, 1)) ^ + Td3(byte(t0, 0)) ^ + rk[3]; + } +#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */ + +/* + apply last round and map cipher state to byte array block: + */ + s0 = + (Td4[byte(t0, 3)] & 0xff000000) ^ + (Td4[byte(t3, 2)] & 0x00ff0000) ^ + (Td4[byte(t2, 1)] & 0x0000ff00) ^ + (Td4[byte(t1, 0)] & 0x000000ff) ^ + rk[0]; + STORE32H(s0, pt); + s1 = + (Td4[byte(t1, 3)] & 0xff000000) ^ + (Td4[byte(t0, 2)] & 0x00ff0000) ^ + (Td4[byte(t3, 1)] & 0x0000ff00) ^ + (Td4[byte(t2, 0)] & 0x000000ff) ^ + rk[1]; + STORE32H(s1, pt+4); + s2 = + (Td4[byte(t2, 3)] & 0xff000000) ^ + (Td4[byte(t1, 2)] & 0x00ff0000) ^ + (Td4[byte(t0, 1)] & 0x0000ff00) ^ + (Td4[byte(t3, 0)] & 0x000000ff) ^ + rk[2]; + STORE32H(s2, pt+8); + s3 = + (Td4[byte(t3, 3)] & 0xff000000) ^ + (Td4[byte(t2, 2)] & 0x00ff0000) ^ + (Td4[byte(t1, 1)] & 0x0000ff00) ^ + (Td4[byte(t0, 0)] & 0x000000ff) ^ + rk[3]; + STORE32H(s3, pt+12); +} + + +/******************************************************************************/ +/******************************************************************************/ +#endif /* !USE_AES_CBC_EXTERNAL */ +#endif /* USE_AES */ +/******************************************************************************/ + diff --git a/networking/tls_aes.h b/networking/tls_aes.h new file mode 100644 index 000000000..ea8ed7ea9 --- /dev/null +++ b/networking/tls_aes.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + * + * Selected few declarations for AES. + */ + +int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey); +void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey); +void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey); + +int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, + unsigned char *key, uint32 keylen); +int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, + unsigned char *ct, uint32 len); +int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, + unsigned char *pt, uint32 len); diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h new file mode 100644 index 000000000..712ee600c --- /dev/null +++ b/networking/tls_symmetric.h @@ -0,0 +1,500 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + + +/* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h + * Changes are flagged with ///bbox + * TODO: + * Take a look at "roll %%cl" part... rotates by constant use fewer registers, + * and on many Intel CPUs rotates by %cl are slower: they take 2 cycles, not 1. + */ + +/******************************************************************************/ +/* 32-bit Rotates */ +/******************************************************************************/ +#if defined(_MSC_VER) +/******************************************************************************/ + +/* instrinsic rotate */ +#include +#pragma intrinsic(_lrotr,_lrotl) +#define ROR(x,n) _lrotr(x,n) +#define ROL(x,n) _lrotl(x,n) + +/******************************************************************************/ +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \ + !defined(INTEL_CC) && !defined(PS_NO_ASM) + +static inline unsigned ROL(unsigned word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline unsigned ROR(unsigned word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +/******************************************************************************/ +#else + +/* rotates the hard way */ +#define ROL(x, y) \ + ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \ + (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \ + 0xFFFFFFFFUL) +#define ROR(x, y) \ + ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ + ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#endif /* 32-bit Rotates */ +/******************************************************************************/ + +#ifdef HAVE_NATIVE_INT64 +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 +#else + #define CONST64(n) n ## ULL +#endif +#endif + +/******************************************************************************/ +/* + Endian helper macros + */ +#if defined (ENDIAN_NEUTRAL) +#define STORE32L(x, y) { \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD32L(x, y) { \ +x = ((unsigned long)((y)[3] & 255)<<24) | \ +((unsigned long)((y)[2] & 255)<<16) | \ +((unsigned long)((y)[1] & 255)<<8) | \ +((unsigned long)((y)[0] & 255)); \ +} + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +#define STORE32H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} + +#define LOAD32H(x, y) { \ +x = ((unsigned long)((y)[0] & 255)<<24) | \ +((unsigned long)((y)[1] & 255)<<16) | \ +((unsigned long)((y)[2] & 255)<<8) | \ +((unsigned long)((y)[3] & 255)); \ +} + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ +(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \ +} + +#endif /* ENDIAN_NEUTRAL */ + +#ifdef ENDIAN_LITTLE +#define STORE32H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>24)&255); \ +(y)[1] = (unsigned char)(((x)>>16)&255); \ +(y)[2] = (unsigned char)(((x)>>8)&255); \ +(y)[3] = (unsigned char)((x)&255); \ +} + +#define LOAD32H(x, y) { \ +x = ((unsigned long)((y)[0] & 255)<<24) | \ +((unsigned long)((y)[1] & 255)<<16) | \ +((unsigned long)((y)[2] & 255)<<8) | \ +((unsigned long)((y)[3] & 255)); \ +} + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \ +(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); } + +#ifdef ENDIAN_32BITWORD +#define STORE32L(x, y) { \ +unsigned long __t = (x); memcpy(y, &__t, 4); \ +} + +#define LOAD32L(x, y) memcpy(&(x), y, 4); + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +#else /* 64-bit words then */ +#define STORE32L(x, y) \ +{ unsigned long __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32L(x, y) \ +{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64L(x, y) \ +{ uint64 __t = (x); memcpy(y, &__t, 8); } + +#define LOAD64L(x, y) \ +{ memcpy(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_LITTLE */ + +#ifdef ENDIAN_BIG +#define STORE32L(x, y) { \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD32L(x, y) { \ +x = ((unsigned long)((y)[3] & 255)<<24) | \ +((unsigned long)((y)[2] & 255)<<16) | \ +((unsigned long)((y)[1] & 255)<<8) | \ +((unsigned long)((y)[0] & 255)); \ +} + +#define STORE64L(x, y) { \ +(y)[7] = (unsigned char)(((x)>>56)&255); \ +(y)[6] = (unsigned char)(((x)>>48)&255); \ +(y)[5] = (unsigned char)(((x)>>40)&255); \ +(y)[4] = (unsigned char)(((x)>>32)&255); \ +(y)[3] = (unsigned char)(((x)>>24)&255); \ +(y)[2] = (unsigned char)(((x)>>16)&255); \ +(y)[1] = (unsigned char)(((x)>>8)&255); \ +(y)[0] = (unsigned char)((x)&255); \ +} + +#define LOAD64L(x, y) { \ +x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \ +(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \ +(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \ +(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \ +} + +#ifdef ENDIAN_32BITWORD +#define STORE32H(x, y) \ +{ unsigned int __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32H(x, y) memcpy(&(x), y, 4); + +#define STORE64H(x, y) { \ +(y)[0] = (unsigned char)(((x)>>56)&255); \ +(y)[1] = (unsigned char)(((x)>>48)&255); \ +(y)[2] = (unsigned char)(((x)>>40)&255); \ +(y)[3] = (unsigned char)(((x)>>32)&255); \ +(y)[4] = (unsigned char)(((x)>>24)&255); \ +(y)[5] = (unsigned char)(((x)>>16)&255); \ +(y)[6] = (unsigned char)(((x)>>8)&255); \ +(y)[7] = (unsigned char)((x)&255); \ +} + +#define LOAD64H(x, y) { \ +x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \ +(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \ +(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \ +(((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \ +} + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ +{ unsigned long __t = (x); memcpy(y, &__t, 4); } + +#define LOAD32H(x, y) \ +{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; } + +#define STORE64H(x, y) \ +{ uint64 __t = (x); memcpy(y, &__t, 8); } + +#define LOAD64H(x, y) \ +{ memcpy(&(x), y, 8); } + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +#ifdef HAVE_NATIVE_INT64 +#define ROL64c(x, y) \ +( (((x)<<((uint64)(y)&63)) | \ +(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ +( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \ +((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF)) +#endif /* HAVE_NATIVE_INT64 */ +/******************************************************************************/ + + + +/* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. + * Changes are flagged with ///bbox + */ + +/** + * @file symmetric.h + * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master) + * + * Header for internal symmetric key cryptography support. + */ +/* + * Copyright (c) 2013-2015 INSIDE Secure Corporation + * Copyright (c) PeerSec Networks, 2002-2011 + * All Rights Reserved + * + * The latest version of this code is available at http://www.matrixssl.org + * + * This software is open source; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This General Public License does NOT permit incorporating this software + * into proprietary programs. If you are unable to comply with the GPL, a + * commercial license for this software may be purchased from INSIDE at + * http://www.insidesecure.com/eng/Company/Locations + * + * This program is distributed in WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * http://www.gnu.org/copyleft/gpl.html + */ +/******************************************************************************/ + +#ifndef _h_PS_SYMMETRIC +#define _h_PS_SYMMETRIC + +/******************************************************************************/ +#ifdef USE_AES +/******************************************************************************/ + + +#ifndef USE_AES_CBC_EXTERNAL +typedef struct { + uint32 eK[64], dK[64]; + int32 Nr; +} psAesKey_t; + +typedef struct { + int32 blocklen; + unsigned char IV[16]; + psAesKey_t key; +#if defined(USE_AES_GCM) || defined(USE_AES_CCM) + unsigned char EncCtr[16]; + unsigned char CtrBlock[16]; +#endif +#ifdef USE_AES_GCM + unsigned char gInit[16]; + uint32 TagTemp[4]; + unsigned char Hash_SubKey[16]; + uint32 ProcessedBitCount[4]; + uint32 InputBufferCount; + uint32 OutputBufferCount; + union + { + unsigned char Buffer[128]; + uint32 BufferAlignment; + } Input; +#endif /* USE_AES_GCM */ +#ifdef USE_AES_CCM + uint32_t ccmTagTemp[16 / sizeof(uint32_t)]; /* 32 */ + union + { + /* Used for formatting IV. */ + uint8_t Temporary[16]; + /* Used for processing Mac. */ + uint8_t Y0[16]; + } u; /* 48 */ +#endif /* USE_AES_CCM */ +} psAesCipher_t; +#endif /* USE_AES_CBC_EXTERNAL */ + +#endif /* USE_AES */ + +#ifdef USE_IDEA +#define SSL_IDEA_KEY_LEN 16 +#define SSL_IDEA_IV_LEN 8 +#define SSL_IDEA_BLOCK_LEN 8 + +typedef struct { + uint16 key_schedule[52]; +} psIdeaKey_t; + +typedef struct { + psIdeaKey_t key; + uint32 IV[2]; + short for_encryption; + short inverted; +} idea_CBC; +#endif +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_SEED +/******************************************************************************/ +#define SSL_SEED_KEY_LEN 16 +#define SSL_SEED_IV_LEN 16 + + +typedef struct { + uint32 K[32], dK[32]; +} psSeedKey_t; + +typedef struct { + int32 blocklen; + unsigned char IV[16]; + psSeedKey_t key; +} seed_CBC; + +#endif /* USE_SEED */ +/******************************************************************************/ + +/******************************************************************************/ +#if defined(USE_3DES) || defined(USE_DES) +/******************************************************************************/ +#define DES3_KEY_LEN 24 +#define DES3_IV_LEN 8 +#define DES_KEY_LEN 8 + +typedef struct { + uint32 ek[3][32], dk[3][32]; +} psDes3Key_t; + +/* + A block cipher CBC structure + */ +typedef struct { + int32 blocklen; + unsigned char IV[8]; + psDes3Key_t key; +} des3_CBC; + +#endif /* USE_3DES || USE_DES */ +/******************************************************************************/ + +/******************************************************************************/ +#ifdef USE_ARC4 +typedef struct { + unsigned char state[256]; + uint32 byteCount; + unsigned char x; + unsigned char y; +} psRc4Key_t; +#endif /* USE_ARC4 */ +/******************************************************************************/ +#ifdef USE_RC2 +typedef struct { + unsigned xkey[64]; +} psRc2Key_t; + +typedef struct { + int32 blocklen; + unsigned char IV[8]; + psRc2Key_t key; +} rc2_CBC; +#endif /* USE_RC2 */ +/******************************************************************************/ +/* Universal types and defines */ +/******************************************************************************/ +#define MAXBLOCKSIZE 24 + +typedef union { +#ifdef USE_RC2 + rc2_CBC rc2; +#endif +#ifdef USE_ARC4 + psRc4Key_t arc4; +#endif +#ifdef USE_3DES + des3_CBC des3; +#endif +#ifdef USE_AES + psAesCipher_t aes; +#endif +#ifdef USE_SEED + seed_CBC seed; +#endif +#ifdef USE_IDEA + idea_CBC idea; +#endif +} psCipherContext_t; + +#define byte(x, n) (((x) >> (8 * (n))) & 255) + +#endif /* _h_PS_SYMMETRIC */ +/******************************************************************************/ -- cgit v1.2.3-55-g6feb From b5dfc3dfd69ec20358827f8ecb2a42ca4b290f03 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2017 20:37:24 +0100 Subject: tls: teach it to send AES256-encrypted data >> CLIENT_HELLO wrote 50 bytes insize:0 tail:0 got block len:74 got HANDSHAKE << SERVER_HELLO insize:79 tail:0 got block len:2397 got HANDSHAKE << CERTIFICATE key bytes:271, first:0x00 server_rsa_pub_key.size:256 insize:2402 tail:0 got block len:4 got HANDSHAKE << SERVER_HELLO_DONE >> CLIENT_KEY_EXCHANGE wrote 267 bytes master secret:c51df5b1e3b3f57373cdd8ea28e8ce562059636cf9f585d0b89c7f4bacec97e674d7b91f93e7b500cb64637f240c3b78 client_write_MAC_key:3b0b7e2bab241b629c37eb3a3824f09b39fe71a00876b0c8026dda16ef0d2f82 client_write_key:d36e801470ed2f0a8fc886ac25df57ffbe4265d06e3192122c4ef4df1e32fab2 >> CHANGE_CIPHER_SPEC from secret: c51df5b1e3b3f57373cdd8ea28e8ce562059636cf9f585d0b89c7f4bacec97e674d7b91f93e7b500cb64637f240c3b78 from labelSeed: 636c69656e742066696e6973686564b22e0e6008b8ee218cc02e4a93e4a42b570535f9b57662e262d43b379d125b69 => digest: a45bfee8ed6507a2a9920d0c >> FINISHED before crypt: 5 hdr + 16 data + 32 hash bytes writing 5 + 16 IV + 64 encrypted bytes, padding_length:0x0f wrote 85 bytes insize:9 tail:0 got block len:1 << CHANGE_CIPHER_SPEC insize:6 tail:0 got block len:80 < hdr_type:22 ver:3.3 len:80 type:21 len24:9541723 |1591985b...a3da| The last line is the server's FINISHED response, encrypted. Signed-off-by: Denys Vlasenko --- networking/tls.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 11 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 4986c991d..2b1e36110 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -143,14 +143,25 @@ //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? -#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) //#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE //^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) -//test TLS_RSA_WITH_AES_128_CBC_SHA, in tls 1.2 it's mandated to be always supported +//test TLS_RSA_WITH_AES_128_CBC_SHA, in TLS 1.2 it's mandated to be always supported + +// works against "openssl s_server -cipher NULL" +// and against wolfssl-3.9.10-stable/examples/server/server.c: +//#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) +// "works", meaning +// "can send encrypted FINISHED to wolfssl-3.9.10-stable/examples/server/server.c", +// don't yet read its encrypted answers: +#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE enum { SHA256_INSIZE = 64, SHA256_OUTSIZE = 32, + + AES_BLOCKSIZE = 16, + AES128_KEYSIZE = 16, + AES256_KEYSIZE = 32, }; struct record_hdr { @@ -172,6 +183,9 @@ typedef struct tls_state { uint8_t encrypt_on_write; uint8_t decrypt_on_read; uint8_t client_write_MAC_key[SHA256_OUTSIZE]; + uint8_t server_write_MAC_key[SHA256_OUTSIZE]; + uint8_t client_write_key[AES256_KEYSIZE]; + uint8_t server_write_key[AES256_KEYSIZE]; // RFC 5246 // sequence number // Each connection state contains a sequence number, which is @@ -208,7 +222,10 @@ typedef struct tls_state { // Since our buffer also contains 5-byte headers, make it a bit bigger: int insize; int tail; - uint8_t inbuf[18*1024]; +//needed? + uint64_t align____; + uint8_t inbuf[20*1024]; + uint8_t outbuf[20*1024]; } tls_state_t; @@ -512,13 +529,114 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size NULL); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); - xhdr->len16_lo += SHA256_OUTSIZE; - xwrite(tls->fd, buf, size); - xhdr->len16_lo -= SHA256_OUTSIZE; - dbg("wrote %u bytes\n", size); + if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { + /* No encryption, only signing */ + xhdr->len16_lo += SHA256_OUTSIZE; +//FIXME: overflow into len16_hi? + xwrite(tls->fd, buf, size); + xhdr->len16_lo -= SHA256_OUTSIZE; + dbg("wrote %u bytes\n", size); + + xwrite(tls->fd, mac_hash, sizeof(mac_hash)); + dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); + return; + } + + // RFC 5246 + // 6.2.3.2. CBC Block Cipher + // For block ciphers (such as 3DES or AES), the encryption and MAC + // functions convert TLSCompressed.fragment structures to and from block + // TLSCiphertext.fragment structures. + // struct { + // opaque IV[SecurityParameters.record_iv_length]; + // block-ciphered struct { + // opaque content[TLSCompressed.length]; + // opaque MAC[SecurityParameters.mac_length]; + // uint8 padding[GenericBlockCipher.padding_length]; + // uint8 padding_length; + // }; + // } GenericBlockCipher; + //... + // IV + // The Initialization Vector (IV) SHOULD be chosen at random, and + // MUST be unpredictable. Note that in versions of TLS prior to 1.1, + // there was no IV field (...). For block ciphers, the IV length is + // of length SecurityParameters.record_iv_length, which is equal to the + // SecurityParameters.block_size. + // padding + // Padding that is added to force the length of the plaintext to be + // an integral multiple of the block cipher's block length. + // padding_length + // The padding length MUST be such that the total size of the + // GenericBlockCipher structure is a multiple of the cipher's block + // length. Legal values range from zero to 255, inclusive. + //... + // Appendix C. Cipher Suite Definitions + //... + // Key IV Block + // Cipher Type Material Size Size + // ------------ ------ -------- ---- ----- + // NULL Stream 0 0 N/A + // RC4_128 Stream 16 0 N/A + // 3DES_EDE_CBC Block 24 8 8 + // AES_128_CBC Block 16 16 16 + // AES_256_CBC Block 32 16 16 + { + psCipherContext_t ctx; + uint8_t *p; + uint8_t padding_length; + + /* Build IV+content+MAC+padding in outbuf */ + tls_get_random(tls->outbuf, AES_BLOCKSIZE); /* IV */ + p = tls->outbuf + AES_BLOCKSIZE; + size -= sizeof(*xhdr); + dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, sizeof(mac_hash)); + p = mempcpy(p, buf + sizeof(*xhdr), size); /* content */ + p = mempcpy(p, mac_hash, sizeof(mac_hash)); /* MAC */ + size += sizeof(mac_hash); + // RFC is talking nonsense: + // Padding that is added to force the length of the plaintext to be + // an integral multiple of the block cipher's block length. + // WRONG. _padding+padding_length_, not just _padding_, + // pads the data. + // IOW: padding_length is the last byte of padding[] array, + // contrary to what RFC depicts. + // + // What actually happens is that there is always padding. + // If you need one byte to reach BLOCKSIZE, this byte is 0x00. + // If you need two bytes, they are both 0x01. + // If you need three, they are 0x02,0x02,0x02. And so on. + // If you need no bytes to reach BLOCKSIZE, you have to pad a full + // BLOCKSIZE with bytes of value (BLOCKSIZE-1). + // It's ok to have more than minimum padding, but we do minimum. + padding_length = (~size) & (AES_BLOCKSIZE - 1); + do { + *p++ = padding_length; /* padding */ + size++; + } while ((size & (AES_BLOCKSIZE - 1)) != 0); + + /* Encrypt content+MAC+padding in place */ + psAesInit(&ctx, tls->outbuf, /* IV */ + tls->client_write_key, sizeof(tls->client_write_key) + ); + psAesEncrypt(&ctx, + tls->outbuf + AES_BLOCKSIZE, /* plaintext */ + tls->outbuf + AES_BLOCKSIZE, /* ciphertext */ + size + ); - xwrite(tls->fd, mac_hash, sizeof(mac_hash)); - dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); + /* Write out */ + dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", + AES_BLOCKSIZE, size, padding_length); + size += AES_BLOCKSIZE; /* + IV */ + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + xwrite(tls->fd, xhdr, sizeof(*xhdr)); + xwrite(tls->fd, tls->outbuf, size); + dbg("wrote %u bytes\n", sizeof(*xhdr) + size); +//restore xhdr->len16_hi = ; +//restore xhdr->len16_lo = ; + } } static int xread_tls_block(tls_state_t *tls) @@ -1048,14 +1166,30 @@ static void send_client_key_exchange(tls_state_t *tls) // server_write_key[SecurityParameters.enc_key_length] // client_write_IV[SecurityParameters.fixed_iv_length] // server_write_IV[SecurityParameters.fixed_iv_length] + + + // Key IV Block + // Cipher Type Material Size Size + // ------------ ------ -------- ---- ----- + // NULL Stream 0 0 N/A + // RC4_128 Stream 16 0 N/A + // 3DES_EDE_CBC Block 24 8 8 + // AES_128_CBC Block 16 16 16 + // AES_256_CBC Block 32 16 16 + { uint8_t tmp64[64]; - /* make server_rand32 + client_rand32 */ + + /* make "server_rand32 + client_rand32" */ memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); prf_hmac_sha256( - tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), + tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), + // also fills: + // server_write_MAC_key[SHA256_OUTSIZE] + // client_write_key[AES256_KEYSIZE] + // server_write_key[AES256_KEYSIZE] tls->master_secret, sizeof(tls->master_secret), "key expansion", tmp64, 64 @@ -1063,6 +1197,9 @@ static void send_client_key_exchange(tls_state_t *tls) dump_hex("client_write_MAC_key:%s\n", tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key) ); + dump_hex("client_write_key:%s\n", + tls->client_write_key, sizeof(tls->client_write_key) + ); } } -- cgit v1.2.3-55-g6feb From a9e186680668056e2c35ce5a99769a7ff0df44cd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Jan 2017 21:00:23 +0100 Subject: tls: trim comments Signed-off-by: Denys Vlasenko --- networking/tls.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 2b1e36110..6928582df 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -494,16 +494,11 @@ static void tls_error_die(tls_state_t *tls) // Key IV Block // Cipher Type Material Size Size // ------------ ------ -------- ---- ----- -// NULL Stream 0 0 N/A -// RC4_128 Stream 16 0 N/A -// 3DES_EDE_CBC Block 24 8 8 // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 // // MAC Algorithm mac_length mac_key_length // -------- ----------- ---------- -------------- -// NULL N/A 0 0 -// MD5 HMAC-MD5 16 16 // SHA HMAC-SHA1 20 20 // SHA256 HMAC-SHA256 32 32 static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size) @@ -576,9 +571,6 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size // Key IV Block // Cipher Type Material Size Size // ------------ ------ -------- ---- ----- - // NULL Stream 0 0 N/A - // RC4_128 Stream 16 0 N/A - // 3DES_EDE_CBC Block 24 8 8 // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 { @@ -595,8 +587,8 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size p = mempcpy(p, mac_hash, sizeof(mac_hash)); /* MAC */ size += sizeof(mac_hash); // RFC is talking nonsense: - // Padding that is added to force the length of the plaintext to be - // an integral multiple of the block cipher's block length. + // Padding that is added to force the length of the plaintext to be + // an integral multiple of the block cipher's block length. // WRONG. _padding+padding_length_, not just _padding_, // pads the data. // IOW: padding_length is the last byte of padding[] array, @@ -1166,17 +1158,6 @@ static void send_client_key_exchange(tls_state_t *tls) // server_write_key[SecurityParameters.enc_key_length] // client_write_IV[SecurityParameters.fixed_iv_length] // server_write_IV[SecurityParameters.fixed_iv_length] - - - // Key IV Block - // Cipher Type Material Size Size - // ------------ ------ -------- ---- ----- - // NULL Stream 0 0 N/A - // RC4_128 Stream 16 0 N/A - // 3DES_EDE_CBC Block 24 8 8 - // AES_128_CBC Block 16 16 16 - // AES_256_CBC Block 32 16 16 - { uint8_t tmp64[64]; -- cgit v1.2.3-55-g6feb From cccf8e735da9eb62f1de021534ca50255d82e931 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 00:20:45 +0100 Subject: tls: teach it to decrypt AES256-encrypted data This adds decryption only. There is no MAC verification, code simply throws away MAC. Signed-off-by: Denys Vlasenko --- networking/tls.c | 73 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 6928582df..f3d0bde90 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -181,7 +181,7 @@ typedef struct tls_state { uint8_t master_secret[48]; uint8_t encrypt_on_write; - uint8_t decrypt_on_read; + int min_encrypted_len_on_read; uint8_t client_write_MAC_key[SHA256_OUTSIZE]; uint8_t server_write_MAC_key[SHA256_OUTSIZE]; uint8_t client_write_key[AES256_KEYSIZE]; @@ -634,7 +634,7 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size static int xread_tls_block(tls_state_t *tls) { struct record_hdr *xhdr; - int len; + int sz; int total; int target; @@ -658,24 +658,57 @@ static int xread_tls_block(tls_state_t *tls) /* if total >= target, we have a full packet (and possibly more)... */ if (total - target >= 0) break; - len = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); - if (len <= 0) + sz = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); + if (sz <= 0) bb_perror_msg_and_die("short read"); - total += len; + total += sz; } tls->tail = total - target; tls->insize = target; - target -= sizeof(*xhdr); + sz = target - sizeof(*xhdr); + + /* Needs to be decrypted? */ + if (tls->min_encrypted_len_on_read) { + psCipherContext_t ctx; + uint8_t *p = tls->inbuf + sizeof(*xhdr); + int padding_len; + + if (sz & (AES_BLOCKSIZE-1) + || sz < tls->min_encrypted_len_on_read + ) { + bb_error_msg_and_die("bad encrypted len:%u", sz); + } + /* Decrypt content+MAC+padding in place */ + psAesInit(&ctx, p, /* IV */ + tls->server_write_key, sizeof(tls->server_write_key) + ); + psAesDecrypt(&ctx, + p + AES_BLOCKSIZE, /* ciphertext */ + p + AES_BLOCKSIZE, /* plaintext */ + sz + ); + padding_len = p[sz - 1]; + dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); + padding_len++; + sz -= AES_BLOCKSIZE + SHA256_OUTSIZE + padding_len; + if (sz < 0) { + bb_error_msg_and_die("bad padding size:%u", padding_len); + } + if (sz != 0) { + /* Skip IV */ + memmove(tls->inbuf + 5, tls->inbuf + 5 + AES_BLOCKSIZE, sz); + } + } /* RFC 5246 is not saying it explicitly, but sha256 hash * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, target); + sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, sz); } - dbg("got block len:%u\n", target); - return target; + dbg("got block len:%u\n", sz); + return sz; } /* @@ -1194,9 +1227,6 @@ static void send_change_cipher_spec(tls_state_t *tls) /* Not "xwrite_and_hash": this is not a handshake message */ dbg(">> CHANGE_CIPHER_SPEC\n"); xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); - - /* tls->write_seq64_be = 0; - already is */ - tls->encrypt_on_write = 1; } // 7.4.9. Finished @@ -1335,7 +1365,9 @@ static void tls_handshake(tls_state_t *tls) send_client_key_exchange(tls); send_change_cipher_spec(tls); - /* we now should send encrypted... as soon as we grok AES. */ + /* from now on we should send encrypted */ + /* tls->write_seq64_be = 0; - already is */ + tls->encrypt_on_write = 1; send_client_finished(tls); @@ -1344,8 +1376,8 @@ static void tls_handshake(tls_state_t *tls) if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) tls_error_die(tls); dbg("<< CHANGE_CIPHER_SPEC\n"); - tls->decrypt_on_read = 1; - /* we now should receive encrypted */ + /* all incoming packets now should be encrypted and have IV + MAC + padding */ + tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; /* Get (encrypted) FINISHED from the server */ len = xread_tls_block(tls); @@ -1356,8 +1388,13 @@ static void tls_handshake(tls_state_t *tls) } // To run a test server using openssl: +// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 +// +// Unencryped SHA256 example: // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' +// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL +// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tls_main(int argc UNUSED_PARAM, char **argv) @@ -1381,12 +1418,8 @@ int tls_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } - /* Unencryped SHA256 example: - * $ openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' - * $ openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL - * $ openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 - * s_client says: + * s_client says: write to 0x1d750b0 [0x1e6f153] (99 bytes => 99 (0x63)) 0000 - 16 03 01 005e 01 00005a 0303 [4d ef 5c 82 3e ....^...Z..M.\.> >> ClHello -- cgit v1.2.3-55-g6feb From 704c606f480ff9b274582fabb2c4006919f9542d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 14:29:42 +0100 Subject: fdisk: add typical values of -H and -S to --help Signed-off-by: Denys Vlasenko --- util-linux/fdisk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 54f37baa6..916d4e30e 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -103,8 +103,8 @@ //usage: ) //usage: "\n -b 2048 (for certain MO disks) use 2048-byte sectors" //usage: "\n -C CYLINDERS Set number of cylinders/heads/sectors" -//usage: "\n -H HEADS" -//usage: "\n -S SECTORS" +//usage: "\n -H HEADS Typically 255" +//usage: "\n -S SECTORS Typically 63" #ifndef _LARGEFILE64_SOURCE /* For lseek64 */ -- cgit v1.2.3-55-g6feb From 1bfc4b85a7915210936edc62ecf0d01a17751222 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 14:42:34 +0100 Subject: ntpd: print result of hostname resolution This is particularly useful if hostname resolution is triggered by host non-reachability: I saw this in real-life, without the message it is not at all obvious that IP that we use for a specific host has changed. Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index bfd5705fc..5cc71ca7a 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -757,7 +757,7 @@ reset_peer_stats(peer_t *p, double offset) * and clear reachable bits, but this proved to be too agressive: * after step (tested with suspending laptop for ~30 secs), * this caused all previous data to be considered invalid, - * making us needing to collect full ~8 datapoins per peer + * making us needing to collect full ~8 datapoints per peer * after step in order to start trusting them. * In turn, this was making poll interval decrease even after * step was done. (Poll interval decreases already before step @@ -800,6 +800,8 @@ resolve_peer_hostname(peer_t *p) free(p->p_dotted); p->p_lsa = lsa; p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); + VERB1 if (strcmp(p->p_hostname, p->p_dotted) != 0) + bb_error_msg("'%s' is %s", p->p_hostname, p->p_dotted); } else { /* error message is emitted by host2sockaddr() */ set_next(p, HOSTNAME_INTERVAL); -- cgit v1.2.3-55-g6feb From 6b1b004845ebec194c4d4868d3deb57f22711b19 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 15:51:00 +0100 Subject: tls: commented out psPool_t use function old new delta psAesEncrypt 159 162 +3 der_binary_to_pstm 42 40 -2 xwrite_and_hash 437 434 -3 xread_tls_block 446 443 -3 pstm_div_2d 449 444 -5 psAesDecrypt 179 174 -5 pstm_init_size 52 45 -7 pstm_init 46 39 -7 pstm_to_unsigned_bin 165 157 -8 tls_main 1265 1256 -9 pstm_mulmod 132 123 -9 pstm_mod 125 116 -9 pstm_init_copy 93 84 -9 psAesInitKey 840 825 -15 send_client_key_exchange 362 342 -20 psAesInit 103 80 -23 psRsaEncryptPub 429 403 -26 psAesDecryptBlock 1211 1184 -27 psAesEncryptBlock 1223 1193 -30 pstm_exptmod 1582 1524 -58 pstm_div 1557 1472 -85 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/20 up/down: 3/-360) Total: -357 bytes Signed-off-by: Denys Vlasenko --- networking/tls.h | 3 +- networking/tls_aes.c | 60 +++++++++++++++++++-------------- networking/tls_pstm.c | 27 ++++++++------- networking/tls_pstm.h | 47 +++++++++++++++++++++++--- networking/tls_pstm_montgomery_reduce.c | 6 ++-- networking/tls_pstm_mul_comba.c | 10 +++--- networking/tls_pstm_sqr_comba.c | 10 +++--- networking/tls_rsa.c | 20 ++++++----- networking/tls_rsa.h | 4 +-- networking/tls_symmetric.h | 4 +-- 10 files changed, 122 insertions(+), 69 deletions(-) diff --git a/networking/tls.h b/networking/tls.h index 5a0cb67e9..5e6b346e2 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -66,8 +66,7 @@ typedef int32_t int32; typedef uint16_t uint16; typedef int16_t int16; -//FIXME -typedef char psPool_t; +//typedef char psPool_t; //#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM #define PS_EXPTMOD_WINSIZE 3 diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 661bd8272..6c3c39373 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -6,7 +6,7 @@ #include "tls.h" /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -43,7 +43,7 @@ */ /******************************************************************************/ -///vda +//bbox //#include "../cryptoApi.h" #ifdef USE_AES @@ -1084,10 +1084,11 @@ int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, { int32 x, err; - if (IV == NULL || key == NULL || ctx == NULL) { - psTraceCrypto("psAesInit arg fail\n"); - return PS_ARG_FAIL; - } +//bbox +// if (IV == NULL || key == NULL || ctx == NULL) { +// psTraceCrypto("psAesInit arg fail\n"); +// return PS_ARG_FAIL; +// } memset(ctx, 0x0, sizeof(psCipherContext_t)); /* setup cipher @@ -1112,10 +1113,13 @@ int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, uint32 i; unsigned char tmp[MAXBLOCKSIZE]; - if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { - psTraceCrypto("Bad parameters to psAesEncrypt\n"); - return PS_ARG_FAIL; - } +//bbox +// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { +// psTraceCrypto("Bad parameters to psAesEncrypt\n"); +// return PS_ARG_FAIL; +// } + if ((len & 0x7) != 0) + bb_error_msg_and_die("AES len:%d", len); /* is blocklen valid? @@ -1159,10 +1163,13 @@ int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, uint32 i; unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE]; - if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { - psTraceCrypto("Bad parameters to psAesDecrypt\n"); - return PS_ARG_FAIL; - } +//bbox +// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) { +// psTraceCrypto("Bad parameters to psAesDecrypt\n"); +// return PS_ARG_FAIL; +// } + if ((len & 0x7) != 0) + bb_error_msg_and_die("AES len:%d", len); /* is blocklen valid? @@ -1221,14 +1228,15 @@ int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey) int32 i, j; uint32 temp, *rk, *rrk; - if (key == NULL || skey == NULL) { - psTraceCrypto("Bad args to psAesInitKey\n"); - return PS_ARG_FAIL; - } +//bbox +// if (key == NULL || skey == NULL) { +// psTraceCrypto("Bad args to psAesInitKey\n"); +// return PS_ARG_FAIL; +// } if (keylen != 16 && keylen != 24 && keylen != 32) { psTraceCrypto("Invalid AES key length\n"); - ///bbox return CRYPT_INVALID_KEYSIZE; + //bbox return CRYPT_INVALID_KEYSIZE; //unreachable anyway return PS_ARG_FAIL; } @@ -1398,9 +1406,10 @@ void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; int32 Nr, r; - if (pt == NULL || ct == NULL || skey == NULL) { - return; - } +//bbox +// if (pt == NULL || ct == NULL || skey == NULL) { +// return; +// } Nr = skey->Nr; rk = skey->eK; @@ -1562,9 +1571,10 @@ void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk; int32 Nr, r; - if (pt == NULL || ct == NULL || skey == NULL) { - return; - } +//bbox +// if (pt == NULL || ct == NULL || skey == NULL) { +// return; +// } Nr = skey->Nr; rk = skey->dK; diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c index f802baa15..acd800307 100644 --- a/networking/tls_pstm.c +++ b/networking/tls_pstm.c @@ -6,7 +6,7 @@ #include "tls.h" /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -43,7 +43,7 @@ */ /******************************************************************************/ -///bbox +//bbox //#include "../cryptoApi.h" #ifndef DISABLE_PSTM @@ -55,21 +55,21 @@ static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c); */ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) { -///bbox +//bbox // uint16 x; /* alloc mem */ - a->dp = xzalloc(sizeof (pstm_digit) * size);///bbox - a->pool = pool; + a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox +//bbox a->pool = pool; a->used = 0; a->alloc = (int16)size; a->sign = PSTM_ZPOS; /* zero the digits */ -///bbox +//bbox // for (x = 0; x < size; x++) { // a->dp[x] = 0; // } @@ -82,16 +82,16 @@ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) */ int32 pstm_init(psPool_t *pool, pstm_int * a) { -///bbox +//bbox // int32 i; /* allocate memory required and clear it */ - a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);///bbox + a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);//bbox /* set the digits to zero */ -///bbox +//bbox // for (i = 0; i < PSTM_DEFAULT_INIT; i++) { // a->dp[i] = 0; // } @@ -99,7 +99,7 @@ int32 pstm_init(psPool_t *pool, pstm_int * a) set the used to zero, allocated digits to the default precision and sign to positive */ - a->pool = pool; +//bbox a->pool = pool; a->used = 0; a->alloc = PSTM_DEFAULT_INIT; a->sign = PSTM_ZPOS; @@ -126,7 +126,7 @@ int32 pstm_grow(pstm_int * a, int16 size) We store the return in a temporary variable in case the operation failed we don't want to overwrite the dp member of a. */ - tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);///bbox + tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);//bbox /* reallocation succeeded so set a->dp */ @@ -1622,7 +1622,7 @@ int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, Pre-allocated digit. Used for mul, sqr, AND reduce */ paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit); - paD = xzalloc(paDlen);///bbox + paD = xzalloc(paDlen);//bbox /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ @@ -1941,6 +1941,9 @@ int32 pstm_cmp_d(pstm_int *a, pstm_digit b) in cases where dQ > dP. The values must be switched and a new qP must be calculated using this function */ +//bbox: pool unused +#define pstm_invmod_slow(pool, a, b, c) \ + pstm_invmod_slow( a, b, c) static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b, pstm_int * c) { diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h index de03e3f92..3a0fd8ce6 100644 --- a/networking/tls_pstm.h +++ b/networking/tls_pstm.h @@ -4,7 +4,7 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -124,7 +124,7 @@ typedef struct { int16 used, alloc, sign; pstm_digit *dp; - psPool_t *pool; +//bbox psPool_t *pool; } pstm_int; /******************************************************************************/ @@ -140,15 +140,27 @@ extern void pstm_set(pstm_int *a, pstm_digit b); extern void pstm_zero(pstm_int * a); +//bbox: pool unused +#define pstm_init(pool, a) \ + pstm_init( a) extern int32 pstm_init(psPool_t *pool, pstm_int * a); +//bbox: pool unused +#define pstm_init_size(pool, a, size) \ + pstm_init_size( a, size) extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size); +//bbox: pool unused +#define pstm_init_copy(pool, a, b, toSqr) \ + pstm_init_copy( a, b, toSqr) extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int16 toSqr); extern int16 pstm_count_bits (pstm_int * a); +//bbox: pool unused +#define pstm_init_for_read_unsigned_bin(pool, a, len) \ + pstm_init_for_read_unsigned_bin( a, len) extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len); @@ -178,9 +190,15 @@ extern void pstm_rshd(pstm_int *a, int16 x); extern int32 pstm_lshd(pstm_int * a, int16 b); +//bbox: pool unused +#define pstm_div(pool, a, b, c, d) \ + pstm_div( a, b, c, d) extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, pstm_int *d); +//bbox: pool unused +#define pstm_div_2d(pool, a, b, c, d) \ + pstm_div_2d( a, b, c, d) extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c, pstm_int *d); @@ -190,15 +208,27 @@ extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); +//bbox: pool unused +#define pstm_sub_d(pool, a, b, c) \ + pstm_sub_d( a, b, c) extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c); extern int32 pstm_mul_2(pstm_int * a, pstm_int * b); +//bbox: pool unused +#define pstm_mod(pool, a, b, c) \ + pstm_mod( a, b, c) extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c); +//bbox: pool unused +#define pstm_mulmod(pool, a, b, c, d) \ + pstm_mulmod( a, b, c, d) extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, pstm_int *d); +//bbox: pool unused +#define pstm_exptmod(pool, G, X, P, Y) \ + pstm_exptmod( G, X, P, Y) extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, pstm_int *Y); @@ -206,15 +236,21 @@ extern int32 pstm_2expt(pstm_int *a, int16 b); extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c); +//bbox: pool unused +#define pstm_to_unsigned_bin(pool, a, b) \ + pstm_to_unsigned_bin( a, b) extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b); +//bbox: pool unused +#define pstm_to_unsigned_bin_nr(pool, a, b) \ + pstm_to_unsigned_bin_nr( a, b) extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b); extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho); -///bbox: pool unused +//bbox: pool unused #define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \ pstm_montgomery_reduce( a, m, mp, paD, paDlen) extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, @@ -225,7 +261,7 @@ extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C, pstm_digit *paD, uint32 paDlen); -///bbox: pool unused +//bbox: pool unused #define pstm_sqr_comba(pool, A, B, paD, paDlen) \ pstm_sqr_comba( A, B, paD, paDlen) extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, @@ -237,6 +273,9 @@ extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c); +//bbox: pool unused +#define pstm_invmod(pool, a, b, c) \ + pstm_invmod( a, b, c) extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b, pstm_int * c); diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c index e9ae81c53..dc2fe0a48 100644 --- a/networking/tls_pstm_montgomery_reduce.c +++ b/networking/tls_pstm_montgomery_reduce.c @@ -6,7 +6,7 @@ #include "tls.h" /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -43,7 +43,7 @@ */ /******************************************************************************/ -///bbox +//bbox //#include "../cryptoApi.h" #ifndef DISABLE_PSTM @@ -357,7 +357,7 @@ int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, c = paD; memset(c, 0x0, paDlen); } else { - c = xzalloc(2*pa+1);///bbox + c = xzalloc(2*pa+1);//bbox } /* copy the input */ oldused = a->used; diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c index 7967231df..47cbb9618 100644 --- a/networking/tls_pstm_mul_comba.c +++ b/networking/tls_pstm_mul_comba.c @@ -6,7 +6,7 @@ #include "tls.h" /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -43,7 +43,7 @@ */ /******************************************************************************/ -///bbox +//bbox //#include "../cryptoApi.h" #ifndef DISABLE_PSTM @@ -222,7 +222,7 @@ asm( \ /******************************************************************************/ /* generic PxQ multiplier */ -///bbox: pool unused +//bbox: pool unused #define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \ pstm_mul_comba_gen( A, B, C, paD, paDlen) static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, @@ -250,13 +250,13 @@ static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, if (paD != NULL) { if (paDlen < (sizeof(pstm_digit) * pa)) { paDfail = 1; /* have a paD but it's not large enough */ - dst = xzalloc(sizeof(pstm_digit) * pa);///bbox + dst = xzalloc(sizeof(pstm_digit) * pa);//bbox } else { dst = paD; memset(dst, 0x0, paDlen); } } else { - dst = xzalloc(sizeof(pstm_digit) * pa);///bbox + dst = xzalloc(sizeof(pstm_digit) * pa);//bbox } for (ix = 0; ix < pa; ix++) { diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c index 378e0647b..36cb9ea97 100644 --- a/networking/tls_pstm_sqr_comba.c +++ b/networking/tls_pstm_sqr_comba.c @@ -6,7 +6,7 @@ #include "tls.h" /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** @@ -43,7 +43,7 @@ */ /******************************************************************************/ -///bbox +//bbox //#include "../cryptoApi.h" #ifndef DISABLE_PSTM @@ -439,7 +439,7 @@ asm( \ /* Non-unrolled comba squarer */ -///bbox: pool unused +//bbox: pool unused #define pstm_sqr_comba_gen(pool, A, B, paD, paDlen) \ pstm_sqr_comba_gen( A, B, paD, paDlen) static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, @@ -470,13 +470,13 @@ static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B, if (paD != NULL) { if (paDlen < (sizeof(pstm_digit) * pa)) { paDfail = 1; /* have a paD, but it's not big enough */ - dst = xzalloc(sizeof(pstm_digit) * pa);///bbox + dst = xzalloc(sizeof(pstm_digit) * pa);//bbox } else { dst = paD; memset(dst, 0x0, paDlen); } } else { - dst = xzalloc(sizeof(pstm_digit) * pa);///bbox + dst = xzalloc(sizeof(pstm_digit) * pa);//bbox } for (ix = 0; ix < pa; ix++) { diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c index df711865c..60c54248e 100644 --- a/networking/tls_rsa.c +++ b/networking/tls_rsa.c @@ -8,12 +8,12 @@ /* The code below is taken from parts of * matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c * matrixssl-3-7-2b-open/crypto/pubkey/rsa.c - * and (so far) almost not modified. Changes are flagged with ///bbox + * and (so far) almost not modified. Changes are flagged with //bbox */ #define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \ pkcs1Pad(in, inlen, out, outlen, cryptType) -static ///bbox +static //bbox int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, int32 cryptType, void *userPtr) { @@ -57,8 +57,8 @@ int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out, } #define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \ - psRsaCrypt(pool, in, inlen, out, outlen, key, type) -static ///bbox + psRsaCrypt( in, inlen, out, outlen, key, type) +static //bbox int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen, unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type, void *data) @@ -67,10 +67,11 @@ int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen, int32 res; uint32 x; - if (in == NULL || out == NULL || outlen == NULL || key == NULL) { - psTraceCrypto("NULL parameter error in psRsaCrypt\n"); - return PS_ARG_FAIL; - } +//bbox +// if (in == NULL || out == NULL || outlen == NULL || key == NULL) { +// psTraceCrypto("NULL parameter error in psRsaCrypt\n"); +// return PS_ARG_FAIL; +// } tmp.dp = tmpa.dp = tmpb.dp = NULL; @@ -187,7 +188,8 @@ int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, size = key->size; if (outlen < size) { - psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub: outlen:%d < size:%d", outlen, size); +//bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n"); + bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size); return PS_ARG_FAIL; } diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h index 93f469e83..c464ed552 100644 --- a/networking/tls_rsa.h +++ b/networking/tls_rsa.h @@ -10,11 +10,11 @@ typedef struct { pstm_int e, d, N, qP, dP, dQ, p, q; uint32 size; /* Size of the key in bytes */ int32 optimized; /* 1 for optimized */ - psPool_t *pool; +//bbox psPool_t *pool; } psRsaKey_t; #define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \ - psRsaEncryptPub(pool, key, in, inlen, out, outlen) + psRsaEncryptPub( key, in, inlen, out, outlen) int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key, unsigned char *in, uint32 inlen, unsigned char *out, uint32 outlen, void *data); diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h index 712ee600c..b6b55c78c 100644 --- a/networking/tls_symmetric.h +++ b/networking/tls_symmetric.h @@ -6,7 +6,7 @@ /* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h - * Changes are flagged with ///bbox + * Changes are flagged with //bbox * TODO: * Take a look at "roll %%cl" part... rotates by constant use fewer registers, * and on many Intel CPUs rotates by %cl are slower: they take 2 cycles, not 1. @@ -299,7 +299,7 @@ x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \ /* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. - * Changes are flagged with ///bbox + * Changes are flagged with //bbox */ /** -- cgit v1.2.3-55-g6feb From 432f1ae2ff184e07fa78bd3797073094069e521d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 16:32:38 +0100 Subject: tls: tested PSTM_X86_64, not enabling it - too large Signed-off-by: Denys Vlasenko --- networking/tls.c | 4 ++-- networking/tls.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index f3d0bde90..092735884 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -582,7 +582,7 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size tls_get_random(tls->outbuf, AES_BLOCKSIZE); /* IV */ p = tls->outbuf + AES_BLOCKSIZE; size -= sizeof(*xhdr); - dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, sizeof(mac_hash)); + dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, (int)sizeof(mac_hash)); p = mempcpy(p, buf + sizeof(*xhdr), size); /* content */ p = mempcpy(p, mac_hash, sizeof(mac_hash)); /* MAC */ size += sizeof(mac_hash); @@ -625,7 +625,7 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size xhdr->len16_lo = size & 0xff; xwrite(tls->fd, xhdr, sizeof(*xhdr)); xwrite(tls->fd, tls->outbuf, size); - dbg("wrote %u bytes\n", sizeof(*xhdr) + size); + dbg("wrote %u bytes\n", (int)sizeof(*xhdr) + size); //restore xhdr->len16_hi = ; //restore xhdr->len16_lo = ; } diff --git a/networking/tls.h b/networking/tls.h index 5e6b346e2..d487f3810 100644 --- a/networking/tls.h +++ b/networking/tls.h @@ -27,11 +27,13 @@ /* pstm: multiprecision numbers */ #undef DISABLE_PSTM #if defined(__GNUC__) && defined(__i386__) + /* PSTM_X86 works correctly. +25 bytes. */ # define PSTM_32BIT # define PSTM_X86 #endif -//test this before enabling: //#if defined(__GNUC__) && defined(__x86_64__) +// /* PSTM_X86_64 works correctly, but +782 bytes. */ +// /* Looks like most of the growth is because of PSTM_64BIT. */ //# define PSTM_64BIT //# define PSTM_X86_64 //#endif -- cgit v1.2.3-55-g6feb From f7806f9d8fc889f1d6cd365b69d9d99a4a5a6e26 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 19 Jan 2017 16:45:41 +0100 Subject: tls: fix ROL/ROR x86 optimization ALWAYS_INLINE: function old new delta psAesInitKey 825 824 -1 ROR 5 - -5 setup_mix2 148 134 -14 psAesDecryptBlock 1184 1139 -45 psAesEncryptBlock 1193 1102 -91 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/4 up/down: 0/-156) Total: -156 bytes ALWAYS_INLINE + __builtin_constant_p(shift_cnt): function old new delta ROR 5 - -5 psAesInitKey 825 818 -7 setup_mix2 148 123 -25 psAesDecryptBlock 1184 1078 -106 psAesEncryptBlock 1193 1017 -176 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/4 up/down: 0/-319) Total: -319 bytes Signed-off-by: Denys Vlasenko --- networking/tls_symmetric.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h index b6b55c78c..8488b437e 100644 --- a/networking/tls_symmetric.h +++ b/networking/tls_symmetric.h @@ -7,9 +7,6 @@ /* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h * Changes are flagged with //bbox - * TODO: - * Take a look at "roll %%cl" part... rotates by constant use fewer registers, - * and on many Intel CPUs rotates by %cl are slower: they take 2 cycles, not 1. */ /******************************************************************************/ @@ -28,16 +25,28 @@ #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \ !defined(INTEL_CC) && !defined(PS_NO_ASM) -static inline unsigned ROL(unsigned word, int i) +static ALWAYS_INLINE unsigned ROL(unsigned word, int i) { + if (__builtin_constant_p(i)) //box + // Rotates by constant use fewer registers, + // and on many Intel CPUs rotates by %cl take 2 cycles, not 1. + asm ("roll %2,%0" //box + :"=r" (word) + :"0" (word),"i" (i)); + else //box asm ("roll %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } -static inline unsigned ROR(unsigned word, int i) +static ALWAYS_INLINE unsigned ROR(unsigned word, int i) { + if (__builtin_constant_p(i)) //box + asm ("rorl %2,%0" //box + :"=r" (word) + :"0" (word),"i" (i)); + else //box asm ("rorl %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); -- cgit v1.2.3-55-g6feb From abbf17abccbf832365d9acf1c280369ba7d5f8b2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 03:15:09 +0100 Subject: tls: add the i/o loop - largish rework of i/o buffering Signed-off-by: Denys Vlasenko --- networking/tls.c | 274 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 166 insertions(+), 108 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 092735884..71be2def8 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -23,9 +23,10 @@ //usage:#define tls_full_usage "\n\n" #include "tls.h" +#include "common_bufsiz.h" #define TLS_DEBUG 1 -#define TLS_DEBUG_HASH 0 +#define TLS_DEBUG_HASH 1 #define TLS_DEBUG_DER 0 #if TLS_DEBUG @@ -150,9 +151,8 @@ // works against "openssl s_server -cipher NULL" // and against wolfssl-3.9.10-stable/examples/server/server.c: //#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) -// "works", meaning -// "can send encrypted FINISHED to wolfssl-3.9.10-stable/examples/server/server.c", -// don't yet read its encrypted answers: +// works against wolfssl-3.9.10-stable/examples/server/server.c +// (getting back and decrypt ok first application data message) #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE enum { @@ -162,6 +162,11 @@ enum { AES_BLOCKSIZE = 16, AES128_KEYSIZE = 16, AES256_KEYSIZE = 32, + + MAX_TLS_RECORD = (1 << 14), + OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ + OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ + MAX_OTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, }; struct record_hdr { @@ -195,6 +200,9 @@ typedef struct tls_state { // exceed 2^64-1. uint64_t write_seq64_be; + int outbuf_size; + uint8_t *outbuf; + // RFC 5246 // |6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext @@ -225,7 +233,6 @@ typedef struct tls_state { //needed? uint64_t align____; uint8_t inbuf[20*1024]; - uint8_t outbuf[20*1024]; } tls_state_t; @@ -462,6 +469,17 @@ static void tls_error_die(tls_state_t *tls) xfunc_die(); } +static void *tls_get_outbuf(tls_state_t *tls, int len) +{ + if (len > MAX_OTBUF) + xfunc_die(); + if (tls->outbuf_size < len + OUTBUF_PFX + OUTBUF_SFX) { + tls->outbuf_size = len + OUTBUF_PFX + OUTBUF_SFX; + tls->outbuf = xrealloc(tls->outbuf, tls->outbuf_size); + } + return tls->outbuf + OUTBUF_PFX; +} + // RFC 5246 // 6.2.3.1. Null or Standard Stream Cipher // @@ -501,39 +519,41 @@ static void tls_error_die(tls_state_t *tls) // -------- ----------- ---------- -------------- // SHA HMAC-SHA1 20 20 // SHA256 HMAC-SHA256 32 32 -static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size) +static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) { - uint8_t mac_hash[SHA256_OUTSIZE]; - struct record_hdr *xhdr = buf; + uint8_t *buf = tls->outbuf + OUTBUF_PFX; + struct record_hdr *xhdr; - if (!tls->encrypt_on_write) { - xwrite(tls->fd, buf, size); - dbg("wrote %u bytes\n", size); - /* Handshake hash does not include record headers */ - if (size > 5 && xhdr->type == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, (uint8_t*)buf + 5, size - 5); - } - return; - } + xhdr = (void*)(buf - sizeof(*xhdr)); + if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) + xhdr = (void*)(buf - sizeof(*xhdr) - AES_BLOCKSIZE); /* place for IV */ + + xhdr->type = type; + xhdr->proto_maj = TLS_MAJ; + xhdr->proto_min = TLS_MIN; + /* fake unencrypted record header len for MAC calculation */ + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + /* Calculate MAC signature */ //TODO: convert hmac_sha256 to precomputed - hmac_sha256(mac_hash, + hmac_sha256(buf + size, tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), &tls->write_seq64_be, sizeof(tls->write_seq64_be), + xhdr, sizeof(*xhdr), buf, size, NULL); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); + size += SHA256_OUTSIZE; + if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { /* No encryption, only signing */ - xhdr->len16_lo += SHA256_OUTSIZE; -//FIXME: overflow into len16_hi? - xwrite(tls->fd, buf, size); - xhdr->len16_lo -= SHA256_OUTSIZE; - dbg("wrote %u bytes\n", size); - - xwrite(tls->fd, mac_hash, sizeof(mac_hash)); - dbg("wrote %u bytes of hash\n", (int)sizeof(mac_hash)); + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); + xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); + dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); return; } @@ -579,13 +599,8 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size uint8_t padding_length; /* Build IV+content+MAC+padding in outbuf */ - tls_get_random(tls->outbuf, AES_BLOCKSIZE); /* IV */ - p = tls->outbuf + AES_BLOCKSIZE; - size -= sizeof(*xhdr); - dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, (int)sizeof(mac_hash)); - p = mempcpy(p, buf + sizeof(*xhdr), size); /* content */ - p = mempcpy(p, mac_hash, sizeof(mac_hash)); /* MAC */ - size += sizeof(mac_hash); + tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ + dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, SHA256_OUTSIZE); // RFC is talking nonsense: // Padding that is added to force the length of the plaintext to be // an integral multiple of the block cipher's block length. @@ -601,6 +616,7 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size // If you need no bytes to reach BLOCKSIZE, you have to pad a full // BLOCKSIZE with bytes of value (BLOCKSIZE-1). // It's ok to have more than minimum padding, but we do minimum. + p = buf + size; padding_length = (~size) & (AES_BLOCKSIZE - 1); do { *p++ = padding_length; /* padding */ @@ -608,12 +624,12 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size } while ((size & (AES_BLOCKSIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ - psAesInit(&ctx, tls->outbuf, /* IV */ + psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ tls->client_write_key, sizeof(tls->client_write_key) ); psAesEncrypt(&ctx, - tls->outbuf + AES_BLOCKSIZE, /* plaintext */ - tls->outbuf + AES_BLOCKSIZE, /* ciphertext */ + buf, /* plaintext */ + buf, /* ciphertext */ size ); @@ -623,14 +639,33 @@ static void xwrite_and_hash(tls_state_t *tls, /*const*/ void *buf, unsigned size size += AES_BLOCKSIZE; /* + IV */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - xwrite(tls->fd, xhdr, sizeof(*xhdr)); - xwrite(tls->fd, tls->outbuf, size); + dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); + xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); dbg("wrote %u bytes\n", (int)sizeof(*xhdr) + size); -//restore xhdr->len16_hi = ; -//restore xhdr->len16_lo = ; } } +static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) +{ + if (!tls->encrypt_on_write) { + uint8_t *buf = tls->outbuf + OUTBUF_PFX; + struct record_hdr *xhdr = (void*)(buf - sizeof(*xhdr)); + + xhdr->type = RECORD_TYPE_HANDSHAKE; + xhdr->proto_maj = TLS_MAJ; + xhdr->proto_min = TLS_MIN; + xhdr->len16_hi = size >> 8; + xhdr->len16_lo = size & 0xff; + dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); + xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); + dbg("wrote %u bytes\n", (int)sizeof(*xhdr) + size); + /* Handshake hash does not include record headers */ + sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size); + return; + } + xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); +} + static int xread_tls_block(tls_state_t *tls) { struct record_hdr *xhdr; @@ -668,7 +703,7 @@ static int xread_tls_block(tls_state_t *tls) sz = target - sizeof(*xhdr); /* Needs to be decrypted? */ - if (tls->min_encrypted_len_on_read) { + if (tls->min_encrypted_len_on_read > SHA256_OUTSIZE) { psCipherContext_t ctx; uint8_t *p = tls->inbuf + sizeof(*xhdr); int padding_len; @@ -698,6 +733,10 @@ static int xread_tls_block(tls_state_t *tls) /* Skip IV */ memmove(tls->inbuf + 5, tls->inbuf + 5 + AES_BLOCKSIZE, sz); } + } else { + /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ + /* else: no encryption yet on input, subtract zero = NOP */ + sz -= tls->min_encrypted_len_on_read; } /* RFC 5246 is not saying it explicitly, but sha256 hash @@ -943,39 +982,24 @@ static int xread_tls_handshake_block(tls_state_t *tls, int min_len) return len; } -static void fill_handshake_record_hdr(struct record_hdr *xhdr, unsigned len) +static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, unsigned len) { struct handshake_hdr { - struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; - } *h = (void*)xhdr; - - h->xhdr.type = RECORD_TYPE_HANDSHAKE; - h->xhdr.proto_maj = TLS_MAJ; - h->xhdr.proto_min = TLS_MIN; - len -= 5; - h->xhdr.len16_hi = len >> 8; - // can be optimized to do one store instead of four: - // uint32_t v = htonl(0x100*(RECORD_TYPE_HANDSHAKE + 0x100*(TLS_MAJ + 0x100*(TLS_MIN)))) - // | ((len >> 8) << 24); // little-endian specific, don't use in this form - // *(uint32_t *)xhdr = v; - - h->xhdr.len16_lo = len & 0xff; + } *h = buf; len -= 4; + h->type = type; h->len24_hi = len >> 16; h->len24_mid = len >> 8; h->len24_lo = len & 0xff; - - memset(h + 1, 0, len); } //TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise static void send_client_hello(tls_state_t *tls) { struct client_hello { - struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; uint8_t proto_maj, proto_min; @@ -987,25 +1011,25 @@ static void send_client_hello(tls_state_t *tls) uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ }; - struct client_hello record; - - fill_handshake_record_hdr(&record.xhdr, sizeof(record)); - record.type = HANDSHAKE_CLIENT_HELLO; - record.proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ - record.proto_min = TLS_MIN; /* can be higher than one in record headers */ - tls_get_random(record.rand32, sizeof(record.rand32)); - /* record.session_id_len = 0; - already is */ - /* record.cipherid_len16_hi = 0; */ - record.cipherid_len16_lo = 2 * 1; - record.cipherid[0] = CIPHER_ID >> 8; - record.cipherid[1] = CIPHER_ID & 0xff; - record.comprtypes_len = 1; - /* record.comprtypes[0] = 0; */ + struct client_hello *record = tls_get_outbuf(tls, sizeof(*record)); + + fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, sizeof(*record)); + record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ + record->proto_min = TLS_MIN; /* can be higher than one in record headers */ + tls_get_random(record->rand32, sizeof(record->rand32)); +memset(record->rand32, 0x11, sizeof(record->rand32)); + memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); + record->session_id_len = 0; + record->cipherid_len16_hi = 0; + record->cipherid_len16_lo = 2 * 1; + record->cipherid[0] = CIPHER_ID >> 8; + record->cipherid[1] = CIPHER_ID & 0xff; + record->comprtypes_len = 1; + record->comprtypes[0] = 0; //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); dbg(">> CLIENT_HELLO\n"); - xwrite_and_hash(tls, &record, sizeof(record)); - memcpy(tls->client_and_server_rand32, record.rand32, sizeof(record.rand32)); + xwrite_and_update_handshake_hash(tls, sizeof(*record)); } static void get_server_hello(tls_state_t *tls) @@ -1099,21 +1123,19 @@ static void get_server_cert(tls_state_t *tls) static void send_client_key_exchange(tls_state_t *tls) { struct client_key_exchange { - struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */ uint8_t keylen16_hi, keylen16_lo; uint8_t key[4 * 1024]; // size?? }; - struct client_key_exchange record; +//FIXME: better size estimate + struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record)); uint8_t rsa_premaster[SSL_HS_RSA_PREMASTER_SIZE]; int len; - fill_handshake_record_hdr(&record.xhdr, sizeof(record) - sizeof(record.key)); - record.type = HANDSHAKE_CLIENT_KEY_EXCHANGE; - tls_get_random(rsa_premaster, sizeof(rsa_premaster)); +memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); // RFC 5246 // "Note: The version number in the PreMasterSecret is the version // offered by the client in the ClientHello.client_version, not the @@ -1123,22 +1145,20 @@ static void send_client_key_exchange(tls_state_t *tls) len = psRsaEncryptPub(/*pool:*/ NULL, /* psRsaKey_t* */ &tls->server_rsa_pub_key, rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), - record.key, sizeof(record.key), + record->key, sizeof(record->key), data_param_ignored ); - /* length fields need fixing */ - record.keylen16_hi = len >> 8; - record.keylen16_lo = len & 0xff; + record->keylen16_hi = len >> 8; + record->keylen16_lo = len & 0xff; len += 2; - /* record.len24_hi = 0; - already is */ - record.len24_mid = len >> 8; - record.len24_lo = len & 0xff; + record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE; + record->len24_hi = 0; + record->len24_mid = len >> 8; + record->len24_lo = len & 0xff; len += 4; - record.xhdr.len16_hi = len >> 8; - record.xhdr.len16_lo = len & 0xff; dbg(">> CLIENT_KEY_EXCHANGE\n"); - xwrite_and_hash(tls, &record, sizeof(record.xhdr) + len); + xwrite_and_update_handshake_hash(tls, len); // RFC 5246 // For all key exchange methods, the same algorithm is used to convert @@ -1224,7 +1244,6 @@ static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { static void send_change_cipher_spec(tls_state_t *tls) { - /* Not "xwrite_and_hash": this is not a handshake message */ dbg(">> CHANGE_CIPHER_SPEC\n"); xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); } @@ -1269,19 +1288,17 @@ static void send_change_cipher_spec(tls_state_t *tls) static void send_client_finished(tls_state_t *tls) { struct finished { - struct record_hdr xhdr; uint8_t type; uint8_t len24_hi, len24_mid, len24_lo; uint8_t prf_result[12]; }; - struct finished record; + struct finished *record = tls_get_outbuf(tls, sizeof(*record)); uint8_t handshake_hash[SHA256_OUTSIZE]; - fill_handshake_record_hdr(&record.xhdr, sizeof(record)); - record.type = HANDSHAKE_FINISHED; + fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); sha256_peek(&tls->handshake_sha256_ctx, handshake_hash); - prf_hmac_sha256(record.prf_result, sizeof(record.prf_result), + prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), tls->master_secret, sizeof(tls->master_secret), "client finished", handshake_hash, sizeof(handshake_hash) @@ -1289,13 +1306,10 @@ static void send_client_finished(tls_state_t *tls) dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); - dump_hex("=> digest: %s\n", record.prf_result, sizeof(record.prf_result)); - -//(1) TODO: well, this should be encrypted on send, really. -//(2) do we really need to also hash it? + dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result)); dbg(">> FINISHED\n"); - xwrite_and_hash(tls, &record, sizeof(record)); + xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); } static void tls_handshake(tls_state_t *tls) @@ -1376,8 +1390,11 @@ static void tls_handshake(tls_state_t *tls) if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) tls_error_die(tls); dbg("<< CHANGE_CIPHER_SPEC\n"); - /* all incoming packets now should be encrypted and have IV + MAC + padding */ - tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; + if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) + tls->min_encrypted_len_on_read = SHA256_OUTSIZE; + else + /* all incoming packets now should be encrypted and have IV + MAC + padding */ + tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; /* Get (encrypted) FINISHED from the server */ len = xread_tls_block(tls); @@ -1387,6 +1404,12 @@ static void tls_handshake(tls_state_t *tls) /* application data can be sent/received */ } +static void tls_xwrite(tls_state_t *tls, int len) +{ + dbg(">> DATA\n"); + xwrite_encrypted(tls, len, RECORD_TYPE_APPLICATION_DATA); +} + // To run a test server using openssl: // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 @@ -1400,8 +1423,8 @@ int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tls_main(int argc UNUSED_PARAM, char **argv) { tls_state_t *tls; - len_and_sockaddr *lsa; - int fd; + fd_set readfds, testfds; + int cfd; // INIT_G(); // getopt32(argv, "myopts") @@ -1409,13 +1432,48 @@ int tls_main(int argc UNUSED_PARAM, char **argv) if (!argv[1]) bb_show_usage(); - lsa = xhost2sockaddr(argv[1], 443); - fd = xconnect_stream(lsa); + cfd = create_and_connect_stream_or_die(argv[1], 443); tls = new_tls_state(); - tls->fd = fd; + tls->fd = cfd; tls_handshake(tls); + /* Select loop copying stdin to cfd, and cfd to stdout */ + FD_ZERO(&readfds); + FD_SET(cfd, &readfds); + FD_SET(STDIN_FILENO, &readfds); + +#define iobuf bb_common_bufsiz1 + setup_common_bufsiz(); + for (;;) { + int nread; + + testfds = readfds; + + if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) + bb_perror_msg_and_die("select"); + + if (FD_ISSET(STDIN_FILENO, &testfds)) { + void *buf = tls_get_outbuf(tls, COMMON_BUFSIZE); + nread = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE); + if (nread < 1) { +//&& errno != EAGAIN + /* Close outgoing half-connection so they get EOF, + * but leave incoming alone so we can see response */ +// shutdown(cfd, SHUT_WR); + FD_CLR(STDIN_FILENO, &readfds); + } + tls_xwrite(tls, nread); + } + if (FD_ISSET(cfd, &testfds)) { + nread = xread_tls_block(tls); + if (nread < 1) +//if eof, just close stdout, but not exit! + return EXIT_SUCCESS; + xwrite(STDOUT_FILENO, tls->inbuf + 5, nread); + } + } + return EXIT_SUCCESS; } /* Unencryped SHA256 example: -- cgit v1.2.3-55-g6feb From a0aae9f71442366ec429657c437fd7dd815978fd Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 14:12:10 +0100 Subject: tls: decode alerts and in particular, EOF alert. Signed-off-by: Denys Vlasenko --- networking/tls.c | 292 ++++++++++++++---------------------------------------- networking/wget.c | 2 +- 2 files changed, 75 insertions(+), 219 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 71be2def8..e037eba69 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -28,6 +28,7 @@ #define TLS_DEBUG 1 #define TLS_DEBUG_HASH 1 #define TLS_DEBUG_DER 0 +#define TLS_DEBUG_FIXED_SECRETS 0 #if TLS_DEBUG # define dbg(...) fprintf(stderr, __VA_ARGS__) @@ -152,7 +153,6 @@ // and against wolfssl-3.9.10-stable/examples/server/server.c: //#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) // works against wolfssl-3.9.10-stable/examples/server/server.c -// (getting back and decrypt ok first application data message) #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE enum { @@ -163,6 +163,8 @@ enum { AES128_KEYSIZE = 16, AES256_KEYSIZE = 32, + RECHDR_LEN = 5, + MAX_TLS_RECORD = (1 << 14), OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ @@ -257,15 +259,15 @@ static void dump_tls_record(const void *vp, int len) while (len > 0) { unsigned xhdr_len; - if (len < 5) { + if (len < RECHDR_LEN) { dump_hex("< |%s|\n", p, len); return; } xhdr_len = 0x100*p[3] + p[4]; dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len); - p += 5; - len -= 5; - if (len >= 4 && p[-5] == RECORD_TYPE_HANDSHAKE) { + p += RECHDR_LEN; + len -= RECHDR_LEN; + if (len >= 4 && p[-RECHDR_LEN] == RECORD_TYPE_HANDSHAKE) { unsigned len24 = get24be(p + 1); dbg(" type:%u len24:%u", p[0], len24); } @@ -524,9 +526,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) uint8_t *buf = tls->outbuf + OUTBUF_PFX; struct record_hdr *xhdr; - xhdr = (void*)(buf - sizeof(*xhdr)); + xhdr = (void*)(buf - RECHDR_LEN); if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) - xhdr = (void*)(buf - sizeof(*xhdr) - AES_BLOCKSIZE); /* place for IV */ + xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */ xhdr->type = type; xhdr->proto_maj = TLS_MAJ; @@ -540,7 +542,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) hmac_sha256(buf + size, tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), &tls->write_seq64_be, sizeof(tls->write_seq64_be), - xhdr, sizeof(*xhdr), + xhdr, RECHDR_LEN, buf, size, NULL); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); @@ -551,8 +553,8 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) /* No encryption, only signing */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); - xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); + dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + xwrite(tls->fd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); return; } @@ -639,9 +641,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) size += AES_BLOCKSIZE; /* + IV */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); - xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); - dbg("wrote %u bytes\n", (int)sizeof(*xhdr) + size); + dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + xwrite(tls->fd, xhdr, RECHDR_LEN + size); + dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } } @@ -649,16 +651,16 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) { if (!tls->encrypt_on_write) { uint8_t *buf = tls->outbuf + OUTBUF_PFX; - struct record_hdr *xhdr = (void*)(buf - sizeof(*xhdr)); + struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN); xhdr->type = RECORD_TYPE_HANDSHAKE; xhdr->proto_maj = TLS_MAJ; xhdr->proto_min = TLS_MIN; xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, sizeof(*xhdr) + size); - xwrite(tls->fd, xhdr, sizeof(*xhdr) + size); - dbg("wrote %u bytes\n", (int)sizeof(*xhdr) + size); + dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + xwrite(tls->fd, xhdr, RECHDR_LEN + size); + dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); /* Handshake hash does not include record headers */ sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size); return; @@ -673,15 +675,16 @@ static int xread_tls_block(tls_state_t *tls) int total; int target; + again: dbg("insize:%u tail:%u\n", tls->insize, tls->tail); memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); errno = 0; total = tls->tail; target = sizeof(tls->inbuf); for (;;) { - if (total >= sizeof(*xhdr) && target == sizeof(tls->inbuf)) { + if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { xhdr = (void*)tls->inbuf; - target = sizeof(*xhdr) + (0x100 * xhdr->len16_hi + xhdr->len16_lo); + target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); if (target >= sizeof(tls->inbuf)) { /* malformed input (too long): yell and die */ tls->tail = 0; @@ -694,18 +697,29 @@ static int xread_tls_block(tls_state_t *tls) if (total - target >= 0) break; sz = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); - if (sz <= 0) - bb_perror_msg_and_die("short read"); + if (sz <= 0) { + if (sz == 0 && total == 0) { + /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ + dbg("EOF (without TLS shutdown) from peer\n"); + tls->tail = 0; + tls->insize = 0; + goto end; + } + bb_perror_msg_and_die("short read, have only %d", total); + } + dbg("read():%d\n", sz); total += sz; } tls->tail = total - target; tls->insize = target; - sz = target - sizeof(*xhdr); + dbg("new insize:%u tail:%u\n", tls->insize, tls->tail); + + sz = target - RECHDR_LEN; /* Needs to be decrypted? */ if (tls->min_encrypted_len_on_read > SHA256_OUTSIZE) { psCipherContext_t ctx; - uint8_t *p = tls->inbuf + sizeof(*xhdr); + uint8_t *p = tls->inbuf + RECHDR_LEN; int padding_len; if (sz & (AES_BLOCKSIZE-1) @@ -731,7 +745,7 @@ static int xread_tls_block(tls_state_t *tls) } if (sz != 0) { /* Skip IV */ - memmove(tls->inbuf + 5, tls->inbuf + 5 + AES_BLOCKSIZE, sz); + memmove(tls->inbuf + RECHDR_LEN, tls->inbuf + RECHDR_LEN + AES_BLOCKSIZE, sz); } } else { /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ @@ -739,13 +753,33 @@ static int xread_tls_block(tls_state_t *tls) sz -= tls->min_encrypted_len_on_read; } + //dump_hex("<< %s\n", tls->inbuf, RECHDR_LEN + sz); + + xhdr = (void*)tls->inbuf; + if (xhdr->type == RECORD_TYPE_ALERT && sz >= 2) { + uint8_t *p = tls->inbuf + RECHDR_LEN; + dbg("ALERT size:%d level:%d description:%d\n", sz, p[0], p[1]); + if (p[0] == 1) { /*warning */ + if (p[1] == 0) { /* warning, close_notify: EOF */ + dbg("EOF (TLS encoded) from peer\n"); + sz = 0; + goto end; + } + /* discard it, get next record */ + goto again; + } + /* p[0] == 1: fatal error, others: not defined in protocol */ + sz = 0; + goto end; + } + /* RFC 5246 is not saying it explicitly, but sha256 hash * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + 5, sz); + sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); } - + end: dbg("got block len:%u\n", sz); return sz; } @@ -1017,7 +1051,8 @@ static void send_client_hello(tls_state_t *tls) record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ record->proto_min = TLS_MIN; /* can be higher than one in record headers */ tls_get_random(record->rand32, sizeof(record->rand32)); -memset(record->rand32, 0x11, sizeof(record->rand32)); + if (TLS_DEBUG_FIXED_SECRETS) + memset(record->rand32, 0x11, sizeof(record->rand32)); memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); record->session_id_len = 0; record->cipherid_len16_hi = 0; @@ -1027,7 +1062,6 @@ memset(record->rand32, 0x11, sizeof(record->rand32)); record->comprtypes_len = 1; record->comprtypes[0] = 0; - //dbg (make it repeatable): memset(record.rand32, 0x11, sizeof(record.rand32)); dbg(">> CLIENT_HELLO\n"); xwrite_and_update_handshake_hash(tls, sizeof(*record)); } @@ -1135,7 +1169,8 @@ static void send_client_key_exchange(tls_state_t *tls) int len; tls_get_random(rsa_premaster, sizeof(rsa_premaster)); -memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); + if (TLS_DEBUG_FIXED_SECRETS) + memset(rsa_premaster, 0x44, sizeof(rsa_premaster)); // RFC 5246 // "Note: The version number in the PreMasterSecret is the version // offered by the client in the ClientHello.client_version, not the @@ -1348,7 +1383,7 @@ static void tls_handshake(tls_state_t *tls) get_server_cert(tls); len = xread_tls_handshake_block(tls, 4); - if (tls->inbuf[5] == HANDSHAKE_SERVER_KEY_EXCHANGE) { + if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) { // 459 bytes: // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... //SvKey len=455^ @@ -1359,7 +1394,7 @@ static void tls_handshake(tls_state_t *tls) xread_tls_handshake_block(tls, 4); } -// if (tls->inbuf[5] == HANDSHAKE_CERTIFICATE_REQUEST) { +// if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { // dbg("<< CERTIFICATE_REQUEST\n"); //RFC 5246: (in response to this,) "If no suitable certificate is available, // the client MUST send a certificate message containing no @@ -1371,7 +1406,7 @@ static void tls_handshake(tls_state_t *tls) // xread_tls_handshake_block(tls, 4); // } - if (tls->inbuf[5] != HANDSHAKE_SERVER_HELLO_DONE) + if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) tls_error_die(tls); // 0e 000000 (len:0) dbg("<< SERVER_HELLO_DONE\n"); @@ -1398,7 +1433,7 @@ static void tls_handshake(tls_state_t *tls) /* Get (encrypted) FINISHED from the server */ len = xread_tls_block(tls); - if (len < 4 || tls->inbuf[5] != HANDSHAKE_FINISHED) + if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) tls_error_die(tls); dbg("<< FINISHED\n"); /* application data can be sent/received */ @@ -1454,7 +1489,10 @@ int tls_main(int argc UNUSED_PARAM, char **argv) bb_perror_msg_and_die("select"); if (FD_ISSET(STDIN_FILENO, &testfds)) { - void *buf = tls_get_outbuf(tls, COMMON_BUFSIZE); + void *buf; + + dbg("STDIN HAS DATA\n"); + buf = tls_get_outbuf(tls, COMMON_BUFSIZE); nread = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE); if (nread < 1) { //&& errno != EAGAIN @@ -1466,196 +1504,14 @@ int tls_main(int argc UNUSED_PARAM, char **argv) tls_xwrite(tls, nread); } if (FD_ISSET(cfd, &testfds)) { + dbg("NETWORK HAS DATA\n"); nread = xread_tls_block(tls); if (nread < 1) //if eof, just close stdout, but not exit! return EXIT_SUCCESS; - xwrite(STDOUT_FILENO, tls->inbuf + 5, nread); + xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); } } return EXIT_SUCCESS; } -/* Unencryped SHA256 example: - * s_client says: - -write to 0x1d750b0 [0x1e6f153] (99 bytes => 99 (0x63)) -0000 - 16 03 01 005e 01 00005a 0303 [4d ef 5c 82 3e ....^...Z..M.\.> >> ClHello -0010 - bf a6 ee f1 1e 04 d1 5c-99 20 86 13 e9 0a cf 58 .......\. .....X -0020 - 75 b1 bd 7a e6 d6 44 f3-d3 a1 52] 00 0004 003b u..z..D...R....; 003b = TLS_RSA_WITH_NULL_SHA256 -0030 - 00ff TLS_EMPTY_RENEGOTIATION_INFO_SCSV - 0100 compr=none - 002d, 0023 0000, 000d 0020 [00 1e .....-.#..... .. extlen, SessionTicketTLS 0 bytes, SignatureAlgorithms 32 bytes -0040 - 06 01 06 02 06 03 05 01-05 02 05 03 04 01 04 02 ................ -0050 - 04 03 03 01 03 02 03 03-02 01 02 02 02 03] 000f ................ Heart Beat 1 byte -0060 - 0001 01 ... - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 16 03 03 00 3a ....: -read from 0x1d750b0 [0x1e6ac08] (58 bytes => 58 (0x3A)) -0000 - 02 000036 0303 [f2 61-ae c8 58 e3 51 42 32 93 ...6...a..X.QB2. << SvHello -0010 - c5 62 e4 f5 06 93 81 65-aa f7 df 74 af 7c 98 b4 .b.....e...t.|.. -0020 - 3e a7 35 c3 25 69] 00,003b,00.................. >.5.%i..;....... - no session id! "The server - may return an empty session_id to indicate that the session will - not be cached and therefore cannot be resumed." - 003b = TLS_RSA_WITH_NULL_SHA256 accepted, 00 - no compr - 000e ff01 0001 extlen, 0xff01=RenegotiationInfo 1 byte -0030 - 00, 0023 0000, SessionTicketTLS 0 bytes - 000f 0001 01 ..#....... Heart Beat 1 byte - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 16 03 03 04 0b ..... -read from 0x1d750b0 [0x1e6ac08] (1035 bytes => 1035 (0x40B)) -0000 - 0b 00 04 07 00 04 04 00-04 01 30 82 03 fd 30 82 ..........0...0. << Cert -0010 - 02 65 a0 03 02 01 02 02-09 00 d9 d9 8d b8 94 ad .e.............. -0020 - 2e 2b 30 0d 06 09 2a 86-48 86 f7 0d 01 01 0b 05 .+0...*.H....... -0030 - 00 30 14 31 12 30 10 06-03 55 04 03 0c 09 6c 6f .0.1.0...U....lo -0040 - 63 61 6c 68 6f 73 74 30-20 17 0d 31 37 30 31 31 calhost0 ..17011 -..."......."......."......."......."......."......."......."......."..... -03f0 - 11 8a cd c5 a3 0a 22 43-d5 13 f9 a5 8a 06 f9 00 ......"C........ -0400 - 3c f7 86 4e e8 a5 d8 5b-92 37 f5 <..N...[.7. -depth=0 CN = localhost -verify error:num=18:self signed certificate -verify return:1 -depth=0 CN = localhost -verify return:1 - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 16 03 03 00 04 ..... - -read from 0x1d750b0 [0x1e6ac08] (4 bytes => 4 (0x4)) << SvDone -0000 - 0e . -0004 - - -write to 0x1d750b0 [0x1e74620] (395 bytes => 395 (0x18B)) >> ClDone -0000 - 16 03 03 01 86 10 00 01-82 01 80 88 f0 87 5d b0 ..............]. -0010 - ea df 3b 4d e2 35 f3 99-e6 d4 29 87 36 86 ea 30 ..;M.5....).6..0 -0020 - 38 80 c7 37 66 7f 5b e7-23 38 7e 87 24 66 82 81 8..7f.[.#8~.$f.. -0030 - e4 ba 6c 2a 0c 92 a8 b9-39 c1 55 16 32 88 14 cd ..l*....9.U.2... -0040 - 95 8c 82 49 a1 c7 f9 9b-e5 8f f6 5e 7e ee 91 b3 ...I.......^~... -0050 - 2c 92 e7 a3 02 f8 9f 56-04 45 39 df a7 d6 1a 16 ,......V.E9..... -0060 - 67 5c a4 f8 87 8a c4 c8-6c 6f c6 f0 9b c9 b4 87 g\......lo...... -0070 - 36 43 c1 67 9f b3 aa 11-34 b0 c2 fc 1f d9 e1 ff 6C.g....4....... -0080 - fb e1 89 db 91 58 ec cc-aa 16 19 9a 91 74 e2 46 .....X.......t.F -0090 - 22 a7 a7 f7 9e 3c 97 82-2c e4 21 b3 fa ef ba 3f "....<..,.!....? -00a0 - 57 48 e4 b2 84 b7 c2 81-92 a9 f1 03 68 f4 e6 0c WH..........h... -00b0 - fd 54 87 f5 e9 a0 5d e6-5f 0e bd 80 86 27 ab 0e .T....]._....'.. -00c0 - cf 92 4f bd fc 24 b9 54-72 5f 58 df 6b 2b 1d 97 ..O..$.Tr_X.k+.. -00d0 - 00 60 fe 95 b0 aa d6 c7-c1 3a f9 2e 7c 92 a9 6d .`.......:..|..m -00e0 - 28 a3 ef 3e c1 e6 2d 2d-e8 db 81 ea 51 02 3f 64 (..>..--....Q.?d -00f0 - a8 66 14 c1 4b 17 1f 55-c6 5b 3b 38 c3 6a 61 a8 .f..K..U.[;8.ja. -0100 - f7 ad 65 7d cb 14 6d b3-0f 76 19 25 8e ed bd 53 ..e}..m..v.%...S -0110 - 35 a9 a1 34 00 9d 07 81-84 51 35 e0 83 83 e3 a6 5..4.....Q5..... -0120 - c7 77 4c 61 e4 78 9c cb-f5 92 4e d6 dd c4 c2 2b .wLa.x....N....+ -0130 - 75 9e 72 a6 7f 81 6a 1c-fc 4a 51 91 81 b4 cc 33 u.r...j..JQ....3 -0140 - 1c 8b 0a b6 94 8b 16 1b-86 2f 31 5e 31 e1 57 14 ........./1^1.W. -0150 - 2e b5 09 5d cf 6f ea b2-94 e9 5c cc b9 fc 24 a0 ...].o....\...$. -0160 - b7 f1 f4 9d 95 46 4f 08-5c 45 c6 2f 9f 7d 76 09 .....FO.\E./.}v. -0170 - 6a af 50 2c 89 76 82 5f-e8 34 d8 4b 84 b6 34 18 j.P,.v._.4.K..4. -0180 - 85 95 4a 3f 0f 28 88 3a-71 32 90 ..J?.(.:q2. - -write to 0x1d750b0 [0x1e74620] (6 bytes => 6 (0x6)) -0000 - 14 03 03 00 01 01 ...... >> CHANGE_CIPHER_SPEC - -write to 0x1d750b0 [0x1e74620] (53 bytes => 53 (0x35)) -0000 - 16 03 03 0030 14 00000c [ed b9 e1 33 36 0b 76 ....0.......36.v >> FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] -0010 - c0 d1 d4 0b a3|73 ec a8-fa b5 cb 12 b6 4c 2a b1 .....s.......L*. -0020 - fb 42 7f 73 0d 06 1c 87-56 f0 db df e6 6a 25 aa .B.s....V....j%. -0030 - fc 42 38 cb 0b] .B8.. - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 16 03 03 00 aa ..... -read from 0x1d750b0 [0x1e6ac08] (170 bytes => 170 (0xAA)) -0000 - 04 00 00 a6 00 00 1c 20-00 a0 dd f4 52 01 54 8d ....... ....R.T. << NEW_SESSION_TICKET -0010 - f8 a6 f9 2d 7d 19 20 5b-14 44 d3 2d 7b f2 ca e8 ...-}. [.D.-{... -0020 - 01 4e 94 7b fe 12 59 3a-00 2e 7e cf 74 43 7a f7 .N.{..Y:..~.tCz. -0030 - 9e cc 70 80 70 7c e3 a5-c6 9d 85 2c 36 19 4c 5c ..p.p|.....,6.L\ -0040 - ba 3b c3 e5 69 dc f3 a4-47 38 11 c9 7d 1a b0 6e .;..i...G8..}..n -0050 - d8 49 a0 a8 e4 de 70 a8-d0 6b e4 7a b7 65 25 df .I....p..k.z.e%. -0060 - 1b 5f 64 0f 89 69 02 72-fe eb d3 7a af 51 78 0e ._d..i.r...z.Qx. -0070 - de 17 06 a5 f0 47 9d e0-04 d4 b1 1e be 7e ed bd .....G.......~.. -0080 - 27 8f 5d e8 ac f6 45 aa-e0 12 93 41 5f a8 4b b9 '.]...E....A_.K. -0090 - bd 43 8f a1 23 51 af 92-77 8f 38 23 3e 2e c2 f0 .C..#Q..w.8#>... -00a0 - a3 74 fa 83 94 ce 19 8a-5b 5b .t......[[ - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 14 03 03 00 01 ..... << CHANGE_CIPHER_SPEC -read from 0x1d750b0 [0x1e6ac08] (1 bytes => 1 (0x1)) -0000 - 01 . - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 16 03 03 00 30 ....0 -read from 0x1d750b0 [0x1e6ac08] (48 bytes => 48 (0x30)) -0000 - 14 00000c [06 86 0d 5c-92 0b 63 04 cc b4 f0 00 .......\..c..... << FINISHED (0x14) [PRF 12 bytes|SHA256_OUTSIZE 32 bytes] -0010 -|49 d6 dd 56 73 e3 d2 e8-22 d6 bd 61 b2 b3 af f0 I..Vs..."..a.... -0020 - f5 00 8a 80 82 04 33 a7-50 8e ae 3b 4c 8c cf 4a] ......3.P..;L..J ---- -Certificate chain - 0 s:/CN=localhost - i:/CN=localhost ---- -Server certificate ------BEGIN CERTIFICATE----- -..."......."......."......."......."......."......."......."......."..... ------END CERTIFICATE----- -subject=/CN=localhost -issuer=/CN=localhost ---- -No client certificate CA names sent ---- -SSL handshake has read 1346 bytes and written 553 bytes ---- -New, TLSv1/SSLv3, Cipher is NULL-SHA256 -Server public key is 3072 bit -Secure Renegotiation IS supported -Compression: NONE -Expansion: NONE -No ALPN negotiated -SSL-Session: - Protocol : TLSv1.2 - Cipher : NULL-SHA256 - Session-ID: 5D62B36950F3DEB571707CD1B815E9E275041B9DB70D7F3E25C4A6535B13B616 - Session-ID-ctx: - Master-Key: 4D08108C59417E0A41656636C51BA5B83F4EFFF9F4C860987B47B31250E5D1816D00940DBCCC196C2D99C8462C889DF1 - Key-Arg : None - Krb5 Principal: None - PSK identity: None - PSK identity hint: None - TLS session ticket lifetime hint: 7200 (seconds) - TLS session ticket: - 0000 - dd f4 52 01 54 8d f8 a6-f9 2d 7d 19 20 5b 14 44 ..R.T....-}. [.D - 0010 - d3 2d 7b f2 ca e8 01 4e-94 7b fe 12 59 3a 00 2e .-{....N.{..Y:.. - 0020 - 7e cf 74 43 7a f7 9e cc-70 80 70 7c e3 a5 c6 9d ~.tCz...p.p|.... - 0030 - 85 2c 36 19 4c 5c ba 3b-c3 e5 69 dc f3 a4 47 38 .,6.L\.;..i...G8 - 0040 - 11 c9 7d 1a b0 6e d8 49-a0 a8 e4 de 70 a8 d0 6b ..}..n.I....p..k - 0050 - e4 7a b7 65 25 df 1b 5f-64 0f 89 69 02 72 fe eb .z.e%.._d..i.r.. - 0060 - d3 7a af 51 78 0e de 17-06 a5 f0 47 9d e0 04 d4 .z.Qx......G.... - 0070 - b1 1e be 7e ed bd 27 8f-5d e8 ac f6 45 aa e0 12 ...~..'.]...E... - 0080 - 93 41 5f a8 4b b9 bd 43-8f a1 23 51 af 92 77 8f .A_.K..C..#Q..w. - 0090 - 38 23 3e 2e c2 f0 a3 74-fa 83 94 ce 19 8a 5b 5b 8#>....t......[[ - - Start Time: 1484574330 - Timeout : 7200 (sec) - Verify return code: 18 (self signed certificate) ---- -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 17 03 03 00 21 ....! -read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) -0000 - 0a 74 5b 50 02 13 75 a4-27 0a 40 b1 53 74 52 14 .t[P..u.'.@.StR. -0010 - e7 1e 6a 6c c1 60 2e 93-7e a5 d9 43 1d 8e f6 08 ..jl.`..~..C.... -0020 - 69 i - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 17 03 03 00 21 ....! -read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) -0000 - 0a 1b ce 44 98 4f 81 c5-28 7a cc 79 62 db d2 86 ...D.O..(z.yb... -0010 - 6a 55 a4 c7 73 49 ef 3e-bd 03 99 76 df 65 2a a1 jU..sI.>...v.e*. -0020 - b6 . - -read from 0x1d750b0 [0x1e6ac03] (5 bytes => 5 (0x5)) -0000 - 17 03 03 00 21 ....! -read from 0x1d750b0 [0x1e6ac08] (33 bytes => 33 (0x21)) -0000 - 0a 67 66 34 ba 68 36 3c-ad 0a c1 f5 c0 5a 50 fe .gf4.h6<.....ZP. -0010 - 68 cd 04 65 e9 de 6e 98-f9 e2 41 1e 0b 9b 84 06 h..e..n...A..... -0020 - 64 d -*/ diff --git a/networking/wget.c b/networking/wget.c index 5da6481c1..58ead4c96 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -472,7 +472,7 @@ static void parse_url(const char *src_url, struct host_info *h) // FYI: // "Real" wget 'http://busybox.net?var=a/b' sends this request: - // 'GET /?var=a/b HTTP 1.0' + // 'GET /?var=a/b HTTP/1.0' // and saves 'index.html?var=a%2Fb' (we save 'b') // wget 'http://busybox.net?login=john@doe': // request: 'GET /?login=john@doe HTTP/1.0' -- cgit v1.2.3-55-g6feb From 19e695ebadda206d1e0fbefa59ed8fabee0d0f64 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 14:27:58 +0100 Subject: tls: do not use common_bufsiz Signed-off-by: Denys Vlasenko --- networking/tls.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index e037eba69..2674997ff 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -23,7 +23,7 @@ //usage:#define tls_full_usage "\n\n" #include "tls.h" -#include "common_bufsiz.h" +//#include "common_bufsiz.h" #define TLS_DEBUG 1 #define TLS_DEBUG_HASH 1 @@ -677,7 +677,8 @@ static int xread_tls_block(tls_state_t *tls) again: dbg("insize:%u tail:%u\n", tls->insize, tls->tail); - memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); + if (tls->tail != 0) + memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); errno = 0; total = tls->tail; target = sizeof(tls->inbuf); @@ -702,7 +703,6 @@ static int xread_tls_block(tls_state_t *tls) /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ dbg("EOF (without TLS shutdown) from peer\n"); tls->tail = 0; - tls->insize = 0; goto end; } bb_perror_msg_and_die("short read, have only %d", total); @@ -1062,6 +1062,8 @@ static void send_client_hello(tls_state_t *tls) record->comprtypes_len = 1; record->comprtypes[0] = 0; +//TODO: send options, at least SNI. + dbg(">> CLIENT_HELLO\n"); xwrite_and_update_handshake_hash(tls, sizeof(*record)); } @@ -1453,6 +1455,9 @@ static void tls_xwrite(tls_state_t *tls, int len) // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 +// +// Talk to kernel.org: +// printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tls_main(int argc UNUSED_PARAM, char **argv) @@ -1478,8 +1483,8 @@ int tls_main(int argc UNUSED_PARAM, char **argv) FD_SET(cfd, &readfds); FD_SET(STDIN_FILENO, &readfds); -#define iobuf bb_common_bufsiz1 - setup_common_bufsiz(); +//#define iobuf bb_common_bufsiz1 +// setup_common_bufsiz(); for (;;) { int nread; @@ -1492,12 +1497,14 @@ int tls_main(int argc UNUSED_PARAM, char **argv) void *buf; dbg("STDIN HAS DATA\n"); - buf = tls_get_outbuf(tls, COMMON_BUFSIZE); - nread = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE); +//TODO: growable buffer + buf = tls_get_outbuf(tls, 4 * 1024); + nread = safe_read(STDIN_FILENO, buf, 4 * 1024); if (nread < 1) { //&& errno != EAGAIN /* Close outgoing half-connection so they get EOF, * but leave incoming alone so we can see response */ +//TLS has no way to encode this, doubt it's ok to do it "raw" // shutdown(cfd, SHUT_WR); FD_CLR(STDIN_FILENO, &readfds); } @@ -1507,7 +1514,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) dbg("NETWORK HAS DATA\n"); nread = xread_tls_block(tls); if (nread < 1) -//if eof, just close stdout, but not exit! +//TODO: if eof, just close stdout, but not exit! return EXIT_SUCCESS; xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); } -- cgit v1.2.3-55-g6feb From 179e88bec91cfe58096900dc5509a080ff37b083 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 16:03:48 +0100 Subject: rdate: make it do something remotely sane, facing 32-bit time overflow function old new delta rdate_main 251 254 +3 packed_usage 31029 31023 -6 Signed-off-by: Denys Vlasenko --- networking/inetd.c | 2 +- util-linux/rdate.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/networking/inetd.c b/networking/inetd.c index 4d0ab2e0d..612284e76 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -1677,7 +1677,7 @@ static uint32_t machtime(void) struct timeval tv; gettimeofday(&tv, NULL); - return htonl((uint32_t)(tv.tv_sec + 2208988800)); + return htonl((uint32_t)(tv.tv_sec + 2208988800U)); } /* ARGSUSED */ static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM) diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 8dd784d3d..a62591914 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -21,11 +21,11 @@ //kbuild:lib-$(CONFIG_RDATE) += rdate.o //usage:#define rdate_trivial_usage -//usage: "[-sp] HOST" +//usage: "[-s/-p] HOST" //usage:#define rdate_full_usage "\n\n" -//usage: "Get and possibly set system time from a remote HOST\n" -//usage: "\n -s Set system time (default)" -//usage: "\n -p Print time" +//usage: "Set and print time from HOST using RFC 868\n" +//usage: "\n -s Only set system time" +//usage: "\n -p Only print time" #include "libbb.h" @@ -58,8 +58,22 @@ static time_t askremotedate(const char *host) * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT * Subtract the RFC 868 time to get Linux epoch. */ - - return ntohl(nett) - RFC_868_BIAS; + nett = ntohl(nett) - RFC_868_BIAS; + + if (sizeof(time_t) > 4) { + /* Now we have 32-bit lsb of a wider time_t + * Imagine that nett = 0x00000001, + * current time cur = 0x123ffffffff. + * Assuming our time is not some 40 years off, + * remote time must be 0x12400000001. + * Need to adjust out time by (int32_t)(nett - cur). + */ + time_t cur = time(NULL); + int32_t adjust = (int32_t)(nett - (uint32_t)cur); + return cur + adjust; + } + /* This is not going to work, but what can we do */ + return (time_t)nett; } int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -73,6 +87,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) remote_time = askremotedate(argv[optind]); + /* Manpages of various Unixes are confusing. What happens is: + * (no opts) set and print time + * -s: set time ("do not print the time") + * -p: print time ("do not set, just print the remote time") + * -sp: print time (that's what we do, not sure this is right) + */ + if (!(flags & 2)) { /* no -p (-s may be present) */ time_t current_time; -- cgit v1.2.3-55-g6feb From 6e511393f90a30c93c445c3d1ed6090e79e7384b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 16:07:14 +0100 Subject: rdate: time(NULL) is shorter than time(&var) function old new delta rdate_main 251 246 -5 Signed-off-by: Denys Vlasenko --- util-linux/rdate.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/util-linux/rdate.c b/util-linux/rdate.c index a62591914..960df25d2 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -95,10 +95,7 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) */ if (!(flags & 2)) { /* no -p (-s may be present) */ - time_t current_time; - - time(¤t_time); - if (current_time == remote_time) + if (time(NULL) == remote_time) bb_error_msg("current time matches remote time"); else if (stime(&remote_time) < 0) -- cgit v1.2.3-55-g6feb From e7863f394e6a963d1e2c6af77ea064442d3ef594 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 17:59:25 +0100 Subject: tls: was psAesDecrypt'ing one block too many, trashing buffered data For the first time printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org successfully reads entire server response and TLS shutdown. Signed-off-by: Denys Vlasenko --- networking/tls.c | 136 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 63 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 2674997ff..cdce1004e 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -26,7 +26,7 @@ //#include "common_bufsiz.h" #define TLS_DEBUG 1 -#define TLS_DEBUG_HASH 1 +#define TLS_DEBUG_HASH 0 #define TLS_DEBUG_DER 0 #define TLS_DEBUG_FIXED_SECRETS 0 @@ -42,6 +42,18 @@ # define dbg_der(...) ((void)0) #endif +#if 0 +# define dump_raw_out(...) dump_hex(__VA_ARGS__) +#else +# define dump_raw_out(...) ((void)0) +#endif + +#if 1 +# define dump_raw_in(...) dump_hex(__VA_ARGS__) +#else +# define dump_raw_in(...) ((void)0) +#endif + #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 #define RECORD_TYPE_ALERT 21 #define RECORD_TYPE_HANDSHAKE 22 @@ -482,49 +494,11 @@ static void *tls_get_outbuf(tls_state_t *tls, int len) return tls->outbuf + OUTBUF_PFX; } -// RFC 5246 -// 6.2.3.1. Null or Standard Stream Cipher -// -// Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) -// convert TLSCompressed.fragment structures to and from stream -// TLSCiphertext.fragment structures. -// -// stream-ciphered struct { -// opaque content[TLSCompressed.length]; -// opaque MAC[SecurityParameters.mac_length]; -// } GenericStreamCipher; -// -// The MAC is generated as: -// MAC(MAC_write_key, seq_num + -// TLSCompressed.type + -// TLSCompressed.version + -// TLSCompressed.length + -// TLSCompressed.fragment); -// where "+" denotes concatenation. -// seq_num -// The sequence number for this record. -// MAC -// The MAC algorithm specified by SecurityParameters.mac_algorithm. -// -// Note that the MAC is computed before encryption. The stream cipher -// encrypts the entire block, including the MAC. -//... -// Appendix C. Cipher Suite Definitions -//... -// Key IV Block -// Cipher Type Material Size Size -// ------------ ------ -------- ---- ----- -// AES_128_CBC Block 16 16 16 -// AES_256_CBC Block 32 16 16 -// -// MAC Algorithm mac_length mac_key_length -// -------- ----------- ---------- -------------- -// SHA HMAC-SHA1 20 20 -// SHA256 HMAC-SHA256 32 32 static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) { uint8_t *buf = tls->outbuf + OUTBUF_PFX; struct record_hdr *xhdr; + uint8_t padding_length; xhdr = (void*)(buf - RECHDR_LEN); if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) @@ -549,17 +523,49 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) size += SHA256_OUTSIZE; + // RFC 5246 + // 6.2.3.1. Null or Standard Stream Cipher + // + // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6) + // convert TLSCompressed.fragment structures to and from stream + // TLSCiphertext.fragment structures. + // + // stream-ciphered struct { + // opaque content[TLSCompressed.length]; + // opaque MAC[SecurityParameters.mac_length]; + // } GenericStreamCipher; + // + // The MAC is generated as: + // MAC(MAC_write_key, seq_num + + // TLSCompressed.type + + // TLSCompressed.version + + // TLSCompressed.length + + // TLSCompressed.fragment); + // where "+" denotes concatenation. + // seq_num + // The sequence number for this record. + // MAC + // The MAC algorithm specified by SecurityParameters.mac_algorithm. + // + // Note that the MAC is computed before encryption. The stream cipher + // encrypts the entire block, including the MAC. + //... + // Appendix C. Cipher Suite Definitions + //... + // MAC Algorithm mac_length mac_key_length + // -------- ----------- ---------- -------------- + // SHA HMAC-SHA1 20 20 + // SHA256 HMAC-SHA256 32 32 if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { /* No encryption, only signing */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); xwrite(tls->fd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); return; } - // RFC 5246 // 6.2.3.2. CBC Block Cipher // For block ciphers (such as 3DES or AES), the encryption and MAC // functions convert TLSCompressed.fragment structures to and from block @@ -595,10 +601,6 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // ------------ ------ -------- ---- ----- // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 - { - psCipherContext_t ctx; - uint8_t *p; - uint8_t padding_length; /* Build IV+content+MAC+padding in outbuf */ tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ @@ -618,22 +620,23 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // If you need no bytes to reach BLOCKSIZE, you have to pad a full // BLOCKSIZE with bytes of value (BLOCKSIZE-1). // It's ok to have more than minimum padding, but we do minimum. - p = buf + size; padding_length = (~size) & (AES_BLOCKSIZE - 1); do { - *p++ = padding_length; /* padding */ - size++; + buf[size++] = padding_length; /* padding */ } while ((size & (AES_BLOCKSIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ - psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ + { + psCipherContext_t ctx; + psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ tls->client_write_key, sizeof(tls->client_write_key) - ); - psAesEncrypt(&ctx, + ); + psAesEncrypt(&ctx, buf, /* plaintext */ buf, /* ciphertext */ size - ); + ); + } /* Write out */ dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", @@ -641,10 +644,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) size += AES_BLOCKSIZE; /* + IV */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); xwrite(tls->fd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); - } } static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) @@ -658,7 +660,7 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) xhdr->proto_min = TLS_MIN; xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; - dump_hex(">> %s\n", xhdr, RECHDR_LEN + size); + dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); xwrite(tls->fd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); /* Handshake hash does not include record headers */ @@ -677,10 +679,13 @@ static int xread_tls_block(tls_state_t *tls) again: dbg("insize:%u tail:%u\n", tls->insize, tls->tail); - if (tls->tail != 0) - memmove(tls->inbuf, tls->inbuf + tls->insize, tls->tail); - errno = 0; total = tls->tail; + if (total != 0) { + memmove(tls->inbuf, tls->inbuf + tls->insize, total); + //dbg("<< remaining at %d [%d] ", tls->insize, total); + //dump_raw_in("<< %s\n", tls->inbuf, total); + } + errno = 0; target = sizeof(tls->inbuf); for (;;) { if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { @@ -692,7 +697,11 @@ static int xread_tls_block(tls_state_t *tls) tls->insize = total; tls_error_die(tls); } - // can also check type/proto_maj/proto_min here + /* can also check type/proto_maj/proto_min here */ + dbg("xhdr type:%d ver:%d.%d len:%d\n", + xhdr->type, xhdr->proto_maj, xhdr->proto_min, + 0x100 * xhdr->len16_hi + xhdr->len16_lo + ); } /* if total >= target, we have a full packet (and possibly more)... */ if (total - target >= 0) @@ -707,12 +716,13 @@ static int xread_tls_block(tls_state_t *tls) } bb_perror_msg_and_die("short read, have only %d", total); } - dbg("read():%d\n", sz); + dump_raw_in("<< %s\n", tls->inbuf + total, sz); total += sz; } tls->tail = total - target; tls->insize = target; - dbg("new insize:%u tail:%u\n", tls->insize, tls->tail); + //dbg("<< stashing at %d [%d] ", tls->insize, tls->tail); + //dump_hex("<< %s\n", tls->inbuf + tls->insize, tls->tail); sz = target - RECHDR_LEN; @@ -734,7 +744,7 @@ static int xread_tls_block(tls_state_t *tls) psAesDecrypt(&ctx, p + AES_BLOCKSIZE, /* ciphertext */ p + AES_BLOCKSIZE, /* plaintext */ - sz + sz - AES_BLOCKSIZE ); padding_len = p[sz - 1]; dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); -- cgit v1.2.3-55-g6feb From 38972a8df1df970a5878bbd7fc5ef6259f1168ab Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 19:11:14 +0100 Subject: tls: improve i/o loop With tls_has_buffered_record(), entire kernel.org response is printed at once, without 6 second pause to see its delayed EOF. Signed-off-by: Denys Vlasenko --- networking/tls.c | 130 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 92 insertions(+), 38 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index cdce1004e..000d2aedc 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -48,7 +48,7 @@ # define dump_raw_out(...) ((void)0) #endif -#if 1 +#if 0 # define dump_raw_in(...) dump_hex(__VA_ARGS__) #else # define dump_raw_in(...) ((void)0) @@ -72,9 +72,6 @@ #define HANDSHAKE_CLIENT_KEY_EXCHANGE 16 #define HANDSHAKE_FINISHED 20 -#define SSL_HS_RANDOM_SIZE 32 -#define SSL_HS_RSA_PREMASTER_SIZE 48 - #define SSL_NULL_WITH_NULL_NULL 0x0000 #define SSL_RSA_WITH_NULL_MD5 0x0001 #define SSL_RSA_WITH_NULL_SHA 0x0002 @@ -175,12 +172,15 @@ enum { AES128_KEYSIZE = 16, AES256_KEYSIZE = 32, + RSA_PREMASTER_SIZE = 48, + RECHDR_LEN = 5, MAX_TLS_RECORD = (1 << 14), + /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */ OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ - MAX_OTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, + MAX_OUTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, }; struct record_hdr { @@ -205,20 +205,21 @@ typedef struct tls_state { uint8_t server_write_MAC_key[SHA256_OUTSIZE]; uint8_t client_write_key[AES256_KEYSIZE]; uint8_t server_write_key[AES256_KEYSIZE]; -// RFC 5246 -// sequence number -// Each connection state contains a sequence number, which is -// maintained separately for read and write states. The sequence -// number MUST be set to zero whenever a connection state is made the -// active state. Sequence numbers are of type uint64 and may not -// exceed 2^64-1. + + // RFC 5246 + // sequence number + // Each connection state contains a sequence number, which is + // maintained separately for read and write states. The sequence + // number MUST be set to zero whenever a connection state is made the + // active state. Sequence numbers are of type uint64 and may not + // exceed 2^64-1. uint64_t write_seq64_be; int outbuf_size; uint8_t *outbuf; // RFC 5246 - // |6.2.1. Fragmentation + // | 6.2.1. Fragmentation // | The record layer fragments information blocks into TLSPlaintext // | records carrying data in chunks of 2^14 bytes or less. Client // | message boundaries are not preserved in the record layer (i.e., @@ -290,6 +291,9 @@ static void dump_tls_record(const void *vp, int len) len -= xhdr_len; } } +#else +# define dump_hex(...) ((void)0) +# define dump_tls_record(...) ((void)0) #endif void tls_get_random(void *buf, unsigned len) @@ -480,12 +484,19 @@ static tls_state_t *new_tls_state(void) static void tls_error_die(tls_state_t *tls) { dump_tls_record(tls->inbuf, tls->insize + tls->tail); - xfunc_die(); + bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); +} + +static void tls_free_outbuf(tls_state_t *tls) +{ + free(tls->outbuf); + tls->outbuf_size = 0; + tls->outbuf = NULL; } static void *tls_get_outbuf(tls_state_t *tls, int len) { - if (len > MAX_OTBUF) + if (len > MAX_OUTBUF) xfunc_die(); if (tls->outbuf_size < len + OUTBUF_PFX + OUTBUF_SFX) { tls->outbuf_size = len + OUTBUF_PFX + OUTBUF_SFX; @@ -670,7 +681,22 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); } -static int xread_tls_block(tls_state_t *tls) +static int tls_has_buffered_record(tls_state_t *tls) +{ + int buffered = tls->tail; + struct record_hdr *xhdr; + int rec_size; + + if (buffered < RECHDR_LEN) + return 0; + xhdr = (void*)(tls->inbuf + tls->insize); + rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); + if (buffered < rec_size) + return 0; + return rec_size; +} + +static int tls_xread_record(tls_state_t *tls) { struct record_hdr *xhdr; int sz; @@ -1012,7 +1038,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) static int xread_tls_handshake_block(tls_state_t *tls, int min_len) { struct record_hdr *xhdr; - int len = xread_tls_block(tls); + int len = tls_xread_record(tls); xhdr = (void*)tls->inbuf; if (len < min_len @@ -1177,7 +1203,7 @@ static void send_client_key_exchange(tls_state_t *tls) }; //FIXME: better size estimate struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record)); - uint8_t rsa_premaster[SSL_HS_RSA_PREMASTER_SIZE]; + uint8_t rsa_premaster[RSA_PREMASTER_SIZE]; int len; tls_get_random(rsa_premaster, sizeof(rsa_premaster)); @@ -1383,7 +1409,7 @@ static void tls_handshake(tls_state_t *tls) send_client_hello(tls); get_server_hello(tls); - //RFC 5246 + // RFC 5246 // The server MUST send a Certificate message whenever the agreed- // upon key exchange method uses certificates for authentication // (this includes all key exchange methods defined in this document @@ -1408,7 +1434,7 @@ static void tls_handshake(tls_state_t *tls) // if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { // dbg("<< CERTIFICATE_REQUEST\n"); -//RFC 5246: (in response to this,) "If no suitable certificate is available, +// RFC 5246: (in response to this,) "If no suitable certificate is available, // the client MUST send a certificate message containing no // certificates. That is, the certificate_list structure has a // length of zero. ... @@ -1433,7 +1459,7 @@ static void tls_handshake(tls_state_t *tls) send_client_finished(tls); /* Get CHANGE_CIPHER_SPEC */ - len = xread_tls_block(tls); + len = tls_xread_record(tls); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) tls_error_die(tls); dbg("<< CHANGE_CIPHER_SPEC\n"); @@ -1444,7 +1470,7 @@ static void tls_handshake(tls_state_t *tls) tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; /* Get (encrypted) FINISHED from the server */ - len = xread_tls_block(tls); + len = tls_xread_record(tls); if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED) tls_error_die(tls); dbg("<< FINISHED\n"); @@ -1473,9 +1499,12 @@ int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int tls_main(int argc UNUSED_PARAM, char **argv) { tls_state_t *tls; - fd_set readfds, testfds; + fd_set readfds; + int inbuf_size; + const int INBUF_STEP = 4 * 1024; int cfd; + // INIT_G(); // getopt32(argv, "myopts") @@ -1493,13 +1522,12 @@ int tls_main(int argc UNUSED_PARAM, char **argv) FD_SET(cfd, &readfds); FD_SET(STDIN_FILENO, &readfds); -//#define iobuf bb_common_bufsiz1 -// setup_common_bufsiz(); + inbuf_size = INBUF_STEP; for (;;) { + fd_set testfds; int nread; testfds = readfds; - if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) bb_perror_msg_and_die("select"); @@ -1507,26 +1535,52 @@ int tls_main(int argc UNUSED_PARAM, char **argv) void *buf; dbg("STDIN HAS DATA\n"); -//TODO: growable buffer - buf = tls_get_outbuf(tls, 4 * 1024); - nread = safe_read(STDIN_FILENO, buf, 4 * 1024); + buf = tls_get_outbuf(tls, inbuf_size); + nread = safe_read(STDIN_FILENO, buf, inbuf_size); if (nread < 1) { -//&& errno != EAGAIN + /* We'd want to do this: */ /* Close outgoing half-connection so they get EOF, - * but leave incoming alone so we can see response */ -//TLS has no way to encode this, doubt it's ok to do it "raw" -// shutdown(cfd, SHUT_WR); + * but leave incoming alone so we can see response + */ + //shutdown(cfd, SHUT_WR); + /* But TLS has no way to encode this, + * doubt it's ok to do it "raw" + */ FD_CLR(STDIN_FILENO, &readfds); + tls_free_outbuf(tls); + } else { + if (nread == inbuf_size) { + /* TLS has per record overhead, if input comes fast, + * read, encrypt and send bigger chunks + */ + inbuf_size += INBUF_STEP; + if (inbuf_size > MAX_OUTBUF) + inbuf_size = MAX_OUTBUF; + } + tls_xwrite(tls, nread); } - tls_xwrite(tls, nread); } if (FD_ISSET(cfd, &testfds)) { dbg("NETWORK HAS DATA\n"); - nread = xread_tls_block(tls); - if (nread < 1) -//TODO: if eof, just close stdout, but not exit! - return EXIT_SUCCESS; + read_record: + nread = tls_xread_record(tls); + if (nread < 1) { + /* TLS protocol has no real concept of one-sided shutdowns: + * if we get "TLS EOF" from the peer, writes will fail too + */ + //FD_CLR(cfd, &readfds); + //close(STDOUT_FILENO); + //continue; + break; + } + if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA) + bb_error_msg_and_die("unexpected record type %d", tls->inbuf[0]); xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread); + /* We may already have a complete next record buffered, + * can process it without network reads (and possible blocking) + */ + if (tls_has_buffered_record(tls)) + goto read_record; } } -- cgit v1.2.3-55-g6feb From 9731ca7611e19827702eb8c690fb6c3b37403319 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 19:47:49 +0100 Subject: password utils: improve --help, make DEFAULT_PASSWD_ALGO visible if CHPASSWD Was: $ cryptpw --help ... Print crypt(3) hashed PASSWORD -P,--password-fd=N Read password from fd N -m,--method=TYPE Encryption method -S,--salt=SALT User: "What methods exist? which one os default?" Now: Print crypt(3) hashed PASSWORD -P,--password-fd N Read password from fd N -m,--method TYPE des,md5,sha256/512 (default des) -S,--salt SALT Signed-off-by: Denys Vlasenko --- include/usage.src.h | 8 ++++++++ loginutils/chpasswd.c | 12 ++++++------ loginutils/cryptpw.c | 8 ++++---- loginutils/passwd.c | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/usage.src.h b/include/usage.src.h index 78beccf4d..00369dfb3 100644 --- a/include/usage.src.h +++ b/include/usage.src.h @@ -14,6 +14,14 @@ #define NOUSAGE_STR "\b" +#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA +# define CRYPT_METHODS_HELP_STR "des,md5,sha256/512" \ + " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" +#else +# define CRYPT_METHODS_HELP_STR "des,md5" \ + " (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")" +#endif + INSERT #define busybox_notes_usage \ diff --git a/loginutils/chpasswd.c b/loginutils/chpasswd.c index 2d268be67..baafd35c8 100644 --- a/loginutils/chpasswd.c +++ b/loginutils/chpasswd.c @@ -13,9 +13,9 @@ //config: and uses this information to update a group of existing users. //config: //config:config FEATURE_DEFAULT_PASSWD_ALGO -//config: string "Default password encryption method (passwd -a, cryptpw -m parameter)" +//config: string "Default encryption method (passwd -a, cryptpw -m, chpasswd -c ALG)" //config: default "des" -//config: depends on PASSWD || CRYPTPW +//config: depends on PASSWD || CRYPTPW || CHPASSWD //config: help //config: Possible choices are "d[es]", "m[d5]", "s[ha256]" or "sha512". @@ -29,13 +29,13 @@ //usage: "Read user:password from stdin and update /etc/passwd\n" //usage: IF_LONG_OPTS( //usage: "\n -e,--encrypted Supplied passwords are in encrypted form" -//usage: "\n -m,--md5 Use MD5 encryption instead of DES" -//usage: "\n -c,--crypt-method Use the specified method to encrypt the passwords" +//usage: "\n -m,--md5 Eencrypt using md5, not des" +//usage: "\n -c,--crypt-method ALG "CRYPT_METHODS_HELP_STR //usage: ) //usage: IF_NOT_LONG_OPTS( //usage: "\n -e Supplied passwords are in encrypted form" -//usage: "\n -m Use MD5 encryption instead of DES" -//usage: "\n -c Use the specified method to encrypt the passwords" +//usage: "\n -m Eencrypt using md5, not des" +//usage: "\n -c ALG "CRYPT_METHODS_HELP_STR //usage: ) #include "libbb.h" diff --git a/loginutils/cryptpw.c b/loginutils/cryptpw.c index d630231c6..696e169fc 100644 --- a/loginutils/cryptpw.c +++ b/loginutils/cryptpw.c @@ -37,15 +37,15 @@ //usage:#define cryptpw_full_usage "\n\n" //usage: "Print crypt(3) hashed PASSWORD\n" //usage: IF_LONG_OPTS( -//usage: "\n -P,--password-fd=N Read password from fd N" +//usage: "\n -P,--password-fd N Read password from fd N" /* //usage: "\n -s,--stdin Use stdin; like -P0" */ -//usage: "\n -m,--method=TYPE Encryption method" -//usage: "\n -S,--salt=SALT" +//usage: "\n -m,--method TYPE "CRYPT_METHODS_HELP_STR +//usage: "\n -S,--salt SALT" //usage: ) //usage: IF_NOT_LONG_OPTS( //usage: "\n -P N Read password from fd N" /* //usage: "\n -s Use stdin; like -P0" */ -//usage: "\n -m TYPE Encryption method TYPE" +//usage: "\n -m TYPE "CRYPT_METHODS_HELP_STR //usage: "\n -S SALT" //usage: ) diff --git a/loginutils/passwd.c b/loginutils/passwd.c index 52b66ca50..b7b7423fd 100644 --- a/loginutils/passwd.c +++ b/loginutils/passwd.c @@ -32,7 +32,7 @@ //usage:#define passwd_full_usage "\n\n" //usage: "Change USER's password (default: current user)" //usage: "\n" -//usage: "\n -a ALG Encryption method" +//usage: "\n -a ALG "CRYPT_METHODS_HELP_STR //usage: "\n -d Set password to ''" //usage: "\n -l Lock (disable) account" //usage: "\n -u Unlock (enable) account" -- cgit v1.2.3-55-g6feb From 3916139ac4b9f60d7b958e5b2d88a277753dcc74 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 20:27:06 +0100 Subject: tls: make input buffer grow as needed As it turns out, it goes only up to "inbuf_size:4608" for kernel.org - fixed 18kb buffer was x4 larger than necessary. Signed-off-by: Denys Vlasenko --- networking/tls.c | 132 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 49 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 000d2aedc..55ad2d83f 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -181,6 +181,42 @@ enum { OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ MAX_OUTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, + + // RFC 5246 + // | 6.2.1. Fragmentation + // | The record layer fragments information blocks into TLSPlaintext + // | records carrying data in chunks of 2^14 bytes or less. Client + // | message boundaries are not preserved in the record layer (i.e., + // | multiple client messages of the same ContentType MAY be coalesced + // | into a single TLSPlaintext record, or a single message MAY be + // | fragmented across several records) + // |... + // | length + // | The length (in bytes) of the following TLSPlaintext.fragment. + // | The length MUST NOT exceed 2^14. + // |... + // | 6.2.2. Record Compression and Decompression + // |... + // | Compression must be lossless and may not increase the content length + // | by more than 1024 bytes. If the decompression function encounters a + // | TLSCompressed.fragment that would decompress to a length in excess of + // | 2^14 bytes, it MUST report a fatal decompression failure error. + // |... + // | length + // | The length (in bytes) of the following TLSCompressed.fragment. + // | The length MUST NOT exceed 2^14 + 1024. + // |... + // | 6.2.3. Record Payload Protection + // | The encryption and MAC functions translate a TLSCompressed + // | structure into a TLSCiphertext. The decryption functions reverse + // | the process. The MAC of the record also includes a sequence + // | number so that missing, extra, or repeated messages are + // | detectable. + // |... + // | length + // | The length (in bytes) of the following TLSCiphertext.fragment. + // | The length MUST NOT exceed 2^14 + 2048. + MAX_INBUF = (1 << 14) + 2048, }; struct record_hdr { @@ -218,36 +254,10 @@ typedef struct tls_state { int outbuf_size; uint8_t *outbuf; - // RFC 5246 - // | 6.2.1. Fragmentation - // | The record layer fragments information blocks into TLSPlaintext - // | records carrying data in chunks of 2^14 bytes or less. Client - // | message boundaries are not preserved in the record layer (i.e., - // | multiple client messages of the same ContentType MAY be coalesced - // | into a single TLSPlaintext record, or a single message MAY be - // | fragmented across several records) - // |... - // | length - // | The length (in bytes) of the following TLSPlaintext.fragment. - // | The length MUST NOT exceed 2^14. - // |... - // | 6.2.2. Record Compression and Decompression - // |... - // | Compression must be lossless and may not increase the content length - // | by more than 1024 bytes. If the decompression function encounters a - // | TLSCompressed.fragment that would decompress to a length in excess of - // | 2^14 bytes, it MUST report a fatal decompression failure error. - // |... - // | length - // | The length (in bytes) of the following TLSCompressed.fragment. - // | The length MUST NOT exceed 2^14 + 1024. - // - // Since our buffer also contains 5-byte headers, make it a bit bigger: - int insize; - int tail; -//needed? - uint64_t align____; - uint8_t inbuf[20*1024]; + int inbuf_size; + int ofs_to_buffered; + int buffered_size; + uint8_t *inbuf; } tls_state_t; @@ -483,10 +493,21 @@ static tls_state_t *new_tls_state(void) static void tls_error_die(tls_state_t *tls) { - dump_tls_record(tls->inbuf, tls->insize + tls->tail); + dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); } +#if 0 //UNUSED +static void tls_free_inbuf(tls_state_t *tls) +{ + if (tls->buffered_size == 0) { + free(tls->inbuf); + tls->inbuf_size = 0; + tls->inbuf = NULL; + } +} +#endif + static void tls_free_outbuf(tls_state_t *tls) { free(tls->outbuf); @@ -683,13 +704,13 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) static int tls_has_buffered_record(tls_state_t *tls) { - int buffered = tls->tail; + int buffered = tls->buffered_size; struct record_hdr *xhdr; int rec_size; if (buffered < RECHDR_LEN) return 0; - xhdr = (void*)(tls->inbuf + tls->insize); + xhdr = (void*)(tls->inbuf + tls->ofs_to_buffered); rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); if (buffered < rec_size) return 0; @@ -704,23 +725,25 @@ static int tls_xread_record(tls_state_t *tls) int target; again: - dbg("insize:%u tail:%u\n", tls->insize, tls->tail); - total = tls->tail; + dbg("ofs_to_buffered:%u buffered_size:%u\n", tls->ofs_to_buffered, tls->buffered_size); + total = tls->buffered_size; if (total != 0) { - memmove(tls->inbuf, tls->inbuf + tls->insize, total); - //dbg("<< remaining at %d [%d] ", tls->insize, total); + memmove(tls->inbuf, tls->inbuf + tls->ofs_to_buffered, total); + //dbg("<< remaining at %d [%d] ", tls->ofs_to_buffered, total); //dump_raw_in("<< %s\n", tls->inbuf, total); } errno = 0; - target = sizeof(tls->inbuf); + target = MAX_INBUF; for (;;) { - if (total >= RECHDR_LEN && target == sizeof(tls->inbuf)) { + int rem; + + if (total >= RECHDR_LEN && target == MAX_INBUF) { xhdr = (void*)tls->inbuf; target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo); - if (target >= sizeof(tls->inbuf)) { + if (target > MAX_INBUF) { /* malformed input (too long): yell and die */ - tls->tail = 0; - tls->insize = total; + tls->buffered_size = 0; + tls->ofs_to_buffered = total; tls_error_die(tls); } /* can also check type/proto_maj/proto_min here */ @@ -732,12 +755,22 @@ static int tls_xread_record(tls_state_t *tls) /* if total >= target, we have a full packet (and possibly more)... */ if (total - target >= 0) break; - sz = safe_read(tls->fd, tls->inbuf + total, sizeof(tls->inbuf) - total); + /* input buffer is grown only as needed */ + rem = tls->inbuf_size - total; + if (rem == 0) { + tls->inbuf_size += MAX_INBUF / 8; + if (tls->inbuf_size > MAX_INBUF) + tls->inbuf_size = MAX_INBUF; + dbg("inbuf_size:%d\n", tls->inbuf_size); + rem = tls->inbuf_size - total; + tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); + } + sz = safe_read(tls->fd, tls->inbuf + total, rem); if (sz <= 0) { if (sz == 0 && total == 0) { /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ dbg("EOF (without TLS shutdown) from peer\n"); - tls->tail = 0; + tls->buffered_size = 0; goto end; } bb_perror_msg_and_die("short read, have only %d", total); @@ -745,10 +778,10 @@ static int tls_xread_record(tls_state_t *tls) dump_raw_in("<< %s\n", tls->inbuf + total, sz); total += sz; } - tls->tail = total - target; - tls->insize = target; - //dbg("<< stashing at %d [%d] ", tls->insize, tls->tail); - //dump_hex("<< %s\n", tls->inbuf + tls->insize, tls->tail); + tls->buffered_size = total - target; + tls->ofs_to_buffered = target; + //dbg("<< stashing at %d [%d] ", tls->ofs_to_buffered, tls->buffered_size); + //dump_hex("<< %s\n", tls->inbuf + tls->ofs_to_buffered, tls->buffered_size); sz = target - RECHDR_LEN; @@ -1547,7 +1580,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) * doubt it's ok to do it "raw" */ FD_CLR(STDIN_FILENO, &readfds); - tls_free_outbuf(tls); + tls_free_outbuf(tls); /* mem usage optimization */ } else { if (nread == inbuf_size) { /* TLS has per record overhead, if input comes fast, @@ -1570,6 +1603,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) */ //FD_CLR(cfd, &readfds); //close(STDOUT_FILENO); + //tls_free_inbuf(tls); /* mem usage optimization */ //continue; break; } -- cgit v1.2.3-55-g6feb From 54b927d78bfdac54873513fb1dd992a7758d29c8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 21:19:38 +0100 Subject: tls: AES decrypt does one unnecessary memmove Signed-off-by: Denys Vlasenko --- networking/tls.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 55ad2d83f..fb49b1523 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -539,7 +539,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->type = type; xhdr->proto_maj = TLS_MAJ; xhdr->proto_min = TLS_MIN; - /* fake unencrypted record header len for MAC calculation */ + /* fake unencrypted record len for MAC calculation */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; @@ -634,7 +634,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // AES_128_CBC Block 16 16 16 // AES_256_CBC Block 32 16 16 - /* Build IV+content+MAC+padding in outbuf */ + /* Fill IV and padding in outbuf */ tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, SHA256_OUTSIZE); // RFC is talking nonsense: @@ -654,7 +654,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // It's ok to have more than minimum padding, but we do minimum. padding_length = (~size) & (AES_BLOCKSIZE - 1); do { - buf[size++] = padding_length; /* padding */ + buf[size++] = padding_length; /* padding */ } while ((size & (AES_BLOCKSIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ @@ -796,26 +796,23 @@ static int tls_xread_record(tls_state_t *tls) ) { bb_error_msg_and_die("bad encrypted len:%u", sz); } - /* Decrypt content+MAC+padding in place */ + /* Decrypt content+MAC+padding, moving it over IV in the process */ psAesInit(&ctx, p, /* IV */ tls->server_write_key, sizeof(tls->server_write_key) ); + sz -= AES_BLOCKSIZE; /* we will overwrite IV now */ psAesDecrypt(&ctx, p + AES_BLOCKSIZE, /* ciphertext */ - p + AES_BLOCKSIZE, /* plaintext */ - sz - AES_BLOCKSIZE + p, /* plaintext */ + sz ); padding_len = p[sz - 1]; - dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[AES_BLOCKSIZE], padding_len); + dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); padding_len++; - sz -= AES_BLOCKSIZE + SHA256_OUTSIZE + padding_len; + sz -= SHA256_OUTSIZE + padding_len; /* drop MAC and padding */ if (sz < 0) { bb_error_msg_and_die("bad padding size:%u", padding_len); } - if (sz != 0) { - /* Skip IV */ - memmove(tls->inbuf + RECHDR_LEN, tls->inbuf + RECHDR_LEN + AES_BLOCKSIZE, sz); - } } else { /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ /* else: no encryption yet on input, subtract zero = NOP */ @@ -828,8 +825,8 @@ static int tls_xread_record(tls_state_t *tls) if (xhdr->type == RECORD_TYPE_ALERT && sz >= 2) { uint8_t *p = tls->inbuf + RECHDR_LEN; dbg("ALERT size:%d level:%d description:%d\n", sz, p[0], p[1]); - if (p[0] == 1) { /*warning */ - if (p[1] == 0) { /* warning, close_notify: EOF */ + if (p[0] == 1) { /* warning */ + if (p[1] == 0) { /* "close_notify" warning: it's EOF */ dbg("EOF (TLS encoded) from peer\n"); sz = 0; goto end; -- cgit v1.2.3-55-g6feb From 0af5265180877f4e8fbf8f1d9f2999b3fd2205d3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 21:23:10 +0100 Subject: tls: check size on "MAC-only, no crypt" code path too Signed-off-by: Denys Vlasenko --- networking/tls.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index fb49b1523..80e3bc662 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -810,14 +810,15 @@ static int tls_xread_record(tls_state_t *tls) dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); padding_len++; sz -= SHA256_OUTSIZE + padding_len; /* drop MAC and padding */ - if (sz < 0) { - bb_error_msg_and_die("bad padding size:%u", padding_len); - } + //if (sz < 0) + // bb_error_msg_and_die("bad padding size:%u", padding_len); } else { /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ /* else: no encryption yet on input, subtract zero = NOP */ sz -= tls->min_encrypted_len_on_read; } + if (sz < 0) + bb_error_msg_and_die("encrypted data too short"); //dump_hex("<< %s\n", tls->inbuf, RECHDR_LEN + sz); -- cgit v1.2.3-55-g6feb From dd2577f21a55e5a4d039590f76efa3f7faa3a135 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 20 Jan 2017 22:48:41 +0100 Subject: tls: send SNI in the client hello Signed-off-by: Denys Vlasenko --- networking/tls.c | 71 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 80e3bc662..8fa532947 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -228,6 +228,8 @@ struct record_hdr { typedef struct tls_state { int fd; +//TODO: store just the DER key here, parse/use/delete it when sending client key +//this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; sha256_ctx_t handshake_sha256_ctx; @@ -1066,7 +1068,7 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) /* * TLS Handshake routines */ -static int xread_tls_handshake_block(tls_state_t *tls, int min_len) +static int tls_xread_handshake_block(tls_state_t *tls, int min_len) { struct record_hdr *xhdr; int len = tls_xread_record(tls); @@ -1098,7 +1100,7 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un } //TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise -static void send_client_hello(tls_state_t *tls) +static void send_client_hello(tls_state_t *tls, const char *sni) { struct client_hello { uint8_t type; @@ -1111,28 +1113,58 @@ static void send_client_hello(tls_state_t *tls) uint8_t cipherid[2 * 1]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ + /* Extensions (SNI shown): + * hi,lo // len of all extensions + * 0x00,0x00 // extension_type: "Server Name" + * 0x00,0x0e // list len (there can be more than one SNI) + * 0x00,0x0c // len of 1st Server Name Indication + * 0x00 // name type: host_name + * 0x00,0x09 // name len + * "localhost" // name + */ }; - struct client_hello *record = tls_get_outbuf(tls, sizeof(*record)); - - fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, sizeof(*record)); + struct client_hello *record; + int len; + int sni_len = sni ? strnlen(sni, 127) : 0; + + len = sizeof(*record); + if (sni_len) + len += 11 + strlen(sni); + record = tls_get_outbuf(tls, len); + memset(record, 0, len); + fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len); record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ record->proto_min = TLS_MIN; /* can be higher than one in record headers */ tls_get_random(record->rand32, sizeof(record->rand32)); if (TLS_DEBUG_FIXED_SECRETS) memset(record->rand32, 0x11, sizeof(record->rand32)); memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); - record->session_id_len = 0; - record->cipherid_len16_hi = 0; + /* record->session_id_len = 0; - already is */ + /* record->cipherid_len16_hi = 0; */ record->cipherid_len16_lo = 2 * 1; record->cipherid[0] = CIPHER_ID >> 8; record->cipherid[1] = CIPHER_ID & 0xff; record->comprtypes_len = 1; - record->comprtypes[0] = 0; - -//TODO: send options, at least SNI. + /* record->comprtypes[0] = 0; */ + + if (sni_len) { + uint8_t *p = (void*)(record + 1); + //p[0] = 0; // + p[1] = sni_len + 9; //ext_len + //p[2] = 0; // + //p[3] = 0; //extension_type + //p[4] = 0; // + p[5] = sni_len + 5; //list len + //p[6] = 0; // + p[7] = sni_len + 3; //len of 1st SNI + //p[8] = 0; //name type + //p[9] = 0; // + p[10] = sni_len; //name len + memcpy(&p[11], sni, sni_len); + } dbg(">> CLIENT_HELLO\n"); - xwrite_and_update_handshake_hash(tls, sizeof(*record)); + xwrite_and_update_handshake_hash(tls, len); } static void get_server_hello(tls_state_t *tls) @@ -1149,10 +1181,11 @@ static void get_server_hello(tls_state_t *tls) uint8_t comprtype; /* extensions may follow, but only those which client offered in its Hello */ }; + struct server_hello *hp; uint8_t *cipherid; - xread_tls_handshake_block(tls, 74); + tls_xread_handshake_block(tls, 74); hp = (void*)tls->inbuf; // 74 bytes: @@ -1199,7 +1232,7 @@ static void get_server_cert(tls_state_t *tls) uint8_t *certbuf; int len, len1; - len = xread_tls_handshake_block(tls, 10); + len = tls_xread_handshake_block(tls, 10); xhdr = (void*)tls->inbuf; certbuf = (void*)(xhdr + 1); @@ -1416,7 +1449,7 @@ static void send_client_finished(tls_state_t *tls) xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); } -static void tls_handshake(tls_state_t *tls) +static void tls_handshake(tls_state_t *tls, const char *sni) { // Client RFC 5246 Server // (*) - optional messages, not always sent @@ -1437,7 +1470,7 @@ static void tls_handshake(tls_state_t *tls) // Application Data <------> Application Data int len; - send_client_hello(tls); + send_client_hello(tls, sni); get_server_hello(tls); // RFC 5246 @@ -1451,7 +1484,7 @@ static void tls_handshake(tls_state_t *tls) // (for example, kernel.org does not even accept DH_anon cipher id) get_server_cert(tls); - len = xread_tls_handshake_block(tls, 4); + len = tls_xread_handshake_block(tls, 4); if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) { // 459 bytes: // 0c 00|01|c7 03|00|17|41|04|87|94|2e|2f|68|d0|c9|f4|97|a8|2d|ef|ed|67|ea|c6|f3|b3|56|47|5d|27|b6|bd|ee|70|25|30|5e|b0|8e|f6|21|5a... @@ -1460,7 +1493,7 @@ static void tls_handshake(tls_state_t *tls) // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); //probably need to save it - xread_tls_handshake_block(tls, 4); + tls_xread_handshake_block(tls, 4); } // if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { @@ -1472,7 +1505,7 @@ static void tls_handshake(tls_state_t *tls) // Client certificates are sent using the Certificate structure // defined in Section 7.4.2." // (i.e. the same format as server certs) -// xread_tls_handshake_block(tls, 4); +// tls_xread_handshake_block(tls, 4); // } if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) @@ -1546,7 +1579,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) tls = new_tls_state(); tls->fd = cfd; - tls_handshake(tls); + tls_handshake(tls, argv[1]); /* Select loop copying stdin to cfd, and cfd to stdout */ FD_ZERO(&readfds); -- cgit v1.2.3-55-g6feb From f6e20724d4aac3655e921ff6072e60bbe182b273 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Jan 2017 02:07:59 +0100 Subject: tls: reorder tls_state fields for smaller offsets function old new delta xwrite_encrypted 363 360 -3 xwrite_and_update_handshake_hash 117 114 -3 tls_xread_handshake_block 72 69 -3 tls_error_die 211 202 -9 tls_get_outbuf 64 49 -15 tls_main 2163 2127 -36 tls_xread_record 702 639 -63 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/7 up/down: 0/-132) Total: -132 bytes Signed-off-by: Denys Vlasenko --- networking/tls.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 8fa532947..b111e4bb4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -226,24 +226,28 @@ struct record_hdr { }; typedef struct tls_state { - int fd; + int fd; + + int min_encrypted_len_on_read; + uint8_t encrypt_on_write; + + uint8_t *outbuf; + int outbuf_size; + + int inbuf_size; + int ofs_to_buffered; + int buffered_size; + uint8_t *inbuf; //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; - - sha256_ctx_t handshake_sha256_ctx; - +// this is also unused after client key is sent uint8_t client_and_server_rand32[2 * 32]; +// these two are unused after finished messages are exchanged: + sha256_ctx_t handshake_sha256_ctx; uint8_t master_secret[48]; - uint8_t encrypt_on_write; - int min_encrypted_len_on_read; - uint8_t client_write_MAC_key[SHA256_OUTSIZE]; - uint8_t server_write_MAC_key[SHA256_OUTSIZE]; - uint8_t client_write_key[AES256_KEYSIZE]; - uint8_t server_write_key[AES256_KEYSIZE]; - // RFC 5246 // sequence number // Each connection state contains a sequence number, which is @@ -251,15 +255,13 @@ typedef struct tls_state { // number MUST be set to zero whenever a connection state is made the // active state. Sequence numbers are of type uint64 and may not // exceed 2^64-1. + /*uint64_t read_seq64_be;*/ uint64_t write_seq64_be; - int outbuf_size; - uint8_t *outbuf; - - int inbuf_size; - int ofs_to_buffered; - int buffered_size; - uint8_t *inbuf; + uint8_t client_write_MAC_key[SHA256_OUTSIZE]; + uint8_t server_write_MAC_key[SHA256_OUTSIZE]; + uint8_t client_write_key[AES256_KEYSIZE]; + uint8_t server_write_key[AES256_KEYSIZE]; } tls_state_t; -- cgit v1.2.3-55-g6feb From bbc7bee9664b582c8237c4b879bba1bdee4d62a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Jan 2017 02:49:58 +0100 Subject: make --help texts more uniform function old new delta packed_usage 31062 31035 -27 Signed-off-by: Denys Vlasenko --- coreutils/expand.c | 8 ++++---- miscutils/nandwrite.c | 4 ++-- networking/udhcp/dumpleases.c | 2 +- selinux/chcon.c | 10 +++++----- selinux/runcon.c | 8 ++++---- util-linux/fstrim.c | 6 +++--- util-linux/getopt.c | 8 ++++---- util-linux/nsenter.c | 26 +++++++++++++------------- util-linux/rtcwake.c | 8 ++++---- util-linux/unshare.c | 16 ++++++++-------- 10 files changed, 48 insertions(+), 48 deletions(-) diff --git a/coreutils/expand.c b/coreutils/expand.c index 29affc932..63b682330 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -8,13 +8,13 @@ * David MacKenzie * * Options for expand: - * -t num --tabs=NUM Convert tabs to num spaces (default 8 spaces). + * -t num --tabs NUM Convert tabs to num spaces (default 8 spaces). * -i --initial Only convert initial tabs on each line to spaces. * * Options for unexpand: * -a --all Convert all blanks, instead of just initial blanks. * -f --first-only Convert only leading sequences of blanks (default). - * -t num --tabs=NUM Have tabs num characters apart instead of 8. + * -t num --tabs NUM Have tabs num characters apart instead of 8. * * Busybox version (C) 2007 by Tito Ragusa * @@ -54,7 +54,7 @@ //usage: "Convert tabs to spaces, writing to stdout\n" //usage: IF_FEATURE_EXPAND_LONG_OPTIONS( //usage: "\n -i,--initial Don't convert tabs after non blanks" -//usage: "\n -t,--tabs=N Tabstops every N chars" +//usage: "\n -t,--tabs N Tabstops every N chars" //usage: ) //usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS( //usage: "\n -i Don't convert tabs after non blanks" @@ -68,7 +68,7 @@ //usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS( //usage: "\n -a,--all Convert all blanks" //usage: "\n -f,--first-only Convert only leading blanks" -//usage: "\n -t,--tabs=N Tabstops every N chars" +//usage: "\n -t,--tabs N Tabstops every N chars" //usage: ) //usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS( //usage: "\n -a Convert all blanks" diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c index c95cbb21e..dbe9043f4 100644 --- a/miscutils/nandwrite.c +++ b/miscutils/nandwrite.c @@ -37,7 +37,7 @@ //usage: "\n -s ADDR Start address" //usage:#define nanddump_trivial_usage -//usage: "[-no]" IF_LONG_OPTS(" [--bb=padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" +//usage: "[-no]" IF_LONG_OPTS(" [--bb padbad|skipbad]") " [-s ADDR] [-l LEN] [-f FILE] MTD_DEVICE" //usage:#define nanddump_full_usage "\n\n" //usage: "Dump MTD_DEVICE\n" //usage: "\n -n Read without ecc" @@ -46,7 +46,7 @@ //usage: "\n -l LEN Length" //usage: "\n -f FILE Dump to file ('-' for stdout)" //usage: IF_LONG_OPTS( -//usage: "\n --bb=METHOD:" +//usage: "\n --bb METHOD" //usage: "\n skipbad: skip bad blocks" //usage: "\n padbad: substitute bad blocks by 0xff (default)" //usage: ) diff --git a/networking/udhcp/dumpleases.c b/networking/udhcp/dumpleases.c index d83344a8d..dce9084b3 100644 --- a/networking/udhcp/dumpleases.c +++ b/networking/udhcp/dumpleases.c @@ -11,7 +11,7 @@ //usage:#define dumpleases_full_usage "\n\n" //usage: "Display DHCP leases granted by udhcpd\n" //usage: IF_LONG_OPTS( -//usage: "\n -f,--file=FILE Lease file" +//usage: "\n -f,--file FILE Lease file" //usage: "\n -r,--remaining Show remaining time" //usage: "\n -a,--absolute Show expiration time" //usage: "\n -d,--decimal Show time in seconds" diff --git a/selinux/chcon.c b/selinux/chcon.c index 4a9a4d3d5..ba9b08638 100644 --- a/selinux/chcon.c +++ b/selinux/chcon.c @@ -36,11 +36,11 @@ //usage: "\n -c,--changes Report changes made" //usage: "\n -h,--no-dereference Affect symlinks instead of their targets" //usage: "\n -f,--silent,--quiet Suppress most error messages" -//usage: "\n --reference=RFILE Use RFILE's group instead of using a CONTEXT value" -//usage: "\n -u,--user=USER Set user/role/type/range in the target" -//usage: "\n -r,--role=ROLE security context" -//usage: "\n -t,--type=TYPE" -//usage: "\n -l,--range=RANGE" +//usage: "\n --reference RFILE Use RFILE's group instead of using a CONTEXT value" +//usage: "\n -u,--user USER Set user/role/type/range in the target" +//usage: "\n -r,--role ROLE security context" +//usage: "\n -t,--type TYPE" +//usage: "\n -l,--range RANGE" //usage: "\n -R,--recursive Recurse" //usage: ) //usage: IF_NOT_FEATURE_CHCON_LONG_OPTIONS( diff --git a/selinux/runcon.c b/selinux/runcon.c index a30e3552f..82f4d50d3 100644 --- a/selinux/runcon.c +++ b/selinux/runcon.c @@ -52,10 +52,10 @@ //usage: "\n CONTEXT Complete security context\n" //usage: IF_FEATURE_RUNCON_LONG_OPTIONS( //usage: "\n -c,--compute Compute process transition context before modifying" -//usage: "\n -t,--type=TYPE Type (for same role as parent)" -//usage: "\n -u,--user=USER User identity" -//usage: "\n -r,--role=ROLE Role" -//usage: "\n -l,--range=RNG Levelrange" +//usage: "\n -t,--type TYPE Type (for same role as parent)" +//usage: "\n -u,--user USER User identity" +//usage: "\n -r,--role ROLE Role" +//usage: "\n -l,--range RNG Levelrange" //usage: ) //usage: IF_NOT_FEATURE_RUNCON_LONG_OPTIONS( //usage: "\n -c Compute process transition context before modifying" diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index fc51878b6..563aa9720 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c @@ -23,9 +23,9 @@ //usage: "[OPTIONS] MOUNTPOINT" //usage:#define fstrim_full_usage "\n\n" //usage: IF_LONG_OPTS( -//usage: " -o,--offset=OFFSET Offset in bytes to discard from" -//usage: "\n -l,--length=LEN Bytes to discard" -//usage: "\n -m,--minimum=MIN Minimum extent length" +//usage: " -o,--offset OFFSET Offset in bytes to discard from" +//usage: "\n -l,--length LEN Bytes to discard" +//usage: "\n -m,--minimum MIN Minimum extent length" //usage: "\n -v,--verbose Print number of discarded bytes" //usage: ) //usage: IF_NOT_LONG_OPTS( diff --git a/util-linux/getopt.c b/util-linux/getopt.c index f6ecc3dde..63294c520 100644 --- a/util-linux/getopt.c +++ b/util-linux/getopt.c @@ -57,13 +57,13 @@ //usage: IF_LONG_OPTS( //usage: IF_FEATURE_GETOPT_LONG( //usage: " -a,--alternative Allow long options starting with single -\n" -//usage: " -l,--longoptions=LOPT[,...] Long options to recognize\n" +//usage: " -l,--longoptions LOPT[,...] Long options to recognize\n" //usage: ) -//usage: " -n,--name=PROGNAME The name under which errors are reported" -//usage: "\n -o,--options=OPTSTRING Short options to recognize" +//usage: " -n,--name PROGNAME The name under which errors are reported" +//usage: "\n -o,--options OPTSTRING Short options to recognize" //usage: "\n -q,--quiet No error messages on unrecognized options" //usage: "\n -Q,--quiet-output No normal output" -//usage: "\n -s,--shell=SHELL Set shell quoting conventions" +//usage: "\n -s,--shell SHELL Set shell quoting conventions" //usage: "\n -T,--test Version test (exits with 4)" //usage: "\n -u,--unquoted Don't quote output" //usage: ) diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c index 6834292da..57b218dab 100644 --- a/util-linux/nsenter.c +++ b/util-linux/nsenter.c @@ -30,19 +30,19 @@ //usage: "[OPTIONS] [PROG [ARGS]]" //usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS //usage:#define nsenter_full_usage "\n" -//usage: "\n -t, --target=PID Target process to get namespaces from" -//usage: "\n -m, --mount[=FILE] Enter mount namespace" -//usage: "\n -u, --uts[=FILE] Enter UTS namespace (hostname etc)" -//usage: "\n -i, --ipc[=FILE] Enter System V IPC namespace" -//usage: "\n -n, --net[=FILE] Enter network namespace" -//usage: "\n -p, --pid[=FILE] Enter pid namespace" -//usage: "\n -U, --user[=FILE] Enter user namespace" -//usage: "\n -S, --setuid=UID Set uid in entered namespace" -//usage: "\n -G, --setgid=GID Set gid in entered namespace" -//usage: "\n --preserve-credentials Don't touch uids or gids" -//usage: "\n -r, --root[=DIR] Set root directory" -//usage: "\n -w, --wd[=DIR] Set working directory" -//usage: "\n -F, --no-fork Don't fork before exec'ing PROG" +//usage: "\n -t,--target PID Target process to get namespaces from" +//usage: "\n -m,--mount[=FILE] Enter mount namespace" +//usage: "\n -u,--uts[=FILE] Enter UTS namespace (hostname etc)" +//usage: "\n -i,--ipc[=FILE] Enter System V IPC namespace" +//usage: "\n -n,--net[=FILE] Enter network namespace" +//usage: "\n -p,--pid[=FILE] Enter pid namespace" +//usage: "\n -U,--user[=FILE] Enter user namespace" +//usage: "\n -S,--setuid UID Set uid in entered namespace" +//usage: "\n -G,--setgid GID Set gid in entered namespace" +//usage: "\n --preserve-credentials Don't touch uids or gids" +//usage: "\n -r,--root[=DIR] Set root directory" +//usage: "\n -w,--wd[=DIR] Set working directory" +//usage: "\n -F,--no-fork Don't fork before exec'ing PROG" //usage:#else //usage:#define nsenter_full_usage "\n" //usage: "\n -t PID Target process to get namespaces from" diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 54fc70583..b63164588 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -41,10 +41,10 @@ //usage: "\n -a,--auto Read clock mode from adjtime" //usage: "\n -l,--local Clock is set to local time" //usage: "\n -u,--utc Clock is set to UTC time" -//usage: "\n -d,--device=DEV Specify the RTC device" -//usage: "\n -m,--mode=MODE Set sleep state (default: standby)" -//usage: "\n -s,--seconds=SEC Set timeout in SEC seconds from now" -//usage: "\n -t,--time=TIME Set timeout to TIME seconds from epoch" +//usage: "\n -d,--device DEV Specify the RTC device" +//usage: "\n -m,--mode MODE Set sleep state (default: standby)" +//usage: "\n -s,--seconds SEC Set timeout in SEC seconds from now" +//usage: "\n -t,--time TIME Set timeout to TIME seconds from epoch" //usage: ) //usage: IF_NOT_LONG_OPTS( //usage: "\n -a Read clock mode from adjtime" diff --git a/util-linux/unshare.c b/util-linux/unshare.c index bbabeef55..52e8f1421 100644 --- a/util-linux/unshare.c +++ b/util-linux/unshare.c @@ -25,14 +25,14 @@ //usage:#define unshare_trivial_usage //usage: "[OPTIONS] [PROG [ARGS]]" //usage:#define unshare_full_usage "\n" -//usage: "\n -m, --mount[=FILE] Unshare mount namespace" -//usage: "\n -u, --uts[=FILE] Unshare UTS namespace (hostname etc.)" -//usage: "\n -i, --ipc[=FILE] Unshare System V IPC namespace" -//usage: "\n -n, --net[=FILE] Unshare network namespace" -//usage: "\n -p, --pid[=FILE] Unshare PID namespace" -//usage: "\n -U, --user[=FILE} Unshare user namespace" -//usage: "\n -f, --fork Fork before execing PROG" -//usage: "\n -r, --map-root-user Map current user to root (implies -u)" +//usage: "\n -m,--mount[=FILE] Unshare mount namespace" +//usage: "\n -u,--uts[=FILE] Unshare UTS namespace (hostname etc.)" +//usage: "\n -i,--ipc[=FILE] Unshare System V IPC namespace" +//usage: "\n -n,--net[=FILE] Unshare network namespace" +//usage: "\n -p,--pid[=FILE] Unshare PID namespace" +//usage: "\n -U,--user[=FILE] Unshare user namespace" +//usage: "\n -f,--fork Fork before execing PROG" +//usage: "\n -r,--map-root-user Map current user to root (implies -u)" //usage: "\n --mount-proc[=DIR] Mount /proc filesystem first (implies -m)" //usage: "\n --propagation slave|shared|private|unchanged" //usage: "\n Modify mount propagation in mount namespace" -- cgit v1.2.3-55-g6feb From f3d705f41bf16183f901e5ddb07c89685e384daf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Jan 2017 03:46:35 +0100 Subject: make --help texts smaller function old new delta packed_usage 31035 30968 -67 Signed-off-by: Denys Vlasenko --- miscutils/crond.c | 2 +- networking/inetd.c | 4 +-- networking/ip.c | 74 +++++++++++++++++++++++++++--------------------------- networking/ping.c | 10 ++++---- procps/nmeter.c | 2 +- sysklogd/syslogd.c | 6 ++--- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/miscutils/crond.c b/miscutils/crond.c index f96c96ee7..88e7b47b3 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -52,7 +52,7 @@ //usage: " -f Foreground" //usage: "\n -b Background (default)" //usage: "\n -S Log to syslog (default)" -//usage: "\n -l N Set log level. Most verbose:0, default:8" +//usage: "\n -l N Set log level. Most verbose 0, default 8" //usage: IF_FEATURE_CROND_D( //usage: "\n -d N Set log level, log to stderr" //usage: ) diff --git a/networking/inetd.c b/networking/inetd.c index 612284e76..01e659f13 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -213,9 +213,9 @@ //usage: "Listen for network connections and launch programs\n" //usage: "\n -f Run in foreground" //usage: "\n -e Log to stderr" -//usage: "\n -q N Socket listen queue (default: 128)" +//usage: "\n -q N Socket listen queue (default 128)" //usage: "\n -R N Pause services after N connects/min" -//usage: "\n (default: 0 - disabled)" +//usage: "\n (default 0 - disabled)" #include #include /* setrlimit */ diff --git a/networking/ip.c b/networking/ip.c index 939721e46..19b63847b 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -142,61 +142,61 @@ /* would need to make the " | " optional depending on more than one selected: */ //usage:#define ip_trivial_usage -//usage: "[OPTIONS] {" -//usage: IF_FEATURE_IP_ADDRESS("address | ") -//usage: IF_FEATURE_IP_ROUTE("route | ") -//usage: IF_FEATURE_IP_LINK("link | ") -//usage: IF_FEATURE_IP_TUNNEL("tunnel | ") -//usage: IF_FEATURE_IP_NEIGH("neigh | ") +//usage: "[OPTIONS] " +//usage: IF_FEATURE_IP_ADDRESS("address|") +//usage: IF_FEATURE_IP_ROUTE("route|") +//usage: IF_FEATURE_IP_LINK("link|") +//usage: IF_FEATURE_IP_TUNNEL("tunnel|") +//usage: IF_FEATURE_IP_NEIGH("neigh|") //usage: IF_FEATURE_IP_RULE("rule") -//usage: "} {COMMAND}" +//usage: " [COMMAND]" //usage:#define ip_full_usage "\n\n" -//usage: "ip [OPTIONS] OBJECT {COMMAND}\n" -//usage: "where OBJECT := {" -//usage: IF_FEATURE_IP_ADDRESS("address | ") -//usage: IF_FEATURE_IP_ROUTE("route | ") -//usage: IF_FEATURE_IP_LINK("link | ") -//usage: IF_FEATURE_IP_TUNNEL("tunnel | ") -//usage: IF_FEATURE_IP_NEIGH("neigh | ") +//usage: "ip [OPTIONS] OBJECT [COMMAND]\n" +//usage: "where OBJECT := " +//usage: IF_FEATURE_IP_ADDRESS("address|") +//usage: IF_FEATURE_IP_ROUTE("route|") +//usage: IF_FEATURE_IP_LINK("link|") +//usage: IF_FEATURE_IP_TUNNEL("tunnel|") +//usage: IF_FEATURE_IP_NEIGH("neigh|") //usage: IF_FEATURE_IP_RULE("rule") -//usage: "}\n" -//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }" +//usage: "\n" +//usage: "OPTIONS := -f[amily] inet|inet6|link | -o[neline]" //usage: //usage:#define ipaddr_trivial_usage -//usage: "{ {add|del} IFADDR dev STRING | {show|flush}\n" -//usage: " [dev STRING] [to PREFIX] }" +//usage: "add|del IFADDR dev STRING | show|flush [dev STRING] [to PREFIX]" //usage:#define ipaddr_full_usage "\n\n" -//usage: "ipaddr {add|change|replace|delete} IFADDR dev STRING\n" -//usage: "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n" +//usage: "ipaddr add|change|replace|delete IFADDR dev STRING\n" +//usage: "ipaddr show|flush [dev STRING] [scope SCOPE-ID]\n" //usage: " [to PREFIX] [label PATTERN]\n" //usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" //usage: " [broadcast ADDR] [anycast ADDR]\n" //usage: " [label STRING] [scope SCOPE-ID]\n" -//usage: " SCOPE-ID := [host | link | global | NUMBER]" +//usage: " SCOPE-ID := [host|link|global|NUMBER]" //usage: //usage:#define iplink_trivial_usage -//usage: "{ set DEVICE { up | down | arp { on | off } | show [DEVICE] }" +//usage: "{ set DEVICE [up|down] [arp on|off] } | show [DEVICE]" //usage:#define iplink_full_usage "\n\n" -//usage: "iplink set DEVICE { up | down | arp | multicast { on | off } |\n" -//usage: " dynamic { on | off } |\n" -//usage: " mtu MTU }\n" +//usage: "iplink set DEVICE [up|down]\n" +//usage: " [arp on|off]\n" +//usage: " [dynamic on|off]\n" +//usage: " [multicast on|off]\n" +//usage: " [mtu MTU]\n" //usage: "iplink show [DEVICE]" //usage: //usage:#define iproute_trivial_usage -//usage: "{ list | flush | add | del | change | append |\n" -//usage: " replace | test } ROUTE" +//usage: "list|flush|add|del|change|append|replace|test ROUTE" //usage:#define iproute_full_usage "\n\n" -//usage: "iproute { list | flush } SELECTOR\n" +//usage: "iproute list|flush SELECTOR\n" //usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n" //usage: " [oif STRING] [tos TOS]\n" -//usage: "iproute { add | del | change | append | replace | test } ROUTE\n" +//usage: "iproute add|del|change|append|replace|test ROUTE\n" //usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" //usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" //usage: //usage:#define iprule_trivial_usage -//usage: "{[list | add | del] RULE}" +//usage: "[list|add|del] RULE" //usage:#define iprule_full_usage "\n\n" -//usage: "iprule [list | add | del] SELECTOR ACTION\n" +//usage: "iprule [list|add|del] SELECTOR ACTION\n" //usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" //usage: " [dev STRING] [pref NUMBER]\n" //usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" @@ -205,19 +205,19 @@ //usage: " TABLE_ID := [local | main | default | NUMBER]" //usage: //usage:#define iptunnel_trivial_usage -//usage: "{ add | change | del | show } [NAME]\n" -//usage: " [mode { ipip | gre | sit }]\n" +//usage: "add|change|del|show [NAME]\n" +//usage: " [mode ipip|gre|sit]\n" //usage: " [remote ADDR] [local ADDR] [ttl TTL]" //usage:#define iptunnel_full_usage "\n\n" -//usage: "iptunnel { add | change | del | show } [NAME]\n" -//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n" +//usage: "iptunnel add|change|del|show [NAME]\n" +//usage: " [mode ipip|gre|sit] [remote ADDR] [local ADDR]\n" //usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n" //usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]" //usage: //usage:#define ipneigh_trivial_usage -//usage: "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" +//usage: "show|flush [to PREFIX] [dev DEV] [nud STATE]" //usage:#define ipneigh_full_usage "\n\n" -//usage: "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" +//usage: "ipneigh show|flush [to PREFIX] [dev DEV] [nud STATE]" #include "libbb.h" diff --git a/networking/ping.c b/networking/ping.c index d0ef7ba62..ef31e000b 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -94,10 +94,10 @@ //usage: "\n -4,-6 Force IP or IPv6 name resolution" //usage: ) //usage: "\n -c CNT Send only CNT pings" -//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" +//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" //usage: "\n -t TTL Set TTL" -//usage: "\n -I IFACE/IP Use interface or IP address as source" -//usage: "\n -W SEC Seconds to wait for the first response (default:10)" +//usage: "\n -I IFACE/IP Source interface or IP address" +//usage: "\n -W SEC Seconds to wait for the first response (default 10)" //usage: "\n (after all -c CNT packets are sent)" //usage: "\n -w SEC Seconds until ping exits (default:infinite)" //usage: "\n (can exit earlier with -c CNT)" @@ -110,8 +110,8 @@ //usage:# define ping6_full_usage "\n\n" //usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" //usage: "\n -c CNT Send only CNT pings" -//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" -//usage: "\n -I IFACE/IP Use interface or IP address as source" +//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)" +//usage: "\n -I IFACE/IP Source interface or IP address" //usage: "\n -q Quiet, only display output at start" //usage: "\n and when finished" //usage: "\n -p Pattern to use for payload" diff --git a/procps/nmeter.c b/procps/nmeter.c index 3eac2d3b2..05bf0a08c 100644 --- a/procps/nmeter.c +++ b/procps/nmeter.c @@ -24,7 +24,7 @@ //usage: "\n -d MSEC Milliseconds between updates, default:1000, none:-1" //usage: "\n" //usage: "\nFormat specifiers:" -//usage: "\n %Nc or %[cN] CPU. N - bar size (default:10)" +//usage: "\n %Nc or %[cN] CPU. N - bar size (default 10)" //usage: "\n (displays: S:system U:user N:niced D:iowait I:irq i:softirq)" //usage: "\n %[nINTERFACE] Network INTERFACE" //usage: "\n %m Allocated memory" diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index ae0840bff..d64ff278f 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -135,8 +135,8 @@ //usage: ) //usage: "\n -O FILE Log to FILE (default: /var/log/messages, stdout if -)" //usage: IF_FEATURE_ROTATE_LOGFILE( -//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)" -//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)" +//usage: "\n -s SIZE Max size (KB) before rotation (default 200KB, 0=off)" +//usage: "\n -b N N rotated logs to keep (default 1, max 99, 0=purge)" //usage: ) //usage: "\n -l N Log only messages more urgent than prio N (1-8)" //usage: "\n -S Smaller output" @@ -146,7 +146,7 @@ //usage: IF_FEATURE_SYSLOGD_CFG( //usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)" //usage: ) -/* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */ +/* //usage: "\n -m MIN Minutes between MARK lines (default 20, 0=off)" */ //usage: //usage:#define syslogd_example_usage //usage: "$ syslogd -R masterlog:514\n" -- cgit v1.2.3-55-g6feb From 8908c1d4f518829cb94e40da54f536a5d7b6404c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Jan 2017 03:56:46 +0100 Subject: more ip --help fixes Signed-off-by: Denys Vlasenko --- networking/ip.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/networking/ip.c b/networking/ip.c index 19b63847b..28e243c2b 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -152,7 +152,7 @@ //usage: " [COMMAND]" //usage:#define ip_full_usage "\n\n" //usage: "ip [OPTIONS] OBJECT [COMMAND]\n" -//usage: "where OBJECT := " +//usage: " OBJECT := " //usage: IF_FEATURE_IP_ADDRESS("address|") //usage: IF_FEATURE_IP_ROUTE("route|") //usage: IF_FEATURE_IP_LINK("link|") @@ -160,17 +160,17 @@ //usage: IF_FEATURE_IP_NEIGH("neigh|") //usage: IF_FEATURE_IP_RULE("rule") //usage: "\n" -//usage: "OPTIONS := -f[amily] inet|inet6|link | -o[neline]" +//usage: " OPTIONS := -f[amily] inet|inet6|link | -o[neline]" //usage: //usage:#define ipaddr_trivial_usage //usage: "add|del IFADDR dev STRING | show|flush [dev STRING] [to PREFIX]" //usage:#define ipaddr_full_usage "\n\n" //usage: "ipaddr add|change|replace|delete IFADDR dev STRING\n" //usage: "ipaddr show|flush [dev STRING] [scope SCOPE-ID]\n" -//usage: " [to PREFIX] [label PATTERN]\n" +//usage: " [to PREFIX] [label PATTERN]\n" //usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" -//usage: " [broadcast ADDR] [anycast ADDR]\n" -//usage: " [label STRING] [scope SCOPE-ID]\n" +//usage: " [broadcast ADDR] [anycast ADDR]\n" +//usage: " [label STRING] [scope SCOPE-ID]\n" //usage: " SCOPE-ID := [host|link|global|NUMBER]" //usage: //usage:#define iplink_trivial_usage @@ -200,9 +200,9 @@ //usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" //usage: " [dev STRING] [pref NUMBER]\n" //usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" -//usage: " [prohibit | reject | unreachable]\n" +//usage: " [prohibit|reject|unreachable]\n" //usage: " [realms [SRCREALM/]DSTREALM]\n" -//usage: " TABLE_ID := [local | main | default | NUMBER]" +//usage: " TABLE_ID := [local|main|default|NUMBER]" //usage: //usage:#define iptunnel_trivial_usage //usage: "add|change|del|show [NAME]\n" -- cgit v1.2.3-55-g6feb From 12389889c052cf7bf494bd7cabc0819f6fe9888f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Jan 2017 14:27:07 +0100 Subject: ip: better --help Was: Usage: ip [OPTIONS] address|route|link|tunnel|neigh|rule [COMMAND] ip [OPTIONS] OBJECT [COMMAND] where OBJECT := address|route|link|tunnel|neigh|rule OPTIONS := -f[amily] inet|inet6|link | -o[neline] User: instead of repeating list of OBJECTs twice, you could at least show available COMMANDs... Now: Usage: ip [OPTIONS] address|route|link|tunnel|neigh|rule [COMMAND] OPTIONS := -f[amily] inet|inet6|link | -o[neline] COMMAND := ip addr add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX] ip route list|flush|add|del|change|append|replace|test ROUTE ip link set IFACE [up|down] [arp on|off] | show [IFACE] ip tunnel add|change|del|show [NAME] [mode ipip|gre|sit] [remote ADDR] [local ADDR] [ttl TTL] ip neigh show|flush [to PREFIX] [dev DEV] [nud STATE] ip rule [list] | add|del SELECTOR ACTION While at it, tweak tc --help too (it stays disabled, thus no effect) Signed-off-by: Denys Vlasenko --- networking/ip.c | 88 +++++++++++++++++++++++++++++++++++---------------------- networking/tc.c | 30 ++++++++++---------- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/networking/ip.c b/networking/ip.c index 28e243c2b..0f52b19dd 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -140,33 +140,11 @@ //kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o //kbuild:lib-$(CONFIG_IPNEIGH) += ip.o -/* would need to make the " | " optional depending on more than one selected: */ -//usage:#define ip_trivial_usage -//usage: "[OPTIONS] " -//usage: IF_FEATURE_IP_ADDRESS("address|") -//usage: IF_FEATURE_IP_ROUTE("route|") -//usage: IF_FEATURE_IP_LINK("link|") -//usage: IF_FEATURE_IP_TUNNEL("tunnel|") -//usage: IF_FEATURE_IP_NEIGH("neigh|") -//usage: IF_FEATURE_IP_RULE("rule") -//usage: " [COMMAND]" -//usage:#define ip_full_usage "\n\n" -//usage: "ip [OPTIONS] OBJECT [COMMAND]\n" -//usage: " OBJECT := " -//usage: IF_FEATURE_IP_ADDRESS("address|") -//usage: IF_FEATURE_IP_ROUTE("route|") -//usage: IF_FEATURE_IP_LINK("link|") -//usage: IF_FEATURE_IP_TUNNEL("tunnel|") -//usage: IF_FEATURE_IP_NEIGH("neigh|") -//usage: IF_FEATURE_IP_RULE("rule") -//usage: "\n" -//usage: " OPTIONS := -f[amily] inet|inet6|link | -o[neline]" -//usage: //usage:#define ipaddr_trivial_usage -//usage: "add|del IFADDR dev STRING | show|flush [dev STRING] [to PREFIX]" +//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]" //usage:#define ipaddr_full_usage "\n\n" -//usage: "ipaddr add|change|replace|delete IFADDR dev STRING\n" -//usage: "ipaddr show|flush [dev STRING] [scope SCOPE-ID]\n" +//usage: "ipaddr add|change|replace|delete IFADDR dev IFACE\n" +//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE-ID]\n" //usage: " [to PREFIX] [label PATTERN]\n" //usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" //usage: " [broadcast ADDR] [anycast ADDR]\n" @@ -174,14 +152,14 @@ //usage: " SCOPE-ID := [host|link|global|NUMBER]" //usage: //usage:#define iplink_trivial_usage -//usage: "{ set DEVICE [up|down] [arp on|off] } | show [DEVICE]" +//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]" //usage:#define iplink_full_usage "\n\n" -//usage: "iplink set DEVICE [up|down]\n" +//usage: "iplink set IFACE [up|down]\n" //usage: " [arp on|off]\n" //usage: " [dynamic on|off]\n" //usage: " [multicast on|off]\n" //usage: " [mtu MTU]\n" -//usage: "iplink show [DEVICE]" +//usage: "iplink show [IFACE]" //usage: //usage:#define iproute_trivial_usage //usage: "list|flush|add|del|change|append|replace|test ROUTE" @@ -194,11 +172,10 @@ //usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" //usage: //usage:#define iprule_trivial_usage -//usage: "[list|add|del] RULE" +//usage: "[list] | add|del SELECTOR ACTION" //usage:#define iprule_full_usage "\n\n" -//usage: "iprule [list|add|del] SELECTOR ACTION\n" //usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" -//usage: " [dev STRING] [pref NUMBER]\n" +//usage: " [dev IFACE] [pref NUMBER]\n" //usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" //usage: " [prohibit|reject|unreachable]\n" //usage: " [realms [SRCREALM/]DSTREALM]\n" @@ -216,8 +193,53 @@ //usage: //usage:#define ipneigh_trivial_usage //usage: "show|flush [to PREFIX] [dev DEV] [nud STATE]" -//usage:#define ipneigh_full_usage "\n\n" -//usage: "ipneigh show|flush [to PREFIX] [dev DEV] [nud STATE]" +//usage:#define ipneigh_full_usage "" +//usage: +//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE +//usage:# define IP_BAR_LINK "|" +//usage:#else +//usage:# define IP_BAR_LINK "" +//usage:#endif +//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK +//usage:# define IP_BAR_TUNNEL "|" +//usage:#else +//usage:# define IP_BAR_TUNNEL "" +//usage:#endif +//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL +//usage:# define IP_BAR_NEIGH "|" +//usage:#else +//usage:# define IP_BAR_NEIGH "" +//usage:#endif +//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL || ENABLE_FEATURE_IP_NEIGH +//usage:# define IP_BAR_RULE "|" +//usage:#else +//usage:# define IP_BAR_RULE "" +//usage:#endif +//usage: +//usage:#define ip_trivial_usage +//usage: "[OPTIONS] " +//usage: IF_FEATURE_IP_ADDRESS("address") +//usage: IF_FEATURE_IP_ROUTE( IF_FEATURE_IP_ADDRESS("|")"route") +//usage: IF_FEATURE_IP_LINK( IP_BAR_LINK "link") +//usage: IF_FEATURE_IP_TUNNEL( IP_BAR_TUNNEL"tunnel") +//usage: IF_FEATURE_IP_NEIGH( IP_BAR_NEIGH "neigh") +//usage: IF_FEATURE_IP_RULE( IP_BAR_RULE "rule") +//usage: " [COMMAND]" +//usage:#define ip_full_usage "\n\n" +//usage: "OPTIONS := -f[amily] inet|inet6|link | -o[neline]\n" +//usage: "COMMAND :=" +//usage: IF_FEATURE_IP_ADDRESS("\n" +//usage: "ip addr "ipaddr_trivial_usage) +//usage: IF_FEATURE_IP_ROUTE("\n" +//usage: "ip route "iproute_trivial_usage) +//usage: IF_FEATURE_IP_LINK("\n" +//usage: "ip link "iplink_trivial_usage) +//usage: IF_FEATURE_IP_TUNNEL("\n" +//usage: "ip tunnel "iptunnel_trivial_usage) +//usage: IF_FEATURE_IP_NEIGH("\n" +//usage: "ip neigh "ipneigh_trivial_usage) +//usage: IF_FEATURE_IP_RULE("\n" +//usage: "ip rule "iprule_trivial_usage) #include "libbb.h" diff --git a/networking/tc.c b/networking/tc.c index 25875aa3e..23abf636c 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -27,22 +27,22 @@ /* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */ //usage: "OBJECT CMD [dev STRING]" //usage:#define tc_full_usage "\n\n" -//usage: "OBJECT: {qdisc|class|filter}\n" -//usage: "CMD: {add|del|change|replace|show}\n" +//usage: "OBJECT: qdisc|class|filter\n" +//usage: "CMD: add|del|change|replace|show\n" //usage: "\n" -//usage: "qdisc [ handle QHANDLE ] [ root |"IF_FEATURE_TC_INGRESS(" ingress |")" parent CLASSID ]\n" -/* //usage: "[ estimator INTERVAL TIME_CONSTANT ]\n" */ -//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" -//usage: " QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n" -//usage: "qdisc show [ dev STRING ]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n" -//usage: "class [ classid CLASSID ] [ root | parent CLASSID ]\n" -//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" -//usage: "class show [ dev STRING ] [ root | parent CLASSID ]\n" -//usage: "filter [ pref PRIO ] [ protocol PROTO ]\n" -/* //usage: "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */ -//usage: " [ root | classid CLASSID ] [ handle FILTERID ]\n" -//usage: " [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n" -//usage: "filter show [ dev STRING ] [ root | parent CLASSID ]" +//usage: "qdisc [handle QHANDLE] [root|"IF_FEATURE_TC_INGRESS("ingress|")"parent CLASSID]\n" +/* //usage: "[estimator INTERVAL TIME_CONSTANT]\n" */ +//usage: " [[QDISC_KIND] [help|OPTIONS]]\n" +//usage: " QDISC_KIND := [p|b]fifo|tbf|prio|cbq|red|etc.\n" +//usage: "qdisc show [dev STRING]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n" +//usage: "class [classid CLASSID] [root|parent CLASSID]\n" +//usage: " [[QDISC_KIND] [help|OPTIONS] ]\n" +//usage: "class show [ dev STRING ] [root|parent CLASSID]\n" +//usage: "filter [pref PRIO] [protocol PROTO]\n" +/* //usage: "\t[estimator INTERVAL TIME_CONSTANT]\n" */ +//usage: " [root|classid CLASSID] [handle FILTERID]\n" +//usage: " [[FILTER_TYPE] [help|OPTIONS]]\n" +//usage: "filter show [dev STRING] [root|parent CLASSID]" #include "libbb.h" #include "common_bufsiz.h" -- cgit v1.2.3-55-g6feb From 194b2ebd2a0cfc1d27744dea10ef706975c61317 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Jan 2017 17:32:20 +0100 Subject: ls: replace -e with --full-time, add --group-directories-first, delete -K -K and -e were non-standard function old new delta static.ls_longopts 9 47 +38 ls_main 748 776 +28 display_single 901 928 +27 sortcmp 254 258 +4 ls_options 32 31 -1 opt_flags 100 96 -4 packed_usage 31032 30977 -55 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/3 up/down: 97/-60) Total: 37 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 130 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 56 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 13df77410..0774a9a45 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -130,17 +130,20 @@ //usage: "\n -i List inode numbers" //usage: "\n -n List numeric UIDs and GIDs instead of names" //usage: "\n -s List allocated blocks" -//usage: IF_FEATURE_LS_TIMESTAMPS( -//usage: "\n -e List full date and time" -//usage: ) +//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS( +//usage: "\n --full-time List full date and time" +//usage: )) //usage: IF_FEATURE_HUMAN_READABLE( //usage: "\n -h List sizes in human readable format (1K 243M 2G)" //usage: ) //usage: IF_FEATURE_LS_SORTFILES( -//usage: "\n -r Sort in reverse order" +//usage: IF_LONG_OPTS( +//usage: "\n --group-directories-first" +//usage: ) //usage: "\n -S Sort by size" //usage: "\n -X Sort by extension" //usage: "\n -v Sort by version" +//usage: "\n -r Reverse sort order" //usage: ) //usage: IF_FEATURE_LS_TIMESTAMPS( //usage: "\n -c With -l: sort by ctime" @@ -149,7 +152,6 @@ //usage: ) //usage: IF_SELINUX( //usage: "\n -k List security context" -//usage: "\n -K List security context in long format" //usage: "\n -Z List security context and permission" //usage: ) //usage: IF_FEATURE_LS_WIDTH( @@ -230,16 +232,16 @@ TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, /* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ SORT_REVERSE = 1 << 23, +SORT_DIRS_FIRST = 1 << 24, SORT_NAME = 0, /* sort by file name */ -SORT_SIZE = 1 << 24, /* sort by file size */ -SORT_ATIME = 2 << 24, /* sort by last access time */ -SORT_CTIME = 3 << 24, /* sort by last change time */ -SORT_MTIME = 4 << 24, /* sort by last modification time */ -SORT_VERSION = 5 << 24, /* sort by version */ -SORT_EXT = 6 << 24, /* sort by file name extension */ -SORT_DIR = 7 << 24, /* sort by file or directory */ -SORT_MASK = (7 << 24) * ENABLE_FEATURE_LS_SORTFILES, +SORT_SIZE = 1 << 25, /* sort by file size */ +SORT_ATIME = 2 << 25, /* sort by last access time */ +SORT_CTIME = 3 << 25, /* sort by last change time */ +SORT_MTIME = 4 << 25, /* sort by last modification time */ +SORT_VERSION = 5 << 25, /* sort by version */ +SORT_EXT = 6 << 25, /* sort by file name extension */ +SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES, LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ LIST_DATE_TIME | LIST_SYMLINK, @@ -249,26 +251,24 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ /* -gnsxA Std options, busybox always supports */ /* -Q GNU option, busybox always supports */ /* -k SELinux option, busybox always supports (ignores if !SELinux) */ -/* Std has -k which means "show sizes in kbytes" */ +/* Std has -k which means "for -s, show sizes in kbytes" */ +/* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */ +/* since otherwise -s shows kbytes anyway */ /* -LHRctur Std options, busybox optionally supports */ /* -Fp Std options, busybox optionally supports */ /* -SXvhTw GNU options, busybox optionally supports */ /* -T WIDTH Ignored (we don't use tabs on output) */ -/* -KZ SELinux mandated options, busybox optionally supports */ -/* (coreutils 8.4 has no -K, remove it?) */ -/* -e I think we made this one up (looks similar to GNU --full-time) */ -/* We already used up all 32 bits, if we need to add more, candidates for removal: */ -/* -K, -T, -e (add --full-time instead) */ +/* -Z SELinux mandated option, busybox optionally supports */ static const char ls_options[] ALIGN1 = "Cadil1gnsxQAk" /* 13 opts, total 13 */ - IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ - IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ - IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ - IF_FEATURE_LS_RECURSIVE("R") /* 1, 24 */ - IF_SELINUX("KZ") /* 2, 26 */ - IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ - IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ - IF_FEATURE_LS_WIDTH("T:w:") /* 2, 31 */ + IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 16 */ + IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 20 */ + IF_FEATURE_LS_FILETYPES("Fp") /* 2, 22 */ + IF_FEATURE_LS_RECURSIVE("R") /* 1, 23 */ + IF_SELINUX("Z") /* 1, 24 */ + IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ + IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ + IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ /* with --color, we use all 32 bits */; enum { //OPT_C = (1 << 0), @@ -286,27 +286,26 @@ enum { //OPT_k = (1 << 12), OPTBIT_c = 13, - OPTBIT_e, OPTBIT_t, OPTBIT_u, - OPTBIT_S = OPTBIT_c + 4 * ENABLE_FEATURE_LS_TIMESTAMPS, - OPTBIT_X, /* 18 */ + OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, + OPTBIT_X, /* 17 */ OPTBIT_r, OPTBIT_v, OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, - OPTBIT_p, /* 22 */ + OPTBIT_p, /* 21 */ OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, - OPTBIT_K = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, - OPTBIT_Z, /* 25 */ - OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, - OPTBIT_H, /* 27 */ + OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, + OPTBIT_L = OPTBIT_Z + 2 * ENABLE_SELINUX, + OPTBIT_H, /* 25 */ OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, - OPTBIT_w, /* 30 */ - OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, + OPTBIT_w, /* 28 */ + OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, + OPTBIT_dirs_first = OPTBIT_color + 1 * ENABLE_FEATURE_LS_COLOR, + OPTBIT_full_time, OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, - OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES, @@ -316,14 +315,15 @@ enum { OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE, - OPT_K = (1 << OPTBIT_K) * ENABLE_SELINUX, OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX, OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH, OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH, - OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR, + OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, + OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, + OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, }; /* TODO: simple toggles may be stored as OPT_xxx bits instead */ @@ -343,7 +343,6 @@ static const uint32_t opt_flags[] = { ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ #if ENABLE_FEATURE_LS_TIMESTAMPS TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ - LIST_FULLTIME, /* e */ ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */ TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */ #endif @@ -361,7 +360,6 @@ static const uint32_t opt_flags[] = { DISP_RECURSIVE, /* R */ #endif #if ENABLE_SELINUX - LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME|STYLE_SINGLE, /* K */ LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */ #endif (1U << 31) @@ -634,21 +632,22 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #if ENABLE_FEATURE_LS_TIMESTAMPS if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { - char *filetime; const time_t *ttime = &dn->dn_mtime; if (G.all_fmt & TIME_ACCESS) ttime = &dn->dn_atime; if (G.all_fmt & TIME_CHANGE) ttime = &dn->dn_ctime; - filetime = ctime(ttime); - /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ - if (G.all_fmt & LIST_FULLTIME) { /* -e */ - /* Note: coreutils 8.4 ls --full-time prints: + if (G.all_fmt & LIST_FULLTIME) { /* --full-time */ + /* coreutils 8.4 ls --full-time prints: * 2009-07-13 17:49:27.000000000 +0200 */ - column += printf("%.24s ", filetime); + char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")]; + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", localtime(ttime)); + column += printf("%s ", buf); } else { /* LIST_DATE_TIME */ - /* G.current_time_t ~== time(NULL) */ + /* G.current_time_t is ~== time(NULL) */ + char *filetime = ctime(ttime); + /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ time_t age = G.current_time_t - *ttime; if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { /* less than 6 months old */ @@ -943,6 +942,12 @@ static int sortcmp(const void *a, const void *b) dif = 0; /* assume SORT_NAME */ // TODO: use pre-initialized function pointer // instead of branch forest + if (G.all_fmt & SORT_DIRS_FIRST) { + dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode); + if (dif != 0) + goto maybe_invert_and_ret; + } + if (sort_opts == SORT_SIZE) { dif = (d2->dn_size - d1->dn_size); } else @@ -955,9 +960,6 @@ static int sortcmp(const void *a, const void *b) if (sort_opts == SORT_MTIME) { dif = (d2->dn_mtime - d1->dn_mtime); } else - if (sort_opts == SORT_DIR) { - dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode); - } else #if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 if (sort_opts == SORT_VERSION) { dif = strverscmp(d1->name, d2->name); @@ -982,7 +984,7 @@ static int sortcmp(const void *a, const void *b) dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT); } } - + maybe_invert_and_ret: return (G.all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif; } @@ -1157,7 +1159,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv) * (and substrings: "--color=alwa" work too) */ static const char ls_longopts[] ALIGN1 = - "color\0" Optional_argument "\xff"; /* no short equivalent */ + "color\0" Optional_argument "\xff" /* no short equivalent */ + "group-directories-first\0" No_argument "\xfe" + "full-time\0" No_argument "\xfd" + ; static const char color_str[] ALIGN1 = "always\0""yes\0""force\0" "auto\0""tty\0""if-tty\0"; @@ -1182,8 +1187,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* process options */ IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) opt_complementary = - /* -e implies -l */ - IF_FEATURE_LS_TIMESTAMPS("el") + /* --full-time implies -l */ + IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xfd""l")) /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: * in some pairs of opts, only last one takes effect: */ @@ -1200,6 +1205,15 @@ int ls_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_LS_WIDTH(, NULL, &G_terminal_width) IF_FEATURE_LS_COLOR(, &color_opt) ); +#if 0 /* option bits debug */ + bb_error_msg("opt:0x%08x H:%x color:%x dirs:%x", opt, OPT_H, OPT_color, OPT_dirs_first); + if (opt & OPT_c ) bb_error_msg("-c"); + if (opt & OPT_H ) bb_error_msg("-H"); + if (opt & OPT_color ) bb_error_msg("--color"); + if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first"); + if (opt & OPT_full_time ) bb_error_msg("--full-time"); + exit(0); +#endif for (i = 0; opt_flags[i] != (1U << 31); i++) { if (opt & (1 << i)) { uint32_t flags = opt_flags[i]; @@ -1239,6 +1253,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv) } } #endif + if (opt & OPT_dirs_first) + G.all_fmt |= SORT_DIRS_FIRST; + if (opt & OPT_full_time) + G.all_fmt |= LIST_FULLTIME; /* sort out which command line options take precedence */ if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) -- cgit v1.2.3-55-g6feb From f580baf94a5ad9cdfed919c17a1a1cdf26089f15 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Jan 2017 19:02:57 +0100 Subject: ls: more correct handling of -c, -u function old new delta my_stat 302 318 +16 packed_usage 30977 30969 -8 display_single 928 910 -18 sortcmp 258 228 -30 ls_main 776 732 -44 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/4 up/down: 16/-100) Total: -84 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 109 ++++++++++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 59 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 0774a9a45..b9d74a2cb 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -101,11 +101,10 @@ //usage: IF_FEATURE_LS_FOLLOWLINKS("LH") //usage: IF_FEATURE_LS_RECURSIVE("R") //usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" -//usage: IF_FEATURE_LS_TIMESTAMPS("e") //usage: IF_FEATURE_HUMAN_READABLE("h") //usage: IF_FEATURE_LS_SORTFILES("rSXv") //usage: IF_FEATURE_LS_TIMESTAMPS("ctu") -//usage: IF_SELINUX("kKZ") "]" +//usage: IF_SELINUX("kZ") "]" //usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..." //usage:#define ls_full_usage "\n\n" //usage: "List directory contents\n" @@ -130,6 +129,10 @@ //usage: "\n -i List inode numbers" //usage: "\n -n List numeric UIDs and GIDs instead of names" //usage: "\n -s List allocated blocks" +//usage: IF_FEATURE_LS_TIMESTAMPS( +//usage: "\n -c List ctime" +//usage: "\n -u List atime" +//usage: ) //usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS( //usage: "\n --full-time List full date and time" //usage: )) @@ -143,13 +146,13 @@ //usage: "\n -S Sort by size" //usage: "\n -X Sort by extension" //usage: "\n -v Sort by version" -//usage: "\n -r Reverse sort order" //usage: ) //usage: IF_FEATURE_LS_TIMESTAMPS( -//usage: "\n -c With -l: sort by ctime" -//usage: "\n -t With -l: sort by mtime" -//usage: "\n -u With -l: sort by atime" +//usage: "\n -t Sort by mtime" +//usage: "\n -tc Sort by ctime" +//usage: "\n -tu Sort by atime" //usage: ) +//usage: "\n -r Reverse sort order" //usage: IF_SELINUX( //usage: "\n -k List security context" //usage: "\n -Z List security context and permission" @@ -225,22 +228,15 @@ STYLE_LONG = 2 << 19, /* one record per line, extended info */ STYLE_SINGLE = 3 << 19, /* one record per line */ STYLE_MASK = STYLE_SINGLE, -/* which of the three times will be used */ -TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, -TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, -TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, - /* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ SORT_REVERSE = 1 << 23, SORT_DIRS_FIRST = 1 << 24, SORT_NAME = 0, /* sort by file name */ SORT_SIZE = 1 << 25, /* sort by file size */ -SORT_ATIME = 2 << 25, /* sort by last access time */ -SORT_CTIME = 3 << 25, /* sort by last change time */ -SORT_MTIME = 4 << 25, /* sort by last modification time */ -SORT_VERSION = 5 << 25, /* sort by version */ -SORT_EXT = 6 << 25, /* sort by file name extension */ +SORT_TIME = 2 << 25, /* sort by {a,m,c}time */ +SORT_VERSION = 3 << 25, /* sort by version */ +SORT_EXT = 4 << 25, /* sort by file name extension */ SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES, LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ @@ -268,14 +264,14 @@ static const char ls_options[] ALIGN1 = IF_SELINUX("Z") /* 1, 24 */ IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ - IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ - /* with --color, we use all 32 bits */; + IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ +; enum { //OPT_C = (1 << 0), //OPT_a = (1 << 1), //OPT_d = (1 << 2), //OPT_i = (1 << 3), - //OPT_l = (1 << 4), + OPT_l = (1 << 4), //OPT_1 = (1 << 5), OPT_g = (1 << 6), //OPT_n = (1 << 7), @@ -301,9 +297,10 @@ enum { OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, OPTBIT_w, /* 28 */ - OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, - OPTBIT_dirs_first = OPTBIT_color + 1 * ENABLE_FEATURE_LS_COLOR, - OPTBIT_full_time, + OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, + OPTBIT_dirs_first, + OPTBIT_color, /* 31 */ + /* with long opts, we use all 32 bits */ OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, @@ -321,9 +318,9 @@ enum { OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH, OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH, - OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, - OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, + OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS, + OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, }; /* TODO: simple toggles may be stored as OPT_xxx bits instead */ @@ -342,9 +339,9 @@ static const uint32_t opt_flags[] = { DISP_HIDDEN, /* A */ ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ #if ENABLE_FEATURE_LS_TIMESTAMPS - TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ - ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */ - TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */ + 0, /* c - handled via OPT_c */ + (ENABLE_FEATURE_LS_SORTFILES * SORT_TIME), /* t */ + 0, /* u - handled via OPT_u */ #endif #if ENABLE_FEATURE_LS_SORTFILES SORT_SIZE, /* S */ @@ -396,9 +393,7 @@ struct dnode { mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */ off_t dn_size; #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES - time_t dn_atime; - time_t dn_mtime; - time_t dn_ctime; + time_t dn_time; #endif ino_t dn_ino; blkcnt_t dn_blocks; @@ -632,14 +627,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #if ENABLE_FEATURE_LS_TIMESTAMPS if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { - const time_t *ttime = &dn->dn_mtime; - if (G.all_fmt & TIME_ACCESS) - ttime = &dn->dn_atime; - if (G.all_fmt & TIME_CHANGE) - ttime = &dn->dn_ctime; + const time_t *ttime = &dn->dn_time; if (G.all_fmt & LIST_FULLTIME) { /* --full-time */ /* coreutils 8.4 ls --full-time prints: * 2009-07-13 17:49:27.000000000 +0200 + * we don't show fractional seconds. */ char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")]; strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", localtime(ttime)); @@ -820,9 +812,11 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f cur->dn_mode = statbuf.st_mode ; cur->dn_size = statbuf.st_size ; #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES - cur->dn_atime = statbuf.st_atime ; - cur->dn_mtime = statbuf.st_mtime ; - cur->dn_ctime = statbuf.st_ctime ; + cur->dn_time = statbuf.st_mtime ; + if (option_mask32 & OPT_u) + cur->dn_time = statbuf.st_atime; + if (option_mask32 & OPT_c) + cur->dn_time = statbuf.st_ctime; #endif cur->dn_ino = statbuf.st_ino ; cur->dn_blocks = statbuf.st_blocks; @@ -951,14 +945,8 @@ static int sortcmp(const void *a, const void *b) if (sort_opts == SORT_SIZE) { dif = (d2->dn_size - d1->dn_size); } else - if (sort_opts == SORT_ATIME) { - dif = (d2->dn_atime - d1->dn_atime); - } else - if (sort_opts == SORT_CTIME) { - dif = (d2->dn_ctime - d1->dn_ctime); - } else - if (sort_opts == SORT_MTIME) { - dif = (d2->dn_mtime - d1->dn_mtime); + if (sort_opts == SORT_TIME) { + dif = (d2->dn_time - d1->dn_time); } else #if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 if (sort_opts == SORT_VERSION) { @@ -1159,9 +1147,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv) * (and substrings: "--color=alwa" work too) */ static const char ls_longopts[] ALIGN1 = - "color\0" Optional_argument "\xff" /* no short equivalent */ + "full-time\0" No_argument "\xff" "group-directories-first\0" No_argument "\xfe" - "full-time\0" No_argument "\xfd" + "color\0" Optional_argument "\xfd" ; static const char color_str[] ALIGN1 = "always\0""yes\0""force\0" @@ -1188,7 +1176,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) opt_complementary = /* --full-time implies -l */ - IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xfd""l")) + IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xff""l")) /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: * in some pairs of opts, only last one takes effect: */ @@ -1206,8 +1194,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_LS_COLOR(, &color_opt) ); #if 0 /* option bits debug */ - bb_error_msg("opt:0x%08x H:%x color:%x dirs:%x", opt, OPT_H, OPT_color, OPT_dirs_first); + bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first); if (opt & OPT_c ) bb_error_msg("-c"); + if (opt & OPT_l ) bb_error_msg("-l"); if (opt & OPT_H ) bb_error_msg("-H"); if (opt & OPT_color ) bb_error_msg("--color"); if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first"); @@ -1222,8 +1211,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv) G.all_fmt &= ~STYLE_MASK; if (flags & SORT_MASK) G.all_fmt &= ~SORT_MASK; - if (flags & TIME_MASK) - G.all_fmt &= ~TIME_MASK; G.all_fmt |= flags; } @@ -1261,14 +1248,18 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* sort out which command line options take precedence */ if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ - if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { - if (G.all_fmt & TIME_CHANGE) - G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_CTIME; - if (G.all_fmt & TIME_ACCESS) - G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_ATIME; - } - if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */ + if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */ G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); + if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { + /* when to sort by time? -t[cu] sorts by time even with -l */ + /* (this is achieved by opt_flags[] element for -t) */ + /* without -l, bare -c or -u enable sort too */ + /* (with -l, bare -c or -u just select which time to show) */ + if (opt & (OPT_c|OPT_u)) { + G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_TIME; + } + } + } /* choose a display format if one was not already specified by an option */ if (!(G.all_fmt & STYLE_MASK)) -- cgit v1.2.3-55-g6feb From e1f90d13fa07d2974908470ce818ef956b7740f2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Jan 2017 22:02:19 +0100 Subject: ls: -1 should be ignored by -l (and options which imply -l) Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index b9d74a2cb..b48df8bf5 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -130,8 +130,8 @@ //usage: "\n -n List numeric UIDs and GIDs instead of names" //usage: "\n -s List allocated blocks" //usage: IF_FEATURE_LS_TIMESTAMPS( -//usage: "\n -c List ctime" -//usage: "\n -u List atime" +//usage: "\n -lc List ctime" +//usage: "\n -lu List atime" //usage: ) //usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS( //usage: "\n --full-time List full date and time" @@ -243,7 +243,7 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ LIST_DATE_TIME | LIST_SYMLINK, }; -/* -Cadil1 Std options, busybox always supports */ +/* -Cadi1l Std options, busybox always supports */ /* -gnsxA Std options, busybox always supports */ /* -Q GNU option, busybox always supports */ /* -k SELinux option, busybox always supports (ignores if !SELinux) */ @@ -256,7 +256,7 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ /* -T WIDTH Ignored (we don't use tabs on output) */ /* -Z SELinux mandated option, busybox optionally supports */ static const char ls_options[] ALIGN1 = - "Cadil1gnsxQAk" /* 13 opts, total 13 */ + "Cadi1lgnsxQAk" /* 13 opts, total 13 */ IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 16 */ IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 20 */ IF_FEATURE_LS_FILETYPES("Fp") /* 2, 22 */ @@ -271,8 +271,8 @@ enum { //OPT_a = (1 << 1), //OPT_d = (1 << 2), //OPT_i = (1 << 3), - OPT_l = (1 << 4), - //OPT_1 = (1 << 5), + //OPT_1 = (1 << 4), + OPT_l = (1 << 5), OPT_g = (1 << 6), //OPT_n = (1 << 7), //OPT_s = (1 << 8), @@ -329,10 +329,10 @@ static const uint32_t opt_flags[] = { DISP_HIDDEN | DISP_DOT, /* a */ DISP_NOLIST, /* d */ LIST_INO, /* i */ - LIST_LONG | STYLE_LONG, /* l */ STYLE_SINGLE, /* 1 */ + LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ - LIST_ID_NUMERIC | LIST_LONG | STYLE_LONG, /* n (assumes l) */ + LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ LIST_BLOCKS, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ 0, /* Q (quote filename) - handled via OPT_Q */ @@ -1215,6 +1215,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv) G.all_fmt |= flags; } } + if (opt & OPT_dirs_first) + G.all_fmt |= SORT_DIRS_FIRST; + if (opt & OPT_full_time) + G.all_fmt |= LIST_FULLTIME; #if ENABLE_FEATURE_LS_COLOR /* set G_show_color = 1/0 */ @@ -1240,10 +1244,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv) } } #endif - if (opt & OPT_dirs_first) - G.all_fmt |= SORT_DIRS_FIRST; - if (opt & OPT_full_time) - G.all_fmt |= LIST_FULLTIME; /* sort out which command line options take precedence */ if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) -- cgit v1.2.3-55-g6feb From 9a647c326a41e8160d53e6cb5470161a44c0e8cf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 01:08:16 +0100 Subject: separate TLS code into a library, use in in wget A new applet, ssl_client, is the TLS debug thing now. It doubles as wget's NOMMU helper. In MMU mode, wget still forks, but then directly calls TLS code, without execing. This can also be applied to sendmail/popmail (SMTPS / SMTP+starttls support) and nc --ssl (ncat, nmap's nc clone, has such option). function old new delta tls_handshake - 1691 +1691 tls_run_copy_loop - 443 +443 ssl_client_main - 128 +128 packed_usage 30978 31007 +29 wget_main 2508 2535 +27 applet_names 2553 2560 +7 ... xwrite_encrypted 360 342 -18 tls_main 2127 - -2127 ------------------------------------------------------------------------------ (add/remove: 4/1 grow/shrink: 13/8 up/down: 2351/-2195) Total: 156 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 88 +++++++++++++++++++++------- networking/ssl_client.c | 55 ++++++++++++++++++ networking/tls.c | 151 +++++++++++++++--------------------------------- networking/wget.c | 102 +++++++++++++++++--------------- 4 files changed, 221 insertions(+), 175 deletions(-) create mode 100644 networking/ssl_client.c diff --git a/include/libbb.h b/include/libbb.h index 87f89c76d..ba3b1479e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -355,6 +355,27 @@ extern char *skip_dev_pfx(const char *tty_name) FAST_FUNC; extern char *strrstr(const char *haystack, const char *needle) FAST_FUNC; +/* dmalloc will redefine these to it's own implementation. It is safe + * to have the prototypes here unconditionally. */ +void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC; +void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC; +void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC; +void *xrealloc(void *old, size_t size) FAST_FUNC; +/* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use + * at least v[idx] and v[idx+1], for all idx values. + * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...) + * when all elements are used up. New elements are zeroed out. + * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs - + * skipping an index is a bad bug - it may miss a realloc! + */ +#define xrealloc_vector(vector, shift, idx) \ + xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx)) +void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC; +char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; +char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; +void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; + + //TODO: supply a pointer to char[11] buffer (avoid statics)? extern const char *bb_mode_string(mode_t mode) FAST_FUNC; extern int is_directory(const char *name, int followLinks) FAST_FUNC; @@ -692,6 +713,52 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC; // Also mount.c and inetd.c are using gethostbyname(), // + inet_common.c has additional IPv4-only stuff +#define SHA256_INSIZE 64 +#define SHA256_OUTSIZE 32 +#define AES_BLOCKSIZE 16 +#define AES128_KEYSIZE 16 +#define AES256_KEYSIZE 32 +struct tls_handshake_data; /* opaque */ +typedef struct tls_state { + int ofd; + int ifd; + + int min_encrypted_len_on_read; + uint8_t encrypt_on_write; + + uint8_t *outbuf; + int outbuf_size; + + int inbuf_size; + int ofs_to_buffered; + int buffered_size; + uint8_t *inbuf; + + struct tls_handshake_data *hsd; + + // RFC 5246 + // sequence number + // Each connection state contains a sequence number, which is + // maintained separately for read and write states. The sequence + // number MUST be set to zero whenever a connection state is made the + // active state. Sequence numbers are of type uint64 and may not + // exceed 2^64-1. + /*uint64_t read_seq64_be;*/ + uint64_t write_seq64_be; + + uint8_t client_write_MAC_key[SHA256_OUTSIZE]; + uint8_t server_write_MAC_key[SHA256_OUTSIZE]; + uint8_t client_write_key[AES256_KEYSIZE]; + uint8_t server_write_key[AES256_KEYSIZE]; +} tls_state_t; + +static inline tls_state_t *new_tls_state(void) +{ + tls_state_t *tls = xzalloc(sizeof(*tls)); + return tls; +} +void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; +void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC; void socket_want_pktinfo(int fd) FAST_FUNC; ssize_t send_to_from(int fd, void *buf, size_t len, int flags, @@ -705,9 +772,6 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; -char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; -char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; -void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; @@ -753,24 +817,6 @@ enum { }; void visible(unsigned ch, char *buf, int flags) FAST_FUNC; -/* dmalloc will redefine these to it's own implementation. It is safe - * to have the prototypes here unconditionally. */ -void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC; -void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC; -void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC; -void *xrealloc(void *old, size_t size) FAST_FUNC; -/* After v = xrealloc_vector(v, SHIFT, idx) it's ok to use - * at least v[idx] and v[idx+1], for all idx values. - * SHIFT specifies how many new elements are added (1:2, 2:4, ..., 8:256...) - * when all elements are used up. New elements are zeroed out. - * xrealloc_vector(v, SHIFT, idx) *MUST* be called with consecutive IDXs - - * skipping an index is a bad bug - it may miss a realloc! - */ -#define xrealloc_vector(vector, shift, idx) \ - xrealloc_vector_helper((vector), (sizeof((vector)[0]) << 8) + (shift), (idx)) -void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) FAST_FUNC; - - extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; // NB: will return short read on error, not -1, diff --git a/networking/ssl_client.c b/networking/ssl_client.c new file mode 100644 index 000000000..cfeae1587 --- /dev/null +++ b/networking/ssl_client.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config SSL_CLIENT +//config: bool "ssl_client" +//config: default y +//config: select TLS +//config: help +//config: This tool pipes data to/from a socket, TLS-encrypting it. + +//applet:IF_SSL_CLIENT(APPLET(ssl_client, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o + +//usage:#define ssl_client_trivial_usage +//usage: "-s FD [-r FD] [-n SNI]" +//usage:#define ssl_client_full_usage "" + +#include "libbb.h" + +int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int ssl_client_main(int argc UNUSED_PARAM, char **argv) +{ + tls_state_t *tls; + const char *sni = NULL; + int opt; + + // INIT_G(); + + tls = new_tls_state(); + opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni); + if (!(opt & 2)) { + /* -r N defaults to -s N */ + tls->ifd = tls->ofd; + } + + if (!(opt & 3)) { + if (!argv[1]) + bb_show_usage(); + /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */ + // + // Talk to kernel.org: + // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org + if (!sni) + sni = argv[1]; + tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443); + } + + tls_handshake(tls, sni); + tls_run_copy_loop(tls); + + return EXIT_SUCCESS; +} diff --git a/networking/tls.c b/networking/tls.c index b111e4bb4..29cc5b9f3 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -4,11 +4,9 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ //config:config TLS -//config: bool "tls (debugging)" +//config: bool #No description makes it a hidden option //config: default n -//applet:IF_TLS(APPLET(tls, BB_DIR_USR_BIN, BB_SUID_DROP)) - //kbuild:lib-$(CONFIG_TLS) += tls.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm.o //kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o @@ -18,12 +16,7 @@ //kbuild:lib-$(CONFIG_TLS) += tls_aes.o ////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o -//usage:#define tls_trivial_usage -//usage: "HOST[:PORT]" -//usage:#define tls_full_usage "\n\n" - #include "tls.h" -//#include "common_bufsiz.h" #define TLS_DEBUG 1 #define TLS_DEBUG_HASH 0 @@ -165,13 +158,6 @@ #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE enum { - SHA256_INSIZE = 64, - SHA256_OUTSIZE = 32, - - AES_BLOCKSIZE = 16, - AES128_KEYSIZE = 16, - AES256_KEYSIZE = 32, - RSA_PREMASTER_SIZE = 48, RECHDR_LEN = 5, @@ -225,20 +211,7 @@ struct record_hdr { uint8_t len16_hi, len16_lo; }; -typedef struct tls_state { - int fd; - - int min_encrypted_len_on_read; - uint8_t encrypt_on_write; - - uint8_t *outbuf; - int outbuf_size; - - int inbuf_size; - int ofs_to_buffered; - int buffered_size; - uint8_t *inbuf; - +struct tls_handshake_data { //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; @@ -247,22 +220,7 @@ typedef struct tls_state { // these two are unused after finished messages are exchanged: sha256_ctx_t handshake_sha256_ctx; uint8_t master_secret[48]; - - // RFC 5246 - // sequence number - // Each connection state contains a sequence number, which is - // maintained separately for read and write states. The sequence - // number MUST be set to zero whenever a connection state is made the - // active state. Sequence numbers are of type uint64 and may not - // exceed 2^64-1. - /*uint64_t read_seq64_be;*/ - uint64_t write_seq64_be; - - uint8_t client_write_MAC_key[SHA256_OUTSIZE]; - uint8_t server_write_MAC_key[SHA256_OUTSIZE]; - uint8_t client_write_key[AES256_KEYSIZE]; - uint8_t server_write_key[AES256_KEYSIZE]; -} tls_state_t; +}; static unsigned get24be(const uint8_t *p) @@ -487,14 +445,6 @@ static void prf_hmac_sha256( #undef SEED } -static tls_state_t *new_tls_state(void) -{ - tls_state_t *tls = xzalloc(sizeof(*tls)); - tls->fd = -1; - sha256_begin(&tls->handshake_sha256_ctx); - return tls; -} - static void tls_error_die(tls_state_t *tls) { dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); @@ -597,7 +547,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size); return; } @@ -681,7 +631,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } @@ -697,10 +647,10 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); - xwrite(tls->fd, xhdr, RECHDR_LEN + size); + xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); /* Handshake hash does not include record headers */ - sha256_hash_dbg(">> sha256:%s", &tls->handshake_sha256_ctx, buf, size); + sha256_hash_dbg(">> sha256:%s", &tls->hsd->handshake_sha256_ctx, buf, size); return; } xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); @@ -769,7 +719,7 @@ static int tls_xread_record(tls_state_t *tls) rem = tls->inbuf_size - total; tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size); } - sz = safe_read(tls->fd, tls->inbuf + total, rem); + sz = safe_read(tls->ifd, tls->inbuf + total, rem); if (sz <= 0) { if (sz == 0 && total == 0) { /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */ @@ -848,7 +798,7 @@ static int tls_xread_record(tls_state_t *tls) * in our FINISHED record must include data of incoming packets too! */ if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg("<< sha256:%s", &tls->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); + sha256_hash_dbg("<< sha256:%s", &tls->hsd->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); } end: dbg("got block len:%u\n", sz); @@ -1059,12 +1009,12 @@ static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len) xfunc_die(); der++; der = enter_der_item(der, &end); /* enter SEQ */ - /* memset(tls->server_rsa_pub_key, 0, sizeof(tls->server_rsa_pub_key)); - already is */ - der_binary_to_pstm(&tls->server_rsa_pub_key.N, der, end); /* modulus */ + /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */ + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */ der = skip_der_item(der, end); - der_binary_to_pstm(&tls->server_rsa_pub_key.e, der, end); /* exponent */ - tls->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->server_rsa_pub_key.N); - dbg("server_rsa_pub_key.size:%d\n", tls->server_rsa_pub_key.size); + der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */ + tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N); + dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size); } /* @@ -1140,7 +1090,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni) tls_get_random(record->rand32, sizeof(record->rand32)); if (TLS_DEBUG_FIXED_SECRETS) memset(record->rand32, 0x11, sizeof(record->rand32)); - memcpy(tls->client_and_server_rand32, record->rand32, sizeof(record->rand32)); + memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ /* record->cipherid_len16_hi = 0; */ record->cipherid_len16_lo = 2 * 1; @@ -1225,7 +1175,7 @@ static void get_server_hello(tls_state_t *tls) } dbg("<< SERVER_HELLO\n"); - memcpy(tls->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); + memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); } static void get_server_cert(tls_state_t *tls) @@ -1282,7 +1232,7 @@ static void send_client_key_exchange(tls_state_t *tls) rsa_premaster[0] = TLS_MAJ; rsa_premaster[1] = TLS_MIN; len = psRsaEncryptPub(/*pool:*/ NULL, - /* psRsaKey_t* */ &tls->server_rsa_pub_key, + /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), record->key, sizeof(record->key), data_param_ignored @@ -1310,12 +1260,12 @@ static void send_client_key_exchange(tls_state_t *tls) // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. prf_hmac_sha256( - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", - tls->client_and_server_rand32, sizeof(tls->client_and_server_rand32) + tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32) ); - dump_hex("master secret:%s\n", tls->master_secret, sizeof(tls->master_secret)); + dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); // RFC 5246 // 6.3. Key Calculation @@ -1354,8 +1304,8 @@ static void send_client_key_exchange(tls_state_t *tls) uint8_t tmp64[64]; /* make "server_rand32 + client_rand32" */ - memcpy(&tmp64[0] , &tls->client_and_server_rand32[32], 32); - memcpy(&tmp64[32], &tls->client_and_server_rand32[0] , 32); + memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32); + memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); prf_hmac_sha256( tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), @@ -1363,7 +1313,7 @@ static void send_client_key_exchange(tls_state_t *tls) // server_write_MAC_key[SHA256_OUTSIZE] // client_write_key[AES256_KEYSIZE] // server_write_key[AES256_KEYSIZE] - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "key expansion", tmp64, 64 ); @@ -1384,7 +1334,7 @@ static const uint8_t rec_CHANGE_CIPHER_SPEC[] = { static void send_change_cipher_spec(tls_state_t *tls) { dbg(">> CHANGE_CIPHER_SPEC\n"); - xwrite(tls->fd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); + xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC)); } // 7.4.9. Finished @@ -1436,13 +1386,13 @@ static void send_client_finished(tls_state_t *tls) fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); - sha256_peek(&tls->handshake_sha256_ctx, handshake_hash); + sha256_peek(&tls->hsd->handshake_sha256_ctx, handshake_hash); prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), - tls->master_secret, sizeof(tls->master_secret), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "client finished", handshake_hash, sizeof(handshake_hash) ); - dump_hex("from secret: %s\n", tls->master_secret, sizeof(tls->master_secret)); + dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); dump_hex("%s\n", handshake_hash, sizeof(handshake_hash)); dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result)); @@ -1451,7 +1401,7 @@ static void send_client_finished(tls_state_t *tls) xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE); } -static void tls_handshake(tls_state_t *tls, const char *sni) +void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) { // Client RFC 5246 Server // (*) - optional messages, not always sent @@ -1472,6 +1422,9 @@ static void tls_handshake(tls_state_t *tls, const char *sni) // Application Data <------> Application Data int len; + tls->hsd = xzalloc(sizeof(*tls->hsd)); + sha256_begin(&tls->hsd->handshake_sha256_ctx); + send_client_hello(tls, sni); get_server_hello(tls); @@ -1541,6 +1494,12 @@ static void tls_handshake(tls_state_t *tls, const char *sni) tls_error_die(tls); dbg("<< FINISHED\n"); /* application data can be sent/received */ + + /* free handshake data */ +// if (PARANOIA) +// memset(tls->hsd, 0, sizeof(*tls->hsd)); + free(tls->hsd); + tls->hsd = NULL; } static void tls_xwrite(tls_state_t *tls, int len) @@ -1557,35 +1516,17 @@ static void tls_xwrite(tls_state_t *tls, int len) // openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost' // openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL // openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256 -// -// Talk to kernel.org: -// printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox tls kernel.org -int tls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int tls_main(int argc UNUSED_PARAM, char **argv) +void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) { - tls_state_t *tls; fd_set readfds; int inbuf_size; const int INBUF_STEP = 4 * 1024; - int cfd; - - // INIT_G(); - // getopt32(argv, "myopts") - - if (!argv[1]) - bb_show_usage(); - - cfd = create_and_connect_stream_or_die(argv[1], 443); - - tls = new_tls_state(); - tls->fd = cfd; - tls_handshake(tls, argv[1]); - - /* Select loop copying stdin to cfd, and cfd to stdout */ +//TODO: convert to poll + /* Select loop copying stdin to ofd, and ifd to stdout */ FD_ZERO(&readfds); - FD_SET(cfd, &readfds); + FD_SET(tls->ifd, &readfds); FD_SET(STDIN_FILENO, &readfds); inbuf_size = INBUF_STEP; @@ -1594,7 +1535,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) int nread; testfds = readfds; - if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0) + if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0) bb_perror_msg_and_die("select"); if (FD_ISSET(STDIN_FILENO, &testfds)) { @@ -1608,7 +1549,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) /* Close outgoing half-connection so they get EOF, * but leave incoming alone so we can see response */ - //shutdown(cfd, SHUT_WR); + //shutdown(tls->ofd, SHUT_WR); /* But TLS has no way to encode this, * doubt it's ok to do it "raw" */ @@ -1626,7 +1567,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) tls_xwrite(tls, nread); } } - if (FD_ISSET(cfd, &testfds)) { + if (FD_ISSET(tls->ifd, &testfds)) { dbg("NETWORK HAS DATA\n"); read_record: nread = tls_xread_record(tls); @@ -1634,7 +1575,7 @@ int tls_main(int argc UNUSED_PARAM, char **argv) /* TLS protocol has no real concept of one-sided shutdowns: * if we get "TLS EOF" from the peer, writes will fail too */ - //FD_CLR(cfd, &readfds); + //FD_CLR(tls->ifd, &readfds); //close(STDOUT_FILENO); //tls_free_inbuf(tls); /* mem usage optimization */ //continue; @@ -1650,6 +1591,4 @@ int tls_main(int argc UNUSED_PARAM, char **argv) goto read_record; } } - - return EXIT_SUCCESS; } diff --git a/networking/wget.c b/networking/wget.c index 58ead4c96..a448acdae 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -47,18 +47,26 @@ //config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option //config: will work in addition to -T. //config: +//config:config FEATURE_WGET_HTTPS +//config: bool "Support HTTPS using internal TLS code" +//config: default y +//config: depends on WGET +//config: select TLS +//config: help +//config: wget will use internal TLS code to connect to https:// URLs. +//config: Note: +//config: On NOMMU machines, ssl_helper applet should be available +//config: in the $PATH for this to work. Make sure to select that applet. +//config: //config:config FEATURE_WGET_OPENSSL //config: bool "Try to connect to HTTPS using openssl" //config: default y //config: depends on WGET //config: help -//config: Choose how wget establishes SSL connection for https:// URLs. -//config: -//config: Busybox itself contains no SSL code. wget will spawn -//config: a helper program to talk over HTTPS. +//config: Try to use openssl to handle HTTPS. //config: //config: OpenSSL has a simple SSL client for debug purposes. -//config: If you select "openssl" helper, wget will effectively run: +//config: If you select this option, wget will effectively run: //config: "openssl s_client -quiet -connect hostname:443 //config: -servername hostname 2>/dev/null" and pipe its data //config: through it. -servername is not used if hostname is numeric. @@ -71,24 +79,9 @@ //config: openssl is also a big binary, often dynamically linked //config: against ~15 libraries. //config: -//config:config FEATURE_WGET_SSL_HELPER -//config: bool "Try to connect to HTTPS using ssl_helper" -//config: default y -//config: depends on WGET -//config: help -//config: Choose how wget establishes SSL connection for https:// URLs. -//config: -//config: Busybox itself contains no SSL code. wget will spawn -//config: a helper program to talk over HTTPS. -//config: -//config: ssl_helper is a tool which can be built statically -//config: from busybox sources against a small embedded SSL library. -//config: Please see networking/ssl_helper/README. -//config: It does not require double host resolution and emits -//config: error messages to stderr. -//config: -//config: Precompiled static binary may be available at -//config: http://busybox.net/downloads/binaries/ +//config: If openssl can't be executed, internal TLS code will be used +//config: (if you enabled it); if openssl can be executed but fails later, +//config: wget can't detect this, and download will fail. //applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) @@ -137,7 +130,7 @@ #endif -#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER) +#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS) struct host_info { char *allocated; @@ -657,7 +650,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) char *servername; int sp[2]; int pid; - IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) + IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;) if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) /* Kernel can have AF_UNIX support disabled */ @@ -702,7 +695,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) BB_EXECVP(argv[0], argv); xmove_fd(3, 2); -# if ENABLE_FEATURE_WGET_SSL_HELPER +# if ENABLE_FEATURE_WGET_HTTPS child_failed = 1; xfunc_die(); # else @@ -715,7 +708,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) free(servername); free(allocated); close(sp[1]); -# if ENABLE_FEATURE_WGET_SSL_HELPER +# if ENABLE_FEATURE_WGET_HTTPS if (child_failed) { close(sp[0]); return -1; @@ -725,38 +718,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port) } #endif -/* See networking/ssl_helper/README how to build one */ -#if ENABLE_FEATURE_WGET_SSL_HELPER -static void spawn_https_helper_small(int network_fd) +#if ENABLE_FEATURE_WGET_HTTPS +static void spawn_ssl_client(const char *host, int network_fd) { int sp[2]; int pid; + char *servername, *p; + + servername = xstrdup(host); + p = strrchr(servername, ':'); + if (p) *p = '\0'; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) /* Kernel can have AF_UNIX support disabled */ bb_perror_msg_and_die("socketpair"); + fflush_all(); pid = BB_MMU ? xfork() : xvfork(); if (pid == 0) { /* Child */ - char *argv[3]; - close(sp[0]); xmove_fd(sp[1], 0); xdup2(0, 1); - xmove_fd(network_fd, 3); - /* - * A simple ssl/tls helper - */ - argv[0] = (char*)"ssl_helper"; - argv[1] = (char*)"-d3"; - argv[2] = NULL; - BB_EXECVP(argv[0], argv); - bb_perror_msg_and_die("can't execute '%s'", argv[0]); + if (BB_MMU) { + tls_state_t *tls = new_tls_state(); + tls->ifd = tls->ofd = network_fd; + tls_handshake(tls, servername); + tls_run_copy_loop(tls); + exit(0); + } else { + char *argv[5]; + xmove_fd(network_fd, 3); + argv[0] = (char*)"ssl_client"; + argv[1] = (char*)"-s3"; + //TODO: if (!is_ip_address(servername))... + argv[2] = (char*)"-n"; + argv[3] = servername; + argv[4] = NULL; + BB_EXECVP(argv[0], argv); + bb_perror_msg_and_die("can't execute '%s'", argv[0]); + } /* notreached */ } /* Parent */ + free(servername); close(sp[1]); xmove_fd(sp[0], network_fd); } @@ -1005,16 +1011,16 @@ static void download_one_url(const char *url) /* Open socket to http(s) server */ #if ENABLE_FEATURE_WGET_OPENSSL - /* openssl (and maybe ssl_helper) support is configured */ + /* openssl (and maybe internal TLS) support is configured */ if (target.protocol == P_HTTPS) { /* openssl-based helper * Inconvenient API since we can't give it an open fd */ int fd = spawn_https_helper_openssl(server.host, server.port); -# if ENABLE_FEATURE_WGET_SSL_HELPER - if (fd < 0) { /* no openssl? try ssl_helper */ +# if ENABLE_FEATURE_WGET_HTTPS + if (fd < 0) { /* no openssl? try internal */ sfp = open_socket(lsa); - spawn_https_helper_small(fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp)); goto socket_opened; } # else @@ -1027,11 +1033,11 @@ static void download_one_url(const char *url) } sfp = open_socket(lsa); socket_opened: -#elif ENABLE_FEATURE_WGET_SSL_HELPER - /* Only ssl_helper support is configured */ +#elif ENABLE_FEATURE_WGET_HTTPS + /* Only internal TLS support is configured */ sfp = open_socket(lsa); if (target.protocol == P_HTTPS) - spawn_https_helper_small(fileno(sfp)); + spawn_ssl_client(server.host, fileno(sfp)); #else /* ssl (https) support is not configured */ sfp = open_socket(lsa); -- cgit v1.2.3-55-g6feb From 9492da7e63deae898d7bf924be5790c7fab1a4fb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 01:15:13 +0100 Subject: tls: set TLS_DEBUG to 0; placate a gcc indentation warning Signed-off-by: Denys Vlasenko --- networking/tls.c | 2 +- networking/tls_symmetric.h | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 29cc5b9f3..89f2ec603 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -18,7 +18,7 @@ #include "tls.h" -#define TLS_DEBUG 1 +#define TLS_DEBUG 0 #define TLS_DEBUG_HASH 0 #define TLS_DEBUG_DER 0 #define TLS_DEBUG_FIXED_SECRETS 0 diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h index 8488b437e..5e0e4b6d8 100644 --- a/networking/tls_symmetric.h +++ b/networking/tls_symmetric.h @@ -27,30 +27,32 @@ static ALWAYS_INLINE unsigned ROL(unsigned word, int i) { - if (__builtin_constant_p(i)) //box + if (__builtin_constant_p(i)) { //box // Rotates by constant use fewer registers, // and on many Intel CPUs rotates by %cl take 2 cycles, not 1. - asm ("roll %2,%0" //box + asm ("roll %2,%0" :"=r" (word) :"0" (word),"i" (i)); - else //box - asm ("roll %%cl,%0" + return word; + } //box + asm ("roll %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); - return word; + return word; } static ALWAYS_INLINE unsigned ROR(unsigned word, int i) { - if (__builtin_constant_p(i)) //box - asm ("rorl %2,%0" //box + if (__builtin_constant_p(i)) { //box + asm ("rorl %2,%0" :"=r" (word) :"0" (word),"i" (i)); - else //box - asm ("rorl %%cl,%0" + return word; + } //box + asm ("rorl %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); - return word; + return word; } /******************************************************************************/ -- cgit v1.2.3-55-g6feb From b5bf1913d31512d1c5f4c9656dc96e6b8dcd92ba Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 16:12:17 +0100 Subject: tls: send EMPTY_RENEGOTIATION_INFO_SCSV in our client hello Hoped this can make cdn.kernel.org to like us more. Nope. While at it, made error reporting more useful. Signed-off-by: Denys Vlasenko --- networking/tls.c | 112 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 26 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 89f2ec603..4456c7d26 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -22,6 +22,16 @@ #define TLS_DEBUG_HASH 0 #define TLS_DEBUG_DER 0 #define TLS_DEBUG_FIXED_SECRETS 0 +#if 0 +# define dump_raw_out(...) dump_hex(__VA_ARGS__) +#else +# define dump_raw_out(...) ((void)0) +#endif +#if 0 +# define dump_raw_in(...) dump_hex(__VA_ARGS__) +#else +# define dump_raw_in(...) ((void)0) +#endif #if TLS_DEBUG # define dbg(...) fprintf(stderr, __VA_ARGS__) @@ -35,18 +45,6 @@ # define dbg_der(...) ((void)0) #endif -#if 0 -# define dump_raw_out(...) dump_hex(__VA_ARGS__) -#else -# define dump_raw_out(...) ((void)0) -#endif - -#if 0 -# define dump_raw_in(...) dump_hex(__VA_ARGS__) -#else -# define dump_raw_in(...) ((void)0) -#endif - #define RECORD_TYPE_CHANGE_CIPHER_SPEC 20 #define RECORD_TYPE_ALERT 21 #define RECORD_TYPE_HANDSHAKE 22 @@ -154,8 +152,18 @@ // works against "openssl s_server -cipher NULL" // and against wolfssl-3.9.10-stable/examples/server/server.c: //#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) + // works against wolfssl-3.9.10-stable/examples/server/server.c -#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE +// works for kernel.org +// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) +// getting alert 40 "handshake failure" at once +// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA +#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer enum { RSA_PREMASTER_SIZE = 48, @@ -445,6 +453,18 @@ static void prf_hmac_sha256( #undef SEED } +static void bad_record_die(tls_state_t *tls, const char *expected, int len) +{ + bb_error_msg_and_die("got bad TLS record (len:%d) while expecting %s", len, expected); + if (len > 0) { + uint8_t *p = tls->inbuf; + while (len > 0) + fprintf(stderr, " %02x", *p++); + fputc('\n', stderr); + } + xfunc_die(); +} + static void tls_error_die(tls_state_t *tls) { dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); @@ -671,6 +691,18 @@ static int tls_has_buffered_record(tls_state_t *tls) return rec_size; } +static const char *alert_text(int code) +{ + switch (code) { + case 20: return "bad MAC"; + case 50: return "decode error"; + case 51: return "decrypt error"; + case 40: return "handshake failure"; + case 112: return "unrecognized name"; + } + return itoa(code); +} + static int tls_xread_record(tls_state_t *tls) { struct record_hdr *xhdr; @@ -780,16 +812,28 @@ static int tls_xread_record(tls_state_t *tls) if (xhdr->type == RECORD_TYPE_ALERT && sz >= 2) { uint8_t *p = tls->inbuf + RECHDR_LEN; dbg("ALERT size:%d level:%d description:%d\n", sz, p[0], p[1]); + if (p[0] == 2) { /* fatal */ + bb_error_msg_and_die("TLS %s from peer (alert code %d): %s", + "error", + p[1], alert_text(p[1]) + ); + } if (p[0] == 1) { /* warning */ if (p[1] == 0) { /* "close_notify" warning: it's EOF */ dbg("EOF (TLS encoded) from peer\n"); sz = 0; goto end; } +//This possibly needs to be cached and shown only if +//a fatal alert follows +// bb_error_msg("TLS %s from peer (alert code %d): %s", +// "warning", +// p[1], alert_text(p[1]) +// ); /* discard it, get next record */ goto again; } - /* p[0] == 1: fatal error, others: not defined in protocol */ + /* p[0] not 1 or 2: not defined in protocol */ sz = 0; goto end; } @@ -1031,7 +1075,7 @@ static int tls_xread_handshake_block(tls_state_t *tls, int min_len) || xhdr->proto_maj != TLS_MAJ || xhdr->proto_min != TLS_MIN ) { - tls_error_die(tls); + bad_record_die(tls, "handshake record", len); } dbg("got HANDSHAKE\n"); return len; @@ -1051,7 +1095,6 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un h->len24_lo = len & 0xff; } -//TODO: implement RFC 5746 (Renegotiation Indication Extension) - some servers will refuse to work with us otherwise static void send_client_hello(tls_state_t *tls, const char *sni) { struct client_hello { @@ -1062,18 +1105,27 @@ static void send_client_hello(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * 1]; /* actually variable */ + uint8_t cipherid[2 * 2]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): * hi,lo // len of all extensions - * 0x00,0x00 // extension_type: "Server Name" - * 0x00,0x0e // list len (there can be more than one SNI) - * 0x00,0x0c // len of 1st Server Name Indication - * 0x00 // name type: host_name - * 0x00,0x09 // name len + * 00,00 // extension_type: "Server Name" + * 00,0e // list len (there can be more than one SNI) + * 00,0c // len of 1st Server Name Indication + * 00 // name type: host_name + * 00,09 // name len * "localhost" // name */ +// GNU Wget 1.18 to cdn.kernel.org sends these extensions: +// 0055 +// 0005 0005 0100000000 - status_request +// 0000 0013 0011 00 000e 63646e 2e 6b65726e656c 2e 6f7267 - server_name +// ff01 0001 00 - renegotiation_info +// 0023 0000 - session_ticket +// 000a 0008 0006001700180019 - supported_groups +// 000b 0002 0100 - ec_point_formats +// 000d 0016 00140401040305010503060106030301030302010203 - signature_algorithms }; struct client_hello *record; int len; @@ -1084,6 +1136,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni) len += 11 + strlen(sni); record = tls_get_outbuf(tls, len); memset(record, 0, len); + fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len); record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */ record->proto_min = TLS_MIN; /* can be higher than one in record headers */ @@ -1092,10 +1145,16 @@ static void send_client_hello(tls_state_t *tls, const char *sni) memset(record->rand32, 0x11, sizeof(record->rand32)); memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ + /* record->cipherid_len16_hi = 0; */ - record->cipherid_len16_lo = 2 * 1; - record->cipherid[0] = CIPHER_ID >> 8; + record->cipherid_len16_lo = 2 * 2; + if ((CIPHER_ID >> 8) != 0) + record->cipherid[0] = CIPHER_ID >> 8; record->cipherid[1] = CIPHER_ID & 0xff; + /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ + /*record->cipherid[2] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */ + record->cipherid[3] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff; + record->comprtypes_len = 1; /* record->comprtypes[0] = 0; */ @@ -1136,8 +1195,9 @@ static void get_server_hello(tls_state_t *tls) struct server_hello *hp; uint8_t *cipherid; + int len; - tls_xread_handshake_block(tls, 74); + len = tls_xread_handshake_block(tls, 74); hp = (void*)tls->inbuf; // 74 bytes: @@ -1150,7 +1210,7 @@ static void get_server_hello(tls_state_t *tls) || hp->proto_maj != TLS_MAJ || hp->proto_min != TLS_MIN ) { - tls_error_die(tls); + bad_record_die(tls, "'server hello'", len); } cipherid = &hp->cipherid_hi; -- cgit v1.2.3-55-g6feb From 7a18b9502aedbd6a9201c7c7603ded997a401f53 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 16:37:04 +0100 Subject: tls: reorder tls_handshake_data fields for smaller size, tweak comments Signed-off-by: Denys Vlasenko --- networking/tls.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 4456c7d26..8549a21da 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -112,7 +112,7 @@ #define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */ #define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */ -// RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" +/* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */ #define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */ #define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */ #define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */ @@ -125,16 +125,13 @@ #define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ //Tested against kernel.org: -//TLS 1.1 -//#define TLS_MAJ 3 -//#define TLS_MIN 2 -//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE //TLS 1.2 #define TLS_MAJ 3 #define TLS_MIN 3 //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box //#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE -// All GCMs: +//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE +//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it) //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE @@ -145,9 +142,6 @@ //#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE //#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE //#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? -//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE -//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck) -//test TLS_RSA_WITH_AES_128_CBC_SHA, in TLS 1.2 it's mandated to be always supported // works against "openssl s_server -cipher NULL" // and against wolfssl-3.9.10-stable/examples/server/server.c: @@ -163,6 +157,7 @@ // fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA +// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) #define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer enum { @@ -220,14 +215,12 @@ struct record_hdr { }; struct tls_handshake_data { + sha256_ctx_t handshake_sha256_ctx; + uint8_t client_and_server_rand32[2 * 32]; + uint8_t master_secret[48]; //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; -// this is also unused after client key is sent - uint8_t client_and_server_rand32[2 * 32]; -// these two are unused after finished messages are exchanged: - sha256_ctx_t handshake_sha256_ctx; - uint8_t master_secret[48]; }; @@ -612,8 +605,8 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, SHA256_OUTSIZE); // RFC is talking nonsense: - // Padding that is added to force the length of the plaintext to be - // an integral multiple of the block cipher's block length. + // "Padding that is added to force the length of the plaintext to be + // an integral multiple of the block cipher's block length." // WRONG. _padding+padding_length_, not just _padding_, // pads the data. // IOW: padding_length is the last byte of padding[] array, -- cgit v1.2.3-55-g6feb From 11540a8da47318e34267f6ff033825ebabbd9181 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 18:01:48 +0100 Subject: ls: handle all sort options through option_mask32 function old new delta packed_usage 31007 31024 +17 my_stat 318 324 +6 sort_and_display_files 419 420 +1 print_name 216 217 +1 sortcmp 228 216 -12 opt_flags 96 64 -32 ls_main 732 685 -47 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/3 up/down: 25/-91) Total: -66 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 113 +++++++++++++++++++++------------------------------------ 1 file changed, 42 insertions(+), 71 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index b48df8bf5..eb14a34e4 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -137,7 +137,7 @@ //usage: "\n --full-time List full date and time" //usage: )) //usage: IF_FEATURE_HUMAN_READABLE( -//usage: "\n -h List sizes in human readable format (1K 243M 2G)" +//usage: "\n -h Human readable sizes (1K 243M 2G)" //usage: ) //usage: IF_FEATURE_LS_SORTFILES( //usage: IF_LONG_OPTS( @@ -158,7 +158,7 @@ //usage: "\n -Z List security context and permission" //usage: ) //usage: IF_FEATURE_LS_WIDTH( -//usage: "\n -w N Assume the terminal is N columns wide" +//usage: "\n -w N Format N columns wide" //usage: ) //usage: IF_FEATURE_LS_COLOR( //usage: "\n --color[={always,never,auto}] Control coloring" @@ -228,17 +228,6 @@ STYLE_LONG = 2 << 19, /* one record per line, extended info */ STYLE_SINGLE = 3 << 19, /* one record per line */ STYLE_MASK = STYLE_SINGLE, -/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ -SORT_REVERSE = 1 << 23, -SORT_DIRS_FIRST = 1 << 24, - -SORT_NAME = 0, /* sort by file name */ -SORT_SIZE = 1 << 25, /* sort by file size */ -SORT_TIME = 2 << 25, /* sort by {a,m,c}time */ -SORT_VERSION = 3 << 25, /* sort by version */ -SORT_EXT = 4 << 25, /* sort by file name extension */ -SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES, - LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ LIST_DATE_TIME | LIST_SYMLINK, }; @@ -256,12 +245,13 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ /* -T WIDTH Ignored (we don't use tabs on output) */ /* -Z SELinux mandated option, busybox optionally supports */ static const char ls_options[] ALIGN1 = - "Cadi1lgnsxQAk" /* 13 opts, total 13 */ - IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 16 */ - IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 20 */ - IF_FEATURE_LS_FILETYPES("Fp") /* 2, 22 */ - IF_FEATURE_LS_RECURSIVE("R") /* 1, 23 */ - IF_SELINUX("Z") /* 1, 24 */ + "Cadi1lgnsxAk" /* 12 opts, total 12 */ + IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */ + IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */ + IF_SELINUX("Z") /* 1, 16 */ + "Q" /* 1, 17 */ + IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */ + IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */ IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ @@ -277,22 +267,22 @@ enum { //OPT_n = (1 << 7), //OPT_s = (1 << 8), //OPT_x = (1 << 9), - OPT_Q = (1 << 10), - //OPT_A = (1 << 11), - //OPT_k = (1 << 12), + //OPT_A = (1 << 10), + //OPT_k = (1 << 11), - OPTBIT_c = 13, - OPTBIT_t, - OPTBIT_u, - OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, - OPTBIT_X, /* 17 */ - OPTBIT_r, - OPTBIT_v, - OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, - OPTBIT_p, /* 21 */ + OPTBIT_F = 12, + OPTBIT_p, /* 13 */ OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, - OPTBIT_L = OPTBIT_Z + 2 * ENABLE_SELINUX, + OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX, + OPTBIT_c, /* 17 */ + OPTBIT_t, /* 18 */ + OPTBIT_u, /* 19 */ + OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS, + OPTBIT_X, /* 21 */ + OPTBIT_r, /* 22 */ + OPTBIT_v, /* 23 */ + OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES, OPTBIT_H, /* 25 */ OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, @@ -302,6 +292,11 @@ enum { OPTBIT_color, /* 31 */ /* with long opts, we use all 32 bits */ + OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, + OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, + OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE, + OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX, + OPT_Q = (1 << OPTBIT_Q), OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, @@ -309,10 +304,6 @@ enum { OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES, OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES, OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES, - OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, - OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES, - OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE, - OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX, OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, @@ -335,20 +326,8 @@ static const uint32_t opt_flags[] = { LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ LIST_BLOCKS, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ - 0, /* Q (quote filename) - handled via OPT_Q */ DISP_HIDDEN, /* A */ ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ -#if ENABLE_FEATURE_LS_TIMESTAMPS - 0, /* c - handled via OPT_c */ - (ENABLE_FEATURE_LS_SORTFILES * SORT_TIME), /* t */ - 0, /* u - handled via OPT_u */ -#endif -#if ENABLE_FEATURE_LS_SORTFILES - SORT_SIZE, /* S */ - SORT_EXT, /* X */ - SORT_REVERSE, /* r */ - SORT_VERSION, /* v */ -#endif #if ENABLE_FEATURE_LS_FILETYPES LIST_FILETYPE | LIST_CLASSIFY, /* F */ LIST_FILETYPE, /* p */ @@ -930,30 +909,30 @@ static int sortcmp(const void *a, const void *b) { struct dnode *d1 = *(struct dnode **)a; struct dnode *d2 = *(struct dnode **)b; - unsigned sort_opts = G.all_fmt & SORT_MASK; + unsigned opt = option_mask32; off_t dif; - dif = 0; /* assume SORT_NAME */ + dif = 0; /* assume sort by name */ // TODO: use pre-initialized function pointer // instead of branch forest - if (G.all_fmt & SORT_DIRS_FIRST) { + if (opt & OPT_dirs_first) { dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode); if (dif != 0) goto maybe_invert_and_ret; } - if (sort_opts == SORT_SIZE) { + if (opt & OPT_S) { /* sort by size */ dif = (d2->dn_size - d1->dn_size); } else - if (sort_opts == SORT_TIME) { + if (opt & OPT_t) { /* sort by time */ dif = (d2->dn_time - d1->dn_time); } else #if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 - if (sort_opts == SORT_VERSION) { + if (opt & OPT_v) { /* sort by version */ dif = strverscmp(d1->name, d2->name); } else #endif - if (sort_opts == SORT_EXT) { + if (opt & OPT_X) { /* sort by extension */ dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.')); } if (dif == 0) { @@ -962,18 +941,17 @@ static int sortcmp(const void *a, const void *b) dif = strcoll(d1->name, d2->name); else dif = strcmp(d1->name, d2->name); - } - - /* Make dif fit into an int */ - if (sizeof(dif) > sizeof(int)) { - enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) }; - /* shift leaving only "int" worth of bits */ - if (dif != 0) { + } else { + /* Make dif fit into an int */ + if (sizeof(dif) > sizeof(int)) { + enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) }; + /* shift leaving only "int" worth of bits */ + /* (this requires dif != 0, and here it is nonzero) */ dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT); } } maybe_invert_and_ret: - return (G.all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif; + return (opt & OPT_r) ? -(int)dif : (int)dif; } static void dnsort(struct dnode **dn, int size) @@ -1162,9 +1140,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv) init_unicode(); - if (ENABLE_FEATURE_LS_SORTFILES) - G.all_fmt = SORT_NAME; - #if ENABLE_FEATURE_LS_WIDTH /* obtain the terminal width */ G_terminal_width = get_terminal_width(STDIN_FILENO); @@ -1209,14 +1184,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (flags & STYLE_MASK) G.all_fmt &= ~STYLE_MASK; - if (flags & SORT_MASK) - G.all_fmt &= ~SORT_MASK; G.all_fmt |= flags; } } - if (opt & OPT_dirs_first) - G.all_fmt |= SORT_DIRS_FIRST; if (opt & OPT_full_time) G.all_fmt |= LIST_FULLTIME; @@ -1256,7 +1227,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* without -l, bare -c or -u enable sort too */ /* (with -l, bare -c or -u just select which time to show) */ if (opt & (OPT_c|OPT_u)) { - G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_TIME; + option_mask32 |= OPT_t; } } } -- cgit v1.2.3-55-g6feb From f5bd6f631c22530698024afb595418f156e48261 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 18:23:19 +0100 Subject: ls: handle -a and -A through option_mask32 function old new delta ls_main 685 682 -3 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index eb14a34e4..d11019f7d 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -215,8 +215,6 @@ LIST_MASK = (LIST_CLASSIFY << 1) - 1, /* what files will be displayed */ DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */ -DISP_HIDDEN = 1 << 14, /* show filenames starting with . */ -DISP_DOT = 1 << 15, /* show . and .. */ DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */ DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */ DISP_ROWS = 1 << 18, /* print across rows */ @@ -258,7 +256,7 @@ static const char ls_options[] ALIGN1 = ; enum { //OPT_C = (1 << 0), - //OPT_a = (1 << 1), + OPT_a = (1 << 1), //OPT_d = (1 << 2), //OPT_i = (1 << 3), //OPT_1 = (1 << 4), @@ -267,7 +265,7 @@ enum { //OPT_n = (1 << 7), //OPT_s = (1 << 8), //OPT_x = (1 << 9), - //OPT_A = (1 << 10), + OPT_A = (1 << 10), //OPT_k = (1 << 11), OPTBIT_F = 12, @@ -317,7 +315,7 @@ enum { /* TODO: simple toggles may be stored as OPT_xxx bits instead */ static const uint32_t opt_flags[] = { STYLE_COLUMNAR, /* C */ - DISP_HIDDEN | DISP_DOT, /* a */ + 0, /* a */ DISP_NOLIST, /* d */ LIST_INO, /* i */ STYLE_SINGLE, /* 1 */ @@ -326,7 +324,7 @@ static const uint32_t opt_flags[] = { LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ LIST_BLOCKS, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ - DISP_HIDDEN, /* A */ + 0, /* A */ ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ #if ENABLE_FEATURE_LS_FILETYPES LIST_FILETYPE | LIST_CLASSIFY, /* F */ @@ -990,13 +988,13 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) /* are we going to list the file- it may be . or .. or a hidden file */ if (entry->d_name[0] == '.') { - if ((!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2])) - && !(G.all_fmt & DISP_DOT) + if (!(option_mask32 & (OPT_a|OPT_A))) + continue; /* skip all dotfiles if no -a/-A */ + if (!(option_mask32 & OPT_a) + && (!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2])) ) { - continue; + continue; /* if only -A, skip . and .. but show other dotfiles */ } - if (!(G.all_fmt & DISP_HIDDEN)) - continue; } fullname = concat_path_file(path, entry->d_name); cur = my_stat(fullname, bb_basename(fullname), 0); @@ -1220,7 +1218,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */ - G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); + G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME); if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { /* when to sort by time? -t[cu] sorts by time even with -l */ /* (this is achieved by opt_flags[] element for -t) */ -- cgit v1.2.3-55-g6feb From b60686cc2a9550527a548f9e52ff4dd96bdfe222 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 18:34:11 +0100 Subject: ls: handle -i through option_mask32 function old new delta sort_and_display_files 420 424 +4 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index d11019f7d..7ed6a1fdc 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -198,7 +198,6 @@ SPLIT_SUBDIR = 2, /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -LIST_INO = 1 << 0, LIST_BLOCKS = 1 << 1, LIST_MODEBITS = 1 << 2, LIST_NLINKS = 1 << 3, @@ -258,7 +257,7 @@ enum { //OPT_C = (1 << 0), OPT_a = (1 << 1), //OPT_d = (1 << 2), - //OPT_i = (1 << 3), + OPT_i = (1 << 3), //OPT_1 = (1 << 4), OPT_l = (1 << 5), OPT_g = (1 << 6), @@ -317,7 +316,7 @@ static const uint32_t opt_flags[] = { STYLE_COLUMNAR, /* C */ 0, /* a */ DISP_NOLIST, /* d */ - LIST_INO, /* i */ + 0, /* i */ STYLE_SINGLE, /* 1 */ LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ @@ -557,7 +556,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) if (S_ISLNK(dn->dn_mode)) lpath = xmalloc_readlink_or_warn(dn->fullname); - if (G.all_fmt & LIST_INO) + if (option_mask32 & OPT_i) /* list inodes */ column += printf("%7llu ", (long long) dn->dn_ino); //TODO: -h should affect -s too: if (G.all_fmt & LIST_BLOCKS) @@ -707,8 +706,8 @@ static void display_files(struct dnode **dn, unsigned nfiles) } column_width += 2 + IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + ) - ((G.all_fmt & LIST_INO) ? 8 : 0) + - ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ + + ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); ncols = (unsigned)G_terminal_width / column_width; } -- cgit v1.2.3-55-g6feb From 5d43ddc59bf62d03cfc0017f24e36533294c455e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 18:43:43 +0100 Subject: ls: handle -s through option_mask32 function old new delta scan_and_display_dirs_recur 493 494 +1 sort_and_display_files 424 423 -1 ls_main 682 677 -5 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 7ed6a1fdc..b138520b3 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -198,7 +198,6 @@ SPLIT_SUBDIR = 2, /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -LIST_BLOCKS = 1 << 1, LIST_MODEBITS = 1 << 2, LIST_NLINKS = 1 << 3, LIST_ID_NAME = 1 << 4, @@ -210,23 +209,21 @@ LIST_FULLTIME = 1 << 9, LIST_SYMLINK = 1 << 10, LIST_FILETYPE = 1 << 11, /* show / suffix for dirs */ LIST_CLASSIFY = 1 << 12, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ -LIST_MASK = (LIST_CLASSIFY << 1) - 1, + +LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ + LIST_DATE_TIME | LIST_SYMLINK, /* what files will be displayed */ DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */ DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */ DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */ DISP_ROWS = 1 << 18, /* print across rows */ -DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1), /* what is the overall style of the listing */ STYLE_COLUMNAR = 1 << 19, /* many records per line */ STYLE_LONG = 2 << 19, /* one record per line, extended info */ STYLE_SINGLE = 3 << 19, /* one record per line */ STYLE_MASK = STYLE_SINGLE, - -LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ - LIST_DATE_TIME | LIST_SYMLINK, }; /* -Cadi1l Std options, busybox always supports */ @@ -262,7 +259,7 @@ enum { OPT_l = (1 << 5), OPT_g = (1 << 6), //OPT_n = (1 << 7), - //OPT_s = (1 << 8), + OPT_s = (1 << 8), //OPT_x = (1 << 9), OPT_A = (1 << 10), //OPT_k = (1 << 11), @@ -321,7 +318,7 @@ static const uint32_t opt_flags[] = { LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ - LIST_BLOCKS, /* s */ + 0, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ 0, /* A */ ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ @@ -559,7 +556,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) if (option_mask32 & OPT_i) /* list inodes */ column += printf("%7llu ", (long long) dn->dn_ino); //TODO: -h should affect -s too: - if (G.all_fmt & LIST_BLOCKS) + if (option_mask32 & OPT_s) /* list allocated blocks */ column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); if (G.all_fmt & LIST_MODEBITS) column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); @@ -704,10 +701,11 @@ static void display_files(struct dnode **dn, unsigned nfiles) if (column_width < len) column_width = len; } - column_width += 2 + - IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + ) - ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ - + ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); + column_width += 2 + IF_SELINUX(+ ((G.all_fmt & LIST_CONTEXT) ? 33 : 0)) + + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ + + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ + ; ncols = (unsigned)G_terminal_width / column_width; } @@ -1069,8 +1067,11 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) } subdnp = scan_one_dir((*dn)->fullname, &nfiles); #if ENABLE_DESKTOP - if ((G.all_fmt & STYLE_MASK) == STYLE_LONG || (G.all_fmt & LIST_BLOCKS)) + if ((G.all_fmt & STYLE_MASK) == STYLE_LONG + || (option_mask32 & OPT_s) + ) { printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp)); + } #endif if (nfiles > 0) { /* list all files at this level */ @@ -1247,8 +1248,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) cur = my_stat(*argv, *argv, /* follow links on command line unless -l, -s or -F: */ !((G.all_fmt & STYLE_MASK) == STYLE_LONG - || (G.all_fmt & LIST_BLOCKS) - || (option_mask32 & OPT_F) + || (option_mask32 & (OPT_s|OPT_F)) ) /* ... or if -H: */ || (option_mask32 & OPT_H) -- cgit v1.2.3-55-g6feb From 2c3131d88e438fff3cc578293e82cc5ffd4693d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 19:05:11 +0100 Subject: ls: LIST_NLINKS/SIZE/DATE_TIME/SYMLINK are always the same, merge as LIST_LOPT They are always set and cleared together function old new delta append_char 69 68 -1 display_single 910 908 -2 ls_main 677 664 -13 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-16) Total: -16 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 64 +++++++++++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index b138520b3..b7eded73b 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -198,31 +198,27 @@ SPLIT_SUBDIR = 2, /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -LIST_MODEBITS = 1 << 2, -LIST_NLINKS = 1 << 3, -LIST_ID_NAME = 1 << 4, -LIST_ID_NUMERIC = 1 << 5, -LIST_CONTEXT = 1 << 6, -LIST_SIZE = 1 << 7, -LIST_DATE_TIME = 1 << 8, -LIST_FULLTIME = 1 << 9, -LIST_SYMLINK = 1 << 10, -LIST_FILETYPE = 1 << 11, /* show / suffix for dirs */ -LIST_CLASSIFY = 1 << 12, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ - -LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ - LIST_DATE_TIME | LIST_SYMLINK, +LIST_MODEBITS = 1 << 0, +LIST_LOPT = 1 << 1, /* long listing (-l and equivalents) */ +LIST_ID_NAME = 1 << 2, +LIST_ID_NUMERIC = 1 << 3, +LIST_CONTEXT = 1 << 4, +LIST_FULLTIME = 1 << 5, +LIST_FILETYPE = 1 << 6, /* show / suffix for dirs */ +LIST_CLASSIFY = 1 << 7, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ + +LIST_LONG = LIST_LOPT | LIST_MODEBITS | LIST_ID_NAME, /* what files will be displayed */ -DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */ -DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */ -DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */ -DISP_ROWS = 1 << 18, /* print across rows */ +DISP_DIRNAME = 1 << 8, /* 2 or more items? label directories */ +DISP_NOLIST = 1 << 9, /* show directory as itself, not contents */ +DISP_RECURSIVE = 1 << 10, /* show directory and everything below it */ +DISP_ROWS = 1 << 11, /* print across rows */ /* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 19, /* many records per line */ -STYLE_LONG = 2 << 19, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 19, /* one record per line */ +STYLE_COLUMNAR = 1 << 12, /* many records per line */ +STYLE_LONG = 2 << 12, /* one record per line, extended info */ +STYLE_SINGLE = 3 << 12, /* one record per line */ STYLE_MASK = STYLE_SINGLE, }; @@ -549,18 +545,18 @@ static NOINLINE unsigned display_single(const struct dnode *dn) /* Do readlink early, so that if it fails, error message * does not appear *inside* the "ls -l" line */ lpath = NULL; - if (G.all_fmt & LIST_SYMLINK) + if (G.all_fmt & LIST_LOPT) if (S_ISLNK(dn->dn_mode)) lpath = xmalloc_readlink_or_warn(dn->fullname); - if (option_mask32 & OPT_i) /* list inodes */ + if (option_mask32 & OPT_i) /* show inode# */ column += printf("%7llu ", (long long) dn->dn_ino); //TODO: -h should affect -s too: - if (option_mask32 & OPT_s) /* list allocated blocks */ + if (option_mask32 & OPT_s) /* show allocated blocks */ column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); if (G.all_fmt & LIST_MODEBITS) column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); - if (G.all_fmt & LIST_NLINKS) + if (G.all_fmt & LIST_LOPT) /* long listing: show number of links */ column += printf("%4lu ", (long) dn->dn_nlink); if (G.all_fmt & LIST_ID_NUMERIC) { if (option_mask32 & OPT_g) @@ -582,7 +578,8 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } } #endif - if (G.all_fmt & LIST_SIZE) { + if (G.all_fmt & LIST_LOPT) { + /* long listing: show size */ if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) { column += printf("%4u, %3u ", dn->dn_rdev_maj, @@ -597,23 +594,22 @@ static NOINLINE unsigned display_single(const struct dnode *dn) column += printf("%9"OFF_FMT"u ", dn->dn_size); } } - } #if ENABLE_FEATURE_LS_TIMESTAMPS - if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { - const time_t *ttime = &dn->dn_time; + /* long listing: show {m,c,a}time */ if (G.all_fmt & LIST_FULLTIME) { /* --full-time */ /* coreutils 8.4 ls --full-time prints: * 2009-07-13 17:49:27.000000000 +0200 * we don't show fractional seconds. */ char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")]; - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", localtime(ttime)); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", + localtime(&dn->dn_time)); column += printf("%s ", buf); - } else { /* LIST_DATE_TIME */ + } else { /* ordinary time format */ /* G.current_time_t is ~== time(NULL) */ - char *filetime = ctime(ttime); + char *filetime = ctime(&dn->dn_time); /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ - time_t age = G.current_time_t - *ttime; + time_t age = G.current_time_t - dn->dn_time; if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { /* less than 6 months old */ /* "mmm dd hh:mm " */ @@ -626,8 +622,8 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } column += 13; } - } #endif + } #if ENABLE_SELINUX if (G.all_fmt & LIST_CONTEXT) { column += printf("%-32s ", dn->sid ? dn->sid : "unknown"); -- cgit v1.2.3-55-g6feb From a1cbaca1ba6f4a3ffc7727fcd4c4ebb61c47e1a7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 19:30:14 +0100 Subject: ls: make -Z output compatible with GNU coreutils 8.25 This also makes it clear that LIST_MODEBITS == LIST_LOPT function old new delta ls_main 752 777 +25 display_files 400 399 -1 display_single 1055 1053 -2 my_stat 320 317 -3 packed_usage 32311 32280 -31 .rodata 168895 168864 -31 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/5 up/down: 25/-68) Total: -43 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index b7eded73b..70118b1b2 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -154,7 +154,6 @@ //usage: ) //usage: "\n -r Reverse sort order" //usage: IF_SELINUX( -//usage: "\n -k List security context" //usage: "\n -Z List security context and permission" //usage: ) //usage: IF_FEATURE_LS_WIDTH( @@ -198,16 +197,14 @@ SPLIT_SUBDIR = 2, /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -LIST_MODEBITS = 1 << 0, LIST_LOPT = 1 << 1, /* long listing (-l and equivalents) */ LIST_ID_NAME = 1 << 2, LIST_ID_NUMERIC = 1 << 3, -LIST_CONTEXT = 1 << 4, LIST_FULLTIME = 1 << 5, LIST_FILETYPE = 1 << 6, /* show / suffix for dirs */ LIST_CLASSIFY = 1 << 7, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ -LIST_LONG = LIST_LOPT | LIST_MODEBITS | LIST_ID_NAME, +LIST_LONG = LIST_LOPT | LIST_ID_NAME, /* what files will be displayed */ DISP_DIRNAME = 1 << 8, /* 2 or more items? label directories */ @@ -225,8 +222,8 @@ STYLE_MASK = STYLE_SINGLE, /* -Cadi1l Std options, busybox always supports */ /* -gnsxA Std options, busybox always supports */ /* -Q GNU option, busybox always supports */ -/* -k SELinux option, busybox always supports (ignores if !SELinux) */ -/* Std has -k which means "for -s, show sizes in kbytes" */ +/* -k Std options, busybox always supports (by ignoring) */ +/* It means "for -s, show sizes in kbytes" */ /* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */ /* since otherwise -s shows kbytes anyway */ /* -LHRctur Std options, busybox optionally supports */ @@ -317,7 +314,7 @@ static const uint32_t opt_flags[] = { 0, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ 0, /* A */ - ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ + 0, /* k (ignored) */ #if ENABLE_FEATURE_LS_FILETYPES LIST_FILETYPE | LIST_CLASSIFY, /* F */ LIST_FILETYPE, /* p */ @@ -326,7 +323,7 @@ static const uint32_t opt_flags[] = { DISP_RECURSIVE, /* R */ #endif #if ENABLE_SELINUX - LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */ + 0, /* Z */ #endif (1U << 31) /* options after Z are not processed through opt_flags */ @@ -554,10 +551,12 @@ static NOINLINE unsigned display_single(const struct dnode *dn) //TODO: -h should affect -s too: if (option_mask32 & OPT_s) /* show allocated blocks */ column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); - if (G.all_fmt & LIST_MODEBITS) + if (G.all_fmt & LIST_LOPT) { + /* long listing: show mode */ column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); - if (G.all_fmt & LIST_LOPT) /* long listing: show number of links */ + /* long listing: show number of links */ column += printf("%4lu ", (long) dn->dn_nlink); + } if (G.all_fmt & LIST_ID_NUMERIC) { if (option_mask32 & OPT_g) column += printf("%-8u ", (int) dn->dn_gid); @@ -577,6 +576,12 @@ static NOINLINE unsigned display_single(const struct dnode *dn) get_cached_groupname(dn->dn_gid)); } } +#endif +#if ENABLE_SELINUX + if (option_mask32 & OPT_Z) { + column += printf("%-32s ", dn->sid ? dn->sid : "?"); + freecon(dn->sid); + } #endif if (G.all_fmt & LIST_LOPT) { /* long listing: show size */ @@ -624,12 +629,6 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #endif } -#if ENABLE_SELINUX - if (G.all_fmt & LIST_CONTEXT) { - column += printf("%-32s ", dn->sid ? dn->sid : "unknown"); - freecon(dn->sid); - } -#endif #if ENABLE_FEATURE_LS_COLOR if (G_show_color) { @@ -698,7 +697,7 @@ static void display_files(struct dnode **dn, unsigned nfiles) column_width = len; } column_width += 2 - IF_SELINUX(+ ((G.all_fmt & LIST_CONTEXT) ? 33 : 0)) + + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */ + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ ; @@ -752,7 +751,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f if ((option_mask32 & OPT_L) || force_follow) { #if ENABLE_SELINUX - if (is_selinux_enabled()) { + if (option_mask32 & OPT_Z) { getfilecon(fullname, &cur->sid); } #endif @@ -765,7 +764,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f cur->dn_mode_stat = statbuf.st_mode; } else { #if ENABLE_SELINUX - if (is_selinux_enabled()) { + if (option_mask32 & OPT_Z) { lgetfilecon(fullname, &cur->sid); } #endif @@ -1182,6 +1181,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv) G.all_fmt |= flags; } } +#if ENABLE_SELINUX + if (opt & OPT_Z) { + if (!is_selinux_enabled()) + option_mask32 &= ~OPT_Z; + } +#endif if (opt & OPT_full_time) G.all_fmt |= LIST_FULLTIME; -- cgit v1.2.3-55-g6feb From 51b01fda30418e4114a63be3db8ab0135dea12fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 19:42:12 +0100 Subject: ls: LIST_ID_NAME/ID_NUMERIC/LOPT/LONG are the same, merge as LONG Also, handle -n and --full-time using option_mask32 function old new delta scan_and_display_dirs_recur 548 545 -3 display_single 1053 1039 -14 ls_main 777 736 -41 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-58) Total: -58 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 79 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 70118b1b2..77fc530d8 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -197,32 +197,27 @@ SPLIT_SUBDIR = 2, /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -LIST_LOPT = 1 << 1, /* long listing (-l and equivalents) */ -LIST_ID_NAME = 1 << 2, -LIST_ID_NUMERIC = 1 << 3, -LIST_FULLTIME = 1 << 5, -LIST_FILETYPE = 1 << 6, /* show / suffix for dirs */ -LIST_CLASSIFY = 1 << 7, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ - -LIST_LONG = LIST_LOPT | LIST_ID_NAME, +LIST_LONG = 1 << 0, /* long listing (-l and equivalents) */ +LIST_FILETYPE = 1 << 1, /* show / suffix for dirs */ +LIST_CLASSIFY = 1 << 2, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ /* what files will be displayed */ -DISP_DIRNAME = 1 << 8, /* 2 or more items? label directories */ -DISP_NOLIST = 1 << 9, /* show directory as itself, not contents */ -DISP_RECURSIVE = 1 << 10, /* show directory and everything below it */ -DISP_ROWS = 1 << 11, /* print across rows */ +DISP_DIRNAME = 1 << 3, /* 2 or more items? label directories */ +DISP_NOLIST = 1 << 4, /* show directory as itself, not contents */ +DISP_RECURSIVE = 1 << 5, /* show directory and everything below it */ +DISP_ROWS = 1 << 6, /* print across rows */ /* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 12, /* many records per line */ -STYLE_LONG = 2 << 12, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 12, /* one record per line */ +STYLE_COLUMNAR = 1 << 7, /* many records per line */ +STYLE_LONG = 2 << 8, /* one record per line, extended info */ +STYLE_SINGLE = 3 << 9, /* one record per line */ STYLE_MASK = STYLE_SINGLE, }; /* -Cadi1l Std options, busybox always supports */ /* -gnsxA Std options, busybox always supports */ /* -Q GNU option, busybox always supports */ -/* -k Std options, busybox always supports (by ignoring) */ +/* -k Std option, busybox always supports (by ignoring) */ /* It means "for -s, show sizes in kbytes" */ /* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */ /* since otherwise -s shows kbytes anyway */ @@ -251,7 +246,7 @@ enum { //OPT_1 = (1 << 4), OPT_l = (1 << 5), OPT_g = (1 << 6), - //OPT_n = (1 << 7), + OPT_n = (1 << 7), OPT_s = (1 << 8), //OPT_x = (1 << 9), OPT_A = (1 << 10), @@ -310,7 +305,7 @@ static const uint32_t opt_flags[] = { STYLE_SINGLE, /* 1 */ LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ - LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ + LIST_LONG | STYLE_LONG, /* n (numeris uid/gid) - handled via OPT_n. assumes l */ 0, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ 0, /* A */ @@ -542,7 +537,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) /* Do readlink early, so that if it fails, error message * does not appear *inside* the "ls -l" line */ lpath = NULL; - if (G.all_fmt & LIST_LOPT) + if (G.all_fmt & LIST_LONG) if (S_ISLNK(dn->dn_mode)) lpath = xmalloc_readlink_or_warn(dn->fullname); @@ -551,39 +546,40 @@ static NOINLINE unsigned display_single(const struct dnode *dn) //TODO: -h should affect -s too: if (option_mask32 & OPT_s) /* show allocated blocks */ column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); - if (G.all_fmt & LIST_LOPT) { + if (G.all_fmt & LIST_LONG) { /* long listing: show mode */ column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); /* long listing: show number of links */ column += printf("%4lu ", (long) dn->dn_nlink); - } - if (G.all_fmt & LIST_ID_NUMERIC) { - if (option_mask32 & OPT_g) - column += printf("%-8u ", (int) dn->dn_gid); - else - column += printf("%-8u %-8u ", - (int) dn->dn_uid, - (int) dn->dn_gid); - } + /* long listing: show user/group */ + if (option_mask32 & OPT_n) { + if (option_mask32 & OPT_g) + column += printf("%-8u ", (int) dn->dn_gid); + else + column += printf("%-8u %-8u ", + (int) dn->dn_uid, + (int) dn->dn_gid); + } #if ENABLE_FEATURE_LS_USERNAME - else if (G.all_fmt & LIST_ID_NAME) { - if (option_mask32 & OPT_g) { - column += printf("%-8.8s ", - get_cached_groupname(dn->dn_gid)); - } else { - column += printf("%-8.8s %-8.8s ", - get_cached_username(dn->dn_uid), - get_cached_groupname(dn->dn_gid)); + else { + if (option_mask32 & OPT_g) { + column += printf("%-8.8s ", + get_cached_groupname(dn->dn_gid)); + } else { + column += printf("%-8.8s %-8.8s ", + get_cached_username(dn->dn_uid), + get_cached_groupname(dn->dn_gid)); + } } - } #endif #if ENABLE_SELINUX + } if (option_mask32 & OPT_Z) { column += printf("%-32s ", dn->sid ? dn->sid : "?"); freecon(dn->sid); } + if (G.all_fmt & LIST_LONG) { #endif - if (G.all_fmt & LIST_LOPT) { /* long listing: show size */ if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) { column += printf("%4u, %3u ", @@ -601,7 +597,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #if ENABLE_FEATURE_LS_TIMESTAMPS /* long listing: show {m,c,a}time */ - if (G.all_fmt & LIST_FULLTIME) { /* --full-time */ + if (option_mask32 & OPT_full_time) { /* --full-time */ /* coreutils 8.4 ls --full-time prints: * 2009-07-13 17:49:27.000000000 +0200 * we don't show fractional seconds. @@ -1187,8 +1183,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv) option_mask32 &= ~OPT_Z; } #endif - if (opt & OPT_full_time) - G.all_fmt |= LIST_FULLTIME; #if ENABLE_FEATURE_LS_COLOR /* set G_show_color = 1/0 */ @@ -1219,7 +1213,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */ - G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME); if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { /* when to sort by time? -t[cu] sorts by time even with -l */ /* (this is achieved by opt_flags[] element for -t) */ -- cgit v1.2.3-55-g6feb From 96d9c5bdbd5829decd478231846baaad8dd55426 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 19:56:13 +0100 Subject: ls: handle -p and -F through option_mask32 function old new delta display_single 1039 1044 +5 append_char 67 68 +1 display_files 399 396 -3 scan_and_display_dirs_recur 545 541 -4 ls_main 736 722 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/3 up/down: 6/-21) Total: -15 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 77fc530d8..c62e84263 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -194,23 +194,18 @@ SPLIT_DIR = 1, SPLIT_SUBDIR = 2, /* Bits in G.all_fmt: */ - -/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ -/* what file information will be listed */ LIST_LONG = 1 << 0, /* long listing (-l and equivalents) */ -LIST_FILETYPE = 1 << 1, /* show / suffix for dirs */ -LIST_CLASSIFY = 1 << 2, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */ /* what files will be displayed */ -DISP_DIRNAME = 1 << 3, /* 2 or more items? label directories */ -DISP_NOLIST = 1 << 4, /* show directory as itself, not contents */ -DISP_RECURSIVE = 1 << 5, /* show directory and everything below it */ -DISP_ROWS = 1 << 6, /* print across rows */ +DISP_DIRNAME = 1 << 1, /* 2 or more items? label directories */ +DISP_NOLIST = 1 << 2, /* show directory as itself, not contents */ +DISP_RECURSIVE = 1 << 3, /* show directory and everything below it */ +DISP_ROWS = 1 << 4, /* print across rows */ /* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 7, /* many records per line */ -STYLE_LONG = 2 << 8, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 9, /* one record per line */ +STYLE_COLUMNAR = 1 << 5, /* many records per line */ +STYLE_LONG = 2 << 5, /* one record per line, extended info */ +STYLE_SINGLE = 3 << 5, /* one record per line */ STYLE_MASK = STYLE_SINGLE, }; @@ -311,8 +306,8 @@ static const uint32_t opt_flags[] = { 0, /* A */ 0, /* k (ignored) */ #if ENABLE_FEATURE_LS_FILETYPES - LIST_FILETYPE | LIST_CLASSIFY, /* F */ - LIST_FILETYPE, /* p */ + 0, /* F */ + 0, /* p */ #endif #if ENABLE_FEATURE_LS_RECURSIVE DISP_RECURSIVE, /* R */ @@ -449,11 +444,12 @@ static char bold(mode_t mode) #if ENABLE_FEATURE_LS_FILETYPES static char append_char(mode_t mode) { - if (!(G.all_fmt & LIST_FILETYPE)) + if (!(option_mask32 & (OPT_F|OPT_p))) return '\0'; + if (S_ISDIR(mode)) return '/'; - if (!(G.all_fmt & LIST_CLASSIFY)) + if (!(option_mask32 & OPT_F)) return '\0'; if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*'; @@ -643,7 +639,9 @@ static NOINLINE unsigned display_single(const struct dnode *dn) if (lpath) { printf(" -> "); #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR - if ((G.all_fmt & LIST_FILETYPE) || G_show_color) { + if ((option_mask32 & (OPT_F|OPT_p)) + || G_show_color + ) { mode_t mode = dn->dn_mode_stat; if (!mode) if (stat(dn->fullname, &statbuf) == 0) @@ -665,7 +663,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } } #if ENABLE_FEATURE_LS_FILETYPES - if (G.all_fmt & LIST_FILETYPE) { + if (option_mask32 & (OPT_F|OPT_p)) { if (append) { putchar(append); column++; -- cgit v1.2.3-55-g6feb From 4cde4cca65c80106bdd97a7e532f3b80cf25fae5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 20:08:22 +0100 Subject: ls: handle -d and -R through option_mask32 function old new delta scan_and_display_dirs_recur 545 550 +5 display_single 1039 1044 +5 append_char 67 68 +1 display_files 399 396 -3 ls_main 736 717 -19 opt_flags 68 11 -57 .rodata 168864 168784 -80 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/4 up/down: 11/-159) Total: -148 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index c62e84263..3052fda32 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -198,14 +198,12 @@ LIST_LONG = 1 << 0, /* long listing (-l and equivalents) */ /* what files will be displayed */ DISP_DIRNAME = 1 << 1, /* 2 or more items? label directories */ -DISP_NOLIST = 1 << 2, /* show directory as itself, not contents */ -DISP_RECURSIVE = 1 << 3, /* show directory and everything below it */ -DISP_ROWS = 1 << 4, /* print across rows */ +DISP_ROWS = 1 << 2, /* print across rows */ /* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 5, /* many records per line */ -STYLE_LONG = 2 << 5, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 5, /* one record per line */ +STYLE_COLUMNAR = 1 << 3, /* many records per line */ +STYLE_LONG = 2 << 3, /* one record per line, extended info */ +STYLE_SINGLE = 3 << 3, /* one record per line */ STYLE_MASK = STYLE_SINGLE, }; @@ -236,7 +234,7 @@ static const char ls_options[] ALIGN1 = enum { //OPT_C = (1 << 0), OPT_a = (1 << 1), - //OPT_d = (1 << 2), + OPT_d = (1 << 2), OPT_i = (1 << 3), //OPT_1 = (1 << 4), OPT_l = (1 << 5), @@ -292,10 +290,10 @@ enum { }; /* TODO: simple toggles may be stored as OPT_xxx bits instead */ -static const uint32_t opt_flags[] = { +static const uint8_t opt_flags[] = { STYLE_COLUMNAR, /* C */ 0, /* a */ - DISP_NOLIST, /* d */ + 0, /* d */ 0, /* i */ STYLE_SINGLE, /* 1 */ LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ @@ -303,20 +301,8 @@ static const uint32_t opt_flags[] = { LIST_LONG | STYLE_LONG, /* n (numeris uid/gid) - handled via OPT_n. assumes l */ 0, /* s */ DISP_ROWS | STYLE_COLUMNAR, /* x */ - 0, /* A */ - 0, /* k (ignored) */ -#if ENABLE_FEATURE_LS_FILETYPES - 0, /* F */ - 0, /* p */ -#endif -#if ENABLE_FEATURE_LS_RECURSIVE - DISP_RECURSIVE, /* R */ -#endif -#if ENABLE_SELINUX - 0, /* Z */ -#endif - (1U << 31) - /* options after Z are not processed through opt_flags */ + 0xff + /* options after -x are not processed through opt_flags */ }; @@ -1048,7 +1034,9 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) struct dnode **subdnp; for (; *dn; dn++) { - if (G.all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { + if ((G.all_fmt & DISP_DIRNAME) + || (option_mask32 & OPT_R) + ) { if (!first) bb_putchar('\n'); first = 0; @@ -1067,7 +1055,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) sort_and_display_files(subdnp, nfiles); if (ENABLE_FEATURE_LS_RECURSIVE - && (G.all_fmt & DISP_RECURSIVE) + && (option_mask32 & OPT_R) ) { struct dnode **dnd; unsigned dndirs; @@ -1165,7 +1153,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_full_time ) bb_error_msg("--full-time"); exit(0); #endif - for (i = 0; opt_flags[i] != (1U << 31); i++) { + for (i = 0; opt_flags[i] != 0xff; i++) { if (opt & (1 << i)) { uint32_t flags = opt_flags[i]; @@ -1208,8 +1196,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv) #endif /* sort out which command line options take precedence */ - if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) - G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ + if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d)) + option_mask32 &= ~OPT_R; /* no recurse if listing only dir */ if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */ if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { /* when to sort by time? -t[cu] sorts by time even with -l */ @@ -1270,7 +1258,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) break; } - if (G.all_fmt & DISP_NOLIST) { + if (option_mask32 & OPT_d) { sort_and_display_files(dnp, nfiles); } else { dnd = splitdnarray(dnp, SPLIT_DIR); -- cgit v1.2.3-55-g6feb From 92c6898e10bde9889aa61e1a4f7253245b8f592e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 20:21:14 +0100 Subject: ls: handle -x through option_mask32, remove default -C from --help function old new delta packed_usage 31024 31002 -22 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 3052fda32..ac142c36b 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -111,7 +111,7 @@ //usage: "\n -1 One column output" //usage: "\n -a Include entries which start with ." //usage: "\n -A Like -a, but exclude . and .." -//usage: "\n -C List by columns" +////usage: "\n -C List by columns" - don't show, this is a default anyway //usage: "\n -x List by lines" //usage: "\n -d List directory entries instead of contents" //usage: IF_FEATURE_LS_FOLLOWLINKS( @@ -198,12 +198,11 @@ LIST_LONG = 1 << 0, /* long listing (-l and equivalents) */ /* what files will be displayed */ DISP_DIRNAME = 1 << 1, /* 2 or more items? label directories */ -DISP_ROWS = 1 << 2, /* print across rows */ /* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 3, /* many records per line */ -STYLE_LONG = 2 << 3, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 3, /* one record per line */ +STYLE_COLUMNAR = 1 << 2, /* many records per line */ +STYLE_LONG = 2 << 2, /* one record per line, extended info */ +STYLE_SINGLE = 3 << 2, /* one record per line */ STYLE_MASK = STYLE_SINGLE, }; @@ -241,7 +240,7 @@ enum { OPT_g = (1 << 6), OPT_n = (1 << 7), OPT_s = (1 << 8), - //OPT_x = (1 << 9), + OPT_x = (1 << 9), OPT_A = (1 << 10), //OPT_k = (1 << 11), @@ -300,7 +299,7 @@ static const uint8_t opt_flags[] = { LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ LIST_LONG | STYLE_LONG, /* n (numeris uid/gid) - handled via OPT_n. assumes l */ 0, /* s */ - DISP_ROWS | STYLE_COLUMNAR, /* x */ + STYLE_COLUMNAR, /* x */ 0xff /* options after -x are not processed through opt_flags */ }; @@ -698,7 +697,7 @@ static void display_files(struct dnode **dn, unsigned nfiles) for (row = 0; row < nrows; row++) { for (nc = 0; nc < ncols; nc++) { /* reach into the array based on the column and row */ - if (G.all_fmt & DISP_ROWS) + if (option_mask32 & OPT_x) i = (row * ncols) + nc; /* display across row */ else i = (nc * nrows) + row; /* display by column */ -- cgit v1.2.3-55-g6feb From ccc1699e3ec5ae0ec43a24fcad58c110f6f8360c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 20:43:06 +0100 Subject: ls: get rid of opt_flags[], handle -l1c through option_mask32 function old new delta display_single 885 888 +3 scan_and_display_dirs_recur 496 486 -10 opt_flags 11 - -11 ls_main 618 553 -65 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/2 up/down: 3/-86) Total: -83 bytes Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 100 +++++++++++++++++++-------------------------------------- 1 file changed, 33 insertions(+), 67 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index ac142c36b..f90784a1a 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -194,16 +194,8 @@ SPLIT_DIR = 1, SPLIT_SUBDIR = 2, /* Bits in G.all_fmt: */ -LIST_LONG = 1 << 0, /* long listing (-l and equivalents) */ - /* what files will be displayed */ -DISP_DIRNAME = 1 << 1, /* 2 or more items? label directories */ - -/* what is the overall style of the listing */ -STYLE_COLUMNAR = 1 << 2, /* many records per line */ -STYLE_LONG = 2 << 2, /* one record per line, extended info */ -STYLE_SINGLE = 3 << 2, /* one record per line */ -STYLE_MASK = STYLE_SINGLE, +DISP_DIRNAME = 1 << 9, /* 2 or more items? label directories */ }; /* -Cadi1l Std options, busybox always supports */ @@ -231,11 +223,11 @@ static const char ls_options[] ALIGN1 = IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ ; enum { - //OPT_C = (1 << 0), + OPT_C = (1 << 0), OPT_a = (1 << 1), OPT_d = (1 << 2), OPT_i = (1 << 3), - //OPT_1 = (1 << 4), + OPT_1 = (1 << 4), OPT_l = (1 << 5), OPT_g = (1 << 6), OPT_n = (1 << 7), @@ -288,23 +280,6 @@ enum { OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR, }; -/* TODO: simple toggles may be stored as OPT_xxx bits instead */ -static const uint8_t opt_flags[] = { - STYLE_COLUMNAR, /* C */ - 0, /* a */ - 0, /* d */ - 0, /* i */ - STYLE_SINGLE, /* 1 */ - LIST_LONG | STYLE_LONG, /* l - by keeping it after -1, "ls -l -1" ignores -1 */ - LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */ - LIST_LONG | STYLE_LONG, /* n (numeris uid/gid) - handled via OPT_n. assumes l */ - 0, /* s */ - STYLE_COLUMNAR, /* x */ - 0xff - /* options after -x are not processed through opt_flags */ -}; - - /* * a directory entry and its stat info */ @@ -465,8 +440,8 @@ static unsigned calc_name_len(const char *name) } /* Return the number of used columns. - * Note that only STYLE_COLUMNAR uses return value. - * STYLE_SINGLE and STYLE_LONG don't care. + * Note that only columnar output uses return value. + * -l and -1 modes don't care. * coreutils 7.2 also supports: * ls -b (--escape) = octal escapes (although it doesn't look like working) * ls -N (--literal) = not escape at all @@ -499,13 +474,14 @@ static unsigned print_name(const char *name) } /* Return the number of used columns. - * Note that only STYLE_COLUMNAR uses return value, - * STYLE_SINGLE and STYLE_LONG don't care. + * Note that only columnar output uses return value, + * -l and -1 modes don't care. */ static NOINLINE unsigned display_single(const struct dnode *dn) { unsigned column = 0; char *lpath; + int opt; #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR struct stat statbuf; char append; @@ -514,27 +490,28 @@ static NOINLINE unsigned display_single(const struct dnode *dn) #if ENABLE_FEATURE_LS_FILETYPES append = append_char(dn->dn_mode); #endif + opt = option_mask32; /* Do readlink early, so that if it fails, error message * does not appear *inside* the "ls -l" line */ lpath = NULL; - if (G.all_fmt & LIST_LONG) + if (opt & OPT_l) if (S_ISLNK(dn->dn_mode)) lpath = xmalloc_readlink_or_warn(dn->fullname); - if (option_mask32 & OPT_i) /* show inode# */ + if (opt & OPT_i) /* show inode# */ column += printf("%7llu ", (long long) dn->dn_ino); //TODO: -h should affect -s too: - if (option_mask32 & OPT_s) /* show allocated blocks */ + if (opt & OPT_s) /* show allocated blocks */ column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); - if (G.all_fmt & LIST_LONG) { + if (opt & OPT_l) { /* long listing: show mode */ column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); /* long listing: show number of links */ column += printf("%4lu ", (long) dn->dn_nlink); /* long listing: show user/group */ - if (option_mask32 & OPT_n) { - if (option_mask32 & OPT_g) + if (opt & OPT_n) { + if (opt & OPT_g) column += printf("%-8u ", (int) dn->dn_gid); else column += printf("%-8u %-8u ", @@ -543,7 +520,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #if ENABLE_FEATURE_LS_USERNAME else { - if (option_mask32 & OPT_g) { + if (opt & OPT_g) { column += printf("%-8.8s ", get_cached_groupname(dn->dn_gid)); } else { @@ -555,11 +532,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn) #endif #if ENABLE_SELINUX } - if (option_mask32 & OPT_Z) { + if (opt & OPT_Z) { column += printf("%-32s ", dn->sid ? dn->sid : "?"); freecon(dn->sid); } - if (G.all_fmt & LIST_LONG) { + if (opt & OPT_l) { #endif /* long listing: show size */ if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) { @@ -567,7 +544,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) dn->dn_rdev_maj, dn->dn_rdev_min); } else { - if (option_mask32 & OPT_h) { + if (opt & OPT_h) { column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", /* print size, show one fractional, use suffixes */ make_human_readable_str(dn->dn_size, 1, 0) @@ -578,7 +555,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } #if ENABLE_FEATURE_LS_TIMESTAMPS /* long listing: show {m,c,a}time */ - if (option_mask32 & OPT_full_time) { /* --full-time */ + if (opt & OPT_full_time) { /* --full-time */ /* coreutils 8.4 ls --full-time prints: * 2009-07-13 17:49:27.000000000 +0200 * we don't show fractional seconds. @@ -624,7 +601,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) if (lpath) { printf(" -> "); #if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR - if ((option_mask32 & (OPT_F|OPT_p)) + if ((opt & (OPT_F|OPT_p)) || G_show_color ) { mode_t mode = dn->dn_mode_stat; @@ -648,7 +625,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } } #if ENABLE_FEATURE_LS_FILETYPES - if (option_mask32 & (OPT_F|OPT_p)) { + if (opt & (OPT_F|OPT_p)) { if (append) { putchar(append); column++; @@ -664,9 +641,9 @@ static void display_files(struct dnode **dn, unsigned nfiles) unsigned i, ncols, nrows, row, nc; unsigned column; unsigned nexttab; - unsigned column_width = 0; /* used only by STYLE_COLUMNAR */ + unsigned column_width = 0; /* used only by coulmnal output */ - if (G.all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */ + if (option_mask32 & (OPT_l|OPT_1)) { ncols = 1; } else { /* find the longest file name, use that as the column width */ @@ -1043,9 +1020,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) } subdnp = scan_one_dir((*dn)->fullname, &nfiles); #if ENABLE_DESKTOP - if ((G.all_fmt & STYLE_MASK) == STYLE_LONG - || (option_mask32 & OPT_s) - ) { + if (option_mask32 & (OPT_s|OPT_l)) { printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp)); } #endif @@ -1124,8 +1099,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* process options */ IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) opt_complementary = + /* -n and -g imply -l */ + "nl:gl" /* --full-time implies -l */ - IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xff""l")) + IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(":\xff""l")) /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: * in some pairs of opts, only last one takes effect: */ @@ -1139,7 +1116,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* -w NUM: */ IF_FEATURE_LS_WIDTH(":w+"); opt = getopt32(argv, ls_options - IF_FEATURE_LS_WIDTH(, NULL, &G_terminal_width) + IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width) IF_FEATURE_LS_COLOR(, &color_opt) ); #if 0 /* option bits debug */ @@ -1152,16 +1129,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_full_time ) bb_error_msg("--full-time"); exit(0); #endif - for (i = 0; opt_flags[i] != 0xff; i++) { - if (opt & (1 << i)) { - uint32_t flags = opt_flags[i]; - - if (flags & STYLE_MASK) - G.all_fmt &= ~STYLE_MASK; - G.all_fmt |= flags; - } - } #if ENABLE_SELINUX if (opt & OPT_Z) { if (!is_selinux_enabled()) @@ -1197,7 +1165,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) /* sort out which command line options take precedence */ if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d)) option_mask32 &= ~OPT_R; /* no recurse if listing only dir */ - if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */ + if (!(opt & OPT_l)) { /* not -l? */ if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { /* when to sort by time? -t[cu] sorts by time even with -l */ /* (this is achieved by opt_flags[] element for -t) */ @@ -1210,8 +1178,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv) } /* choose a display format if one was not already specified by an option */ - if (!(G.all_fmt & STYLE_MASK)) - G.all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNAR : STYLE_SINGLE); + if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C))) + option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1); argv += optind; if (!argv[0]) @@ -1226,9 +1194,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) do { cur = my_stat(*argv, *argv, /* follow links on command line unless -l, -s or -F: */ - !((G.all_fmt & STYLE_MASK) == STYLE_LONG - || (option_mask32 & (OPT_s|OPT_F)) - ) + !(option_mask32 & (OPT_l|OPT_s|OPT_F)) /* ... or if -H: */ || (option_mask32 & OPT_H) /* ... or if -L, but my_stat always follows links if -L */ -- cgit v1.2.3-55-g6feb From 9a64c3337cc0a5e84e9ad457eeb1d475c311e9fc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Jan 2017 20:46:12 +0100 Subject: ls: convert DISP_DIRNAME to a bool variable function old new delta ls_main 553 548 -5 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index f90784a1a..a858a3217 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -192,10 +192,6 @@ TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ SPLIT_FILE = 0, SPLIT_DIR = 1, SPLIT_SUBDIR = 2, - -/* Bits in G.all_fmt: */ -/* what files will be displayed */ -DISP_DIRNAME = 1 << 9, /* 2 or more items? label directories */ }; /* -Cadi1l Std options, busybox always supports */ @@ -330,7 +326,7 @@ struct globals { # define G_show_color 0 #endif smallint exit_code; - unsigned all_fmt; + smallint show_dirname; #if ENABLE_FEATURE_LS_WIDTH unsigned terminal_width; # define G_terminal_width (G.terminal_width) @@ -1010,9 +1006,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) struct dnode **subdnp; for (; *dn; dn++) { - if ((G.all_fmt & DISP_DIRNAME) - || (option_mask32 & OPT_R) - ) { + if (G.show_dirname || (option_mask32 & OPT_R)) { if (!first) bb_putchar('\n'); first = 0; @@ -1186,7 +1180,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv) *--argv = (char*)"."; if (argv[1]) - G.all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ + G.show_dirname = 1; /* 2 or more items? label directories */ /* stuff the command line file names into a dnode array */ dn = NULL; -- cgit v1.2.3-55-g6feb From 49ecee098d062b92fcf095e05e15779c32899646 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 16:00:54 +0100 Subject: tls: add 2nd cipher_id, TLS_RSA_WITH_AES_128_CBC_SHA, so far it doesn't work Good news that TLS_RSA_WITH_AES_256_CBC_SHA256 still works with new code ;) This change adds inevitable extension to have different sized hashes and AES key sizes. In libbb, md5_end() and shaX_end() are extended to return result size instead of void - this helps *a lot* in tls (the cost is ~5 bytes per _end() function). Signed-off-by: Denys Vlasenko --- coreutils/md5_sha1_sum.c | 2 +- include/libbb.h | 42 +++-- libbb/hash_md5_sha.c | 15 +- libbb/hash_md5prime.c | 3 +- libbb/pw_encrypt_sha.c | 3 +- networking/tls.c | 413 ++++++++++++++++++++++++++++------------------- 6 files changed, 288 insertions(+), 190 deletions(-) diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c index 76788554c..50111bd26 100644 --- a/coreutils/md5_sha1_sum.c +++ b/coreutils/md5_sha1_sum.c @@ -166,7 +166,7 @@ static uint8_t *hash_file(const char *filename, unsigned sha3_width) } context; uint8_t *hash_value; void FAST_FUNC (*update)(void*, const void*, size_t); - void FAST_FUNC (*final)(void*, void*); + unsigned FAST_FUNC (*final)(void*, void*); char hash_algo; src_fd = open_or_warn_stdin(filename); diff --git a/include/libbb.h b/include/libbb.h index ba3b1479e..b1ceb3278 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -713,18 +713,19 @@ struct hostent *xgethostbyname(const char *name) FAST_FUNC; // Also mount.c and inetd.c are using gethostbyname(), // + inet_common.c has additional IPv4-only stuff -#define SHA256_INSIZE 64 -#define SHA256_OUTSIZE 32 -#define AES_BLOCKSIZE 16 -#define AES128_KEYSIZE 16 -#define AES256_KEYSIZE 32 + +#define TLS_MAX_MAC_SIZE 32 +#define TLS_MAX_KEY_SIZE 32 struct tls_handshake_data; /* opaque */ typedef struct tls_state { - int ofd; - int ifd; + int ofd; + int ifd; - int min_encrypted_len_on_read; - uint8_t encrypt_on_write; + int min_encrypted_len_on_read; + uint16_t cipher_id; + uint8_t encrypt_on_write; + unsigned MAC_size; + unsigned key_size; uint8_t *outbuf; int outbuf_size; @@ -746,10 +747,12 @@ typedef struct tls_state { /*uint64_t read_seq64_be;*/ uint64_t write_seq64_be; - uint8_t client_write_MAC_key[SHA256_OUTSIZE]; - uint8_t server_write_MAC_key[SHA256_OUTSIZE]; - uint8_t client_write_key[AES256_KEYSIZE]; - uint8_t server_write_key[AES256_KEYSIZE]; + uint8_t *client_write_key; + uint8_t *server_write_key; + uint8_t client_write_MAC_key[TLS_MAX_MAC_SIZE]; + uint8_t server_write_MAC_k__[TLS_MAX_MAC_SIZE]; + uint8_t client_write_k__[TLS_MAX_KEY_SIZE]; + uint8_t server_write_k__[TLS_MAX_KEY_SIZE]; } tls_state_t; static inline tls_state_t *new_tls_state(void) @@ -760,6 +763,7 @@ static inline tls_state_t *new_tls_state(void) void tls_handshake(tls_state_t *tls, const char *sni) FAST_FUNC; void tls_run_copy_loop(tls_state_t *tls) FAST_FUNC; + void socket_want_pktinfo(int fd) FAST_FUNC; ssize_t send_to_from(int fd, void *buf, size_t len, int flags, const struct sockaddr *to, @@ -1799,19 +1803,23 @@ typedef struct sha3_ctx_t { } sha3_ctx_t; void md5_begin(md5_ctx_t *ctx) FAST_FUNC; void md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; -void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; +unsigned md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; #define sha1_hash md5_hash -void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; +unsigned sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC; #define sha256_hash md5_hash #define sha256_end sha1_end void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC; void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; -void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; +unsigned sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC; void sha3_begin(sha3_ctx_t *ctx) FAST_FUNC; void sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC; -void sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC; +unsigned sha3_end(sha3_ctx_t *ctx, void *resbuf) FAST_FUNC; +/* TLS benefits from knowing that sha1 and sha256 share these. Give them "agnostic" names too */ +typedef struct md5_ctx_t md5sha_ctx_t; +#define md5sha_hash md5_hash +#define sha_end sha1_end extern uint32_t *global_crc32_table; uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index d325584d7..2a7247430 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -458,7 +458,7 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) * endian byte order, so that a byte-wise output yields to the wanted * ASCII representation of the message digest. */ -void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) +unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) { /* MD5 stores total in LE, need to swap on BE arches: */ common64_end(ctx, /*swap_needed:*/ BB_BIG_ENDIAN); @@ -472,6 +472,7 @@ void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf) } memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4); + return sizeof(ctx->hash[0]) * 4; } @@ -865,7 +866,7 @@ void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) #endif /* NEED_SHA512 */ /* Used also for sha256 */ -void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) +unsigned FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) { unsigned hash_size; @@ -879,11 +880,13 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf) for (i = 0; i < hash_size; ++i) ctx->hash[i] = SWAP_BE32(ctx->hash[i]); } - memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size); + hash_size *= sizeof(ctx->hash[0]); + memcpy(resbuf, ctx->hash, hash_size); + return hash_size; } #if NEED_SHA512 -void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) +unsigned FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) { unsigned bufpos = ctx->total64[0] & 127; @@ -915,6 +918,7 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) ctx->hash[i] = SWAP_BE64(ctx->hash[i]); } memcpy(resbuf, ctx->hash, sizeof(ctx->hash)); + return sizeof(ctx->hash); } #endif /* NEED_SHA512 */ @@ -1450,7 +1454,7 @@ void FAST_FUNC sha3_hash(sha3_ctx_t *ctx, const void *buffer, size_t len) #endif } -void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) +unsigned FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) { /* Padding */ uint8_t *buf = (uint8_t*)ctx->state; @@ -1475,4 +1479,5 @@ void FAST_FUNC sha3_end(sha3_ctx_t *ctx, void *resbuf) /* Output */ memcpy(resbuf, ctx->state, 64); + return 64; } diff --git a/libbb/hash_md5prime.c b/libbb/hash_md5prime.c index e089a15f5..4b58d37ff 100644 --- a/libbb/hash_md5prime.c +++ b/libbb/hash_md5prime.c @@ -437,7 +437,7 @@ void FAST_FUNC md5_hash(const void *buffer, size_t inputLen, md5_ctx_t *context) * MD5 finalization. Ends an MD5 message-digest operation, * writing the message digest. */ -void FAST_FUNC md5_end(void *digest, md5_ctx_t *context) +unsigned FAST_FUNC md5_end(void *digest, md5_ctx_t *context) { unsigned idx, padLen; unsigned char bits[8]; @@ -457,4 +457,5 @@ void FAST_FUNC md5_end(void *digest, md5_ctx_t *context) /* Store state in digest */ memcpy32_cpu2le(digest, context->state, 16); + return 16; } diff --git a/libbb/pw_encrypt_sha.c b/libbb/pw_encrypt_sha.c index 72e37e485..5457d7ab6 100644 --- a/libbb/pw_encrypt_sha.c +++ b/libbb/pw_encrypt_sha.c @@ -18,9 +18,10 @@ static char * NOINLINE sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) { +#undef sha_end void (*sha_begin)(void *ctx) FAST_FUNC; void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC; - void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC; + unsigned (*sha_end)(void *ctx, void *resbuf) FAST_FUNC; int _32or64; char *result, *resptr; diff --git a/networking/tls.c b/networking/tls.c index 8549a21da..a65da4ad4 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -18,10 +18,50 @@ #include "tls.h" -#define TLS_DEBUG 0 -#define TLS_DEBUG_HASH 0 -#define TLS_DEBUG_DER 0 -#define TLS_DEBUG_FIXED_SECRETS 0 +//Tested against kernel.org: +//TLS 1.2 +#define TLS_MAJ 3 +#define TLS_MIN 3 +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box +//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE +//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE +//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it) +//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE +//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE +//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE +//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? + +// works against "openssl s_server -cipher NULL" +// and against wolfssl-3.9.10-stable/examples/server/server.c: +//#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) + +// works against wolfssl-3.9.10-stable/examples/server/server.c +// works for kernel.org +// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) +// getting alert 40 "handshake failure" at once +// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384 +// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 +// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA +// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) +#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer +// Does not work yet: +//#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA +#define CIPHER_ID2 0 + + +#define TLS_DEBUG 1 +#define TLS_DEBUG_HASH 1 +#define TLS_DEBUG_DER 1 +#define TLS_DEBUG_FIXED_SECRETS 1 #if 0 # define dump_raw_out(...) dump_hex(__VA_ARGS__) #else @@ -124,52 +164,26 @@ #define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */ #define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */ -//Tested against kernel.org: -//TLS 1.2 -#define TLS_MAJ 3 -#define TLS_MIN 3 -//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box -//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE -//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE -//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it) -//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE -//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE -//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE -//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 -//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE -//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 -//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE -//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE -//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this? +/* Might go to libbb.h */ +#define TLS_MAX_CRYPTBLOCK_SIZE 16 +#define TLS_MAX_OUTBUF (1 << 14) -// works against "openssl s_server -cipher NULL" -// and against wolfssl-3.9.10-stable/examples/server/server.c: -//#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting) +enum { + SHA_INSIZE = 64, + SHA1_OUTSIZE = 20, + SHA256_OUTSIZE = 32, -// works against wolfssl-3.9.10-stable/examples/server/server.c -// works for kernel.org -// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page) -// getting alert 40 "handshake failure" at once -// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256 -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384 -// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256 -// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256 -// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA -// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) -#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer + AES_BLOCKSIZE = 16, + AES128_KEYSIZE = 16, + AES256_KEYSIZE = 32, -enum { RSA_PREMASTER_SIZE = 48, RECHDR_LEN = 5, - MAX_TLS_RECORD = (1 << 14), /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */ OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */ - OUTBUF_SFX = SHA256_OUTSIZE + AES_BLOCKSIZE, /* MAC + padding */ - MAX_OUTBUF = MAX_TLS_RECORD - OUTBUF_PFX - OUTBUF_SFX, + OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */ // RFC 5246 // | 6.2.1. Fragmentation @@ -205,7 +219,7 @@ enum { // | length // | The length (in bytes) of the following TLSCiphertext.fragment. // | The length MUST NOT exceed 2^14 + 2048. - MAX_INBUF = (1 << 14) + 2048, + MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048, }; struct record_hdr { @@ -215,12 +229,17 @@ struct record_hdr { }; struct tls_handshake_data { - sha256_ctx_t handshake_sha256_ctx; + /* In bbox, md5/sha1/sha256 ctx's are the same structure */ + md5sha_ctx_t handshake_hash_ctx; + uint8_t client_and_server_rand32[2 * 32]; uint8_t master_secret[48]; //TODO: store just the DER key here, parse/use/delete it when sending client key //this way it will stay key type agnostic here. psRsaKey_t server_rsa_pub_key; + + unsigned saved_client_hello_size; + uint8_t saved_client_hello[1]; }; @@ -275,37 +294,41 @@ void tls_get_random(void *buf, unsigned len) xfunc_die(); } -//TODO rename this to sha256_hash, and sha256_hash -> sha256_update -static void hash_sha256(uint8_t out[SHA256_OUTSIZE], const void *data, unsigned size) +/* Nondestructively see the current hash value */ +static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer) { - sha256_ctx_t ctx; - sha256_begin(&ctx); - sha256_hash(&ctx, data, size); - sha256_end(&ctx, out); + md5sha_ctx_t ctx_copy = *ctx; /* struct copy */ + return sha_end(&ctx_copy, buffer); } -/* Nondestructively see the current hash value */ -static void sha256_peek(sha256_ctx_t *ctx, void *buffer) +static ALWAYS_INLINE unsigned get_handshake_hash(tls_state_t *tls, void *buffer) { - sha256_ctx_t ctx_copy = *ctx; - sha256_end(&ctx_copy, buffer); + return sha_peek(&tls->hsd->handshake_hash_ctx, buffer); } -#if TLS_DEBUG_HASH -static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buffer, size_t len) +#if !TLS_DEBUG_HASH +# define hash_handshake(tls, fmt, buffer, len) \ + hash_handshake(tls, buffer, len) +#endif +static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer, unsigned len) { - uint8_t h[SHA256_OUTSIZE]; - - sha256_hash(ctx, buffer, len); - dump_hex(fmt, buffer, len); - dbg(" (%u) ", (int)len); - sha256_peek(ctx, h); - dump_hex("%s\n", h, SHA256_OUTSIZE); -} -#else -# define sha256_hash_dbg(fmt, ctx, buffer, len) \ - sha256_hash(ctx, buffer, len) + md5sha_hash(&tls->hsd->handshake_hash_ctx, buffer, len); +#if TLS_DEBUG_HASH + { + uint8_t h[TLS_MAX_MAC_SIZE]; + dump_hex(fmt, buffer, len); + dbg(" (%u bytes) ", (int)len); + len = sha_peek(&tls->hsd->handshake_hash_ctx, h); + if (len == SHA1_OUTSIZE) + dump_hex("sha1:%s\n", h, len); + else + if (len == SHA256_OUTSIZE) + dump_hex("sha256:%s\n", h, len); + else + dump_hex("sha???:%s\n", h, len); + } #endif +} // RFC 2104 // HMAC(key, text) based on a hash H (say, sha256) is: @@ -317,12 +340,13 @@ static void sha256_hash_dbg(const char *fmt, sha256_ctx_t *ctx, const void *buff // if we often need HMAC hmac with the same key. // // text is often given in disjoint pieces. -static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE], - sha256_ctx_t *hashed_key_xor_ipad, - sha256_ctx_t *hashed_key_xor_opad, +static unsigned hmac_sha_precomputed_v(uint8_t *out, + md5sha_ctx_t *hashed_key_xor_ipad, + md5sha_ctx_t *hashed_key_xor_opad, va_list va) { uint8_t *text; + unsigned len; /* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ /* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ @@ -330,24 +354,24 @@ static void hmac_sha256_precomputed_v(uint8_t out[SHA256_OUTSIZE], /* calculate out = H((key XOR ipad) + text) */ while ((text = va_arg(va, uint8_t*)) != NULL) { unsigned text_size = va_arg(va, unsigned); - sha256_hash(hashed_key_xor_ipad, text, text_size); + md5sha_hash(hashed_key_xor_ipad, text, text_size); } - sha256_end(hashed_key_xor_ipad, out); + len = sha_end(hashed_key_xor_ipad, out); /* out = H((key XOR opad) + out) */ - sha256_hash(hashed_key_xor_opad, out, SHA256_OUTSIZE); - sha256_end(hashed_key_xor_opad, out); + md5sha_hash(hashed_key_xor_opad, out, len); + return sha_end(hashed_key_xor_opad, out); } -static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_size, ...) +static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) { - sha256_ctx_t hashed_key_xor_ipad; - sha256_ctx_t hashed_key_xor_opad; - uint8_t key_xor_ipad[SHA256_INSIZE]; - uint8_t key_xor_opad[SHA256_INSIZE]; + md5sha_ctx_t hashed_key_xor_ipad; + md5sha_ctx_t hashed_key_xor_opad; + uint8_t key_xor_ipad[SHA_INSIZE]; + uint8_t key_xor_opad[SHA_INSIZE]; uint8_t tempkey[SHA256_OUTSIZE]; va_list va; - int i; + unsigned i; va_start(va, key_size); @@ -355,27 +379,38 @@ static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_ // block length of the hash function. Applications that use keys longer // than INSIZE bytes will first hash the key using H and then use the // resultant OUTSIZE byte string as the actual key to HMAC." - if (key_size > SHA256_INSIZE) { - hash_sha256(tempkey, key, key_size); - key = tempkey; - key_size = SHA256_OUTSIZE; + if (key_size > SHA_INSIZE) { + md5sha_ctx_t ctx; + if (tls->MAC_size == SHA256_OUTSIZE) + sha256_begin(&ctx); + else + sha1_begin(&ctx); + md5sha_hash(&ctx, key, key_size); + key_size = sha_end(&ctx, tempkey); } for (i = 0; i < key_size; i++) { key_xor_ipad[i] = key[i] ^ 0x36; key_xor_opad[i] = key[i] ^ 0x5c; } - for (; i < SHA256_INSIZE; i++) { + for (; i < SHA_INSIZE; i++) { key_xor_ipad[i] = 0x36; key_xor_opad[i] = 0x5c; } - sha256_begin(&hashed_key_xor_ipad); - sha256_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA256_INSIZE); - sha256_begin(&hashed_key_xor_opad); - sha256_hash(&hashed_key_xor_opad, key_xor_opad, SHA256_INSIZE); - hmac_sha256_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); + if (tls->MAC_size == SHA256_OUTSIZE) { + sha256_begin(&hashed_key_xor_ipad); + sha256_begin(&hashed_key_xor_opad); + } else { + sha1_begin(&hashed_key_xor_ipad); + sha1_begin(&hashed_key_xor_opad); + } + md5sha_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); + md5sha_hash(&hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); + + i = hmac_sha_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); va_end(va); + return i; } // RFC 5246: @@ -406,40 +441,41 @@ static void hmac_sha256(uint8_t out[SHA256_OUTSIZE], uint8_t *key, unsigned key_ // PRF(secret, label, seed) = P_(secret, label + seed) // // The label is an ASCII string. -static void prf_hmac_sha256( +static void prf_hmac(tls_state_t *tls, uint8_t *outbuf, unsigned outbuf_size, uint8_t *secret, unsigned secret_size, const char *label, uint8_t *seed, unsigned seed_size) { - uint8_t a[SHA256_OUTSIZE]; + uint8_t a[TLS_MAX_MAC_SIZE]; uint8_t *out_p = outbuf; unsigned label_size = strlen(label); + unsigned MAC_size = tls->MAC_size; /* In P_hash() calculation, "seed" is "label + seed": */ #define SEED label, label_size, seed, seed_size #define SECRET secret, secret_size -#define A a, (int)(sizeof(a)) +#define A a, MAC_size /* A(1) = HMAC_hash(secret, seed) */ - hmac_sha256(a, SECRET, SEED, NULL); -//TODO: convert hmac_sha256 to precomputed + hmac(tls, a, SECRET, SEED, NULL); +//TODO: convert hmac to precomputed for(;;) { /* HMAC_hash(secret, A(1) + seed) */ - if (outbuf_size <= SHA256_OUTSIZE) { + if (outbuf_size <= MAC_size) { /* Last, possibly incomplete, block */ /* (use a[] as temp buffer) */ - hmac_sha256(a, SECRET, A, SEED, NULL); + hmac(tls, a, SECRET, A, SEED, NULL); memcpy(out_p, a, outbuf_size); return; } /* Not last block. Store directly to result buffer */ - hmac_sha256(out_p, SECRET, A, SEED, NULL); - out_p += SHA256_OUTSIZE; - outbuf_size -= SHA256_OUTSIZE; + hmac(tls, out_p, SECRET, A, SEED, NULL); + out_p += MAC_size; + outbuf_size -= MAC_size; /* A(2) = HMAC_hash(secret, A(1)) */ - hmac_sha256(a, SECRET, A, NULL); + hmac(tls, a, SECRET, A, NULL); } #undef A #undef SECRET @@ -484,11 +520,12 @@ static void tls_free_outbuf(tls_state_t *tls) static void *tls_get_outbuf(tls_state_t *tls, int len) { - if (len > MAX_OUTBUF) + if (len > TLS_MAX_OUTBUF) xfunc_die(); - if (tls->outbuf_size < len + OUTBUF_PFX + OUTBUF_SFX) { - tls->outbuf_size = len + OUTBUF_PFX + OUTBUF_SFX; - tls->outbuf = xrealloc(tls->outbuf, tls->outbuf_size); + len += OUTBUF_PFX + OUTBUF_SFX; + if (tls->outbuf_size < len) { + tls->outbuf_size = len; + tls->outbuf = xrealloc(tls->outbuf, len); } return tls->outbuf + OUTBUF_PFX; } @@ -500,7 +537,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) uint8_t padding_length; xhdr = (void*)(buf - RECHDR_LEN); - if (CIPHER_ID != TLS_RSA_WITH_NULL_SHA256) + if (tls->cipher_id != TLS_RSA_WITH_NULL_SHA256) xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */ xhdr->type = type; @@ -511,16 +548,16 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) xhdr->len16_lo = size & 0xff; /* Calculate MAC signature */ -//TODO: convert hmac_sha256 to precomputed - hmac_sha256(buf + size, - tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key), - &tls->write_seq64_be, sizeof(tls->write_seq64_be), - xhdr, RECHDR_LEN, - buf, size, - NULL); + hmac(tls, buf + size, /* result */ + tls->client_write_MAC_key, tls->MAC_size, + &tls->write_seq64_be, sizeof(tls->write_seq64_be), + xhdr, RECHDR_LEN, + buf, size, + NULL + ); tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); - size += SHA256_OUTSIZE; + size += tls->MAC_size; // RFC 5246 // 6.2.3.1. Null or Standard Stream Cipher @@ -555,7 +592,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) // -------- ----------- ---------- -------------- // SHA HMAC-SHA1 20 20 // SHA256 HMAC-SHA256 32 32 - if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) { + if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) { /* No encryption, only signing */ xhdr->len16_hi = size >> 8; xhdr->len16_lo = size & 0xff; @@ -603,7 +640,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) /* Fill IV and padding in outbuf */ tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */ - dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, SHA256_OUTSIZE); + dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, tls->MAC_size); // RFC is talking nonsense: // "Padding that is added to force the length of the plaintext to be // an integral multiple of the block cipher's block length." @@ -628,7 +665,7 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) { psCipherContext_t ctx; psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ - tls->client_write_key, sizeof(tls->client_write_key) + tls->client_write_key, tls->key_size /* selects 128/256 */ ); psAesEncrypt(&ctx, buf, /* plaintext */ @@ -648,9 +685,9 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); } -static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) +static void xwrite_handshake_record(tls_state_t *tls, unsigned size) { - if (!tls->encrypt_on_write) { + //if (!tls->encrypt_on_write) { uint8_t *buf = tls->outbuf + OUTBUF_PFX; struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN); @@ -662,8 +699,20 @@ static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size); xwrite(tls->ofd, xhdr, RECHDR_LEN + size); dbg("wrote %u bytes\n", (int)RECHDR_LEN + size); + // return; + //} + //xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); +} + +static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size) +{ + if (!tls->encrypt_on_write) { + uint8_t *buf; + + xwrite_handshake_record(tls, size); /* Handshake hash does not include record headers */ - sha256_hash_dbg(">> sha256:%s", &tls->hsd->handshake_sha256_ctx, buf, size); + buf = tls->outbuf + OUTBUF_PFX; + hash_handshake(tls, ">> hash:%s", buf, size); return; } xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE); @@ -765,7 +814,7 @@ static int tls_xread_record(tls_state_t *tls) sz = target - RECHDR_LEN; /* Needs to be decrypted? */ - if (tls->min_encrypted_len_on_read > SHA256_OUTSIZE) { + if (tls->min_encrypted_len_on_read > tls->MAC_size) { psCipherContext_t ctx; uint8_t *p = tls->inbuf + RECHDR_LEN; int padding_len; @@ -777,7 +826,7 @@ static int tls_xread_record(tls_state_t *tls) } /* Decrypt content+MAC+padding, moving it over IV in the process */ psAesInit(&ctx, p, /* IV */ - tls->server_write_key, sizeof(tls->server_write_key) + tls->server_write_key, tls->key_size /* selects 128/256 */ ); sz -= AES_BLOCKSIZE; /* we will overwrite IV now */ psAesDecrypt(&ctx, @@ -788,7 +837,7 @@ static int tls_xread_record(tls_state_t *tls) padding_len = p[sz - 1]; dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); padding_len++; - sz -= SHA256_OUTSIZE + padding_len; /* drop MAC and padding */ + sz -= tls->MAC_size + padding_len; /* drop MAC and padding */ //if (sz < 0) // bb_error_msg_and_die("bad padding size:%u", padding_len); } else { @@ -834,8 +883,10 @@ static int tls_xread_record(tls_state_t *tls) /* RFC 5246 is not saying it explicitly, but sha256 hash * in our FINISHED record must include data of incoming packets too! */ - if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE) { - sha256_hash_dbg("<< sha256:%s", &tls->hsd->handshake_sha256_ctx, tls->inbuf + RECHDR_LEN, sz); + if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE + && tls->MAC_size != 0 /* do we know which hash to use? (server_hello() does not!) */ + ) { + hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz); } end: dbg("got block len:%u\n", sz); @@ -1088,7 +1139,7 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un h->len24_lo = len & 0xff; } -static void send_client_hello(tls_state_t *tls, const char *sni) +static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) { struct client_hello { uint8_t type; @@ -1098,7 +1149,7 @@ static void send_client_hello(tls_state_t *tls, const char *sni) uint8_t session_id_len; /* uint8_t session_id[]; */ uint8_t cipherid_len16_hi, cipherid_len16_lo; - uint8_t cipherid[2 * 2]; /* actually variable */ + uint8_t cipherid[2 * (2 + !!CIPHER_ID2)]; /* actually variable */ uint8_t comprtypes_len; uint8_t comprtypes[1]; /* actually variable */ /* Extensions (SNI shown): @@ -1136,17 +1187,19 @@ static void send_client_hello(tls_state_t *tls, const char *sni) tls_get_random(record->rand32, sizeof(record->rand32)); if (TLS_DEBUG_FIXED_SECRETS) memset(record->rand32, 0x11, sizeof(record->rand32)); - memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); /* record->session_id_len = 0; - already is */ /* record->cipherid_len16_hi = 0; */ - record->cipherid_len16_lo = 2 * 2; - if ((CIPHER_ID >> 8) != 0) - record->cipherid[0] = CIPHER_ID >> 8; - record->cipherid[1] = CIPHER_ID & 0xff; + record->cipherid_len16_lo = sizeof(record->cipherid); /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ - /*record->cipherid[2] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */ - record->cipherid[3] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff; + /*record->cipherid[0] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */ + record->cipherid[1] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff; + if ((CIPHER_ID1 >> 8) != 0) record->cipherid[2] = CIPHER_ID1 >> 8; + /*************************/ record->cipherid[3] = CIPHER_ID1 & 0xff; +#if CIPHER_ID2 + if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8; + /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff; +#endif record->comprtypes_len = 1; /* record->comprtypes[0] = 0; */ @@ -1168,7 +1221,14 @@ static void send_client_hello(tls_state_t *tls, const char *sni) } dbg(">> CLIENT_HELLO\n"); - xwrite_and_update_handshake_hash(tls, len); + /* Can hash it only when we know which MAC hash to use */ + /*xwrite_and_update_handshake_hash(tls, len); - WRONG! */ + xwrite_handshake_record(tls, len); + + tls->hsd = xzalloc(sizeof(*tls->hsd) + len); + tls->hsd->saved_client_hello_size = len; + memcpy(tls->hsd->saved_client_hello, record, len); + memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32)); } static void get_server_hello(tls_state_t *tls) @@ -1188,7 +1248,8 @@ static void get_server_hello(tls_state_t *tls) struct server_hello *hp; uint8_t *cipherid; - int len; + unsigned cipher; + int len, len24; len = tls_xread_handshake_block(tls, 74); @@ -1207,6 +1268,7 @@ static void get_server_hello(tls_state_t *tls) } cipherid = &hp->cipherid_hi; + len24 = hp->len24_lo; if (hp->session_id_len != 32) { if (hp->session_id_len != 0) tls_error_die(tls); @@ -1216,19 +1278,39 @@ static void get_server_hello(tls_state_t *tls) // may return an empty session_id to indicate that the session will // not be cached and therefore cannot be resumed." cipherid -= 32; - hp->len24_lo += 32; /* what len would be if session id would be present */ + len24 += 32; /* what len would be if session id would be present */ } - if (hp->len24_lo < 70 - || cipherid[0] != (CIPHER_ID >> 8) - || cipherid[1] != (CIPHER_ID & 0xff) - || cipherid[2] != 0 /* comprtype */ + if (len24 < 70 +// || cipherid[0] != (CIPHER_ID >> 8) +// || cipherid[1] != (CIPHER_ID & 0xff) +// || cipherid[2] != 0 /* comprtype */ ) { tls_error_die(tls); } - dbg("<< SERVER_HELLO\n"); + memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32)); + + tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1]; + dbg("server chose cipher %04x\n", cipher); + + if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) { + tls->key_size = AES128_KEYSIZE; + tls->MAC_size = SHA1_OUTSIZE; + sha1_begin(&tls->hsd->handshake_hash_ctx); + } + else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ + tls->key_size = AES256_KEYSIZE; + tls->MAC_size = SHA256_OUTSIZE; + sha256_begin(&tls->hsd->handshake_hash_ctx); + } + hash_handshake(tls, ">> client hello hash:%s", + tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size + ); + hash_handshake(tls, "<< server hello hash:%s", + tls->inbuf + RECHDR_LEN, len + ); } static void get_server_cert(tls_state_t *tls) @@ -1312,7 +1394,7 @@ static void send_client_key_exchange(tls_state_t *tls) // [0..47]; // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. - prf_hmac_sha256( + prf_hmac(tls, tls->hsd->master_secret, sizeof(tls->hsd->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", @@ -1360,21 +1442,23 @@ static void send_client_key_exchange(tls_state_t *tls) memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32); memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); - prf_hmac_sha256( - tls->client_write_MAC_key, 2 * (SHA256_OUTSIZE + AES256_KEYSIZE), + prf_hmac(tls, + tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size), // also fills: - // server_write_MAC_key[SHA256_OUTSIZE] - // client_write_key[AES256_KEYSIZE] - // server_write_key[AES256_KEYSIZE] + // server_write_MAC_key[] + // client_write_key[] + // server_write_key[] tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "key expansion", tmp64, 64 ); + tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size); + tls->server_write_key = tls->client_write_key + tls->key_size; dump_hex("client_write_MAC_key:%s\n", - tls->client_write_MAC_key, sizeof(tls->client_write_MAC_key) + tls->client_write_MAC_key, tls->MAC_size ); dump_hex("client_write_key:%s\n", - tls->client_write_key, sizeof(tls->client_write_key) + tls->client_write_key, tls->key_size ); } } @@ -1435,15 +1519,17 @@ static void send_client_finished(tls_state_t *tls) uint8_t prf_result[12]; }; struct finished *record = tls_get_outbuf(tls, sizeof(*record)); - uint8_t handshake_hash[SHA256_OUTSIZE]; + uint8_t handshake_hash[TLS_MAX_MAC_SIZE]; + unsigned len; fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); - sha256_peek(&tls->hsd->handshake_sha256_ctx, handshake_hash); - prf_hmac_sha256(record->prf_result, sizeof(record->prf_result), - tls->hsd->master_secret, sizeof(tls->hsd->master_secret), - "client finished", - handshake_hash, sizeof(handshake_hash) + len = get_handshake_hash(tls, handshake_hash); + prf_hmac(tls, + record->prf_result, sizeof(record->prf_result), + tls->hsd->master_secret, sizeof(tls->hsd->master_secret), + "client finished", + handshake_hash, len ); dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret)); dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1); @@ -1475,10 +1561,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // Application Data <------> Application Data int len; - tls->hsd = xzalloc(sizeof(*tls->hsd)); - sha256_begin(&tls->hsd->handshake_sha256_ctx); - - send_client_hello(tls, sni); + send_client_hello_and_alloc_hsd(tls, sni); get_server_hello(tls); // RFC 5246 @@ -1535,11 +1618,11 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) tls_error_die(tls); dbg("<< CHANGE_CIPHER_SPEC\n"); - if (CIPHER_ID == TLS_RSA_WITH_NULL_SHA256) - tls->min_encrypted_len_on_read = SHA256_OUTSIZE; + if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) + tls->min_encrypted_len_on_read = tls->MAC_size; else /* all incoming packets now should be encrypted and have IV + MAC + padding */ - tls->min_encrypted_len_on_read = AES_BLOCKSIZE + SHA256_OUTSIZE + AES_BLOCKSIZE; + tls->min_encrypted_len_on_read = AES_BLOCKSIZE + tls->MAC_size + AES_BLOCKSIZE; /* Get (encrypted) FINISHED from the server */ len = tls_xread_record(tls); @@ -1550,7 +1633,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) /* free handshake data */ // if (PARANOIA) -// memset(tls->hsd, 0, sizeof(*tls->hsd)); +// memset(tls->hsd, 0, tls->hsd->hsd_size); free(tls->hsd); tls->hsd = NULL; } @@ -1614,8 +1697,8 @@ void FAST_FUNC tls_run_copy_loop(tls_state_t *tls) * read, encrypt and send bigger chunks */ inbuf_size += INBUF_STEP; - if (inbuf_size > MAX_OUTBUF) - inbuf_size = MAX_OUTBUF; + if (inbuf_size > TLS_MAX_OUTBUF) + inbuf_size = TLS_MAX_OUTBUF; } tls_xwrite(tls, nread); } -- cgit v1.2.3-55-g6feb From 1500b3a50d587adeca7be96b36394f23f2d80a82 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 17:06:10 +0100 Subject: tls: if got CERTIFICATE_REQUEST, send an empty CERTIFICATE wolfssl test server is not satisfied by an empty one, but some real servers might be. Signed-off-by: Denys Vlasenko --- networking/tls.c | 65 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index a65da4ad4..dc94a8b9b 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -484,21 +484,24 @@ static void prf_hmac(tls_state_t *tls, static void bad_record_die(tls_state_t *tls, const char *expected, int len) { - bb_error_msg_and_die("got bad TLS record (len:%d) while expecting %s", len, expected); + bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected); if (len > 0) { uint8_t *p = tls->inbuf; - while (len > 0) + while (len > 0) { fprintf(stderr, " %02x", *p++); + len--; + } fputc('\n', stderr); } xfunc_die(); } -static void tls_error_die(tls_state_t *tls) +static void tls_error_die(tls_state_t *tls, int line) { dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size); - bb_error_msg_and_die("TODO: useful diagnostic about %p", tls); + bb_error_msg_and_die("tls error at line %d cipher:%04x", line, tls->cipher_id); } +#define tls_error_die(tls) tls_error_die(tls, __LINE__) #if 0 //UNUSED static void tls_free_inbuf(tls_state_t *tls) @@ -1343,6 +1346,26 @@ static void get_server_cert(tls_state_t *tls) find_key_in_der_cert(tls, certbuf + 10, len); } +static void send_empty_client_cert(tls_state_t *tls) +{ + struct client_empty_cert { + uint8_t type; + uint8_t len24_hi, len24_mid, len24_lo; + uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo; + }; + struct client_empty_cert *record; + + record = tls_get_outbuf(tls, sizeof(*record)); +//FIXME: can just memcpy a ready-made one. + fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record)); + record->cert_chain_len24_hi = 0; + record->cert_chain_len24_mid = 0; + record->cert_chain_len24_lo = 0; + + dbg(">> CERTIFICATE\n"); + xwrite_and_update_handshake_hash(tls, sizeof(*record)); +} + static void send_client_key_exchange(tls_state_t *tls) { struct client_key_exchange { @@ -1584,23 +1607,25 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) // 0c 00|01|c9 03|00|17|41|04|cd|9b|b4|29|1f|f6|b0|c2|84|82|7f|29|6a|47|4e|ec|87|0b|c1|9c|69|e1|f8|c6|d0|53|e9|27|90|a5|c8|02|15|75... dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len); //probably need to save it - tls_xread_handshake_block(tls, 4); + len = tls_xread_handshake_block(tls, 4); } -// if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { -// dbg("<< CERTIFICATE_REQUEST\n"); -// RFC 5246: (in response to this,) "If no suitable certificate is available, -// the client MUST send a certificate message containing no -// certificates. That is, the certificate_list structure has a -// length of zero. ... -// Client certificates are sent using the Certificate structure -// defined in Section 7.4.2." -// (i.e. the same format as server certs) -// tls_xread_handshake_block(tls, 4); -// } - - if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) - tls_error_die(tls); + if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) { + dbg("<< CERTIFICATE_REQUEST\n"); + // RFC 5246: "If no suitable certificate is available, + // the client MUST send a certificate message containing no + // certificates. That is, the certificate_list structure has a + // length of zero. ... + // Client certificates are sent using the Certificate structure + // defined in Section 7.4.2." + // (i.e. the same format as server certs) + send_empty_client_cert(tls); + len = tls_xread_handshake_block(tls, 4); + } + + if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) { + bad_record_die(tls, "'server hello done'", len); + } // 0e 000000 (len:0) dbg("<< SERVER_HELLO_DONE\n"); @@ -1616,7 +1641,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) /* Get CHANGE_CIPHER_SPEC */ len = tls_xread_record(tls); if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0) - tls_error_die(tls); + bad_record_die(tls, "switch to encrypted traffic", len); dbg("<< CHANGE_CIPHER_SPEC\n"); if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) tls->min_encrypted_len_on_read = tls->MAC_size; -- cgit v1.2.3-55-g6feb From 89193f985bf50af702e0f98a3c86573277c03287 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 18:08:07 +0100 Subject: tls: can download kernels now :) Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- networking/tls.c | 172 ++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 121 insertions(+), 53 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index b1ceb3278..8c652e2d7 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -721,7 +721,7 @@ typedef struct tls_state { int ofd; int ifd; - int min_encrypted_len_on_read; + unsigned min_encrypted_len_on_read; uint16_t cipher_id; uint8_t encrypt_on_write; unsigned MAC_size; diff --git a/networking/tls.c b/networking/tls.c index dc94a8b9b..335324568 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -53,15 +53,14 @@ // ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA // (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported) #define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer -// Does not work yet: -//#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA -#define CIPHER_ID2 0 +// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz" +#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA -#define TLS_DEBUG 1 -#define TLS_DEBUG_HASH 1 -#define TLS_DEBUG_DER 1 -#define TLS_DEBUG_FIXED_SECRETS 1 +#define TLS_DEBUG 0 +#define TLS_DEBUG_HASH 0 +#define TLS_DEBUG_DER 0 +#define TLS_DEBUG_FIXED_SECRETS 0 #if 0 # define dump_raw_out(...) dump_hex(__VA_ARGS__) #else @@ -340,51 +339,48 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer // if we often need HMAC hmac with the same key. // // text is often given in disjoint pieces. -static unsigned hmac_sha_precomputed_v(uint8_t *out, - md5sha_ctx_t *hashed_key_xor_ipad, - md5sha_ctx_t *hashed_key_xor_opad, +typedef struct hmac_precomputed { + md5sha_ctx_t hashed_key_xor_ipad; + md5sha_ctx_t hashed_key_xor_opad; +} hmac_precomputed_t; + +static unsigned hmac_sha_precomputed_v( + hmac_precomputed_t *pre, + uint8_t *out, va_list va) { uint8_t *text; unsigned len; - /* hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ - /* hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ + /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */ + /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */ /* calculate out = H((key XOR ipad) + text) */ while ((text = va_arg(va, uint8_t*)) != NULL) { unsigned text_size = va_arg(va, unsigned); - md5sha_hash(hashed_key_xor_ipad, text, text_size); + md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size); } - len = sha_end(hashed_key_xor_ipad, out); + len = sha_end(&pre->hashed_key_xor_ipad, out); /* out = H((key XOR opad) + out) */ - md5sha_hash(hashed_key_xor_opad, out, len); - return sha_end(hashed_key_xor_opad, out); + md5sha_hash(&pre->hashed_key_xor_opad, out, len); + return sha_end(&pre->hashed_key_xor_opad, out); } -static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) +static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size) { - md5sha_ctx_t hashed_key_xor_ipad; - md5sha_ctx_t hashed_key_xor_opad; uint8_t key_xor_ipad[SHA_INSIZE]; uint8_t key_xor_opad[SHA_INSIZE]; uint8_t tempkey[SHA256_OUTSIZE]; - va_list va; unsigned i; - va_start(va, key_size); - // "The authentication key can be of any length up to INSIZE, the // block length of the hash function. Applications that use keys longer // than INSIZE bytes will first hash the key using H and then use the // resultant OUTSIZE byte string as the actual key to HMAC." if (key_size > SHA_INSIZE) { md5sha_ctx_t ctx; - if (tls->MAC_size == SHA256_OUTSIZE) - sha256_begin(&ctx); - else - sha1_begin(&ctx); + sha256_begin(&ctx); md5sha_hash(&ctx, key, key_size); key_size = sha_end(&ctx, tempkey); } @@ -398,19 +394,77 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ key_xor_opad[i] = 0x5c; } - if (tls->MAC_size == SHA256_OUTSIZE) { - sha256_begin(&hashed_key_xor_ipad); - sha256_begin(&hashed_key_xor_opad); - } else { - sha1_begin(&hashed_key_xor_ipad); - sha1_begin(&hashed_key_xor_opad); + sha256_begin(&pre->hashed_key_xor_ipad); + sha256_begin(&pre->hashed_key_xor_opad); + md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); + md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); +} +// TODO: ^^^ vvv merge? +static void hmac_sha1_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size) +{ + uint8_t key_xor_ipad[SHA_INSIZE]; + uint8_t key_xor_opad[SHA_INSIZE]; + uint8_t tempkey[SHA1_OUTSIZE]; + unsigned i; + + // "The authentication key can be of any length up to INSIZE, the + // block length of the hash function. Applications that use keys longer + // than INSIZE bytes will first hash the key using H and then use the + // resultant OUTSIZE byte string as the actual key to HMAC." + if (key_size > SHA_INSIZE) { + md5sha_ctx_t ctx; + sha1_begin(&ctx); + md5sha_hash(&ctx, key, key_size); + key_size = sha_end(&ctx, tempkey); + } + + for (i = 0; i < key_size; i++) { + key_xor_ipad[i] = key[i] ^ 0x36; + key_xor_opad[i] = key[i] ^ 0x5c; + } + for (; i < SHA_INSIZE; i++) { + key_xor_ipad[i] = 0x36; + key_xor_opad[i] = 0x5c; } - md5sha_hash(&hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); - md5sha_hash(&hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); - i = hmac_sha_precomputed_v(out, &hashed_key_xor_ipad, &hashed_key_xor_opad, va); + sha1_begin(&pre->hashed_key_xor_ipad); + sha1_begin(&pre->hashed_key_xor_opad); + md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); + md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); +} + +static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) +{ + hmac_precomputed_t pre; + va_list va; + unsigned len; + + va_start(va, key_size); + + if (tls->MAC_size == SHA256_OUTSIZE) + hmac_sha256_begin(&pre, key, key_size); + else + hmac_sha1_begin(&pre, key, key_size); + + len = hmac_sha_precomputed_v(&pre, out, va); + va_end(va); - return i; + return len; +} + +static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, unsigned key_size, ...) +{ + hmac_precomputed_t pre; + va_list va; + unsigned len; + + va_start(va, key_size); + + hmac_sha256_begin(&pre, key, key_size); + len = hmac_sha_precomputed_v(&pre, out, va); + + va_end(va); + return len; } // RFC 5246: @@ -420,6 +474,9 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ // SHA-256 hash function is used for all cipher suites defined in this // document and in TLS documents published prior to this document when // TLS 1.2 is negotiated. +// ^^^^^^^^^^^^^ IMPORTANT! +// PRF uses sha256 regardless of cipher (at least for all ciphers +// defined by RFC5246). It's not sha1 for AES_128_CBC_SHA! //... // P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + // HMAC_hash(secret, A(2) + seed) + @@ -441,7 +498,7 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_ // PRF(secret, label, seed) = P_(secret, label + seed) // // The label is an ASCII string. -static void prf_hmac(tls_state_t *tls, +static void prf_hmac_sha256(/*tls_state_t *tls,*/ uint8_t *outbuf, unsigned outbuf_size, uint8_t *secret, unsigned secret_size, const char *label, @@ -450,7 +507,7 @@ static void prf_hmac(tls_state_t *tls, uint8_t a[TLS_MAX_MAC_SIZE]; uint8_t *out_p = outbuf; unsigned label_size = strlen(label); - unsigned MAC_size = tls->MAC_size; + unsigned MAC_size = SHA256_OUTSIZE;///tls->MAC_size; /* In P_hash() calculation, "seed" is "label + seed": */ #define SEED label, label_size, seed, seed_size @@ -458,7 +515,7 @@ static void prf_hmac(tls_state_t *tls, #define A a, MAC_size /* A(1) = HMAC_hash(secret, seed) */ - hmac(tls, a, SECRET, SEED, NULL); + hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL); //TODO: convert hmac to precomputed for(;;) { @@ -466,16 +523,16 @@ static void prf_hmac(tls_state_t *tls, if (outbuf_size <= MAC_size) { /* Last, possibly incomplete, block */ /* (use a[] as temp buffer) */ - hmac(tls, a, SECRET, A, SEED, NULL); + hmac_sha256(/*tls,*/ a, SECRET, A, SEED, NULL); memcpy(out_p, a, outbuf_size); return; } /* Not last block. Store directly to result buffer */ - hmac(tls, out_p, SECRET, A, SEED, NULL); + hmac_sha256(/*tls,*/ out_p, SECRET, A, SEED, NULL); out_p += MAC_size; outbuf_size -= MAC_size; /* A(2) = HMAC_hash(secret, A(1)) */ - hmac(tls, a, SECRET, A, NULL); + hmac_sha256(/*tls,*/ a, SECRET, A, NULL); } #undef A #undef SECRET @@ -823,9 +880,10 @@ static int tls_xread_record(tls_state_t *tls) int padding_len; if (sz & (AES_BLOCKSIZE-1) - || sz < tls->min_encrypted_len_on_read + || sz < (int)tls->min_encrypted_len_on_read ) { - bb_error_msg_and_die("bad encrypted len:%u", sz); + bb_error_msg_and_die("bad encrypted len:%u < %u", + sz, tls->min_encrypted_len_on_read); } /* Decrypt content+MAC+padding, moving it over IV in the process */ psAesInit(&ctx, p, /* IV */ @@ -1301,13 +1359,17 @@ static void get_server_hello(tls_state_t *tls) if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) { tls->key_size = AES128_KEYSIZE; tls->MAC_size = SHA1_OUTSIZE; - sha1_begin(&tls->hsd->handshake_hash_ctx); } else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */ tls->key_size = AES256_KEYSIZE; tls->MAC_size = SHA256_OUTSIZE; - sha256_begin(&tls->hsd->handshake_hash_ctx); } + /* Handshake hash eventually destined to FINISHED record + * is sha256 regardless of cipher + * (at least for all ciphers defined by RFC5246). + * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash. + */ + sha256_begin(&tls->hsd->handshake_hash_ctx); hash_handshake(tls, ">> client hello hash:%s", tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size ); @@ -1389,6 +1451,7 @@ static void send_client_key_exchange(tls_state_t *tls) // version negotiated for the connection." rsa_premaster[0] = TLS_MAJ; rsa_premaster[1] = TLS_MIN; + dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster)); len = psRsaEncryptPub(/*pool:*/ NULL, /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key, rsa_premaster, /*inlen:*/ sizeof(rsa_premaster), @@ -1417,7 +1480,7 @@ static void send_client_key_exchange(tls_state_t *tls) // [0..47]; // The master secret is always exactly 48 bytes in length. The length // of the premaster secret will vary depending on key exchange method. - prf_hmac(tls, + prf_hmac_sha256(/*tls,*/ tls->hsd->master_secret, sizeof(tls->hsd->master_secret), rsa_premaster, sizeof(rsa_premaster), "master secret", @@ -1465,7 +1528,7 @@ static void send_client_key_exchange(tls_state_t *tls) memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32); memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32); - prf_hmac(tls, + prf_hmac_sha256(/*tls,*/ tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size), // also fills: // server_write_MAC_key[] @@ -1548,7 +1611,7 @@ static void send_client_finished(tls_state_t *tls) fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record)); len = get_handshake_hash(tls, handshake_hash); - prf_hmac(tls, + prf_hmac_sha256(/*tls,*/ record->prf_result, sizeof(record->prf_result), tls->hsd->master_secret, sizeof(tls->hsd->master_secret), "client finished", @@ -1645,9 +1708,14 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni) dbg("<< CHANGE_CIPHER_SPEC\n"); if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) tls->min_encrypted_len_on_read = tls->MAC_size; - else - /* all incoming packets now should be encrypted and have IV + MAC + padding */ - tls->min_encrypted_len_on_read = AES_BLOCKSIZE + tls->MAC_size + AES_BLOCKSIZE; + else { + unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE; + /* all incoming packets now should be encrypted and have + * at least IV + (MAC padded to blocksize): + */ + tls->min_encrypted_len_on_read = AES_BLOCKSIZE + (mac_blocks * AES_BLOCKSIZE); + dbg("min_encrypted_len_on_read: %u", tls->min_encrypted_len_on_read); + } /* Get (encrypted) FINISHED from the server */ len = tls_xread_record(tls); -- cgit v1.2.3-55-g6feb From bca4ea8b68403e6f751341b82c65937f14590679 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 20:52:42 +0100 Subject: remove "local" bashism from a few scripts Signed-off-by: Denys Vlasenko --- examples/depmod | 2 +- scripts/gen_build_files.sh | 4 +++- scripts/trylink | 14 ++++++-------- testsuite/runtest | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/depmod b/examples/depmod index d769590d0..8d421c6ab 100755 --- a/examples/depmod +++ b/examples/depmod @@ -7,7 +7,7 @@ # Licensed under GPLv2, see file LICENSE in this source tree. # -local BASE="${1:-/usr/lib/modules}" +BASE="${1:-/usr/lib/modules}" find "$BASE" -name '*.ko.gz' | while read I ; do N=`basename "$I" '.ko.gz'` diff --git a/scripts/gen_build_files.sh b/scripts/gen_build_files.sh index ebee17c64..f79fa2f83 100755 --- a/scripts/gen_build_files.sh +++ b/scripts/gen_build_files.sh @@ -20,7 +20,9 @@ chk() { status "CHK" "$@"; } generate() { # NB: data to be inserted at INSERT line is coming on stdin - local src="$1" dst="$2" header="$3" + src="$1" + dst="$2" + header="$3" #chk "${dst}" { # Need to use printf: different shells have inconsistent diff --git a/scripts/trylink b/scripts/trylink index c2a431626..9f288c141 100755 --- a/scripts/trylink +++ b/scripts/trylink @@ -46,8 +46,7 @@ try() { } check_cc() { - local tempname="$(mktemp tmp.XXXXXXXXXX)" - local r + tempname="$(mktemp tmp.XXXXXXXXXX)" echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( # Was using "-xc /dev/null", but we need a valid C program. @@ -55,14 +54,13 @@ check_cc() { # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...' # and we need shell to process quotes! $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1 - r=$? + exitcode=$? rm -f "$tempname" "$tempname".c "$tempname".o - return $r + return $exitcode } check_libc_is_glibc() { - local tempname="$(mktemp tmp.XXXXXXXXXX)" - local r + tempname="$(mktemp tmp.XXXXXXXXXX)" echo "\ #include /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ @@ -71,9 +69,9 @@ check_libc_is_glibc() { #endif " >"$tempname".c ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1 - r=$? + exitcode=$? rm -f "$tempname" "$tempname".c "$tempname".o - return $r + return $exitcode } EXE="$1" diff --git a/testsuite/runtest b/testsuite/runtest index 51575d926..44f9cd1a1 100755 --- a/testsuite/runtest +++ b/testsuite/runtest @@ -12,12 +12,12 @@ total_failed=0 # Option -e will make testcase stop on the first failed command. run_applet_testcase() { - local applet="$1" - local testcase="$2" + applet="$1" + testcase="$2" - local status=0 - local uc_applet=$(echo "$applet" | tr a-z A-Z) - local testname="$testcase" + status=0 + uc_applet=$(echo "$applet" | tr a-z A-Z) + testname="$testcase" testname="${testname##*/}" # take basename if grep "^# CONFIG_$uc_applet is not set$" "$bindir/.config" >/dev/null; then -- cgit v1.2.3-55-g6feb From dff9fefd500401ad7821c9890fee4c3fb88f64eb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 24 Jan 2017 21:41:43 +0100 Subject: wget: add support for -S --server-response Based on the patch by stephane.billiart@gmail.com function old new delta ftpcmd 87 129 +42 fgets_and_trim 86 119 +33 static.wget_longopts 234 252 +18 packed_usage 31002 31015 +13 wget_main 2535 2540 +5 gethdr 158 163 +5 retrieve_file_data 424 428 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 7/0 up/down: 120/0) Total: 120 bytes Signed-off-by: Denys Vlasenko --- networking/wget.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index a448acdae..90eedaf7a 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -94,20 +94,21 @@ /* Since we ignore these opts, we don't show them in --help */ /* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ /* //usage: " [-nv] [-nc] [-nH] [-np]" */ -//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." +//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." //usage: ) //usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( -//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" +//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" //usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." //usage: ) //usage:#define wget_full_usage "\n\n" //usage: "Retrieve files via HTTP or FTP\n" //usage: IF_FEATURE_WGET_LONG_OPTIONS( -//usage: "\n --spider Spider mode - only check file existence" +//usage: "\n --spider Only check URL existence: $? is 0 if exists" //usage: ) //usage: "\n -c Continue retrieval of aborted transfer" //usage: "\n -q Quiet" //usage: "\n -P DIR Save to DIR (default .)" +//usage: "\n -S Show server response" //usage: IF_FEATURE_WGET_TIMEOUT( //usage: "\n -T SEC Network read timeout is SEC seconds" //usage: ) @@ -223,16 +224,17 @@ struct globals { enum { WGET_OPT_CONTINUE = (1 << 0), WGET_OPT_QUIET = (1 << 1), - WGET_OPT_OUTNAME = (1 << 2), - WGET_OPT_PREFIX = (1 << 3), - WGET_OPT_PROXY = (1 << 4), - WGET_OPT_USER_AGENT = (1 << 5), - WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 6), - WGET_OPT_RETRIES = (1 << 7), - WGET_OPT_nsomething = (1 << 8), - WGET_OPT_HEADER = (1 << 9) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_POST_DATA = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, - WGET_OPT_SPIDER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_SERVER_RESPONSE = (1 << 2), + WGET_OPT_OUTNAME = (1 << 3), + WGET_OPT_PREFIX = (1 << 4), + WGET_OPT_PROXY = (1 << 5), + WGET_OPT_USER_AGENT = (1 << 6), + WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7), + WGET_OPT_RETRIES = (1 << 8), + WGET_OPT_nsomething = (1 << 9), + WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, + WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, }; enum { @@ -386,7 +388,7 @@ static FILE *open_socket(len_and_sockaddr *lsa) } /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ -static char fgets_and_trim(FILE *fp) +static char fgets_and_trim(FILE *fp, const char *fmt) { char c; char *buf_ptr; @@ -404,6 +406,9 @@ static char fgets_and_trim(FILE *fp) log_io("< %s", G.wget_buf); + if (fmt && (option_mask32 & WGET_OPT_SERVER_RESPONSE)) + fprintf(stderr, fmt, G.wget_buf); + return c; } @@ -414,12 +419,15 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp) if (!s2) s2 = ""; fprintf(fp, "%s%s\r\n", s1, s2); + /* With --server-response, wget also shows its ftp commands */ + if (option_mask32 & WGET_OPT_SERVER_RESPONSE) + fprintf(stderr, "--> %s%s\n\n", s1, s2); fflush(fp); log_io("> %s%s", s1, s2); } do { - fgets_and_trim(fp); + fgets_and_trim(fp, "%s\n"); } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); G.wget_buf[3] = '\0'; @@ -516,7 +524,7 @@ static char *gethdr(FILE *fp) int c; /* retrieve header line */ - c = fgets_and_trim(fp); + c = fgets_and_trim(fp, " %s\n"); /* end of the headers? */ if (G.wget_buf[0] == '\0') @@ -884,9 +892,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp) if (!G.chunked) break; - fgets_and_trim(dfp); /* Eat empty line */ + fgets_and_trim(dfp, NULL); /* Eat empty line */ get_clen: - fgets_and_trim(dfp); + fgets_and_trim(dfp, NULL); G.content_len = STRTOOFF(G.wget_buf, NULL, 16); /* FIXME: error check? */ if (G.content_len == 0) @@ -1116,7 +1124,7 @@ static void download_one_url(const char *url) * Retrieve HTTP response line and check for "200" status code. */ read_response: - fgets_and_trim(sfp); + fgets_and_trim(sfp, " %s\n"); str = G.wget_buf; str = skip_non_whitespace(str); @@ -1301,6 +1309,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) /* name, has_arg, val */ "continue\0" No_argument "c" "quiet\0" No_argument "q" + "server-response\0" No_argument "S" "output-document\0" Required_argument "O" "directory-prefix\0" Required_argument "P" "proxy\0" Required_argument "Y" @@ -1343,7 +1352,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0") #endif opt_complementary = "-1" /* at least one URL */ IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ - getopt32(argv, "cqO:P:Y:U:T:+" + getopt32(argv, "cqSO:P:Y:U:T:+" /*ignored:*/ "t:" /*ignored:*/ "n::" /* wget has exactly four -n opts, all of which we can ignore: -- cgit v1.2.3-55-g6feb From 2181fb4af8680730e0157310ffeeb3a35768beb0 Mon Sep 17 00:00:00 2001 From: Andrey Mozzhuhin Date: Tue, 24 Jan 2017 23:02:04 +0100 Subject: ftpd: new option -a ANON_USER to allow anonymous logins Anonymous ftpd login is useful even when ftpd authentication feature is enabled. Anonymous logins provide simple password-less connection for FTP clients. To allow password-less connection user command line option '-a USER' is added. This option specifies the system user to use when 'anonymous' username is given in USER command. No password is required in this case. function old new delta ftpd_main 2164 2232 +68 packed_usage 31015 31046 +31 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 99/0) Total: 99 bytes Signed-off-by: Andrey Mozzhuhin Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index a4626c0b5..104d414de 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -47,20 +47,26 @@ //kbuild:lib-$(CONFIG_FTPD) += ftpd.o //usage:#define ftpd_trivial_usage -//usage: "[-wvS] [-t N] [-T N] [DIR]" +//usage: "[-wvS]"IF_FEATURE_FTPD_AUTHENTICATION(" [-a USER]")" [-t N] [-T N] [DIR]" //usage:#define ftpd_full_usage "\n\n" -//usage: "Anonymous FTP server\n" -//usage: "\n" -//usage: "ftpd should be used as an inetd service.\n" -//usage: "ftpd's line for inetd.conf:\n" +//usage: IF_NOT_FEATURE_FTPD_AUTHENTICATION( +//usage: "Anonymous FTP server. Accesses by clients occur under ftpd's UID.\n" +//usage: ) +//usage: IF_FEATURE_FTPD_AUTHENTICATION( +//usage: "FTP server. " +//usage: ) +//usage: "Chroots to DIR, if this fails (run by non-root), cds to it.\n" +//usage: "Should be used as inetd service, inetd.conf line:\n" //usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n" -//usage: "It also can be ran from tcpsvd:\n" +//usage: "Can be run from tcpsvd:\n" //usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" //usage: "\n -w Allow upload" //usage: "\n -v Log errors to stderr. -vv: verbose log" //usage: "\n -S Log errors to syslog. -SS: verbose log" +//usage: IF_FEATURE_FTPD_AUTHENTICATION( +//usage: "\n -a USER Enable 'anonymous' login and map it to USER" +//usage: ) //usage: "\n -t,-T Idle and absolute timeouts" -//usage: "\n DIR Change root to this directory" #include "libbb.h" #include "common_bufsiz.h" @@ -1154,6 +1160,7 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) { #if ENABLE_FEATURE_FTPD_AUTHENTICATION struct passwd *pw = NULL; + char *anon_opt = NULL; #endif unsigned abs_timeout; unsigned verbose_S; @@ -1166,12 +1173,18 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) G.timeout = 2 * 60; opt_complementary = "vv:SS"; #if BB_MMU - opts = getopt32(argv, "vS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); + opts = getopt32(argv, "vS" + IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"), + &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,) + &G.verbose, &verbose_S); #else - opts = getopt32(argv, "l1AvS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); + opts = getopt32(argv, "l1AvS" + IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"), + &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,) + &G.verbose, &verbose_S); if (opts & (OPT_l|OPT_1)) { /* Our secret backdoor to ls */ -/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */ +/* TODO: pass --group-directories-first? */ if (fchdir(3) != 0) _exit(127); /* memset(&G, 0, sizeof(G)); - ls_main does it */ @@ -1234,7 +1247,12 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_FTPD_AUTHENTICATION while (1) { uint32_t cmdval = cmdio_get_cmd_and_arg(); - if (cmdval == const_USER) { + if (cmdval == const_USER) { + if (anon_opt && strcmp(G.ftp_arg, "anonymous") == 0) { + pw = getpwnam(anon_opt); + if (pw) + break; /* does not even ask for password */ + } pw = getpwnam(G.ftp_arg); cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); } else if (cmdval == const_PASS) { -- cgit v1.2.3-55-g6feb From 0f4364775fbc0b716024d5211325045c40b431c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 01:58:00 +0100 Subject: xxd: new applet Yet Another Hexdumper function old new delta xxd_main - 364 +364 packed_usage 31046 31116 +70 applet_names 2560 2564 +4 applet_main 1476 1480 +4 rewrite 1022 1013 -9 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 3/1 up/down: 442/-9) Total: 433 bytes Signed-off-by: Denys Vlasenko --- libbb/dump.c | 12 ++--- util-linux/hexdump.c | 21 ++++---- util-linux/hexdump_xxd.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 util-linux/hexdump_xxd.c diff --git a/libbb/dump.c b/libbb/dump.c index 154be5d80..e9ac0c673 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -165,16 +165,14 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) byte_count_str = "\001"; DO_BYTE_COUNT: if (fu->bcnt) { - do { - if (fu->bcnt == *byte_count_str) { + for (;;) { + if (fu->bcnt == *byte_count_str) break; - } - } while (*++byte_count_str); + if (*++byte_count_str == 0) + bb_error_msg_and_die("bad byte count for conversion character %s", p1); + } } /* Unlike the original, output the remainder of the format string. */ - if (!*byte_count_str) { - bb_error_msg_and_die("bad byte count for conversion character %s", p1); - } pr->bcnt = *byte_count_str; } else if (*p1 == 'l') { ++p2; diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 4a7f641db..4b536e1c2 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -47,6 +47,7 @@ //usage: "\n -d Two-byte decimal display" //usage: "\n -e FORMAT_STRING" //usage: "\n -f FORMAT_FILE" +// exactly the same help text lines in hexdump and xxd: //usage: "\n -n LENGTH Interpret only LENGTH bytes of input" //usage: "\n -o Two-byte octal display" //usage: "\n -s OFFSET Skip OFFSET bytes" @@ -83,11 +84,11 @@ static void bb_dump_addfile(dumper_t *dumper, char *name) } static const char *const add_strings[] = { - "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"", /* b */ - "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"", /* c */ - "\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"", /* d */ - "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"", /* o */ - "\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"", /* x */ + "\"%07.7_ax \"16/1 \"%03o \"\"\n\"", /* b */ + "\"%07.7_ax \"16/1 \"%3_c \"\"\n\"", /* c */ + "\"%07.7_ax \"8/2 \" %05u \"\"\n\"", /* d */ + "\"%07.7_ax \"8/2 \" %06o \"\"\n\"", /* o */ + "\"%07.7_ax \"8/2 \" %04x \"\"\n\"", /* x */ }; static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; @@ -125,9 +126,11 @@ int hexdump_main(int argc, char **argv) /* Save a little bit of space below by omitting the 'else's. */ if (ch == 'C') { hd_applet: - bb_dump_add(dumper, "\"%08.8_Ax\n\""); - bb_dump_add(dumper, "\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" "); - bb_dump_add(dumper, "\" |\" 16/1 \"%_p\" \"|\\n\""); + bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump + //------------------- "address " 8 * "xx " " " 8 * "xx " + bb_dump_add(dumper, "\"%08.8_ax \"8/1 \"%02x \" \" \"8/1 \"%02x \""); + //------------------- " |ASCII...........|\n" + bb_dump_add(dumper, "\" |\"16/1 \"%_p\"\"|\n\""); } if (ch == 'e') { bb_dump_add(dumper, optarg); @@ -158,7 +161,7 @@ int hexdump_main(int argc, char **argv) if (!dumper->fshead) { bb_dump_add(dumper, add_first); - bb_dump_add(dumper, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); + bb_dump_add(dumper, "\"%07.7_ax \"8/2 \"%04x \"\"\n\""); } argv += optind; diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c new file mode 100644 index 000000000..3a7e64bb9 --- /dev/null +++ b/util-linux/hexdump_xxd.c @@ -0,0 +1,132 @@ +/* vi: set sw=4 ts=4: */ +/* + * xxd implementation for busybox + * + * Copyright (c) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config XXD +//config: bool "xxd" +//config: default y +//config: help +//config: The xxd utility is used to display binary data in a readable +//config: way that is comparable to the output from most hex editors. + +//applet:IF_XXD(APPLET_NOEXEC(xxd, xxd, BB_DIR_USR_BIN, BB_SUID_DROP, xxd)) + +//kbuild:lib-$(CONFIG_XXD) += hexdump_xxd.o + +// $ xxd --version +// xxd V1.10 27oct98 by Juergen Weigert +// $ xxd --help +// Usage: +// xxd [options] [infile [outfile]] +// or +// xxd -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]] +// Options: +// -a toggle autoskip: A single '*' replaces nul-lines. Default off. +// -b binary digit dump (incompatible with -ps,-i,-r). Default hex. +// -c cols format octets per line. Default 16 (-i: 12, -ps: 30). +// -E show characters in EBCDIC. Default ASCII. +// -e little-endian dump (incompatible with -ps,-i,-r). +// -g number of octets per group in normal output. Default 2 (-e: 4). +// -i output in C include file style. +// -l len stop after octets. +// -o off add to the displayed file position. +// -ps output in postscript plain hexdump style. +// -r reverse operation: convert (or patch) hexdump into binary. +// -r -s off revert with added to file positions found in hexdump. +// -s [+][-]seek start at bytes abs. (or +: rel.) infile offset. +// -u use upper case hex letters. + +//usage:#define xxd_trivial_usage +//usage: "[OPTIONS] [FILE]" +//usage:#define xxd_full_usage "\n\n" +//usage: "Hex dump FILE (or stdin)\n" +//usage: "\n -g N Bytes per group" +//usage: "\n -c N Bytes per line" +// exactly the same help text lines in hexdump and xxd: +//usage: "\n -l LENGTH Interpret only LENGTH bytes of input" +//usage: "\n -s OFFSET Skip OFFSET bytes" + +#include "libbb.h" +#include "dump.h" + +/* This is a NOEXEC applet. Be very careful! */ + +int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int xxd_main(int argc UNUSED_PARAM, char **argv) +{ + char buf[80]; + dumper_t *dumper; + char *opt_l, *opt_s; + unsigned bytes = 2; + unsigned cols = 0; + unsigned opt; + + dumper = alloc_dumper(); + +#define OPT_l (1 << 0) +#define OPT_s (1 << 1) +#define OPT_a (1 << 2) + opt_complementary = "?1"; /* 1 argument max */ + opt = getopt32(argv, "l:s:ag:+c:+", &opt_l, &opt_s, &bytes, &cols); + argv += optind; + +// dumper->dump_vflag = ALL; // default +// if (opt & OPT_a) +// dumper->dump_vflag = SKIPNUL; ..does not exist + if (opt & OPT_l) { + dumper->dump_length = xstrtou_range( + opt_l, + /*base:*/ 0, + /*lo:*/ 0, /*hi:*/ INT_MAX + ); + } + if (opt & OPT_s) { + dumper->dump_skip = xstrtoull_range( + opt_s, + /*base:*/ 0, + /*lo:*/ 0, /*hi:*/ OFF_T_MAX + ); + //BUGGY for /proc/version (unseekable?) + } + + bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " + if (cols == 0) + cols = 16; + if (bytes < 1 || bytes >= cols) { + sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx" + bb_dump_add(dumper, buf); + } + else if (bytes == 1) { + sprintf(buf, "%u/1 \"%%02x \"", cols); // cols * "xx " + bb_dump_add(dumper, buf); + } + else { +/* Format "print byte" with and without trailing space */ +#define BS "/1 \"%02x \"" +#define B "/1 \"%02x\"" + unsigned i; + char *bigbuf = xmalloc(1 + cols * (sizeof(BS)-1)); + char *p = bigbuf; + for (i = 1; i <= cols; i++) { + if (i == cols || i % bytes) + p = stpcpy(p, B); + else + p = stpcpy(p, BS); + } + // for -g3, this results in B B BS B B BS... B = "xxxxxx xxxxxx .....xx" + // todo: can be more clever and use + // one "cols-1/B" format instead of many "B B B..." formats + //bb_error_msg("ADDED:'%s'", bigbuf); + bb_dump_add(dumper, bigbuf); + free(bigbuf); + } + + sprintf(buf, "\" \" %u/1 \"%%_p\" \"\n\"", cols); // " ASCII\n" + bb_dump_add(dumper, buf); + + return bb_dump_dump(dumper, argv); +} -- cgit v1.2.3-55-g6feb From 8a2657cbf5fe005914cf58836d2599e65e6c3e34 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 03:07:39 +0100 Subject: hexdump/xxd: a bit more condensed formats Signed-off-by: Denys Vlasenko --- util-linux/hexdump.c | 4 ++-- util-linux/hexdump_xxd.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 4b536e1c2..a4483a114 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -127,8 +127,8 @@ int hexdump_main(int argc, char **argv) if (ch == 'C') { hd_applet: bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump - //------------------- "address " 8 * "xx " " " 8 * "xx " - bb_dump_add(dumper, "\"%08.8_ax \"8/1 \"%02x \" \" \"8/1 \"%02x \""); + //------------------- "address " 8 * "xx " " " 8 * "xx " + bb_dump_add(dumper, "\"%08.8_ax \"8/1 \"%02x \"\" \"8/1 \"%02x \""); //------------------- " |ASCII...........|\n" bb_dump_add(dumper, "\" |\"16/1 \"%_p\"\"|\n\""); } diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 3a7e64bb9..813e7fe57 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -125,7 +125,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) free(bigbuf); } - sprintf(buf, "\" \" %u/1 \"%%_p\" \"\n\"", cols); // " ASCII\n" + sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" bb_dump_add(dumper, buf); return bb_dump_dump(dumper, argv); -- cgit v1.2.3-55-g6feb From b13b6183354e6c9d031951fa4f11bcb9b38ae251 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 04:52:45 +0100 Subject: ftpd/ls: show directories first Old TODO finally done function old new delta ls_main 548 568 +20 packed_usage 31116 31097 -19 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 7 ++++++- networking/ftpd.c | 15 +++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index a858a3217..6e0a52d75 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -1045,7 +1045,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) int ls_main(int argc UNUSED_PARAM, char **argv) -{ +{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */ struct dnode **dnd; struct dnode **dnf; struct dnode **dnp; @@ -1175,6 +1175,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv) if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C))) option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1); + if (ENABLE_FTPD && applet_name[0] == 'f') { + /* ftpd secret backdoor. dirs first are much nicer */ + option_mask32 |= OPT_dirs_first; + } + argv += optind; if (!argv[0]) *--argv = (char*)"."; diff --git a/networking/ftpd.c b/networking/ftpd.c index 104d414de..439608ce6 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -61,12 +61,12 @@ //usage: "Can be run from tcpsvd:\n" //usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" //usage: "\n -w Allow upload" -//usage: "\n -v Log errors to stderr. -vv: verbose log" -//usage: "\n -S Log errors to syslog. -SS: verbose log" //usage: IF_FEATURE_FTPD_AUTHENTICATION( //usage: "\n -a USER Enable 'anonymous' login and map it to USER" //usage: ) -//usage: "\n -t,-T Idle and absolute timeouts" +//usage: "\n -v Log errors to stderr. -vv: verbose log" +//usage: "\n -S Log errors to syslog. -SS: verbose log" +//usage: "\n -t,-T N Idle and absolute timeout" #include "libbb.h" #include "common_bufsiz.h" @@ -701,7 +701,7 @@ popen_ls(const char *opt) dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */ #if BB_MMU /* memset(&G, 0, sizeof(G)); - ls_main does it */ - exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv)); + exit(ls_main(/*argc_unused*/ 0, (char**) argv)); #else cur_fd = xopen(".", O_RDONLY | O_DIRECTORY); /* On NOMMU, we want to execute a child - copy of ourself @@ -1152,11 +1152,7 @@ enum { }; int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -#if !BB_MMU -int ftpd_main(int argc, char **argv) -#else int ftpd_main(int argc UNUSED_PARAM, char **argv) -#endif { #if ENABLE_FEATURE_FTPD_AUTHENTICATION struct passwd *pw = NULL; @@ -1184,11 +1180,10 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) &G.verbose, &verbose_S); if (opts & (OPT_l|OPT_1)) { /* Our secret backdoor to ls */ -/* TODO: pass --group-directories-first? */ if (fchdir(3) != 0) _exit(127); /* memset(&G, 0, sizeof(G)); - ls_main does it */ - return ls_main(argc, argv); + return ls_main(/*argc_unused*/ 0, argv); } #endif if (G.verbose < verbose_S) -- cgit v1.2.3-55-g6feb From cb8e84e65a254dcba4939e237b93d03c46ae56aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 16:21:00 +0100 Subject: libbb: shrink sump.c function old new delta dot_flags_width_chars - 16 +16 int_convs - 7 +7 lcc 7 - -7 index_str 16 - -16 rewrite 1013 937 -76 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 0/1 up/down: 23/-99) Total: -76 bytes Signed-off-by: Denys Vlasenko --- libbb/dump.c | 159 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 80 insertions(+), 79 deletions(-) diff --git a/libbb/dump.c b/libbb/dump.c index e9ac0c673..87c1dce13 100644 --- a/libbb/dump.c +++ b/libbb/dump.c @@ -14,12 +14,12 @@ #include "libbb.h" #include "dump.h" -static const char index_str[] ALIGN1 = ".#-+ 0123456789"; +static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; static const char size_conv_str[] ALIGN1 = "\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; -static const char lcc[] ALIGN1 = "diouxX"; +static const char int_convs[] ALIGN1 = "diouxX"; typedef struct priv_dumper_t { @@ -71,7 +71,7 @@ static NOINLINE int bb_dump_size(FS *fs) * skip any special chars -- save precision in * case it's a %s format. */ - while (strchr(index_str + 1, *++fmt)) + while (strchr(dot_flags_width_chars + 1, *++fmt)) continue; if (*fmt == '.' && isdigit(*++fmt)) { prec = atoi(fmt); @@ -82,14 +82,15 @@ static NOINLINE int bb_dump_size(FS *fs) if (!p) { if (*fmt == 's') { bcnt += prec; - } else if (*fmt == '_') { + } + if (*fmt == '_') { ++fmt; if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) { bcnt += 1; } } } else { - bcnt += size_conv_str[p - (size_conv_str + 12)]; + bcnt += p[-12]; } } cur_size += bcnt * fu->reps; @@ -99,32 +100,30 @@ static NOINLINE int bb_dump_size(FS *fs) static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) { - enum { NOTOKAY, USEBCNT, USEPREC } sokay; FU *fu; - PR *pr; - char *p1, *p2, *p3; - char savech, *fmtp; - const char *byte_count_str; - int nconv, prec = 0; for (fu = fs->nextfu; fu; fu = fu->nextfu) { + PR *pr; + char *p1, *p2, *p3; + char *fmtp; + int nconv = 0; /* * break each format unit into print units; each * conversion character gets its own. */ - for (nconv = 0, fmtp = fu->fmt; *fmtp; ) { - /* NOSTRICT */ - /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL*/ - pr = xzalloc(sizeof(PR)); + for (fmtp = fu->fmt; *fmtp; ) { + unsigned len; + const char *prec; + const char *byte_count_str; + + /* DBU:[dvae@cray.com] zalloc so that forward ptrs start out NULL */ + pr = xzalloc(sizeof(*pr)); if (!fu->nextpr) fu->nextpr = pr; /* skip preceding text and up to the next % sign */ - for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) - continue; - - /* only text in the string */ - if (!*p1) { + p1 = strchr(fmtp, '%'); + if (!p1) { /* only text in the string */ pr->fmt = fmtp; pr->flags = F_TEXT; break; @@ -134,22 +133,20 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) * get precision for %s -- if have a byte count, don't * need it. */ + prec = NULL; if (fu->bcnt) { - sokay = USEBCNT; /* skip to conversion character */ - for (++p1; strchr(index_str, *p1); ++p1) + while (strchr(dot_flags_width_chars, *++p1)) continue; } else { /* skip any special chars, field width */ - while (strchr(index_str + 1, *++p1)) + while (strchr(dot_flags_width_chars + 1, *++p1)) continue; if (*p1 == '.' && isdigit(*++p1)) { - sokay = USEPREC; - prec = atoi(p1); + prec = p1; while (isdigit(*++p1)) continue; - } else - sokay = NOTOKAY; + } } p2 = p1 + 1; /* set end pointer */ @@ -174,63 +171,63 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) } /* Unlike the original, output the remainder of the format string. */ pr->bcnt = *byte_count_str; - } else if (*p1 == 'l') { + } else + if (*p1 == 'l') { /* %ld etc */ + const char *e; + ++p2; ++p1; DO_INT_CONV: - { - const char *e; - e = strchr(lcc, *p1); - if (!e) { - goto DO_BAD_CONV_CHAR; - } - pr->flags = F_INT; - if (e > lcc + 1) { - pr->flags = F_UINT; - } - byte_count_str = "\004\002\001"; - goto DO_BYTE_COUNT; - } - /* NOTREACHED */ - } else if (strchr(lcc, *p1)) { + e = strchr(int_convs, *p1); /* "diouxX"? */ + if (!e) + goto DO_BAD_CONV_CHAR; + pr->flags = F_INT; + if (e > int_convs + 1) /* not d or i? */ + pr->flags = F_UINT; + byte_count_str = "\004\002\001"; + goto DO_BYTE_COUNT; + } else + if (strchr(int_convs, *p1)) { /* %d etc */ goto DO_INT_CONV; - } else if (strchr("eEfgG", *p1)) { + } else + if (strchr("eEfgG", *p1)) { /* floating point */ pr->flags = F_DBL; byte_count_str = "\010\004"; goto DO_BYTE_COUNT; - } else if (*p1 == 's') { + } else + if (*p1 == 's') { pr->flags = F_STR; - if (sokay == USEBCNT) { - pr->bcnt = fu->bcnt; - } else if (sokay == USEPREC) { - pr->bcnt = prec; - } else { /* NOTOKAY */ - bb_error_msg_and_die("%%s requires a precision or a byte count"); + pr->bcnt = fu->bcnt; + if (fu->bcnt == 0) { + if (!prec) + bb_error_msg_and_die("%%s needs precision or byte count"); + pr->bcnt = atoi(prec); } - } else if (*p1 == '_') { - ++p2; + } else + if (*p1 == '_') { + p2++; /* move past a in "%_a" */ switch (p1[1]) { - case 'A': + case 'A': /* %_A[dox]: print address and the end */ dumper->endfu = fu; fu->flags |= F_IGNORE; /* FALLTHROUGH */ - case 'a': + case 'a': /* %_a[dox]: current address */ pr->flags = F_ADDRESS; - ++p2; + p2++; /* move past x in "%_ax" */ if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) { goto DO_BAD_CONV_CHAR; } *p1 = p1[2]; break; - case 'c': + case 'c': /* %_c: chars, \ooo, \n \r \t etc */ pr->flags = F_C; /* *p1 = 'c'; set in conv_c */ goto DO_BYTE_COUNT_1; - case 'p': + case 'p': /* %_p: chars, dots for nonprintable */ pr->flags = F_P; *p1 = 'c'; goto DO_BYTE_COUNT_1; - case 'u': + case 'u': /* %_p: chars, 'nul', 'esc' etc for nonprintable */ pr->flags = F_U; /* *p1 = 'c'; set in conv_u */ goto DO_BYTE_COUNT_1; @@ -246,13 +243,8 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) * copy to PR format string, set conversion character * pointer, update original. */ - savech = *p2; - p1[1] = '\0'; - pr->fmt = xstrdup(fmtp); - *p2 = savech; - //Too early! xrealloc can move pr->fmt! - //pr->cchar = pr->fmt + (p1 - fmtp); - + len = (p1 - fmtp) + 1; + pr->fmt = xstrndup(fmtp, len); /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. * Skip subsequent text and up to the next % sign and tack the * additional text onto fmt: eg. if fmt is "%x is a HEX number", @@ -260,16 +252,17 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) */ for (p3 = p2; *p3 && *p3 != '%'; p3++) continue; - if (p3 > p2) { - savech = *p3; - *p3 = '\0'; - pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt) + (p3-p2) + 1); - strcat(pr->fmt, p2); - *p3 = savech; - p2 = p3; + if ((p3 - p2) != 0) { + char *d; + pr->fmt = d = xrealloc(pr->fmt, len + (p3 - p2) + 1); + d += len; + do { + *d++ = *p2++; + } while (p2 != p3); + *d = '\0'; + /* now p2 = p3 */ } - - pr->cchar = pr->fmt + (p1 - fmtp); + pr->cchar = pr->fmt + len - 1; /* must be after realloc! */ fmtp = p2; /* only one conversion character if byte count */ @@ -281,7 +274,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) * if format unit byte count not specified, figure it out * so can adjust rep count later. */ - if (!fu->bcnt) + if (fu->bcnt == 0) for (pr = fu->nextpr; pr; pr = pr->nextpr) fu->bcnt += pr->bcnt; } @@ -303,16 +296,18 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs) fu->reps += (dumper->blocksize - fs->bcnt) / fu->bcnt; } if (fu->reps > 1 && fu->nextpr) { + PR *pr; + char *p1, *p2; + for (pr = fu->nextpr;; pr = pr->nextpr) if (!pr->nextpr) break; - for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) + p2 = NULL; + for (p1 = pr->fmt; *p1; ++p1) p2 = isspace(*p1) ? p1 : NULL; if (p2) pr->nospace = p2; } - if (!fu->nextfu) - break; } } @@ -356,6 +351,7 @@ static NOINLINE int next(priv_dumper_t *dumper) if (dumper->next__done) return 0; /* no next file */ dumper->next__done = 1; +//why stat of stdin is specially prohibited? statok = 0; } if (dumper->pub.dump_skip) @@ -760,6 +756,11 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt) if (!isspace(*p)) { bb_error_msg_and_die("bad format {%s}", fmt); } +// Above check prohibits formats such as '/1"%02x"' - it requires space after 1. +// Other than this, formats can be pretty much jammed together: +// "%07_ax:"8/2 "%04x|""\n" +// but this space is required. The check *can* be removed, but +// keeping it to stay compat with util-linux hexdump. tfu->bcnt = atoi(savep); /* skip trailing white space */ p = skip_whitespace(p + 1); -- cgit v1.2.3-55-g6feb From 62a9b18547462a657ffb18cf03d5cfdcf774c905 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 16:50:30 +0100 Subject: xxd: implement -p While at it, tweaked hexdump --help function old new delta xxd_main 364 414 +50 packed_usage 31097 31114 +17 Signed-off-by: Denys Vlasenko --- util-linux/hexdump.c | 19 ++++++++++--------- util-linux/hexdump_xxd.c | 30 +++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index a4483a114..25f771201 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c @@ -41,20 +41,21 @@ //usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..." //usage:#define hexdump_full_usage "\n\n" //usage: "Display FILEs (or stdin) in a user specified format\n" -//usage: "\n -b One-byte octal display" -//usage: "\n -c One-byte character display" -//usage: "\n -C Canonical hex+ASCII, 16 bytes per line" -//usage: "\n -d Two-byte decimal display" -//usage: "\n -e FORMAT_STRING" +//usage: "\n -b 1-byte octal display" +//usage: "\n -c 1-byte character display" +//usage: "\n -d 2-byte decimal display" +//usage: "\n -o 2-byte octal display" +//usage: "\n -x 2-byte hex display" +//usage: "\n -C hex+ASCII 16 bytes per line" +//usage: "\n -v Show all (no dup folding)" +//usage: "\n -e FORMAT_STR Example: '16/1 \"%02x|\"\"\\n\"'" //usage: "\n -f FORMAT_FILE" // exactly the same help text lines in hexdump and xxd: -//usage: "\n -n LENGTH Interpret only LENGTH bytes of input" -//usage: "\n -o Two-byte octal display" +//usage: "\n -n LENGTH Show only first LENGTH bytes" //usage: "\n -s OFFSET Skip OFFSET bytes" -//usage: "\n -v Display all input data" -//usage: "\n -x Two-byte hexadecimal display" //usage: IF_FEATURE_HEXDUMP_REVERSE( //usage: "\n -R Reverse of 'hexdump -Cv'") +// TODO: NONCOMPAT!!! move -R to xxd -r //usage: //usage:#define hd_trivial_usage //usage: "FILE..." diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index 813e7fe57..cc34ea649 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -46,9 +46,11 @@ //usage: "Hex dump FILE (or stdin)\n" //usage: "\n -g N Bytes per group" //usage: "\n -c N Bytes per line" +//usage: "\n -p Show only hex bytes, assumes -c30" // exactly the same help text lines in hexdump and xxd: -//usage: "\n -l LENGTH Interpret only LENGTH bytes of input" +//usage: "\n -l LENGTH Show only first LENGTH bytes" //usage: "\n -s OFFSET Skip OFFSET bytes" +// TODO: implement -r (see hexdump -R) #include "libbb.h" #include "dump.h" @@ -70,11 +72,12 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) #define OPT_l (1 << 0) #define OPT_s (1 << 1) #define OPT_a (1 << 2) +#define OPT_p (1 << 3) opt_complementary = "?1"; /* 1 argument max */ - opt = getopt32(argv, "l:s:ag:+c:+", &opt_l, &opt_s, &bytes, &cols); + opt = getopt32(argv, "l:s:apg:+c:+", &opt_l, &opt_s, &bytes, &cols); argv += optind; -// dumper->dump_vflag = ALL; // default + dumper->dump_vflag = ALL; // if (opt & OPT_a) // dumper->dump_vflag = SKIPNUL; ..does not exist if (opt & OPT_l) { @@ -93,9 +96,16 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) //BUGGY for /proc/version (unseekable?) } - bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " - if (cols == 0) - cols = 16; + if (opt & OPT_p) { + if (cols == 0) + cols = 30; + bytes = cols; /* -p ignores -gN */ + } else { + if (cols == 0) + cols = 16; + bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " + } + if (bytes < 1 || bytes >= cols) { sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx" bb_dump_add(dumper, buf); @@ -109,7 +119,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) #define BS "/1 \"%02x \"" #define B "/1 \"%02x\"" unsigned i; - char *bigbuf = xmalloc(1 + cols * (sizeof(BS)-1)); + char *bigbuf = xmalloc(cols * (sizeof(BS)-1)); char *p = bigbuf; for (i = 1; i <= cols; i++) { if (i == cols || i % bytes) @@ -125,8 +135,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) free(bigbuf); } - sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" - bb_dump_add(dumper, buf); + if (!(opt & OPT_p)) { + sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" + bb_dump_add(dumper, buf); + } return bb_dump_dump(dumper, argv); } -- cgit v1.2.3-55-g6feb From 7dd906a3884a31458d30fc43eb9885c5adf4bbea Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 25 Jan 2017 17:00:38 +0100 Subject: xxd: make -p output lines actually end with a newline Signed-off-by: Denys Vlasenko --- util-linux/hexdump_xxd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index cc34ea649..be4b4f354 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c @@ -129,7 +129,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) } // for -g3, this results in B B BS B B BS... B = "xxxxxx xxxxxx .....xx" // todo: can be more clever and use - // one "cols-1/B" format instead of many "B B B..." formats + // one 'bytes-1/1 "%02x"' format instead of many "B B B..." formats //bb_error_msg("ADDED:'%s'", bigbuf); bb_dump_add(dumper, bigbuf); free(bigbuf); @@ -138,6 +138,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) if (!(opt & OPT_p)) { sprintf(buf, "\" \"%u/1 \"%%_p\"\"\n\"", cols); // " ASCII\n" bb_dump_add(dumper, buf); + } else { + bb_dump_add(dumper, "\"\n\""); } return bb_dump_dump(dumper, argv); -- cgit v1.2.3-55-g6feb From 06f20bf675cdd415c2f796ebea9fc55030ef49cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2017 00:27:53 +0100 Subject: link: new applet coreutils grew itself a tiny simplistic alternative to ln: Usage: link FILE LINK Create hard LINK to FILE function old new delta link_main - 75 +75 packed_usage 31114 31131 +17 applet_names 2564 2569 +5 applet_main 1480 1484 +4 applet_install_loc 185 186 +1 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 102/0) Total: 102 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/data_extract_all.c | 6 +++-- coreutils/link.c | 41 ++++++++++++++++++++++++++++++++++ docs/nofork_noexec.txt | 32 +++++++++++++++++++++----- 3 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 coreutils/link.c diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index bd034afdc..1830ffb8d 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c @@ -127,8 +127,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) if (hard_link) { res = link(hard_link, dst_name); if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { + /* shared message */ bb_perror_msg("can't create %slink " - "from %s to %s", "hard", + "%s to %s", "hard", dst_name, hard_link); } @@ -181,8 +182,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) ) { + /* shared message */ bb_perror_msg("can't create %slink " - "from %s to %s", "sym", + "%s to %s", "sym", dst_name, file_header->link_target); } diff --git a/coreutils/link.c b/coreutils/link.c new file mode 100644 index 000000000..ac3ef85d9 --- /dev/null +++ b/coreutils/link.c @@ -0,0 +1,41 @@ +/* + * link implementation for busybox + * + * Copyright (C) 2017 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ +//config:config LINK +//config: bool "link" +//config: default y +//config: help +//config: link creates hard links between files. + +//applet:IF_LINK(APPLET_NOFORK(link, link, BB_DIR_BIN, BB_SUID_DROP, link)) + +//kbuild:lib-$(CONFIG_LINK) += link.o + +//usage:#define link_trivial_usage +//usage: "FILE LINK" +//usage:#define link_full_usage "\n\n" +//usage: "Create hard LINK to FILE" + +#include "libbb.h" + +/* This is a NOFORK applet. Be very careful! */ + +int link_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int link_main(int argc UNUSED_PARAM, char **argv) +{ + opt_complementary = "=2"; /* exactly 2 params */ + getopt32(argv, ""); + argv += optind; + if (link(argv[0], argv[1]) != 0) { + /* shared message */ + bb_perror_msg_and_die("can't create %slink " + "%s to %s", "hard", + argv[1], argv[0] + ); + } + return EXIT_SUCCESS; +} diff --git a/docs/nofork_noexec.txt b/docs/nofork_noexec.txt index c58f5a83f..2fb184a03 100644 --- a/docs/nofork_noexec.txt +++ b/docs/nofork_noexec.txt @@ -33,6 +33,7 @@ roughly are: * do not expect shared global variables/buffers to be in their "initialized" state. Examples: xfunc_error_retval can be != 1, bb_common_bufsiz1 can be scribbled over, ... + (although usually xfunc_error_retval's state is not a problem). * do not expect that stdio wasn't used before. Calling set[v]buf() can be disastrous. * ... @@ -81,18 +82,37 @@ are probably not worth the effort. Any NOFORK applet is also a NOEXEC applet. + Calling NOFORK applets + +API to call NOFORK applets is two functions: + + run_nofork_applet(appno, argv) + spawn_and_wait(argv) // only if FEATURE_PREFER_APPLETS=y + +First one is directly used by shells if FEATURE_SH_NOFORK=y. +Second one is used by many applets, but main users are xargs and find. +It itself calls run_nofork_applet(), if argv[0] turned out to be a name +of a NOFORK applet. + +run_nofork_applet() saves/inits/restores option parsing, xfunc_error_retval, +applet_name. Thus, for example, caller does not need to worry about +option_mask32 getting trashed. + + Relevant CONFIG options FEATURE_PREFER_APPLETS BB_EXECVP(cmd, argv) will try to exec /proc/self/exe - if command's name matches some applet name - applet tables will contain NOFORK/NOEXEC bits + if command's name matches some applet name; spawn_and_wait(argv) will do NOFORK/NOEXEC tricks -FEATURE_SH_STANDALONE (needs FEATURE_PREFER_APPLETS=y) +//TODO: the above two things probably should have separate options? + +FEATURE_SH_STANDALONE shells will try to exec /proc/self/exe if command's name matches - some applet name - shells will do NOEXEC trick on NOEXEC applets + some applet name; shells will do NOEXEC trick on NOEXEC applets + +//TODO: split (same as for PREFER_APPLETS) -FEATURE_SH_NOFORK (needs FEATURE_PREFER_APPLETS=y) +FEATURE_SH_NOFORK shells will do NOFORK trick on NOFORK applets -- cgit v1.2.3-55-g6feb From 9967c9949e0436879354e76c2847d697c309984c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2017 01:13:58 +0100 Subject: libbb: spawn_and_wait() fflushes before forking NOEXEC; child reinits logmode Signed-off-by: Denys Vlasenko --- docs/nofork_noexec.txt | 7 +++++++ include/libbb.h | 14 +++++++++----- libbb/vfork_daemon_rexec.c | 36 +++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/docs/nofork_noexec.txt b/docs/nofork_noexec.txt index 2fb184a03..a24dd9c27 100644 --- a/docs/nofork_noexec.txt +++ b/docs/nofork_noexec.txt @@ -99,6 +99,13 @@ applet_name. Thus, for example, caller does not need to worry about option_mask32 getting trashed. + Calling NOEXEC applets + +It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y, +it does NOEXEC trick. It resets xfunc_error_retval = 1 and +logmode = LOGMODE_STDIO in the child. + + Relevant CONFIG options FEATURE_PREFER_APPLETS diff --git a/include/libbb.h b/include/libbb.h index 8c652e2d7..07fe20dac 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1093,10 +1093,19 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC; */ int wait4pid(pid_t pid) FAST_FUNC; int wait_for_exitstatus(pid_t pid) FAST_FUNC; +/************************************************************************/ +/* spawn_and_wait/run_nofork_applet/run_applet_no_and_exit need to work */ +/* carefully together to reinit some global state while not disturbing */ +/* other. Be careful if you change them. Consult docs/nofork_noexec.txt */ +/************************************************************************/ /* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ int spawn_and_wait(char **argv) FAST_FUNC; /* Does NOT check that applet is NOFORK, just blindly runs it */ int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; +#ifndef BUILD_INDIVIDUAL +extern int find_applet_by_name(const char *name) FAST_FUNC; +extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; +#endif /* Helpers for daemonization. * @@ -1303,11 +1312,6 @@ const struct hwtype *get_hwtype(const char *name) FAST_FUNC; const struct hwtype *get_hwntype(int type) FAST_FUNC; -#ifndef BUILD_INDIVIDUAL -extern int find_applet_by_name(const char *name) FAST_FUNC; -extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC; -#endif - #ifdef HAVE_MNTENT_H extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index c192829b5..2e7dc2d9b 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -183,26 +183,28 @@ int FAST_FUNC spawn_and_wait(char **argv) #if ENABLE_FEATURE_PREFER_APPLETS int a = find_applet_by_name(argv[0]); - if (a >= 0 && (APPLET_IS_NOFORK(a) -# if BB_MMU - || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ -# endif - )) { -# if BB_MMU + if (a >= 0) { if (APPLET_IS_NOFORK(a)) -# endif - { return run_nofork_applet(a, argv); +# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */ + if (APPLET_IS_NOEXEC(a)) { + fflush_all(); + rc = fork(); + if (rc) /* parent or error */ + return wait4pid(rc); + + /* child */ + /* reset some state and run without execing */ + + /* msg_eol = "\n"; - no caller needs this reinited yet */ + logmode = LOGMODE_STDIO; + /* die_func = NULL; - needed if the caller is a shell, + * init, or a NOFORK applet. But none of those call us + * as of yet (and that should probably always stay true). + */ + /* xfunc_error_retval and applet_name are init by: */ + run_applet_no_and_exit(a, argv); } -# if BB_MMU - /* MMU only */ - /* a->noexec is true */ - rc = fork(); - if (rc) /* parent or error */ - return wait4pid(rc); - /* child */ - xfunc_error_retval = EXIT_FAILURE; - run_applet_no_and_exit(a, argv); # endif } #endif /* FEATURE_PREFER_APPLETS */ -- cgit v1.2.3-55-g6feb From 786c9dc0c1351cea34e71a91c6bf34a3c62b19d4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2017 18:31:51 +0100 Subject: sh: fix FEATURE_SH_STANDALONE help text: it does not enable NOFORK Signed-off-by: Denys Vlasenko --- shell/Config.src | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/shell/Config.src b/shell/Config.src index 3545f05dd..6a7e12aa7 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -121,23 +121,11 @@ config FEATURE_SH_STANDALONE for use as a rescue shell, in the event that you screw up your system. This is implemented by re-execing /proc/self/exe (typically) - with right parameters. Some selected applets ("NOFORK" applets) - can even be executed without creating new process. - Instead, busybox will call _main() internally. - - However, this causes problems in chroot jails without mounted /proc - and with ps/top (command name can be shown as 'exe' for applets - started this way). -# untrue? -# Note that this will *also* cause applets to take precedence -# over shell builtins of the same name. So turning this on will -# eliminate any performance gained by turning on the builtin "echo" -# and "test" commands in ash. -# untrue? -# Note that when using this option, the shell will attempt to directly -# run '/bin/busybox'. If you do not have the busybox binary sitting in -# that exact location with that exact name, this option will not work at -# all. + with right parameters. + + However, there are drawbacks: it is problematic in chroot jails without + mounted /proc, and ps/top may show command name as 'exe' for applets + started this way. config FEATURE_SH_NOFORK bool "Run 'nofork' applets directly" -- cgit v1.2.3-55-g6feb From 4d417709b0fb837fd6884a9bc5a55027dec8a985 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2017 18:54:12 +0100 Subject: adduser: help for -G GRP is misleading, fix it Signed-off-by: Denys Vlasenko --- loginutils/adduser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginutils/adduser.c b/loginutils/adduser.c index c218ac4aa..40bc816a1 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c @@ -64,7 +64,7 @@ //usage: "\n -h DIR Home directory" //usage: "\n -g GECOS GECOS field" //usage: "\n -s SHELL Login shell" -//usage: "\n -G GRP Add user to existing group" +//usage: "\n -G GRP Group" //usage: "\n -S Create a system user" //usage: "\n -D Don't assign a password" //usage: "\n -H Don't create home directory" -- cgit v1.2.3-55-g6feb From b4b12bf2344148976d1cd0f17bca0c0fbf7a364c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Jan 2017 19:35:40 +0100 Subject: httpd: defend against attempts to OOM us. Closes 9611 We were strdup'ing "Cookie: foo" every time we saw it. function old new delta handle_incoming_and_exit 2733 2821 +88 Signed-off-by: Denys Vlasenko --- networking/httpd.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index 39aad90a8..8703fbd3d 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -460,11 +460,6 @@ struct globals { #define ip_a_d (G.ip_a_d ) #define g_realm (G.g_realm ) #define remoteuser (G.remoteuser ) -#define referer (G.referer ) -#define user_agent (G.user_agent ) -#define host (G.host ) -#define http_accept (G.http_accept ) -#define http_accept_language (G.http_accept_language) #define file_size (G.file_size ) #if ENABLE_FEATURE_HTTPD_RANGES #define range_start (G.range_start ) @@ -1529,11 +1524,11 @@ static void send_cgi_and_exit( #endif } } - setenv1("HTTP_USER_AGENT", user_agent); - if (http_accept) - setenv1("HTTP_ACCEPT", http_accept); - if (http_accept_language) - setenv1("HTTP_ACCEPT_LANGUAGE", http_accept_language); + setenv1("HTTP_USER_AGENT", G.user_agent); + if (G.http_accept) + setenv1("HTTP_ACCEPT", G.http_accept); + if (G.http_accept_language) + setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language); if (post_len) putenv(xasprintf("CONTENT_LENGTH=%d", post_len)); if (cookie) @@ -1546,9 +1541,9 @@ static void send_cgi_and_exit( putenv((char*)"AUTH_TYPE=Basic"); } #endif - if (referer) - setenv1("HTTP_REFERER", referer); - setenv1("HTTP_HOST", host); /* set to "" if NULL */ + if (G.referer) + setenv1("HTTP_REFERER", G.referer); + setenv1("HTTP_HOST", G.host); /* set to "" if NULL */ /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this, * just run "env SERVER_NAME=xyz httpd ..." instead */ @@ -2269,10 +2264,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) #if ENABLE_FEATURE_HTTPD_PROXY /* We need 2 more bytes for yet another "\r\n" - * see near fdprintf(proxy_fd...) further below */ - if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 2) { - int len = strlen(iobuf); - if (len > IOBUF_SIZE - (header_ptr - header_buf) - 4) - len = IOBUF_SIZE - (header_ptr - header_buf) - 4; + if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 4) { + int len = strnlen(iobuf, IOBUF_SIZE - (header_ptr - header_buf) - 4); memcpy(header_ptr, iobuf, len); header_ptr += len; header_ptr[0] = '\r'; @@ -2303,19 +2296,26 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) #endif #if ENABLE_FEATURE_HTTPD_CGI else if (STRNCASECMP(iobuf, "Cookie:") == 0) { - cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); + if (!cookie) /* in case they send millions of these, do not OOM */ + cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { - content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); + if (!content_type) + content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); } else if (STRNCASECMP(iobuf, "Referer:") == 0) { - referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); + if (!G.referer) + G.referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { - user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); + if (!G.user_agent) + G.user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); } else if (STRNCASECMP(iobuf, "Host:") == 0) { - host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1)); + if (!G.host) + G.host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1)); } else if (STRNCASECMP(iobuf, "Accept:") == 0) { - http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1)); + if (!G.http_accept) + G.http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1)); } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) { - http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1)); + if (!G.http_accept_language) + G.http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1)); } #endif #if ENABLE_FEATURE_HTTPD_BASIC_AUTH -- cgit v1.2.3-55-g6feb From 205d48e9480e3a60f2bf1094f67d837f1b44aea5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Jan 2017 14:57:33 +0100 Subject: *: add comment about APPLET_ODDNAME format It confused me more than once Signed-off-by: Denys Vlasenko --- archival/bbunzip.c | 48 +++++++++++++++++++++++-------------------- archival/lzop.c | 3 ++- coreutils/expand.c | 1 + coreutils/who.c | 1 + findutils/grep.c | 1 + init/halt.c | 3 ++- loginutils/add-remove-shell.c | 1 + miscutils/flash_lock_unlock.c | 3 ++- miscutils/ubi_tools.c | 11 +++++----- modutils/modprobe-small.c | 5 +++-- networking/hostname.c | 1 + networking/ifupdown.c | 3 ++- printutils/lpr.c | 1 + procps/kill.c | 3 ++- procps/pgrep.c | 1 + runit/chpst.c | 3 ++- selinux/setfiles.c | 1 + shell/ash.c | 3 ++- shell/hush.c | 5 +++-- util-linux/freeramdisk.c | 1 + util-linux/mkfs_ext2.c | 3 ++- util-linux/mkfs_minix.c | 1 + util-linux/mkfs_vfat.c | 3 ++- util-linux/setarch.c | 1 + util-linux/swaponoff.c | 3 ++- 25 files changed, 69 insertions(+), 41 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index fb7a3678d..0e2a261f0 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -314,6 +314,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) //config: depends on (GUNZIP || ZCAT) && LONG_OPTS //applet:IF_GUNZIP(APPLET(gunzip, BB_DIR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_ZCAT(APPLET_ODDNAME(zcat, gunzip, BB_DIR_BIN, BB_SUID_DROP, zcat)) #if ENABLE_FEATURE_GZIP_DECOMPRESS static @@ -425,6 +426,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) //config: Alias to "bunzip2 -c". //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_BZCAT(APPLET_ODDNAME(bzcat, bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP, bzcat)) #if ENABLE_FEATURE_BZIP2_DECOMPRESS int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -467,26 +469,6 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //usage: "[FILE]..." //usage:#define lzcat_full_usage "\n\n" //usage: "Decompress to stdout" -//usage: -//usage:#define unxz_trivial_usage -//usage: "[-cf] [FILE]..." -//usage:#define unxz_full_usage "\n\n" -//usage: "Decompress FILE (or stdin)\n" -//usage: "\n -c Write to stdout" -//usage: "\n -f Force" -//usage: -//usage:#define xz_trivial_usage -//usage: "-d [-cf] [FILE]..." -//usage:#define xz_full_usage "\n\n" -//usage: "Decompress FILE (or stdin)\n" -//usage: "\n -d Decompress" -//usage: "\n -c Write to stdout" -//usage: "\n -f Force" -//usage: -//usage:#define xzcat_trivial_usage -//usage: "[FILE]..." -//usage:#define xzcat_full_usage "\n\n" -//usage: "Decompress to stdout" //config:config UNLZMA //config: bool "unlzma" @@ -528,8 +510,9 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) //config: a 1K bigger binary. //applet:IF_UNLZMA(APPLET(unlzma, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_LZCAT(APPLET_ODDNAME(lzcat, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzcat)) -//applet:IF_LZMA(APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) +//applet:IF_LZMA( APPLET_ODDNAME(lzma, unlzma, BB_DIR_USR_BIN, BB_SUID_DROP, lzma)) //kbuild:lib-$(CONFIG_UNLZMA) += bbunzip.o //kbuild:lib-$(CONFIG_LZCAT) += bbunzip.o //kbuild:lib-$(CONFIG_LZMA) += bbunzip.o @@ -553,6 +536,26 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) #endif +//usage:#define unxz_trivial_usage +//usage: "[-cf] [FILE]..." +//usage:#define unxz_full_usage "\n\n" +//usage: "Decompress FILE (or stdin)\n" +//usage: "\n -c Write to stdout" +//usage: "\n -f Force" +//usage: +//usage:#define xz_trivial_usage +//usage: "-d [-cf] [FILE]..." +//usage:#define xz_full_usage "\n\n" +//usage: "Decompress FILE (or stdin)\n" +//usage: "\n -d Decompress" +//usage: "\n -c Write to stdout" +//usage: "\n -f Force" +//usage: +//usage:#define xzcat_trivial_usage +//usage: "[FILE]..." +//usage:#define xzcat_full_usage "\n\n" +//usage: "Decompress to stdout" + //config:config UNXZ //config: bool "unxz" //config: default y @@ -573,8 +576,9 @@ int unlzma_main(int argc UNUSED_PARAM, char **argv) //config: IOW: you'll get xz applet, but it will always require -d option. //applet:IF_UNXZ(APPLET(unxz, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_XZCAT(APPLET_ODDNAME(xzcat, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xzcat)) -//applet:IF_XZ(APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) +//applet:IF_XZ( APPLET_ODDNAME(xz, unxz, BB_DIR_USR_BIN, BB_SUID_DROP, xz)) //kbuild:lib-$(CONFIG_UNXZ) += bbunzip.o //kbuild:lib-$(CONFIG_XZCAT) += bbunzip.o //kbuild:lib-$(CONFIG_XZ) += bbunzip.o diff --git a/archival/lzop.c b/archival/lzop.c index e0e90ac6c..ca61add3c 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -53,7 +53,8 @@ //config: and take up 3.2K of code. //applet:IF_LZOP(APPLET(lzop, BB_DIR_BIN, BB_SUID_DROP)) -//applet:IF_UNLZOP(APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_UNLZOP( APPLET_ODDNAME(unlzop, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, unlzop)) //applet:IF_LZOPCAT(APPLET_ODDNAME(lzopcat, lzop, BB_DIR_USR_BIN, BB_SUID_DROP, lzopcat)) //kbuild:lib-$(CONFIG_LZOP) += lzop.o //kbuild:lib-$(CONFIG_UNLZOP) += lzop.o diff --git a/coreutils/expand.c b/coreutils/expand.c index 63b682330..9ce86ebff 100644 --- a/coreutils/expand.c +++ b/coreutils/expand.c @@ -43,6 +43,7 @@ //config: depends on UNEXPAND && LONG_OPTS //applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand)) //kbuild:lib-$(CONFIG_EXPAND) += expand.o diff --git a/coreutils/who.c b/coreutils/who.c index ac19dc720..e6179bb00 100644 --- a/coreutils/who.c +++ b/coreutils/who.c @@ -30,6 +30,7 @@ //config: help //config: Print users currently logged on. +// APPLET_ODDNAME:name main location suid_type help //applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users)) //applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/findutils/grep.c b/findutils/grep.c index 547e3d576..ec7605d85 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -46,6 +46,7 @@ //config: Print the specified number of context lines (-C). //applet:IF_GREP(APPLET(grep, BB_DIR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_EGREP(APPLET_ODDNAME(egrep, grep, BB_DIR_BIN, BB_SUID_DROP, egrep)) //applet:IF_FGREP(APPLET_ODDNAME(fgrep, grep, BB_DIR_BIN, BB_SUID_DROP, fgrep)) diff --git a/init/halt.c b/init/halt.c index b7fb10869..f69b89772 100644 --- a/init/halt.c +++ b/init/halt.c @@ -46,8 +46,9 @@ //config: locating telinit executable. //applet:IF_HALT(APPLET(halt, BB_DIR_SBIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_POWEROFF(APPLET_ODDNAME(poweroff, halt, BB_DIR_SBIN, BB_SUID_DROP, poweroff)) -//applet:IF_REBOOT(APPLET_ODDNAME(reboot, halt, BB_DIR_SBIN, BB_SUID_DROP, reboot)) +//applet:IF_REBOOT( APPLET_ODDNAME(reboot, halt, BB_DIR_SBIN, BB_SUID_DROP, reboot)) //kbuild:lib-$(CONFIG_HALT) += halt.o //kbuild:lib-$(CONFIG_POWEROFF) += halt.o diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c index ce4a7bbd2..af7c31779 100644 --- a/loginutils/add-remove-shell.c +++ b/loginutils/add-remove-shell.c @@ -19,6 +19,7 @@ //config: help //config: Remove shells from /etc/shells. +// APPLET_ODDNAME:name main location suid_type help //applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell )) //applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell)) diff --git a/miscutils/flash_lock_unlock.c b/miscutils/flash_lock_unlock.c index 2f698641f..003496d5b 100644 --- a/miscutils/flash_lock_unlock.c +++ b/miscutils/flash_lock_unlock.c @@ -17,7 +17,8 @@ //config: The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This //config: utility unlocks part or all of the flash device. -//applet:IF_FLASH_LOCK(APPLET_ODDNAME(flash_lock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_lock)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_FLASH_LOCK( APPLET_ODDNAME(flash_lock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_lock)) //applet:IF_FLASH_UNLOCK(APPLET_ODDNAME(flash_unlock, flash_lock_unlock, BB_DIR_USR_SBIN, BB_SUID_DROP, flash_unlock)) //kbuild:lib-$(CONFIG_FLASH_LOCK) += flash_lock_unlock.o diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index 8e55e9577..982e3e52a 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -45,11 +45,12 @@ //config: help //config: Update a UBI volume. -//applet:IF_UBIATTACH(APPLET_ODDNAME(ubiattach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiattach)) -//applet:IF_UBIDETACH(APPLET_ODDNAME(ubidetach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubidetach)) -//applet:IF_UBIMKVOL(APPLET_ODDNAME(ubimkvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubimkvol)) -//applet:IF_UBIRMVOL(APPLET_ODDNAME(ubirmvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirmvol)) -//applet:IF_UBIRSVOL(APPLET_ODDNAME(ubirsvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirsvol)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_UBIATTACH( APPLET_ODDNAME(ubiattach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiattach)) +//applet:IF_UBIDETACH( APPLET_ODDNAME(ubidetach, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubidetach)) +//applet:IF_UBIMKVOL( APPLET_ODDNAME(ubimkvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubimkvol)) +//applet:IF_UBIRMVOL( APPLET_ODDNAME(ubirmvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirmvol)) +//applet:IF_UBIRSVOL( APPLET_ODDNAME(ubirsvol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubirsvol)) //applet:IF_UBIUPDATEVOL(APPLET_ODDNAME(ubiupdatevol, ubi_tools, BB_DIR_USR_SBIN, BB_SUID_DROP, ubiupdatevol)) //kbuild:lib-$(CONFIG_UBIATTACH) += ubi_tools.o diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 21fa9dbdd..e44feeefa 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -25,10 +25,11 @@ //config: Check if the module is already loaded. //applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_DEPMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod))) //applet:IF_INSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod))) -//applet:IF_LSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))) -//applet:IF_RMMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))) +//applet:IF_LSMOD(IF_MODPROBE_SMALL( APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))) +//applet:IF_RMMOD(IF_MODPROBE_SMALL( APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))) //kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o diff --git a/networking/hostname.c b/networking/hostname.c index 04a051ede..9f2418422 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -22,6 +22,7 @@ //config: help //config: Alias to "hostname -d". +// APPLET_ODDNAME:name main location suid_type help //applet:IF_DNSDOMAINNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname)) //applet:IF_HOSTNAME(APPLET(hostname, BB_DIR_BIN, BB_SUID_DROP)) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 78baa6690..a76fe1021 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -106,7 +106,8 @@ //config: Otherwise, if udhcpc applet is enabled, it is used. //config: Otherwise, ifup/ifdown will have no support for DHCP. -//applet:IF_IFUP(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_IFUP( APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) //applet:IF_IFDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown)) //kbuild:lib-$(CONFIG_IFUP) += ifupdown.o diff --git a/printutils/lpr.c b/printutils/lpr.c index ed6a84a93..8cc87d167 100644 --- a/printutils/lpr.c +++ b/printutils/lpr.c @@ -23,6 +23,7 @@ //config: help //config: lpq is a print spool queue examination and manipulation program. +// APPLET_ODDNAME:name main location suid_type help //applet:IF_LPQ(APPLET_ODDNAME(lpq, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpq)) //applet:IF_LPR(APPLET_ODDNAME(lpr, lpqr, BB_DIR_USR_BIN, BB_SUID_DROP, lpr)) diff --git a/procps/kill.c b/procps/kill.c index 0ef1716a4..7ae5beead 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -33,7 +33,8 @@ //config: the script it was called from. //applet:IF_KILL(APPLET(kill, BB_DIR_BIN, BB_SUID_DROP)) -//applet:IF_KILLALL(APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_KILLALL( APPLET_ODDNAME(killall, kill, BB_DIR_USR_BIN, BB_SUID_DROP, killall)) //applet:IF_KILLALL5(APPLET_ODDNAME(killall5, kill, BB_DIR_USR_SBIN, BB_SUID_DROP, killall5)) //kbuild:lib-$(CONFIG_KILL) += kill.o diff --git a/procps/pgrep.c b/procps/pgrep.c index ac82b5156..e932a32bc 100644 --- a/procps/pgrep.c +++ b/procps/pgrep.c @@ -19,6 +19,7 @@ //config: Send signals to processes by name. //applet:IF_PGREP(APPLET(pgrep, BB_DIR_USR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_PKILL(APPLET_ODDNAME(pkill, pgrep, BB_DIR_USR_BIN, BB_SUID_DROP, pkill)) //kbuild:lib-$(CONFIG_PGREP) += pgrep.o diff --git a/runit/chpst.c b/runit/chpst.c index 3769af25e..846c846d3 100644 --- a/runit/chpst.c +++ b/runit/chpst.c @@ -60,7 +60,8 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //config: Sets soft resource limits as specified by options //applet:IF_CHPST(APPLET(chpst, BB_DIR_USR_BIN, BB_SUID_DROP)) -//applet:IF_ENVDIR(APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_ENVDIR( APPLET_ODDNAME(envdir, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envdir)) //applet:IF_ENVUIDGID(APPLET_ODDNAME(envuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, envuidgid)) //applet:IF_SETUIDGID(APPLET_ODDNAME(setuidgid, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, setuidgid)) //applet:IF_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, BB_DIR_USR_BIN, BB_SUID_DROP, softlimit)) diff --git a/selinux/setfiles.c b/selinux/setfiles.c index 9fa5d3f30..c14a67be5 100644 --- a/selinux/setfiles.c +++ b/selinux/setfiles.c @@ -30,6 +30,7 @@ //config: the same as setfiles, but usage is a little different. //applet:IF_SETFILES(APPLET(setfiles, BB_DIR_SBIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_RESTORECON(APPLET_ODDNAME(restorecon, setfiles, BB_DIR_SBIN, BB_SUID_DROP, restorecon)) //kbuild:lib-$(CONFIG_SETFILES) += setfiles.o diff --git a/shell/ash.c b/shell/ash.c index d8f41327b..e07b81c05 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -136,7 +136,8 @@ //config:endif # ash options //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP)) -//applet:IF_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash)) //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o diff --git a/shell/hush.c b/shell/hush.c index d90c1485a..4123cc19e 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -277,8 +277,9 @@ //config: msh is deprecated and will be removed, please migrate to hush. //applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP)) -//applet:IF_MSH(APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) -//applet:IF_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_MSH( APPLET_ODDNAME(msh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) +//applet:IF_SH_IS_HUSH( APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) //applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush)) //kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c index 8bc2c443b..28148fcbe 100644 --- a/util-linux/freeramdisk.c +++ b/util-linux/freeramdisk.c @@ -33,6 +33,7 @@ //config: ramdisk. If you have no use for freeing memory from a ramdisk, leave //config: this disabled. +// APPLET_ODDNAME:name main location suid_type help //applet:IF_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, BB_DIR_BIN, BB_SUID_DROP, fdflush)) //applet:IF_FREERAMDISK(APPLET(freeramdisk, BB_DIR_SBIN, BB_SUID_DROP)) diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c index 5816a208e..4a7a878ac 100644 --- a/util-linux/mkfs_ext2.c +++ b/util-linux/mkfs_ext2.c @@ -21,7 +21,8 @@ //config: help //config: Alias to "mke2fs". -//applet:IF_MKE2FS(APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_MKE2FS( APPLET_ODDNAME(mke2fs, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) //applet:IF_MKFS_EXT2(APPLET_ODDNAME(mkfs.ext2, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) ////////:IF_MKFS_EXT3(APPLET_ODDNAME(mkfs.ext3, mkfs_ext2, BB_DIR_SBIN, BB_SUID_DROP, mkfs_ext2)) diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c index 912246b93..0dfe34705 100644 --- a/util-linux/mkfs_minix.c +++ b/util-linux/mkfs_minix.c @@ -80,6 +80,7 @@ //config: this. If you enabled 'mkfs_minix' then you almost certainly want to //config: be using the version 2 filesystem support. +// APPLET_ODDNAME:name main location suid_type help //applet:IF_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, BB_DIR_SBIN, BB_SUID_DROP, mkfs_minix)) //kbuild:lib-$(CONFIG_MKFS_MINIX) += mkfs_minix.o diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index ab70853a1..1fc943430 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -21,7 +21,8 @@ //config: help //config: Alias to "mkdosfs". -//applet:IF_MKDOSFS(APPLET_ODDNAME(mkdosfs, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_MKDOSFS( APPLET_ODDNAME(mkdosfs, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) //applet:IF_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, BB_DIR_SBIN, BB_SUID_DROP, mkfs_vfat)) //kbuild:lib-$(CONFIG_MKDOSFS) += mkfs_vfat.o diff --git a/util-linux/setarch.c b/util-linux/setarch.c index ec473e9cb..e4124b044 100644 --- a/util-linux/setarch.c +++ b/util-linux/setarch.c @@ -31,6 +31,7 @@ //config: Alias to "setarch linux64". //applet:IF_SETARCH(APPLET(setarch, BB_DIR_BIN, BB_SUID_DROP)) +// APPLET_ODDNAME:name main location suid_type help //applet:IF_LINUX32(APPLET_ODDNAME(linux32, setarch, BB_DIR_BIN, BB_SUID_DROP, linux32)) //applet:IF_LINUX64(APPLET_ODDNAME(linux64, setarch, BB_DIR_BIN, BB_SUID_DROP, linux64)) diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index b8f4e9447..313ea0ef9 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c @@ -41,7 +41,8 @@ //config: help //config: This option enables the 'swapoff' utility. -//applet:IF_SWAPON(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) +// APPLET_ODDNAME:name main location suid_type help +//applet:IF_SWAPON( APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) //applet:IF_SWAPOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) //kbuild:lib-$(CONFIG_SWAPON) += swaponoff.o -- cgit v1.2.3-55-g6feb From ef0e76cc2783e83c6cbf90bf264b36b6bb60605b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Jan 2017 18:19:29 +0100 Subject: taskset: rewrite to be task size-agnostic function old new delta packed_usage 31130 31190 +60 taskset_main 623 525 -98 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 60/-98) Total: -38 bytes Signed-off-by: Denys Vlasenko --- miscutils/taskset.c | 205 ++++++++++++++++++++++++++-------------------------- 1 file changed, 103 insertions(+), 102 deletions(-) diff --git a/miscutils/taskset.c b/miscutils/taskset.c index fb352ab8d..a87b9bd43 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c @@ -8,7 +8,7 @@ //config:config TASKSET //config: bool "taskset" -//config: default n # doesn't build on some non-x86 targets (m68k) +//config: default y //config: help //config: Retrieve or set a processes's CPU affinity. //config: This requires sched_{g,s}etaffinity support in your libc. @@ -18,15 +18,15 @@ //config: default y //config: depends on TASKSET //config: help -//config: Add code for fancy output. This merely silences a compiler-warning -//config: and adds about 135 Bytes. May be needed for machines with alot -//config: of CPUs. +//config: Needed for machines with more than 32-64 CPUs: +//config: affinity parameter 0xHHHHHHHHHHHHHHHHHHHH can be arbitrarily long +//config: in this case. Otherwise, it is limited to sizeof(long). //applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_TASKSET) += taskset.o //usage:#define taskset_trivial_usage -//usage: "[-p] [MASK] [PID | PROG ARGS]" +//usage: "[-p] [HEXMASK] [PID | PROG ARGS]" //usage:#define taskset_full_usage "\n\n" //usage: "Set or get CPU affinity\n" //usage: "\n -p Operate on an existing PID" @@ -42,71 +42,80 @@ //usage: "$ taskset -p 1\n" //usage: "pid 1's current affinity mask: 3\n" /* - Not yet implemented: + * Not yet implemented: * -a/--all-tasks (affect all threads) + * needs to get TIDs from /proc/PID/task/ and use _them_ as "pid" in sched_setaffinity(pid) * -c/--cpu-list (specify CPUs via "1,3,5-7") */ #include #include "libbb.h" +typedef unsigned long ul; +#define SZOF_UL (unsigned)(sizeof(ul)) +#define BITS_UL (unsigned)(sizeof(ul)*8) +#define MASK_UL (unsigned)(sizeof(ul)*8 - 1) + #if ENABLE_FEATURE_TASKSET_FANCY #define TASKSET_PRINTF_MASK "%s" /* craft a string from the mask */ -static char *from_cpuset(cpu_set_t *mask) +static char *from_mask(const ul *mask, unsigned sz_in_bytes) { - int i; - char *ret = NULL; - char *str = xzalloc((CPU_SETSIZE / 4) + 1); /* we will leak it */ - - for (i = CPU_SETSIZE - 4; i >= 0; i -= 4) { - int val = 0; - int off; - for (off = 0; off <= 3; ++off) - if (CPU_ISSET(i + off, mask)) - val |= 1 << off; - if (!ret && val) - ret = str; - *str++ = bb_hexdigits_upcase[val] | 0x20; + char *str = xzalloc((sz_in_bytes+1) * 2); /* we will leak it */ + char *p = str; + for (;;) { + ul v = *mask++; + if (SZOF_UL == 4) + p += sprintf(p, "%08lx", v); + if (SZOF_UL == 8) + p += sprintf(p, "%016lx", v); + if (SZOF_UL == 16) + p += sprintf(p, "%032lx", v); /* :) */ + sz_in_bytes -= SZOF_UL; + if ((int)sz_in_bytes <= 0) + break; } - return ret; + while (str[0] == '0' && str[1]) + str++; + return str; } #else -#define TASKSET_PRINTF_MASK "%llx" -static unsigned long long from_cpuset(cpu_set_t *mask) +#define TASKSET_PRINTF_MASK "%lx" +static unsigned long long from_mask(ul *mask, unsigned sz_in_bytes UNUSED_PARAM) { - BUILD_BUG_ON(CPU_SETSIZE < 8*sizeof(int)); - - /* Take the least significant bits. Assume cpu_set_t is - * implemented as an array of unsigned long or unsigned - * int. - */ - if (CPU_SETSIZE < 8*sizeof(long)) - return *(unsigned*)mask; - if (CPU_SETSIZE < 8*sizeof(long long)) - return *(unsigned long*)mask; -# if BB_BIG_ENDIAN - if (sizeof(long long) > sizeof(long)) { - /* We can put two long in the long long, but they have to - * be swapped: the least significant word comes first in the - * array */ - unsigned long *p = (void*)mask; - return p[0] + ((unsigned long long)p[1] << (8*sizeof(long))); - } -# endif - return *(unsigned long long*)mask; + return *mask; } #endif +static unsigned long *get_aff(int pid, unsigned *sz) +{ + int r; + unsigned long *mask = NULL; + unsigned sz_in_bytes = *sz; + + for (;;) { + mask = xrealloc(mask, sz_in_bytes); + r = sched_getaffinity(pid, sz_in_bytes, (void*)mask); + if (r == 0) + break; + sz_in_bytes *= 2; + if (errno == EINVAL && (int)sz_in_bytes > 0) + continue; + bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); + } + //bb_error_msg("get mask[0]:%lx sz_in_bytes:%d", mask[0], sz_in_bytes); + *sz = sz_in_bytes; + return mask; +} int taskset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int taskset_main(int argc UNUSED_PARAM, char **argv) { - cpu_set_t mask; + ul *mask; + unsigned mask_size_in_bytes; pid_t pid = 0; unsigned opt_p; const char *current_new; - char *pid_str; char *aff = aff; /* for compiler */ /* NB: we mimic util-linux's taskset: -p does not take @@ -119,7 +128,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) argv += optind; if (opt_p) { - pid_str = *argv++; + char *pid_str = *argv++; if (*argv) { /* "-p ...rest.is.ignored..." */ aff = pid_str; pid_str = *argv; /* NB: *argv != NULL in this case */ @@ -132,13 +141,14 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) bb_show_usage(); } + mask_size_in_bytes = SZOF_UL; + mask = NULL; current_new = "current\0new"; - if (opt_p) { print_aff: - if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) - bb_perror_msg_and_die("can't %cet pid %d's affinity", 'g', pid); + mask = get_aff(pid, &mask_size_in_bytes); + if (opt_p) { printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", - pid, current_new, from_cpuset(&mask)); + pid, current_new, from_mask(mask, mask_size_in_bytes)); if (!*argv) { /* Either it was just "-p ", * or it was "-p " and we came here @@ -148,72 +158,63 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) *argv = NULL; current_new += 8; /* "new" */ } + memset(mask, 0, mask_size_in_bytes); - /* Affinity was specified, translate it into cpu_set_t */ - CPU_ZERO(&mask); - if (!ENABLE_FEATURE_TASKSET_FANCY) { - unsigned i; - unsigned long long m; + /* Affinity was specified, translate it into mask */ + /* it is always in hex, skip "0x" if it exists */ + if (aff[0] == '0' && (aff[1]|0x20) == 'x') + aff += 2; + if (!ENABLE_FEATURE_TASKSET_FANCY) { /* Do not allow zero mask: */ - m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); - i = 0; - do { - if (m & 1) - CPU_SET(i, &mask); - i++; - m >>= 1; - } while (m != 0); + mask[0] = xstrtoul_range(aff, 16, 1, ULONG_MAX); } else { unsigned i; - char *last_byte; - char *bin; - uint8_t bit_in_byte; - - /* Cheap way to get "long enough" buffer */ - bin = xstrdup(aff); - - if (aff[0] != '0' || (aff[1]|0x20) != 'x') { -/* TODO: decimal/octal masks are still limited to 2^64 */ - unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); - bin += strlen(bin); - last_byte = bin - 1; - while (m) { - *--bin = m & 0xff; - m >>= 8; - } - } else { - /* aff is "0x.....", we accept very long masks in this form */ - last_byte = hex2bin(bin, aff + 2, INT_MAX); - if (!last_byte) { - bad_aff: + char *last_char; + + i = 0; /* bit pos in mask[] */ + + /* aff is ASCII hex string, accept very long masks in this form. + * Process hex string AABBCCDD... to ulong mask[] + * from the rightmost nibble, which is least-significant. + * Bits not fitting into mask[] are ignored: (example: 1234 + * in 12340000000000000000000000000000000000000ff) + */ + last_char = strchrnul(aff, '\0'); + while (last_char > aff) { + char c; + ul val; + + last_char--; + c = *last_char; + if (isdigit(c)) + val = c - '0'; + else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') + val = (c|0x20) - ('a' - 10); + else bb_error_msg_and_die("bad affinity '%s'", aff); - } - last_byte--; /* now points to the last byte */ - } - i = 0; - bit_in_byte = 1; - while (last_byte >= bin) { - if (bit_in_byte & *last_byte) { - if (i >= CPU_SETSIZE) - goto bad_aff; - CPU_SET(i, &mask); + if (i < mask_size_in_bytes * 8) { + mask[i / BITS_UL] |= val << (i & MASK_UL); //bb_error_msg("bit %d set", i); } - i++; - /* bit_in_byte is uint8_t! & 0xff is implied */ - bit_in_byte = (bit_in_byte << 1); - if (!bit_in_byte) { - bit_in_byte = 1; - last_byte--; - } + /* else: + * We can error out here, but we don't. + * For one, kernel itself ignores bits in mask[] + * which do not map to any CPUs. + * If mask has one 32-bit long, + * but you have only 8 CPUs, all bits beyond first 8 + * are ignored, silently. + * No point in making bits past 31th to be errors. + */ + i += 4; } } /* Set pid's or our own (pid==0) affinity */ - if (sched_setaffinity(pid, sizeof(mask), &mask)) + if (sched_setaffinity(pid, mask_size_in_bytes, (void*)mask)) bb_perror_msg_and_die("can't %cet pid %d's affinity", 's', pid); + //bb_error_msg("set mask[0]:%lx", mask[0]); if (!argv[0]) /* "-p [...ignored...]" */ goto print_aff; /* print new affinity and exit */ -- cgit v1.2.3-55-g6feb From b181ca75528ece1a16f36bd7fdabe6916d9e5aac Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Jan 2017 18:48:58 +0100 Subject: typo in comment Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index 1aaf5255c..420695a20 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -86,7 +86,7 @@ const struct dhcp_optflag dhcp_optflags[] = { }; /* Used for converting options from incoming packets to env variables - * for udhcpc stript, and for setting options for udhcpd via + * for udhcpc script, and for setting options for udhcpd via * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. */ /* Must match dhcp_optflags[] order */ -- cgit v1.2.3-55-g6feb From 86663910babe4684fe4ac7cead2fab6f4aa576d7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Jan 2017 18:59:38 +0100 Subject: taskset: separate "current" and "new" strings Better for constant sharing: text data bss dec hex filename 912997 485 6856 920338 e0b12 busybox_old 912988 485 6856 920329 e0b09 busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/taskset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miscutils/taskset.c b/miscutils/taskset.c index a87b9bd43..68b0fa6eb 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c @@ -143,7 +143,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) mask_size_in_bytes = SZOF_UL; mask = NULL; - current_new = "current\0new"; + current_new = "current"; print_aff: mask = get_aff(pid, &mask_size_in_bytes); if (opt_p) { @@ -156,7 +156,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) return EXIT_SUCCESS; } *argv = NULL; - current_new += 8; /* "new" */ + current_new = "new"; } memset(mask, 0, mask_size_in_bytes); -- cgit v1.2.3-55-g6feb From eba7fe6bb9fdc89cf9d4d33043cd3856253d303d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 29 Jan 2017 19:14:26 +0100 Subject: vi,fsck: do not use build timestamp unconditionally. Closes 9626 Signed-off-by: Denys Vlasenko --- e2fsprogs/fsck.c | 2 +- editors/vi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index 6414988b4..eb53002b1 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -1071,7 +1071,7 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) new_args(); /* G.args[G.num_args - 1] is the last, NULL element */ if (!notitle) - puts("fsck (busybox "BB_VER", "BB_BT")"); + puts("fsck (busybox "BB_VER")"); /* Even plain "fsck /dev/hda1" needs fstab to get fs type, * so we are scanning it anyway */ diff --git a/editors/vi.c b/editors/vi.c index 1e5ef44fb..bbaac50df 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -1457,7 +1457,7 @@ static void colon(char *buf) } #endif /* FEATURE_VI_SEARCH */ } else if (strncmp(cmd, "version", i) == 0) { // show software version - status_line(BB_VER " " BB_BT); + status_line(BB_VER); } else if (strncmp(cmd, "write", i) == 0 // write text to file || strncmp(cmd, "wq", i) == 0 || strncmp(cmd, "wn", i) == 0 -- cgit v1.2.3-55-g6feb From 35b54a3c247235b1bffe2a22784a1d5be10267f3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2017 00:45:05 +0100 Subject: libbb: match_fstype() is unreadable in the extreme, fixing it Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/match_fstype.c | 20 ++++++++------------ util-linux/mount.c | 2 +- util-linux/umount.c | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 07fe20dac..b054e0559 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1312,8 +1312,8 @@ const struct hwtype *get_hwtype(const char *name) FAST_FUNC; const struct hwtype *get_hwntype(int type) FAST_FUNC; +extern int fstype_matches(const char *fstype, const char *comma_list) FAST_FUNC; #ifdef HAVE_MNTENT_H -extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC; extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC; #endif extern void erase_mtab(const char * name) FAST_FUNC; diff --git a/libbb/match_fstype.c b/libbb/match_fstype.c index b066b4211..6046bc6db 100644 --- a/libbb/match_fstype.c +++ b/libbb/match_fstype.c @@ -12,34 +12,30 @@ #include "libbb.h" -#ifdef HAVE_MNTENT_H - -int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype) +int FAST_FUNC fstype_matches(const char *fstype, const char *comma_list) { int match = 1; - if (!t_fstype) + if (!comma_list) return match; - if (t_fstype[0] == 'n' && t_fstype[1] == 'o') { + if (comma_list[0] == 'n' && comma_list[1] == 'o') { match--; - t_fstype += 2; + comma_list += 2; } while (1) { - char *after_mnt_type = is_prefixed_with(t_fstype, mt->mnt_type); + char *after_mnt_type = is_prefixed_with(comma_list, fstype); if (after_mnt_type && (*after_mnt_type == '\0' || *after_mnt_type == ',') ) { return match; } - t_fstype = strchr(t_fstype, ','); - if (!t_fstype) + comma_list = strchr(comma_list, ','); + if (!comma_list) break; - t_fstype++; + comma_list++; } return !match; } - -#endif /* HAVE_MNTENT_H */ diff --git a/util-linux/mount.c b/util-linux/mount.c index 4f5dced10..f0245f714 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -2312,7 +2312,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) bb_error_msg_and_die(bb_msg_you_must_be_root); // Does type match? (NULL matches always) - if (!match_fstype(mtcur, fstype)) + if (!fstype_matches(mtcur->mnt_type, fstype)) continue; // Skip noauto and swap anyway diff --git a/util-linux/umount.c b/util-linux/umount.c index 78eef57a5..c958fd552 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -125,8 +125,8 @@ int umount_main(int argc UNUSED_PARAM, char **argv) } else { setup_common_bufsiz(); while (getmntent_r(fp, &me, bb_common_bufsiz1, COMMON_BUFSIZE)) { - /* Match fstype if passed */ - if (!match_fstype(&me, fstype)) + /* Match fstype (fstype==NULL matches always) */ + if (!fstype_matches(me.mnt_type, fstype)) continue; m = xzalloc(sizeof(*m)); m->next = mtl; -- cgit v1.2.3-55-g6feb From 67f6db6b2768e9af44132b0a11fbadf15c330283 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2017 16:27:37 +0100 Subject: wget: add a big explanation what TLS code implements and what does not Signed-off-by: Denys Vlasenko --- networking/wget.c | 33 +++++++++++++++++++++++++++++++++ shell/Config.src | 6 +++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 90eedaf7a..252f94dc6 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -58,6 +58,39 @@ //config: On NOMMU machines, ssl_helper applet should be available //config: in the $PATH for this to work. Make sure to select that applet. //config: +//config: Note: currently, TLS code only makes TLS I/O work, it +//config: does *not* check that the peer is who it claims to be, etc. +//config: IOW: it uses peer-supplied public keys to establish encryption +//config: and signing keys, then encrypts and signs outgoing data and +//config: decrypts incoming data. +//config: It does not check signature hashes on the incoming data: +//config: this means that attackers manipulating TCP packets can +//config: send altered data and we unknowingly receive garbage. +//config: (This check might be relatively easy to add). +//config: It does not check public key's certificate: +//config: this means that the peer may be an attacker impersonating +//config: the server we think we are talking to. +//config: +//config: If you think this is unacceptable, consider this. As more and more +//config: servers switch to HTTPS-only operation, without such "crippled" +//config: TLS code it is *impossible* to simply download a kernel source +//config: from kernel.org. Which can in real world translate into +//config: "my small automatic tooling to build cross-compilers from sources +//config: no longer works, I need to additionally keep a local copy +//config: of ~4 megabyte source tarball of a SSL library and ~2 megabyte +//config: source of wget, need to compile and built both before I can +//config: download anything. All this despite the fact that the build +//config: is done in a QEMU sandbox on a machine with absolutely nothing +//config: worth stealing, so I don't care if someone would go to a lot +//config: of trouble to intercept my HTTPS download to send me an altered +//config: kernel tarball". +//config: +//config: If you still think this is unacceptable, send patches. +//config: +//config: If you still think this is unacceptable, do not want to send +//config: patches, but do want to waste bandwidth expaining how wrong +//config: it is, you will be ignored. +//config: //config:config FEATURE_WGET_OPENSSL //config: bool "Try to connect to HTTPS using openssl" //config: default y diff --git a/shell/Config.src b/shell/Config.src index 6a7e12aa7..ccb1b15fe 100644 --- a/shell/Config.src +++ b/shell/Config.src @@ -123,9 +123,9 @@ config FEATURE_SH_STANDALONE This is implemented by re-execing /proc/self/exe (typically) with right parameters. - However, there are drawbacks: it is problematic in chroot jails without - mounted /proc, and ps/top may show command name as 'exe' for applets - started this way. + However, there are drawbacks: it is problematic in chroot jails + without mounted /proc, and ps/top may show command name as 'exe' + for applets started this way. config FEATURE_SH_NOFORK bool "Run 'nofork' applets directly" -- cgit v1.2.3-55-g6feb From 065e988e7ae66b3f36d280ed6ca580e29cb6358d Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Mon, 30 Jan 2017 19:14:50 +0100 Subject: modutils: fix config options dependency module.aliases and module.symbols files have no use in modprobe-small implementation. So FEATURE_MODUTILS_ALIAS and FEATURE_MODUTILS_SYMBOLS will depend on !MODPROBE_SMALL. The try_to_mmap_module() function is not called in modprobe-small.c, so I will let FEATURE_INSMOD_TRY_MMAP depend on !MODPROBE_SMALL for now. Signed-off-by: Kang-Che Sung Likewise, FEATURE_2_4_MODULES is not used by modprobe-small. Signed-off-by: Denys Vlasenko --- configs/TEST_nommu_defconfig | 3 --- configs/TEST_rh9_defconfig | 3 --- configs/android2_defconfig | 3 --- configs/android_502_defconfig | 3 --- configs/android_defconfig | 3 --- configs/android_ndk_defconfig | 3 --- modutils/Config.src | 8 ++++---- 7 files changed, 4 insertions(+), 22 deletions(-) diff --git a/configs/TEST_nommu_defconfig b/configs/TEST_nommu_defconfig index b7d9a35c2..7fbbbecc7 100644 --- a/configs/TEST_nommu_defconfig +++ b/configs/TEST_nommu_defconfig @@ -452,15 +452,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -CONFIG_FEATURE_INSMOD_TRY_MMAP=y # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/configs/TEST_rh9_defconfig b/configs/TEST_rh9_defconfig index 99deb67fe..34d8e31e2 100644 --- a/configs/TEST_rh9_defconfig +++ b/configs/TEST_rh9_defconfig @@ -467,15 +467,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/configs/android2_defconfig b/configs/android2_defconfig index b079fa759..20866c32b 100644 --- a/configs/android2_defconfig +++ b/configs/android2_defconfig @@ -487,15 +487,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/configs/android_502_defconfig b/configs/android_502_defconfig index 4273d3382..bdca9eebb 100644 --- a/configs/android_502_defconfig +++ b/configs/android_502_defconfig @@ -597,15 +597,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/configs/android_defconfig b/configs/android_defconfig index b9489c456..6ef81750e 100644 --- a/configs/android_defconfig +++ b/configs/android_defconfig @@ -511,15 +511,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/configs/android_ndk_defconfig b/configs/android_ndk_defconfig index caf22e57b..35d03b42e 100644 --- a/configs/android_ndk_defconfig +++ b/configs/android_ndk_defconfig @@ -522,15 +522,12 @@ CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y # Options common to multiple modutils # # CONFIG_FEATURE_2_4_MODULES is not set -# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set # CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set # CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set # CONFIG_FEATURE_INSMOD_LOADINKMEM is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP is not set # CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set # CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set -# CONFIG_FEATURE_MODUTILS_ALIAS is not set -# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set CONFIG_DEFAULT_MODULES_DIR="/system/lib/modules" CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" diff --git a/modutils/Config.src b/modutils/Config.src index 1808f332d..1aee57ee7 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -43,7 +43,7 @@ comment "Options common to multiple modutils" config FEATURE_2_4_MODULES bool "Support version 2.2/2.4 Linux kernels" default n - depends on INSMOD || RMMOD || LSMOD + depends on (INSMOD || RMMOD || LSMOD) && !MODPROBE_SMALL select PLATFORM_LINUX help Support module loading for 2.2.x and 2.4.x Linux kernels. @@ -53,7 +53,7 @@ config FEATURE_2_4_MODULES config FEATURE_INSMOD_TRY_MMAP bool "Try to load module from a mmap'ed area" default n - depends on INSMOD || MODPROBE_SMALL + depends on INSMOD && !MODPROBE_SMALL select PLATFORM_LINUX help This option causes module loading code to try to mmap @@ -135,7 +135,7 @@ config FEATURE_CHECK_TAINTED_MODULE config FEATURE_MODUTILS_ALIAS bool "Support module.aliases file" default y - depends on DEPMOD || MODPROBE + depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL select PLATFORM_LINUX help Generate and parse modules.alias containing aliases for bus @@ -152,7 +152,7 @@ config FEATURE_MODUTILS_ALIAS config FEATURE_MODUTILS_SYMBOLS bool "Support module.symbols file" default y - depends on DEPMOD || MODPROBE + depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL select PLATFORM_LINUX help Generate and parse modules.symbols containing aliases for -- cgit v1.2.3-55-g6feb From ca659f84b20ae63e0d11d9b1bfa2f9d610e05faa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2017 19:21:12 +0100 Subject: modprobe-small: fix --help texts, they are from "big" modutils Signed-off-by: Denys Vlasenko --- modutils/lsmod.c | 2 +- modutils/modprobe-small.c | 37 +++++++------------------------------ 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 24589420a..9ab49f35b 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -34,7 +34,7 @@ //usage:#define lsmod_trivial_usage //usage: "" //usage:#define lsmod_full_usage "\n\n" -//usage: "List the currently loaded kernel modules" +//usage: "List loaded kernel modules" //usage:#endif #include "libbb.h" diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index e44feeefa..49c06d759 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -893,46 +893,23 @@ The following options are useful for people managing distributions: //usage:#define lsmod_trivial_usage //usage: "" //usage:#define lsmod_full_usage "\n\n" -//usage: "List the currently loaded kernel modules" +//usage: "List loaded kernel modules" //usage:#define insmod_trivial_usage -//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") -//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") -//usage: "[SYMBOL=VALUE]..." +//usage: "FILE" IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(" [SYMBOL=VALUE]...") //usage:#define insmod_full_usage "\n\n" //usage: "Load kernel module" -//usage: IF_FEATURE_2_4_MODULES( "\n" -//usage: "\n -f Force module to load into the wrong kernel version" -//usage: "\n -k Make module autoclean-able" -//usage: "\n -v Verbose" -//usage: "\n -q Quiet" -//usage: "\n -L Lock: prevent simultaneous loads" -//usage: IF_FEATURE_INSMOD_LOAD_MAP( -//usage: "\n -m Output load map to stdout" -//usage: ) -//usage: "\n -x Don't export externs" -//usage: ) //usage:#define rmmod_trivial_usage -//usage: "[-wfa] [MODULE]..." +//usage: "MODULE..." //usage:#define rmmod_full_usage "\n\n" -//usage: "Unload kernel modules\n" -//usage: "\n -w Wait until the module is no longer used" -//usage: "\n -f Force unload" -//usage: "\n -a Remove all unused modules (recursively)" -//usage: -//usage:#define rmmod_example_usage -//usage: "$ rmmod tulip\n" +//usage: "Unload kernel modules" //usage:#define modprobe_trivial_usage -//usage: "[-qfwrsv] MODULE [SYMBOL=VALUE]..." +//usage: "[-rq] MODULE" IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(" [SYMBOL=VALUE]...") //usage:#define modprobe_full_usage "\n\n" -//usage: " -r Remove MODULE (stacks) or do autoclean" +//usage: " -r Remove MODULE" //usage: "\n -q Quiet" -//usage: "\n -v Verbose" -//usage: "\n -f Force" -//usage: "\n -w Wait for unload" -//usage: "\n -s Report via syslog instead of stderr" //usage:#endif @@ -964,7 +941,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* depmod? */ if ((MOD_APPLET_CNT == 2 && ENABLE_DEPMOD && ENABLE_LSMOD) - /* ^^^^only depmod and lsmod is configured^^^^^^^^^^^^^^^ */ + /* ^^^"only depmod and lsmod is configured"^^^^^^^^^^^^^^ */ /* note: we already know here it is not lsmod (handled before) */ || is_depmod ) { -- cgit v1.2.3-55-g6feb From d6ace669737571c98977972b7392456f9e5156f6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2017 22:20:06 +0100 Subject: taskset: simplify code a bit; tweak --help Signed-off-by: Denys Vlasenko --- miscutils/taskset.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/miscutils/taskset.c b/miscutils/taskset.c index 68b0fa6eb..94a07383a 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c @@ -26,7 +26,7 @@ //kbuild:lib-$(CONFIG_TASKSET) += taskset.o //usage:#define taskset_trivial_usage -//usage: "[-p] [HEXMASK] [PID | PROG ARGS]" +//usage: "[-p] [HEXMASK] PID | PROG ARGS" //usage:#define taskset_full_usage "\n\n" //usage: "Set or get CPU affinity\n" //usage: "\n -p Operate on an existing PID" @@ -116,7 +116,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) pid_t pid = 0; unsigned opt_p; const char *current_new; - char *aff = aff; /* for compiler */ + char *aff; /* NB: we mimic util-linux's taskset: -p does not take * an argument, i.e., "-pN" is NOT valid, only "-p N"! @@ -127,29 +127,28 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) opt_p = getopt32(argv, "+p"); argv += optind; + aff = *argv++; if (opt_p) { - char *pid_str = *argv++; + char *pid_str = aff; if (*argv) { /* "-p ...rest.is.ignored..." */ - aff = pid_str; pid_str = *argv; /* NB: *argv != NULL in this case */ } /* else it was just "-p ", and *argv == NULL */ pid = xatoul_range(pid_str, 1, ((unsigned)(pid_t)ULONG_MAX) >> 1); } else { - aff = *argv++; /* */ + /* */ if (!*argv) bb_show_usage(); } mask_size_in_bytes = SZOF_UL; - mask = NULL; current_new = "current"; print_aff: mask = get_aff(pid, &mask_size_in_bytes); if (opt_p) { printf("pid %d's %s affinity mask: "TASKSET_PRINTF_MASK"\n", pid, current_new, from_mask(mask, mask_size_in_bytes)); - if (!*argv) { + if (*argv == NULL) { /* Either it was just "-p ", * or it was "-p " and we came here * for the second time (see goto below) */ @@ -166,8 +165,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) aff += 2; if (!ENABLE_FEATURE_TASKSET_FANCY) { - /* Do not allow zero mask: */ - mask[0] = xstrtoul_range(aff, 16, 1, ULONG_MAX); + mask[0] = xstrtoul(aff, 16); } else { unsigned i; char *last_char; @@ -201,8 +199,8 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) /* else: * We can error out here, but we don't. * For one, kernel itself ignores bits in mask[] - * which do not map to any CPUs. - * If mask has one 32-bit long, + * which do not map to any CPUs: + * if mask[] has one 32-bit long element, * but you have only 8 CPUs, all bits beyond first 8 * are ignored, silently. * No point in making bits past 31th to be errors. -- cgit v1.2.3-55-g6feb From b5b21126ca9217e1f721996cbef44c019185dd5d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 31 Jan 2017 21:58:55 +0100 Subject: ash: improve / fix glob expansion When using musl libc glob() a very long string can cause glob() to fail, which leads to an out of memory error being raised by ash. This can happen easily if a very long quoted string contains *, even though no glob expansion should ever be performed on it (since it's quoted). Fix this by properly parsing control characters and escaping and only accept unquoted metacharacters. While we're at it, unify this check for libc and built-in glob expansion Signed-off-by: Felix Fietkau Signed-off-by: Denys Vlasenko --- shell/ash.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index e07b81c05..6be3ec600 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7160,6 +7160,57 @@ addfname(const char *name) exparg.lastp = &sp->next; } +/* Avoid glob() (and thus, stat() et al) for words like "echo" */ +static int +hasmeta(const char *p) +{ + static const char chars[] ALIGN1 = { + '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0 + }; + + for (;;) { + p = strpbrk(p, chars); + if (!p) + break; + switch ((unsigned char) *p) { + case CTLQUOTEMARK: + for (;;) { + p++; + if (*p == CTLQUOTEMARK) + break; + if (*p == CTLESC) + p++; + if (*p == '\0') /* huh? */ + return 0; + } + break; + case '\\': + case CTLESC: + p++; + if (*p == '\0') + return 0; + break; + case '[': + if (!strchr(p + 1, ']')) { + /* It's not a properly closed [] pattern, + * but other metas may follow. Continue checking. + * my[file* _is_ globbed by bash + * and matches filenames like "my[file1". + */ + break; + } + /* fallthrough */ + default: + /* case '*': */ + /* case '?': */ + return 1; + } + p++; + } + + return 0; +} + /* If we want to use glob() from libc... */ #if !ENABLE_ASH_INTERNAL_GLOB @@ -7186,20 +7237,9 @@ expandmeta(struct strlist *str /*, int flag*/) if (fflag) goto nometa; - /* Avoid glob() (and thus, stat() et al) for words like "echo" */ - p = str->text; - while (*p) { - if (*p == '*') - goto need_glob; - if (*p == '?') - goto need_glob; - if (*p == '[') - goto need_glob; - p++; - } - goto nometa; + if (!hasmeta(str->text)) + goto nometa; - need_glob: INT_OFF; p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match @@ -7436,9 +7476,6 @@ expsort(struct strlist *str) static void expandmeta(struct strlist *str /*, int flag*/) { - static const char metachars[] ALIGN1 = { - '*', '?', '[', 0 - }; /* TODO - EXP_REDIR */ while (str) { @@ -7449,7 +7486,7 @@ expandmeta(struct strlist *str /*, int flag*/) if (fflag) goto nometa; - if (!strpbrk(str->text, metachars)) + if (!hasmeta(str->text)) goto nometa; savelastp = exparg.lastp; -- cgit v1.2.3-55-g6feb From dc7637d0aa0efeb7cc8a7bcd798f0b5679251ad9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 1 Feb 2017 01:22:37 +0100 Subject: modprobe-small: improve config help text Signed-off-by: Denys Vlasenko --- modutils/Config.src | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modutils/Config.src b/modutils/Config.src index 1aee57ee7..a9aa63993 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -10,7 +10,10 @@ config MODPROBE_SMALL default y select PLATFORM_LINUX help - Simplified modutils. + Build smaller (~1.5 kbytes), simplified module tools. + + This option by itself does not enable any applets - + you need to select applets individually below. With this option modprobe does not require modules.dep file and does not use /etc/modules.conf file. @@ -31,11 +34,6 @@ config MODPROBE_SMALL Additional module parameters can be stored in /etc/modules/$module_name files. - Apart from modprobe, other utilities are also provided: - - insmod is an alias to modprobe - - rmmod is an alias to modprobe -r - - depmod generates modules.dep.bb - INSERT comment "Options common to multiple modutils" -- cgit v1.2.3-55-g6feb From fdfd716a858f6f63289b1156a80d06d7e86947de Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Tue, 31 Jan 2017 17:06:43 +0800 Subject: modprobe-small: move lsmod code out of modprobe_main() Having lsmod code inside modprobe_main() makes some of the applet name checking code awkward. Besides, this make busybox x86_64 binary a few bytes smaller. :) function old new delta lsmod_main - 23 +23 modprobe_main 599 564 -35 ------------------------------------------------------------------- (add/remove: 1/0 grow/shrink: 0/1 up/down: 23/-35) Total: -12 bytes Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 49c06d759..325f8376b 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -24,12 +24,12 @@ //config: help //config: Check if the module is already loaded. +//applet:IF_LSMOD( IF_MODPROBE_SMALL(APPLET(lsmod, BB_DIR_SBIN, BB_SUID_DROP))) //applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))) // APPLET_ODDNAME:name main location suid_type help //applet:IF_DEPMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod))) //applet:IF_INSMOD(IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod))) -//applet:IF_LSMOD(IF_MODPROBE_SMALL( APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod))) -//applet:IF_RMMOD(IF_MODPROBE_SMALL( APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))) +//applet:IF_RMMOD( IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod))) //kbuild:lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o @@ -59,7 +59,27 @@ #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb" -#define MOD_APPLET_CNT (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD + ENABLE_LSMOD + ENABLE_RMMOD) +//usage:#if ENABLE_MODPROBE_SMALL + +//usage:#define lsmod_trivial_usage +//usage: "" +//usage:#define lsmod_full_usage "\n\n" +//usage: "List loaded kernel modules" + +//usage:#endif + +#if ENABLE_LSMOD +int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) +{ + xprint_and_close_file(xfopen_for_read("/proc/modules")); + return EXIT_SUCCESS; +} +#endif + +/* Num of applets that use modprobe_main() entry point. */ +/* lsmod is not here. */ +#define MOD_APPLET_CNT (ENABLE_MODPROBE + ENABLE_DEPMOD + ENABLE_INSMOD + ENABLE_RMMOD) /* Do not bother if MODPROBE_SMALL=y but no applets selected. */ /* The rest of the file is in this if block. */ @@ -69,7 +89,6 @@ #define is_modprobe (ENABLE_MODPROBE && (ONLY_APPLET || applet_name[0] == 'm')) #define is_depmod (ENABLE_DEPMOD && (ONLY_APPLET || applet_name[0] == 'd')) #define is_insmod (ENABLE_INSMOD && (ONLY_APPLET || applet_name[0] == 'i')) -#define is_lsmod (ENABLE_LSMOD && (ONLY_APPLET || applet_name[0] == 'l')) #define is_rmmod (ENABLE_RMMOD && (ONLY_APPLET || applet_name[0] == 'r')) enum { @@ -890,11 +909,6 @@ The following options are useful for people managing distributions: //usage:#define depmod_trivial_usage NOUSAGE_STR //usage:#define depmod_full_usage "" -//usage:#define lsmod_trivial_usage -//usage: "" -//usage:#define lsmod_full_usage "\n\n" -//usage: "List loaded kernel modules" - //usage:#define insmod_trivial_usage //usage: "FILE" IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(" [SYMBOL=VALUE]...") //usage:#define insmod_full_usage "\n\n" @@ -922,12 +936,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) struct utsname uts; IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options = NULL;) - /* are we lsmod? -> just dump /proc/modules */ - if (is_lsmod) { - xprint_and_close_file(xfopen_for_read("/proc/modules")); - return EXIT_SUCCESS; - } - INIT_G(); /* Prevent ugly corner cases with no modules at all */ @@ -940,11 +948,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) uname(&uts); /* never fails */ /* depmod? */ - if ((MOD_APPLET_CNT == 2 && ENABLE_DEPMOD && ENABLE_LSMOD) - /* ^^^"only depmod and lsmod is configured"^^^^^^^^^^^^^^ */ - /* note: we already know here it is not lsmod (handled before) */ - || is_depmod - ) { + if (is_depmod) { /* Supported: * -n: print result to stdout * -a: process all modules (default) -- cgit v1.2.3-55-g6feb From 264cb01540cdd995e7c376fd8bcef94e09e31819 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Wed, 1 Feb 2017 01:43:32 +0100 Subject: modutils: remove redundant "select PLATFORM_LINUX" configs It is enough to have only applets' configs select PLATFORM_LINUX. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/Config.src | 11 ----------- modutils/lsmod.c | 1 - modutils/modprobe.c | 1 - 3 files changed, 13 deletions(-) diff --git a/modutils/Config.src b/modutils/Config.src index a9aa63993..f2448c914 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -8,7 +8,6 @@ menu "Linux Module Utilities" config MODPROBE_SMALL bool "Simplified modutils" default y - select PLATFORM_LINUX help Build smaller (~1.5 kbytes), simplified module tools. @@ -42,7 +41,6 @@ config FEATURE_2_4_MODULES bool "Support version 2.2/2.4 Linux kernels" default n depends on (INSMOD || RMMOD || LSMOD) && !MODPROBE_SMALL - select PLATFORM_LINUX help Support module loading for 2.2.x and 2.4.x Linux kernels. This increases size considerably. Say N unless you plan @@ -52,7 +50,6 @@ config FEATURE_INSMOD_TRY_MMAP bool "Try to load module from a mmap'ed area" default n depends on INSMOD && !MODPROBE_SMALL - select PLATFORM_LINUX help This option causes module loading code to try to mmap module first. If it does not work (for example, @@ -69,7 +66,6 @@ config FEATURE_INSMOD_VERSION_CHECKING bool "Enable module version checking" default n depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - select PLATFORM_LINUX help Support checking of versions for modules. This is used to ensure that the kernel and module are made for each other. @@ -78,7 +74,6 @@ config FEATURE_INSMOD_KSYMOOPS_SYMBOLS bool "Add module symbols to kernel symbol table" default n depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - select PLATFORM_LINUX help By adding module symbols to the kernel symbol table, Oops messages occuring within kernel modules can be properly debugged. By enabling @@ -90,7 +85,6 @@ config FEATURE_INSMOD_LOADINKMEM bool "In kernel memory optimization (uClinux only)" default n depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) - select PLATFORM_LINUX help This is a special uClinux only memory optimization that lets insmod load the specified kernel module directly into kernel space, reducing @@ -101,7 +95,6 @@ config FEATURE_INSMOD_LOAD_MAP bool "Enable insmod load map (-m) option" default n depends on FEATURE_2_4_MODULES && INSMOD - select PLATFORM_LINUX help Enabling this, one would be able to get a load map output on stdout. This makes kernel module debugging @@ -113,7 +106,6 @@ config FEATURE_INSMOD_LOAD_MAP_FULL bool "Symbols in load map" default y depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL - select PLATFORM_LINUX help Without this option, -m will only output section load map. With this option, -m will also output @@ -123,7 +115,6 @@ config FEATURE_CHECK_TAINTED_MODULE bool "Support tainted module checking with new kernels" default y depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL - select PLATFORM_LINUX help Support checking for tainted modules. These are usually binary only modules that will make the linux-kernel list ignore your @@ -134,7 +125,6 @@ config FEATURE_MODUTILS_ALIAS bool "Support module.aliases file" default y depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL - select PLATFORM_LINUX help Generate and parse modules.alias containing aliases for bus identifiers: @@ -151,7 +141,6 @@ config FEATURE_MODUTILS_SYMBOLS bool "Support module.symbols file" default y depends on (DEPMOD || MODPROBE) && !MODPROBE_SMALL - select PLATFORM_LINUX help Generate and parse modules.symbols containing aliases for symbol_request() kernel calls, such as: diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 9ab49f35b..24e5d35b9 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -18,7 +18,6 @@ //config: bool "Pretty output" //config: default y //config: depends on LSMOD && !MODPROBE_SMALL -//config: select PLATFORM_LINUX //config: help //config: This option makes output format of lsmod adjusted to //config: the format of module-init-tools for Linux kernel 2.6. diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 09e3de6c3..cbec43888 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -19,7 +19,6 @@ //config: bool "Blacklist support" //config: default y //config: depends on MODPROBE && !MODPROBE_SMALL -//config: select PLATFORM_LINUX //config: help //config: Say 'y' here to enable support for the 'blacklist' command in //config: modprobe.conf. This prevents the alias resolver to resolve -- cgit v1.2.3-55-g6feb From b1d6a2c6247bae0b9f1903ba0e0d16c56f4ef556 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Tue, 31 Jan 2017 21:09:17 +0800 Subject: cmdline module options can be disabled on "big" modutils Allow module options on command line to be disabled on "big" modutils. Config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is renamed to FEATURE_CMDLINE_MODULE_OPTIONS and no longer depends on !MODPROBE_SMALL (I'm not sure if disabling this is useful on "big" modutils, but at least the macro can serve as a marker and ensure both implementations of same feature have consistent behavior.) Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/Config.src | 8 ++++++++ modutils/insmod.c | 6 +++--- modutils/modprobe-small.c | 23 ++++++++--------------- modutils/modprobe.c | 8 +++++++- modutils/modutils.c | 2 ++ modutils/modutils.h | 4 ++++ 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/modutils/Config.src b/modutils/Config.src index f2448c914..a15cce518 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -37,6 +37,14 @@ INSERT comment "Options common to multiple modutils" +config FEATURE_CMDLINE_MODULE_OPTIONS + bool "Accept module options on modprobe command line" + default y + depends on INSMOD || MODPROBE + help + Allow insmod and modprobe take module options from the applets' + command line. + config FEATURE_2_4_MODULES bool "Support version 2.2/2.4 Linux kernels" default n diff --git a/modutils/insmod.c b/modutils/insmod.c index f2c70e16f..8526979eb 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -27,9 +27,9 @@ //usage:#if !ENABLE_MODPROBE_SMALL //usage:#define insmod_trivial_usage -//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ") -//usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") -//usage: "[SYMBOL=VALUE]..." +//usage: IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE") +//usage: IF_NOT_FEATURE_2_4_MODULES("FILE") +//usage: IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") //usage:#define insmod_full_usage "\n\n" //usage: "Load kernel module" //usage: IF_FEATURE_2_4_MODULES( "\n" diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 325f8376b..04242634b 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -10,13 +10,6 @@ /* config MODPROBE_SMALL is defined in Config.src to ensure better "make config" order */ -//config:config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE -//config: bool "Accept module options on modprobe command line" -//config: default y -//config: depends on MODPROBE_SMALL && (INSMOD || MODPROBE) -//config: help -//config: Allow insmod and modprobe take module options from command line. -//config: //config:config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED //config: bool "Skip loading of already loaded modules" //config: default y @@ -690,7 +683,7 @@ static int rmmod(const char *filename) * NB: also called by depmod with bogus name "/", * just in order to force modprobe.dep.bb creation. */ -#if !ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE +#if !ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS #define process_module(a,b) process_module(a) #define cmdline_options "" #endif @@ -735,7 +728,7 @@ static int process_module(char *name, const char *cmdline_options) options = xmalloc_open_read_close(opt_filename, NULL); if (options) replace(options, '\n', ' '); -#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS if (cmdline_options) { /* NB: cmdline_options always have one leading ' ' * (see main()), we remove it here */ @@ -910,7 +903,7 @@ The following options are useful for people managing distributions: //usage:#define depmod_full_usage "" //usage:#define insmod_trivial_usage -//usage: "FILE" IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(" [SYMBOL=VALUE]...") +//usage: "FILE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") //usage:#define insmod_full_usage "\n\n" //usage: "Load kernel module" @@ -920,7 +913,7 @@ The following options are useful for people managing distributions: //usage: "Unload kernel modules" //usage:#define modprobe_trivial_usage -//usage: "[-rq] MODULE" IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(" [SYMBOL=VALUE]...") +//usage: "[-rq] MODULE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") //usage:#define modprobe_full_usage "\n\n" //usage: " -r Remove MODULE" //usage: "\n -q Quiet" @@ -934,7 +927,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) int exitcode; #endif struct utsname uts; - IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(char *options = NULL;) + IF_FEATURE_CMDLINE_MODULE_OPTIONS(char *options = NULL;) INIT_G(); @@ -998,7 +991,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) if (!ONLY_APPLET) option_mask32 |= OPT_r; } else if (!ENABLE_MODPROBE || !(option_mask32 & OPT_r)) { -# if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE +# if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS /* If not rmmod/-r, parse possible module options given on command line. * insmod/modprobe takes one module name, the rest are parameters. */ char **arg = argv; @@ -1023,7 +1016,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) if (!map) bb_perror_msg_and_die("can't read '%s'", *argv); if (init_module(map, len, - (IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : ) "") + (IF_FEATURE_CMDLINE_MODULE_OPTIONS(options ? options : ) "") ) != 0 ) { bb_error_msg_and_die("can't insert '%s': %s", @@ -1045,7 +1038,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } while (*++argv); if (ENABLE_FEATURE_CLEAN_UP) { - IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);) + IF_FEATURE_CMDLINE_MODULE_OPTIONS(free(options);) } return exitcode; #endif /* MODPROBE || INSMOD || RMMOD */ diff --git a/modutils/modprobe.c b/modutils/modprobe.c index cbec43888..a6224fa63 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -112,7 +112,7 @@ //usage: //usage:#define modprobe_trivial_usage //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" -//usage: " MODULE [SYMBOL=VALUE]..." +//usage: " MODULE" IF_FEATURE_CMDLINE_MODULE_OPTIONS(" [SYMBOL=VALUE]...") //usage:#define modprobe_full_usage "\n\n" //usage: " -a Load multiple MODULEs" //usage: "\n -l List (MODULE is a pattern)" @@ -174,7 +174,9 @@ static const char modprobe_longopts[] ALIGN1 = struct globals { llist_t *probes; /* MEs of module(s) requested on cmdline */ +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS char *cmdline_mopts; /* module options from cmdline */ +#endif int num_unresolved_deps; /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ smallint need_symbols; @@ -458,8 +460,10 @@ static int do_modprobe(struct module_entry *m) options = m2->options; m2->options = NULL; options = parse_and_add_kcmdline_module_options(options, m2->modname); +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS if (m == m2) options = gather_options_str(options, G.cmdline_mopts); +#endif if (option_mask32 & OPT_SHOW_DEPS) { printf(options ? "insmod %s/%s/%s %s\n" @@ -626,7 +630,9 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* First argument is module name, rest are parameters */ DBG("probing just module %s", *argv); add_probe(argv[0]); +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS G.cmdline_mopts = parse_cmdline_module_options(argv, /*quote_spaces:*/ 1); +#endif } /* Happens if all requested modules are already loaded */ diff --git a/modutils/modutils.c b/modutils/modutils.c index 4204f06fe..dae623ee4 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -120,6 +120,7 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname) return modname; } +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces) { char *options; @@ -155,6 +156,7 @@ char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces) /* if (optlen != 0) options[optlen-1] = '\0'; */ return options; } +#endif #if ENABLE_FEATURE_INSMOD_TRY_MMAP void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p) diff --git a/modutils/modutils.h b/modutils/modutils.h index 2cbd1448a..76ce242ba 100644 --- a/modutils/modutils.h +++ b/modutils/modutils.h @@ -51,7 +51,11 @@ void replace(char *s, char what, char with) FAST_FUNC; char *replace_underscores(char *s) FAST_FUNC; int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; char *filename2modname(const char *filename, char *modname) FAST_FUNC; +#if ENABLE_FEATURE_CMDLINE_MODULE_OPTIONS char *parse_cmdline_module_options(char **argv, int quote_spaces) FAST_FUNC; +#else +# define parse_cmdline_module_options(argv, quote_spaces) "" +#endif /* insmod for 2.4 and modprobe's options (insmod 2.6 has no options at all): */ #define INSMOD_OPTS \ -- cgit v1.2.3-55-g6feb From b6871c1965af0eb87123e13f5d81ec0c9b801b71 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 2 Feb 2017 13:04:30 +0100 Subject: ps: avoid -o stat to contain spaces. Closes 9631 function old new delta procps_scan 1227 1236 +9 Signed-off-by: Denys Vlasenko --- libbb/procps.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libbb/procps.c b/libbb/procps.c index 4edc54d48..b52c0f51b 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -370,6 +370,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) | PSSCAN_TTY | PSSCAN_NICE | PSSCAN_CPU) ) { + int s_idx; char *cp, *comm1; int tty; #if !ENABLE_FEATURE_FAST_TOP @@ -468,17 +469,20 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS sp->niceness = tasknice; #endif - - if (sp->vsz == 0 && sp->state[0] != 'Z') + sp->state[1] = ' '; + sp->state[2] = ' '; + s_idx = 1; + if (sp->vsz == 0 && sp->state[0] != 'Z') { + /* not sure what the purpose of this flag */ sp->state[1] = 'W'; - else - sp->state[1] = ' '; - if (tasknice < 0) - sp->state[2] = '<'; - else if (tasknice) /* > 0 */ - sp->state[2] = 'N'; - else - sp->state[2] = ' '; + s_idx = 2; + } + if (tasknice != 0) { + if (tasknice < 0) + sp->state[s_idx] = '<'; + else /* > 0 */ + sp->state[s_idx] = 'N'; + } } #if ENABLE_FEATURE_TOPMEM -- cgit v1.2.3-55-g6feb From 5f7c82b32f548b5a1d6a4186630e8ef496a9d5e6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 3 Feb 2017 13:00:06 +0100 Subject: ash: add INT_OFF/ON around allocations Signed-off-by: Denys Vlasenko --- shell/ash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 6be3ec600..983f7b108 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12686,7 +12686,7 @@ dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM) fullname = find_dot_file(argv[0]); argv++; args_need_save = argv[0]; - if (args_need_save) { /* . FILE ARGS, ARGS exist */ + if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */ int argc; saveparam = shellparam; shellparam.malloced = 0; @@ -13480,7 +13480,7 @@ procargs(char **argv) #if DEBUG == 2 debug = 1; #endif - /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ + /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */ if (xminusc) { minusc = *xargv++; if (*xargv) @@ -13661,9 +13661,11 @@ int ash_main(int argc UNUSED_PARAM, char **argv) if (!hp) { hp = lookupvar("HOME"); if (hp) { + INT_OFF; hp = concat_path_file(hp, ".ash_history"); setvar0("HISTFILE", hp); free((char*)hp); + INT_ON; hp = lookupvar("HISTFILE"); } } -- cgit v1.2.3-55-g6feb From 5b05d9db29843144b2ed620ca437d6a3bacc3816 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 3 Feb 2017 18:19:59 +0100 Subject: wget/tls: session_id of zero length is ok (arxiv.org responds with such) Signed-off-by: Denys Vlasenko --- networking/tls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 335324568..4e9187d4f 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -1312,7 +1312,7 @@ static void get_server_hello(tls_state_t *tls) unsigned cipher; int len, len24; - len = tls_xread_handshake_block(tls, 74); + len = tls_xread_handshake_block(tls, 74 - 32); hp = (void*)tls->inbuf; // 74 bytes: @@ -1332,7 +1332,7 @@ static void get_server_hello(tls_state_t *tls) len24 = hp->len24_lo; if (hp->session_id_len != 32) { if (hp->session_id_len != 0) - tls_error_die(tls); + bad_record_die(tls, "'server hello'", len); // session_id_len == 0: no session id // "The server @@ -1347,7 +1347,7 @@ static void get_server_hello(tls_state_t *tls) // || cipherid[1] != (CIPHER_ID & 0xff) // || cipherid[2] != 0 /* comprtype */ ) { - tls_error_die(tls); + bad_record_die(tls, "'server hello'", len); } dbg("<< SERVER_HELLO\n"); -- cgit v1.2.3-55-g6feb From c31b54fd81690b3df3898437f5865674d06e6577 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 4 Feb 2017 16:23:49 +0100 Subject: tls: fold AES CBC en/decryption into single functions Signed-off-by: Denys Vlasenko --- networking/tls.c | 30 +++++++++++------------------ networking/tls_aes.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++--- networking/tls_aes.h | 14 ++------------ 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/networking/tls.c b/networking/tls.c index 4e9187d4f..30afd9ea9 100644 --- a/networking/tls.c +++ b/networking/tls.c @@ -722,17 +722,12 @@ static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type) } while ((size & (AES_BLOCKSIZE - 1)) != 0); /* Encrypt content+MAC+padding in place */ - { - psCipherContext_t ctx; - psAesInit(&ctx, buf - AES_BLOCKSIZE, /* IV */ - tls->client_write_key, tls->key_size /* selects 128/256 */ - ); - psAesEncrypt(&ctx, - buf, /* plaintext */ - buf, /* ciphertext */ - size - ); - } + aes_cbc_encrypt( + tls->client_write_key, tls->key_size, /* selects 128/256 */ + buf - AES_BLOCKSIZE, /* IV */ + buf, size, /* plaintext */ + buf /* ciphertext */ + ); /* Write out */ dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n", @@ -875,7 +870,6 @@ static int tls_xread_record(tls_state_t *tls) /* Needs to be decrypted? */ if (tls->min_encrypted_len_on_read > tls->MAC_size) { - psCipherContext_t ctx; uint8_t *p = tls->inbuf + RECHDR_LEN; int padding_len; @@ -886,14 +880,12 @@ static int tls_xread_record(tls_state_t *tls) sz, tls->min_encrypted_len_on_read); } /* Decrypt content+MAC+padding, moving it over IV in the process */ - psAesInit(&ctx, p, /* IV */ - tls->server_write_key, tls->key_size /* selects 128/256 */ - ); sz -= AES_BLOCKSIZE; /* we will overwrite IV now */ - psAesDecrypt(&ctx, - p + AES_BLOCKSIZE, /* ciphertext */ - p, /* plaintext */ - sz + aes_cbc_decrypt( + tls->server_write_key, tls->key_size, /* selects 128/256 */ + p, /* IV */ + p + AES_BLOCKSIZE, sz, /* ciphertext */ + p /* plaintext */ ); padding_len = p[sz - 1]; dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); diff --git a/networking/tls_aes.c b/networking/tls_aes.c index 6c3c39373..ebaab15b1 100644 --- a/networking/tls_aes.c +++ b/networking/tls_aes.c @@ -5,6 +5,46 @@ */ #include "tls.h" +static +int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey); +static +void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, + psAesKey_t *skey); +static +void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, + psAesKey_t *skey); +static +int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, + const unsigned char *key, uint32 keylen); +static +int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt, + unsigned char *ct, uint32 len); +static +int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct, + unsigned char *pt, uint32 len); + +void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +{ + psCipherContext_t ctx; + psAesInit(&ctx, iv, key, klen); + psAesEncrypt(&ctx, + data, /* plaintext */ + dst, /* ciphertext */ + len + ); +} + +void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst) +{ + psCipherContext_t ctx; + psAesInit(&ctx, iv, key, klen); + psAesDecrypt(&ctx, + data, /* ciphertext */ + dst, /* plaintext */ + len + ); +} + /* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/. * Changes are flagged with //bbox */ @@ -1079,8 +1119,9 @@ static uint32 setup_mix2(uint32 temp) Software implementation of AES CBC APIs */ #ifndef USE_AES_CBC_EXTERNAL +static //bbox int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, - unsigned char *key, uint32 keylen) + const unsigned char *key, uint32 keylen) { int32 x, err; @@ -1106,7 +1147,8 @@ int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, return PS_SUCCESS; } -int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, +static //bbox +int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt, unsigned char *ct, uint32 len) { int32 x; @@ -1156,7 +1198,8 @@ int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, return len; } -int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, +static //bbox +int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct, unsigned char *pt, uint32 len) { int32 x; @@ -1223,6 +1266,7 @@ int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, skey: The key in as scheduled by this function. */ +static //bbox int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey) { int32 i, j; @@ -1390,6 +1434,7 @@ int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey) #ifdef USE_BURN_STACK +static //bbox void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, psAesKey_t *skey) { @@ -1399,6 +1444,7 @@ void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, psAesKey_t *skey) #else +static //bbox void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, psAesKey_t *skey) #endif /* USE_BURN_STACK */ @@ -1555,6 +1601,7 @@ void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, } #ifdef USE_BURN_STACK +static //bbox void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, psAesKey_t *skey) { @@ -1564,6 +1611,7 @@ void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, psAesKey_t *skey) #else +static //bbox void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, psAesKey_t *skey) #endif /* USE_BURN_STACK */ diff --git a/networking/tls_aes.h b/networking/tls_aes.h index ea8ed7ea9..c6791866a 100644 --- a/networking/tls_aes.h +++ b/networking/tls_aes.h @@ -6,15 +6,5 @@ * Selected few declarations for AES. */ -int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey); -void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct, - psAesKey_t *skey); -void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt, - psAesKey_t *skey); - -int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV, - unsigned char *key, uint32 keylen); -int32 psAesEncrypt(psCipherContext_t *ctx, unsigned char *pt, - unsigned char *ct, uint32 len); -int32 psAesDecrypt(psCipherContext_t *ctx, unsigned char *ct, - unsigned char *pt, uint32 len); +void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); +void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst); -- cgit v1.2.3-55-g6feb From 8762512fdb088acefb9f3ea5f7b1e1bf2d336ff3 Mon Sep 17 00:00:00 2001 From: Rostislav Skudnov Date: Wed, 1 Feb 2017 18:35:13 +0000 Subject: Replace int -> uint to avoid signed integer overflow An example of such an error (should be compiled with DEBUG_SANITIZE): runtime error: left shift of 1 by 31 places cannot be represented in type 'int' Signed-off-by: Rostislav Skudnov Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_bunzip2.c | 6 +++--- libbb/crc32.c | 2 +- libbb/getopt32.c | 4 ++-- libbb/pw_encrypt.c | 2 +- miscutils/rx.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c index fe5953da2..4fb989c29 100644 --- a/archival/libarchive/decompress_bunzip2.c +++ b/archival/libarchive/decompress_bunzip2.c @@ -134,7 +134,7 @@ static unsigned get_bits(bunzip_data *bd, int bits_wanted) /* Avoid 32-bit overflow (dump bit buffer to top of output) */ if (bit_count >= 24) { - bits = bd->inbufBits & ((1 << bit_count) - 1); + bits = bd->inbufBits & ((1U << bit_count) - 1); bits_wanted -= bit_count; bits <<= bits_wanted; bit_count = 0; @@ -158,11 +158,11 @@ static int get_next_block(bunzip_data *bd) { struct group_data *hufGroup; int dbufCount, dbufSize, groupCount, *base, *limit, selector, - i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256]; + i, j, runPos, symCount, symTotal, nSelectors, byteCount[256]; int runCnt = runCnt; /* for compiler */ uint8_t uc, symToByte[256], mtfSymbol[256], *selectors; uint32_t *dbuf; - unsigned origPtr; + unsigned origPtr, t; dbuf = bd->dbuf; dbufSize = bd->dbufSize; diff --git a/libbb/crc32.c b/libbb/crc32.c index ac9836cc9..0711ca84e 100644 --- a/libbb/crc32.c +++ b/libbb/crc32.c @@ -24,7 +24,7 @@ uint32_t* FAST_FUNC crc32_filltable(uint32_t *crc_table, int endian) { uint32_t polynomial = endian ? 0x04c11db7 : 0xedb88320; uint32_t c; - int i, j; + unsigned i, j; if (!crc_table) crc_table = xmalloc(256 * sizeof(uint32_t)); diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 15b6efc09..497fc016f 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -404,7 +404,7 @@ getopt32(char **argv, const char *applet_opts, ...) if (c >= 32) break; on_off->opt_char = *s; - on_off->switch_on = (1 << c); + on_off->switch_on = (1U << c); if (*++s == ':') { on_off->optarg = va_arg(p, void **); if (s[1] == '+' || s[1] == '*') { @@ -454,7 +454,7 @@ getopt32(char **argv, const char *applet_opts, ...) if (c >= 32) break; on_off->opt_char = l_o->val; - on_off->switch_on = (1 << c); + on_off->switch_on = (1U << c); if (l_o->has_arg != no_argument) on_off->optarg = va_arg(p, void **); c++; diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c index 4cdc2de76..fe06a8fe6 100644 --- a/libbb/pw_encrypt.c +++ b/libbb/pw_encrypt.c @@ -30,7 +30,7 @@ static int i64c(int i) int FAST_FUNC crypt_make_salt(char *p, int cnt /*, int x */) { /* was: x += ... */ - int x = getpid() + monotonic_us(); + unsigned x = getpid() + monotonic_us(); do { /* x = (x*1664525 + 1013904223) % 2^32 generator is lame * (low-order bit is not "random", etc...), diff --git a/miscutils/rx.c b/miscutils/rx.c index 36fc20a72..1f6f2825c 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c @@ -94,7 +94,7 @@ static int receive(/*int read_fd, */int file_fd) int blockBegin; int blockNo, blockNoOnesCompl; int cksum_or_crc; - int expected; + unsigned expected; int i, j; blockBegin = read_byte(timeout); -- cgit v1.2.3-55-g6feb From 8cc1ab3c11538773389060005ba9c053fae0f848 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 4 Feb 2017 23:19:30 +0100 Subject: httpd: use "Content-Length", not "-length" Signed-off-by: Denys Vlasenko --- networking/httpd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/networking/httpd.c b/networking/httpd.c index 8703fbd3d..e072f23c7 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -1147,7 +1147,7 @@ static void send_headers(int responseNum) "Last-Modified: %s\r\n" "%s %"OFF_FMT"u\r\n", date_str, - content_gzip ? "Transfer-length:" : "Content-length:", + content_gzip ? "Transfer-Length:" : "Content-Length:", file_size ); } @@ -2276,14 +2276,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) #if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY /* Try and do our best to parse more lines */ - if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { + if ((STRNCASECMP(iobuf, "Content-Length:") == 0)) { /* extra read only for POST */ if (prequest != request_GET # if ENABLE_FEATURE_HTTPD_CGI && prequest != request_HEAD # endif ) { - tptr = skip_whitespace(iobuf + sizeof("Content-length:") - 1); + tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1); if (!tptr[0]) send_headers_and_exit(HTTP_BAD_REQUEST); /* not using strtoul: it ignores leading minus! */ -- cgit v1.2.3-55-g6feb From 4ae658f077c9b8859e8f1aabee4b95c2c96dae1c Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Sun, 5 Feb 2017 19:02:34 +0100 Subject: modutils: fix config options dependency (2) - The modprobe-small implementation of rmmod no longer chdir's to "/lib/modules/`uname -r`" as it was not necessary for rmmod's operation. (And it no longer need to die if such modules directory doesn't exist.) - Configs DEFAULT_MODULES_DIR and DEFAULT_DEPMOD_FILE no longer depend on MODPROBE_SMALL as the latter may not enable depmod or modprobe that requires these configs. - Clarify DEFAULT_DEPMOD_FILE's description regarding the ".bb" name suffix. Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/Config.src | 10 +++++++--- modutils/modprobe-small.c | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/modutils/Config.src b/modutils/Config.src index a15cce518..d0bae2ea3 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -159,7 +159,7 @@ config FEATURE_MODUTILS_SYMBOLS config DEFAULT_MODULES_DIR string "Default directory containing modules" default "/lib/modules" - depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO + depends on DEPMOD || MODPROBE || MODINFO help Directory that contains kernel modules. Defaults to "/lib/modules" @@ -167,9 +167,13 @@ config DEFAULT_MODULES_DIR config DEFAULT_DEPMOD_FILE string "Default name of modules.dep" default "modules.dep" - depends on DEPMOD || MODPROBE || MODPROBE_SMALL || MODINFO + depends on DEPMOD || MODPROBE || MODINFO help Filename that contains kernel modules dependencies. - Defaults to "modules.dep" + Defaults to "modules.dep". + If you configured the "simplified modutils" (MODPROBE_SMALL), a + ".bb" suffix will be added after this name. Do not specify ".bb" + here unless you intend your depmod or modprobe to work on + "modules.dep.bb.bb" or such. endmenu diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 04242634b..726a3108c 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -934,11 +934,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* Prevent ugly corner cases with no modules at all */ modinfo = xzalloc(sizeof(modinfo[0])); - if (!is_insmod) { + if (is_depmod || is_modprobe) { /* Goto modules directory */ xchdir(CONFIG_DEFAULT_MODULES_DIR); + uname(&uts); /* never fails */ } - uname(&uts); /* never fails */ /* depmod? */ if (is_depmod) { @@ -980,7 +980,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) getopt32(argv, "qrfsvwb"); argv += optind; - if (!is_insmod) { + if (is_modprobe) { /* Goto $VERSION directory */ xchdir(uts.release); } -- cgit v1.2.3-55-g6feb From 415cc42b6aab3a3a90749354432e7d780840b1d8 Mon Sep 17 00:00:00 2001 From: Kang-Che Sung Date: Wed, 1 Feb 2017 19:43:54 +0800 Subject: Reorder modutils config options & fix yet more dependency - modprobe can indirectly benefit from FEATURE_2_4_MODULES and FEATURE_INSMOD_TRY_MAP options. - The position of config FEATURE_INSMOD_TRY_MMAP prevented some other config options from indenting under FEATURE_2_4_MODULES. Reorder to fix this. - FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is now moved to Config.src under "Common options" section. (I wished to edit this config so that it also work with "big" modutils, but it's not done at the moment. Sorry.) Signed-off-by: Kang-Che Sung Signed-off-by: Denys Vlasenko --- modutils/Config.src | 43 +++++++++++++++++++++++++------------------ modutils/modprobe-small.c | 10 ++-------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/modutils/Config.src b/modutils/Config.src index d0bae2ea3..5f0b0cec4 100644 --- a/modutils/Config.src +++ b/modutils/Config.src @@ -45,31 +45,22 @@ config FEATURE_CMDLINE_MODULE_OPTIONS Allow insmod and modprobe take module options from the applets' command line. +config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED + bool "Skip loading of already loaded modules" + default y + depends on MODPROBE_SMALL && (DEPMOD || INSMOD || MODPROBE) + help + Check if the module is already loaded. + config FEATURE_2_4_MODULES bool "Support version 2.2/2.4 Linux kernels" default n - depends on (INSMOD || RMMOD || LSMOD) && !MODPROBE_SMALL + depends on (INSMOD || LSMOD || MODPROBE || RMMOD) && !MODPROBE_SMALL help Support module loading for 2.2.x and 2.4.x Linux kernels. This increases size considerably. Say N unless you plan to run ancient kernels. -config FEATURE_INSMOD_TRY_MMAP - bool "Try to load module from a mmap'ed area" - default n - depends on INSMOD && !MODPROBE_SMALL - help - This option causes module loading code to try to mmap - module first. If it does not work (for example, - it does not work for compressed modules), module will be read - (and unpacked if needed) into a memory block allocated by malloc. - - The only case when mmap works but malloc does not is when - you are trying to load a big module on a very memory-constrained - machine. Malloc will momentarily need 2x as much memory as mmap. - - Choosing N saves about 250 bytes of code (on 32-bit x86). - config FEATURE_INSMOD_VERSION_CHECKING bool "Enable module version checking" default n @@ -113,7 +104,7 @@ config FEATURE_INSMOD_LOAD_MAP config FEATURE_INSMOD_LOAD_MAP_FULL bool "Symbols in load map" default y - depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL + depends on FEATURE_INSMOD_LOAD_MAP help Without this option, -m will only output section load map. With this option, -m will also output @@ -129,6 +120,22 @@ config FEATURE_CHECK_TAINTED_MODULE support request. This option is required to support GPLONLY modules. +config FEATURE_INSMOD_TRY_MMAP + bool "Try to load module from a mmap'ed area" + default n + depends on (INSMOD || MODPROBE) && !MODPROBE_SMALL + help + This option causes module loading code to try to mmap + module first. If it does not work (for example, + it does not work for compressed modules), module will be read + (and unpacked if needed) into a memory block allocated by malloc. + + The only case when mmap works but malloc does not is when + you are trying to load a big module on a very memory-constrained + machine. Malloc will momentarily need 2x as much memory as mmap. + + Choosing N saves about 250 bytes of code (on 32-bit x86). + config FEATURE_MODUTILS_ALIAS bool "Support module.aliases file" default y diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 726a3108c..d6f481415 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -8,14 +8,8 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ -/* config MODPROBE_SMALL is defined in Config.src to ensure better "make config" order */ - -//config:config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED -//config: bool "Skip loading of already loaded modules" -//config: default y -//config: depends on MODPROBE_SMALL && (DEPMOD || INSMOD || MODPROBE) -//config: help -//config: Check if the module is already loaded. +/* modprobe-small configs are defined in Config.src to ensure better + * "make config" order */ //applet:IF_LSMOD( IF_MODPROBE_SMALL(APPLET(lsmod, BB_DIR_SBIN, BB_SUID_DROP))) //applet:IF_MODPROBE(IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))) -- cgit v1.2.3-55-g6feb From c2b18583a3df06aeecf535c3cea6856aa1f2e205 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 7 Feb 2017 16:41:25 +0100 Subject: modprobe_small: if only MODPROBE and DEPMOD are selected, no need to test for them function old new delta modprobe_main 321 306 -15 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index d6f481415..431b8aeb2 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -928,7 +928,9 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) /* Prevent ugly corner cases with no modules at all */ modinfo = xzalloc(sizeof(modinfo[0])); - if (is_depmod || is_modprobe) { + if ((MOD_APPLET_CNT == 2 && ENABLE_DEPMOD && ENABLE_MODPROBE) + || is_depmod || is_modprobe + ) { /* Goto modules directory */ xchdir(CONFIG_DEFAULT_MODULES_DIR); uname(&uts); /* never fails */ -- cgit v1.2.3-55-g6feb