summaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
committerRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
commit373275a708bafb88fa4f0519de2166154f44fed9 (patch)
tree4587b4fd3f695e0f3705b2a217e199f3144df931 /networking
parentb74b2619779b1deb903b7766261807df1e9b1f7f (diff)
parentc2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff)
downloadbusybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'networking')
-rw-r--r--networking/ftpd.c51
-rw-r--r--networking/ftpgetput.c2
-rw-r--r--networking/hostname.c1
-rw-r--r--networking/httpd.c70
-rw-r--r--networking/ifupdown.c11
-rw-r--r--networking/inetd.c6
-rw-r--r--networking/ip.c124
-rw-r--r--networking/ipcalc.c12
-rw-r--r--networking/netstat.c2
-rw-r--r--networking/ntpd.c4
-rw-r--r--networking/ping.c10
-rw-r--r--networking/ssl_client.c55
-rw-r--r--networking/tc.c30
-rw-r--r--networking/telnet.c15
-rw-r--r--networking/tftp.c4
-rw-r--r--networking/tls.c1815
-rw-r--r--networking/tls.h99
-rw-r--r--networking/tls_aes.c1776
-rw-r--r--networking/tls_aes.h10
-rw-r--r--networking/tls_pstm.c2263
-rw-r--r--networking/tls_pstm.h286
-rw-r--r--networking/tls_pstm_montgomery_reduce.c427
-rw-r--r--networking/tls_pstm_mul_comba.c781
-rw-r--r--networking/tls_pstm_sqr_comba.c1111
-rw-r--r--networking/tls_rsa.c211
-rw-r--r--networking/tls_rsa.h20
-rw-r--r--networking/tls_symmetric.h511
-rw-r--r--networking/traceroute.c2
-rw-r--r--networking/udhcp/Config.src4
-rw-r--r--networking/udhcp/common.c2
-rw-r--r--networking/udhcp/dumpleases.c2
-rw-r--r--networking/wget.c226
32 files changed, 9699 insertions, 244 deletions
diff --git a/networking/ftpd.c b/networking/ftpd.c
index bcd60a2ad..439608ce6 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -15,7 +15,7 @@
15//config: bool "ftpd" 15//config: bool "ftpd"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: simple FTP daemon. You have to run it via inetd. 18//config: Simple FTP daemon. You have to run it via inetd.
19//config: 19//config:
20//config:config FEATURE_FTPD_WRITE 20//config:config FEATURE_FTPD_WRITE
21//config: bool "Enable upload commands" 21//config: bool "Enable upload commands"
@@ -47,20 +47,26 @@
47//kbuild:lib-$(CONFIG_FTPD) += ftpd.o 47//kbuild:lib-$(CONFIG_FTPD) += ftpd.o
48 48
49//usage:#define ftpd_trivial_usage 49//usage:#define ftpd_trivial_usage
50//usage: "[-wvS] [-t N] [-T N] [DIR]" 50//usage: "[-wvS]"IF_FEATURE_FTPD_AUTHENTICATION(" [-a USER]")" [-t N] [-T N] [DIR]"
51//usage:#define ftpd_full_usage "\n\n" 51//usage:#define ftpd_full_usage "\n\n"
52//usage: "Anonymous FTP server\n" 52//usage: IF_NOT_FEATURE_FTPD_AUTHENTICATION(
53//usage: "\n" 53//usage: "Anonymous FTP server. Accesses by clients occur under ftpd's UID.\n"
54//usage: "ftpd should be used as an inetd service.\n" 54//usage: )
55//usage: "ftpd's line for inetd.conf:\n" 55//usage: IF_FEATURE_FTPD_AUTHENTICATION(
56//usage: "FTP server. "
57//usage: )
58//usage: "Chroots to DIR, if this fails (run by non-root), cds to it.\n"
59//usage: "Should be used as inetd service, inetd.conf line:\n"
56//usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n" 60//usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n"
57//usage: "It also can be ran from tcpsvd:\n" 61//usage: "Can be run from tcpsvd:\n"
58//usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" 62//usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n"
59//usage: "\n -w Allow upload" 63//usage: "\n -w Allow upload"
64//usage: IF_FEATURE_FTPD_AUTHENTICATION(
65//usage: "\n -a USER Enable 'anonymous' login and map it to USER"
66//usage: )
60//usage: "\n -v Log errors to stderr. -vv: verbose log" 67//usage: "\n -v Log errors to stderr. -vv: verbose log"
61//usage: "\n -S Log errors to syslog. -SS: verbose log" 68//usage: "\n -S Log errors to syslog. -SS: verbose log"
62//usage: "\n -t,-T Idle and absolute timeouts" 69//usage: "\n -t,-T N Idle and absolute timeout"
63//usage: "\n DIR Change root to this directory"
64 70
65#include "libbb.h" 71#include "libbb.h"
66#include "common_bufsiz.h" 72#include "common_bufsiz.h"
@@ -695,7 +701,7 @@ popen_ls(const char *opt)
695 dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */ 701 dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */
696#if BB_MMU 702#if BB_MMU
697 /* memset(&G, 0, sizeof(G)); - ls_main does it */ 703 /* memset(&G, 0, sizeof(G)); - ls_main does it */
698 exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv)); 704 exit(ls_main(/*argc_unused*/ 0, (char**) argv));
699#else 705#else
700 cur_fd = xopen(".", O_RDONLY | O_DIRECTORY); 706 cur_fd = xopen(".", O_RDONLY | O_DIRECTORY);
701 /* On NOMMU, we want to execute a child - copy of ourself 707 /* On NOMMU, we want to execute a child - copy of ourself
@@ -1146,14 +1152,11 @@ enum {
1146}; 1152};
1147 1153
1148int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1154int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1149#if !BB_MMU
1150int ftpd_main(int argc, char **argv)
1151#else
1152int ftpd_main(int argc UNUSED_PARAM, char **argv) 1155int ftpd_main(int argc UNUSED_PARAM, char **argv)
1153#endif
1154{ 1156{
1155#if ENABLE_FEATURE_FTPD_AUTHENTICATION 1157#if ENABLE_FEATURE_FTPD_AUTHENTICATION
1156 struct passwd *pw = NULL; 1158 struct passwd *pw = NULL;
1159 char *anon_opt = NULL;
1157#endif 1160#endif
1158 unsigned abs_timeout; 1161 unsigned abs_timeout;
1159 unsigned verbose_S; 1162 unsigned verbose_S;
@@ -1166,16 +1169,21 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1166 G.timeout = 2 * 60; 1169 G.timeout = 2 * 60;
1167 opt_complementary = "vv:SS"; 1170 opt_complementary = "vv:SS";
1168#if BB_MMU 1171#if BB_MMU
1169 opts = getopt32(argv, "vS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1172 opts = getopt32(argv, "vS"
1173 IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"),
1174 &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,)
1175 &G.verbose, &verbose_S);
1170#else 1176#else
1171 opts = getopt32(argv, "l1AvS" IF_FEATURE_FTPD_WRITE("w") "t:+T:+", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); 1177 opts = getopt32(argv, "l1AvS"
1178 IF_FEATURE_FTPD_WRITE("w") "t:+T:+" IF_FEATURE_FTPD_AUTHENTICATION("a:"),
1179 &G.timeout, &abs_timeout, IF_FEATURE_FTPD_AUTHENTICATION(&anon_opt,)
1180 &G.verbose, &verbose_S);
1172 if (opts & (OPT_l|OPT_1)) { 1181 if (opts & (OPT_l|OPT_1)) {
1173 /* Our secret backdoor to ls */ 1182 /* Our secret backdoor to ls */
1174/* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */
1175 if (fchdir(3) != 0) 1183 if (fchdir(3) != 0)
1176 _exit(127); 1184 _exit(127);
1177 /* memset(&G, 0, sizeof(G)); - ls_main does it */ 1185 /* memset(&G, 0, sizeof(G)); - ls_main does it */
1178 return ls_main(argc, argv); 1186 return ls_main(/*argc_unused*/ 0, argv);
1179 } 1187 }
1180#endif 1188#endif
1181 if (G.verbose < verbose_S) 1189 if (G.verbose < verbose_S)
@@ -1234,7 +1242,12 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
1234#if ENABLE_FEATURE_FTPD_AUTHENTICATION 1242#if ENABLE_FEATURE_FTPD_AUTHENTICATION
1235 while (1) { 1243 while (1) {
1236 uint32_t cmdval = cmdio_get_cmd_and_arg(); 1244 uint32_t cmdval = cmdio_get_cmd_and_arg();
1237 if (cmdval == const_USER) { 1245 if (cmdval == const_USER) {
1246 if (anon_opt && strcmp(G.ftp_arg, "anonymous") == 0) {
1247 pw = getpwnam(anon_opt);
1248 if (pw)
1249 break; /* does not even ask for password */
1250 }
1238 pw = getpwnam(G.ftp_arg); 1251 pw = getpwnam(G.ftp_arg);
1239 cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); 1252 cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n");
1240 } else if (cmdval == const_PASS) { 1253 } else if (cmdval == const_PASS) {
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index 0b06f85b4..3eadd752d 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -28,8 +28,6 @@
28//config: bool "Enable long options in ftpget/ftpput" 28//config: bool "Enable long options in ftpget/ftpput"
29//config: default y 29//config: default y
30//config: depends on LONG_OPTS && (FTPGET || FTPPUT) 30//config: depends on LONG_OPTS && (FTPGET || FTPPUT)
31//config: help
32//config: Support long options for the ftpget/ftpput applet.
33 31
34//applet:IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget)) 32//applet:IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget))
35//applet:IF_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpput)) 33//applet:IF_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpput))
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 @@
22//config: help 22//config: help
23//config: Alias to "hostname -d". 23//config: Alias to "hostname -d".
24 24
25// APPLET_ODDNAME:name main location suid_type help
25//applet:IF_DNSDOMAINNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname)) 26//applet:IF_DNSDOMAINNAME(APPLET_ODDNAME(dnsdomainname, hostname, BB_DIR_BIN, BB_SUID_DROP, dnsdomainname))
26//applet:IF_HOSTNAME(APPLET(hostname, BB_DIR_BIN, BB_SUID_DROP)) 27//applet:IF_HOSTNAME(APPLET(hostname, BB_DIR_BIN, BB_SUID_DROP))
27 28
diff --git a/networking/httpd.c b/networking/httpd.c
index d301d598d..e072f23c7 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -102,7 +102,7 @@
102//config: bool "httpd" 102//config: bool "httpd"
103//config: default y 103//config: default y
104//config: help 104//config: help
105//config: Serve web pages via an HTTP server. 105//config: HTTP server.
106//config: 106//config:
107//config:config FEATURE_HTTPD_RANGES 107//config:config FEATURE_HTTPD_RANGES
108//config: bool "Support 'Ranges:' header" 108//config: bool "Support 'Ranges:' header"
@@ -156,7 +156,7 @@
156//config: when specific URLs are requested. 156//config: when specific URLs are requested.
157//config: 157//config:
158//config:config FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 158//config:config FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
159//config: bool "Support for running scripts through an interpreter" 159//config: bool "Support running scripts through an interpreter"
160//config: default y 160//config: default y
161//config: depends on FEATURE_HTTPD_CGI 161//config: depends on FEATURE_HTTPD_CGI
162//config: help 162//config: help
@@ -185,7 +185,7 @@
185//config: "&#60Hello&#32World&#62". 185//config: "&#60Hello&#32World&#62".
186//config: 186//config:
187//config:config FEATURE_HTTPD_ERROR_PAGES 187//config:config FEATURE_HTTPD_ERROR_PAGES
188//config: bool "Support for custom error pages" 188//config: bool "Support custom error pages"
189//config: default y 189//config: default y
190//config: depends on HTTPD 190//config: depends on HTTPD
191//config: help 191//config: help
@@ -198,7 +198,7 @@
198//config: message. 198//config: message.
199//config: 199//config:
200//config:config FEATURE_HTTPD_PROXY 200//config:config FEATURE_HTTPD_PROXY
201//config: bool "Support for reverse proxy" 201//config: bool "Support reverse proxy"
202//config: default y 202//config: default y
203//config: depends on HTTPD 203//config: depends on HTTPD
204//config: help 204//config: help
@@ -210,7 +210,7 @@
210//config: http://hostname[:port]/new/path/myfile. 210//config: http://hostname[:port]/new/path/myfile.
211//config: 211//config:
212//config:config FEATURE_HTTPD_GZIP 212//config:config FEATURE_HTTPD_GZIP
213//config: bool "Support for GZIP content encoding" 213//config: bool "Support GZIP content encoding"
214//config: default y 214//config: default y
215//config: depends on HTTPD 215//config: depends on HTTPD
216//config: help 216//config: help
@@ -460,11 +460,6 @@ struct globals {
460#define ip_a_d (G.ip_a_d ) 460#define ip_a_d (G.ip_a_d )
461#define g_realm (G.g_realm ) 461#define g_realm (G.g_realm )
462#define remoteuser (G.remoteuser ) 462#define remoteuser (G.remoteuser )
463#define referer (G.referer )
464#define user_agent (G.user_agent )
465#define host (G.host )
466#define http_accept (G.http_accept )
467#define http_accept_language (G.http_accept_language)
468#define file_size (G.file_size ) 463#define file_size (G.file_size )
469#if ENABLE_FEATURE_HTTPD_RANGES 464#if ENABLE_FEATURE_HTTPD_RANGES
470#define range_start (G.range_start ) 465#define range_start (G.range_start )
@@ -1152,7 +1147,7 @@ static void send_headers(int responseNum)
1152 "Last-Modified: %s\r\n" 1147 "Last-Modified: %s\r\n"
1153 "%s %"OFF_FMT"u\r\n", 1148 "%s %"OFF_FMT"u\r\n",
1154 date_str, 1149 date_str,
1155 content_gzip ? "Transfer-length:" : "Content-length:", 1150 content_gzip ? "Transfer-Length:" : "Content-Length:",
1156 file_size 1151 file_size
1157 ); 1152 );
1158 } 1153 }
@@ -1529,11 +1524,11 @@ static void send_cgi_and_exit(
1529#endif 1524#endif
1530 } 1525 }
1531 } 1526 }
1532 setenv1("HTTP_USER_AGENT", user_agent); 1527 setenv1("HTTP_USER_AGENT", G.user_agent);
1533 if (http_accept) 1528 if (G.http_accept)
1534 setenv1("HTTP_ACCEPT", http_accept); 1529 setenv1("HTTP_ACCEPT", G.http_accept);
1535 if (http_accept_language) 1530 if (G.http_accept_language)
1536 setenv1("HTTP_ACCEPT_LANGUAGE", http_accept_language); 1531 setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language);
1537 if (post_len) 1532 if (post_len)
1538 putenv(xasprintf("CONTENT_LENGTH=%d", post_len)); 1533 putenv(xasprintf("CONTENT_LENGTH=%d", post_len));
1539 if (cookie) 1534 if (cookie)
@@ -1546,9 +1541,9 @@ static void send_cgi_and_exit(
1546 putenv((char*)"AUTH_TYPE=Basic"); 1541 putenv((char*)"AUTH_TYPE=Basic");
1547 } 1542 }
1548#endif 1543#endif
1549 if (referer) 1544 if (G.referer)
1550 setenv1("HTTP_REFERER", referer); 1545 setenv1("HTTP_REFERER", G.referer);
1551 setenv1("HTTP_HOST", host); /* set to "" if NULL */ 1546 setenv1("HTTP_HOST", G.host); /* set to "" if NULL */
1552 /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this, 1547 /* setenv1("SERVER_NAME", safe_gethostname()); - don't do this,
1553 * just run "env SERVER_NAME=xyz httpd ..." instead */ 1548 * just run "env SERVER_NAME=xyz httpd ..." instead */
1554 1549
@@ -2269,10 +2264,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2269#if ENABLE_FEATURE_HTTPD_PROXY 2264#if ENABLE_FEATURE_HTTPD_PROXY
2270 /* We need 2 more bytes for yet another "\r\n" - 2265 /* We need 2 more bytes for yet another "\r\n" -
2271 * see near fdprintf(proxy_fd...) further below */ 2266 * see near fdprintf(proxy_fd...) further below */
2272 if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 2) { 2267 if (proxy_entry && (header_ptr - header_buf) < IOBUF_SIZE - 4) {
2273 int len = strlen(iobuf); 2268 int len = strnlen(iobuf, IOBUF_SIZE - (header_ptr - header_buf) - 4);
2274 if (len > IOBUF_SIZE - (header_ptr - header_buf) - 4)
2275 len = IOBUF_SIZE - (header_ptr - header_buf) - 4;
2276 memcpy(header_ptr, iobuf, len); 2269 memcpy(header_ptr, iobuf, len);
2277 header_ptr += len; 2270 header_ptr += len;
2278 header_ptr[0] = '\r'; 2271 header_ptr[0] = '\r';
@@ -2283,14 +2276,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2283 2276
2284#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY 2277#if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY
2285 /* Try and do our best to parse more lines */ 2278 /* Try and do our best to parse more lines */
2286 if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { 2279 if ((STRNCASECMP(iobuf, "Content-Length:") == 0)) {
2287 /* extra read only for POST */ 2280 /* extra read only for POST */
2288 if (prequest != request_GET 2281 if (prequest != request_GET
2289# if ENABLE_FEATURE_HTTPD_CGI 2282# if ENABLE_FEATURE_HTTPD_CGI
2290 && prequest != request_HEAD 2283 && prequest != request_HEAD
2291# endif 2284# endif
2292 ) { 2285 ) {
2293 tptr = skip_whitespace(iobuf + sizeof("Content-length:") - 1); 2286 tptr = skip_whitespace(iobuf + sizeof("Content-Length:") - 1);
2294 if (!tptr[0]) 2287 if (!tptr[0])
2295 send_headers_and_exit(HTTP_BAD_REQUEST); 2288 send_headers_and_exit(HTTP_BAD_REQUEST);
2296 /* not using strtoul: it ignores leading minus! */ 2289 /* not using strtoul: it ignores leading minus! */
@@ -2303,19 +2296,26 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2303#endif 2296#endif
2304#if ENABLE_FEATURE_HTTPD_CGI 2297#if ENABLE_FEATURE_HTTPD_CGI
2305 else if (STRNCASECMP(iobuf, "Cookie:") == 0) { 2298 else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
2306 cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); 2299 if (!cookie) /* in case they send millions of these, do not OOM */
2300 cookie = xstrdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
2307 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { 2301 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
2308 content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); 2302 if (!content_type)
2303 content_type = xstrdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
2309 } else if (STRNCASECMP(iobuf, "Referer:") == 0) { 2304 } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
2310 referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); 2305 if (!G.referer)
2306 G.referer = xstrdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
2311 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { 2307 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
2312 user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); 2308 if (!G.user_agent)
2309 G.user_agent = xstrdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
2313 } else if (STRNCASECMP(iobuf, "Host:") == 0) { 2310 } else if (STRNCASECMP(iobuf, "Host:") == 0) {
2314 host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1)); 2311 if (!G.host)
2312 G.host = xstrdup(skip_whitespace(iobuf + sizeof("Host:")-1));
2315 } else if (STRNCASECMP(iobuf, "Accept:") == 0) { 2313 } else if (STRNCASECMP(iobuf, "Accept:") == 0) {
2316 http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1)); 2314 if (!G.http_accept)
2315 G.http_accept = xstrdup(skip_whitespace(iobuf + sizeof("Accept:")-1));
2317 } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) { 2316 } else if (STRNCASECMP(iobuf, "Accept-Language:") == 0) {
2318 http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1)); 2317 if (!G.http_accept_language)
2318 G.http_accept_language = xstrdup(skip_whitespace(iobuf + sizeof("Accept-Language:")-1));
2319 } 2319 }
2320#endif 2320#endif
2321#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2321#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
@@ -2396,12 +2396,12 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2396 int proxy_fd; 2396 int proxy_fd;
2397 len_and_sockaddr *lsa; 2397 len_and_sockaddr *lsa;
2398 2398
2399 proxy_fd = socket(AF_INET, SOCK_STREAM, 0);
2400 if (proxy_fd < 0)
2401 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2402 lsa = host2sockaddr(proxy_entry->host_port, 80); 2399 lsa = host2sockaddr(proxy_entry->host_port, 80);
2403 if (lsa == NULL) 2400 if (lsa == NULL)
2404 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2401 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2402 proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
2403 if (proxy_fd < 0)
2404 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2405 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) 2405 if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0)
2406 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 2406 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
2407 fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n", 2407 fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n",
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 1806a6ccc..a76fe1021 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -66,14 +66,14 @@
66//config: utilities, or enable these applets in Busybox. 66//config: utilities, or enable these applets in Busybox.
67//config: 67//config:
68//config:config FEATURE_IFUPDOWN_IPV4 68//config:config FEATURE_IFUPDOWN_IPV4
69//config: bool "Support for IPv4" 69//config: bool "Support IPv4"
70//config: default y 70//config: default y
71//config: depends on IFUP || IFDOWN 71//config: depends on IFUP || IFDOWN
72//config: help 72//config: help
73//config: If you want ifup/ifdown to talk IPv4, leave this on. 73//config: If you want ifup/ifdown to talk IPv4, leave this on.
74//config: 74//config:
75//config:config FEATURE_IFUPDOWN_IPV6 75//config:config FEATURE_IFUPDOWN_IPV6
76//config: bool "Support for IPv6" 76//config: bool "Support IPv6"
77//config: default y 77//config: default y
78//config: depends on (IFUP || IFDOWN) && FEATURE_IPV6 78//config: depends on (IFUP || IFDOWN) && FEATURE_IPV6
79//config: help 79//config: help
@@ -81,7 +81,7 @@
81//config: 81//config:
82//UNUSED: 82//UNUSED:
83////////:config FEATURE_IFUPDOWN_IPX 83////////:config FEATURE_IFUPDOWN_IPX
84////////: bool "Support for IPX" 84////////: bool "Support IPX"
85////////: default y 85////////: default y
86////////: depends on IFUP || IFDOWN 86////////: depends on IFUP || IFDOWN
87////////: help 87////////: help
@@ -97,7 +97,7 @@
97//config: a weird network setup you don't need it. 97//config: a weird network setup you don't need it.
98//config: 98//config:
99//config:config FEATURE_IFUPDOWN_EXTERNAL_DHCP 99//config:config FEATURE_IFUPDOWN_EXTERNAL_DHCP
100//config: bool "Support for external dhcp clients" 100//config: bool "Support external DHCP clients"
101//config: default n 101//config: default n
102//config: depends on IFUP || IFDOWN 102//config: depends on IFUP || IFDOWN
103//config: help 103//config: help
@@ -106,7 +106,8 @@
106//config: Otherwise, if udhcpc applet is enabled, it is used. 106//config: Otherwise, if udhcpc applet is enabled, it is used.
107//config: Otherwise, ifup/ifdown will have no support for DHCP. 107//config: Otherwise, ifup/ifdown will have no support for DHCP.
108 108
109//applet:IF_IFUP(APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup)) 109// APPLET_ODDNAME:name main location suid_type help
110//applet:IF_IFUP( APPLET_ODDNAME(ifup, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifup))
110//applet:IF_IFDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown)) 111//applet:IF_IFDOWN(APPLET_ODDNAME(ifdown, ifupdown, BB_DIR_SBIN, BB_SUID_DROP, ifdown))
111 112
112//kbuild:lib-$(CONFIG_IFUP) += ifupdown.o 113//kbuild:lib-$(CONFIG_IFUP) += ifupdown.o
diff --git a/networking/inetd.c b/networking/inetd.c
index 4d0ab2e0d..01e659f13 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -213,9 +213,9 @@
213//usage: "Listen for network connections and launch programs\n" 213//usage: "Listen for network connections and launch programs\n"
214//usage: "\n -f Run in foreground" 214//usage: "\n -f Run in foreground"
215//usage: "\n -e Log to stderr" 215//usage: "\n -e Log to stderr"
216//usage: "\n -q N Socket listen queue (default: 128)" 216//usage: "\n -q N Socket listen queue (default 128)"
217//usage: "\n -R N Pause services after N connects/min" 217//usage: "\n -R N Pause services after N connects/min"
218//usage: "\n (default: 0 - disabled)" 218//usage: "\n (default 0 - disabled)"
219 219
220#include <syslog.h> 220#include <syslog.h>
221#include <sys/resource.h> /* setrlimit */ 221#include <sys/resource.h> /* setrlimit */
@@ -1677,7 +1677,7 @@ static uint32_t machtime(void)
1677 struct timeval tv; 1677 struct timeval tv;
1678 1678
1679 gettimeofday(&tv, NULL); 1679 gettimeofday(&tv, NULL);
1680 return htonl((uint32_t)(tv.tv_sec + 2208988800)); 1680 return htonl((uint32_t)(tv.tv_sec + 2208988800U));
1681} 1681}
1682/* ARGSUSED */ 1682/* ARGSUSED */
1683static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM) 1683static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM)
diff --git a/networking/ip.c b/networking/ip.c
index 939721e46..0f52b19dd 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -140,84 +140,106 @@
140//kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o 140//kbuild:lib-$(CONFIG_IPTUNNEL) += ip.o
141//kbuild:lib-$(CONFIG_IPNEIGH) += ip.o 141//kbuild:lib-$(CONFIG_IPNEIGH) += ip.o
142 142
143/* would need to make the " | " optional depending on more than one selected: */
144//usage:#define ip_trivial_usage
145//usage: "[OPTIONS] {"
146//usage: IF_FEATURE_IP_ADDRESS("address | ")
147//usage: IF_FEATURE_IP_ROUTE("route | ")
148//usage: IF_FEATURE_IP_LINK("link | ")
149//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
150//usage: IF_FEATURE_IP_NEIGH("neigh | ")
151//usage: IF_FEATURE_IP_RULE("rule")
152//usage: "} {COMMAND}"
153//usage:#define ip_full_usage "\n\n"
154//usage: "ip [OPTIONS] OBJECT {COMMAND}\n"
155//usage: "where OBJECT := {"
156//usage: IF_FEATURE_IP_ADDRESS("address | ")
157//usage: IF_FEATURE_IP_ROUTE("route | ")
158//usage: IF_FEATURE_IP_LINK("link | ")
159//usage: IF_FEATURE_IP_TUNNEL("tunnel | ")
160//usage: IF_FEATURE_IP_NEIGH("neigh | ")
161//usage: IF_FEATURE_IP_RULE("rule")
162//usage: "}\n"
163//usage: "OPTIONS := { -f[amily] { inet | inet6 | link } | -o[neline] }"
164//usage:
165//usage:#define ipaddr_trivial_usage 143//usage:#define ipaddr_trivial_usage
166//usage: "{ {add|del} IFADDR dev STRING | {show|flush}\n" 144//usage: "add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]"
167//usage: " [dev STRING] [to PREFIX] }"
168//usage:#define ipaddr_full_usage "\n\n" 145//usage:#define ipaddr_full_usage "\n\n"
169//usage: "ipaddr {add|change|replace|delete} IFADDR dev STRING\n" 146//usage: "ipaddr add|change|replace|delete IFADDR dev IFACE\n"
170//usage: "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n" 147//usage: "ipaddr show|flush [dev IFACE] [scope SCOPE-ID]\n"
171//usage: " [to PREFIX] [label PATTERN]\n" 148//usage: " [to PREFIX] [label PATTERN]\n"
172//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" 149//usage: " IFADDR := PREFIX | ADDR peer PREFIX\n"
173//usage: " [broadcast ADDR] [anycast ADDR]\n" 150//usage: " [broadcast ADDR] [anycast ADDR]\n"
174//usage: " [label STRING] [scope SCOPE-ID]\n" 151//usage: " [label STRING] [scope SCOPE-ID]\n"
175//usage: " SCOPE-ID := [host | link | global | NUMBER]" 152//usage: " SCOPE-ID := [host|link|global|NUMBER]"
176//usage: 153//usage:
177//usage:#define iplink_trivial_usage 154//usage:#define iplink_trivial_usage
178//usage: "{ set DEVICE { up | down | arp { on | off } | show [DEVICE] }" 155//usage: "set IFACE [up|down] [arp on|off] | show [IFACE]"
179//usage:#define iplink_full_usage "\n\n" 156//usage:#define iplink_full_usage "\n\n"
180//usage: "iplink set DEVICE { up | down | arp | multicast { on | off } |\n" 157//usage: "iplink set IFACE [up|down]\n"
181//usage: " dynamic { on | off } |\n" 158//usage: " [arp on|off]\n"
182//usage: " mtu MTU }\n" 159//usage: " [dynamic on|off]\n"
183//usage: "iplink show [DEVICE]" 160//usage: " [multicast on|off]\n"
161//usage: " [mtu MTU]\n"
162//usage: "iplink show [IFACE]"
184//usage: 163//usage:
185//usage:#define iproute_trivial_usage 164//usage:#define iproute_trivial_usage
186//usage: "{ list | flush | add | del | change | append |\n" 165//usage: "list|flush|add|del|change|append|replace|test ROUTE"
187//usage: " replace | test } ROUTE"
188//usage:#define iproute_full_usage "\n\n" 166//usage:#define iproute_full_usage "\n\n"
189//usage: "iproute { list | flush } SELECTOR\n" 167//usage: "iproute list|flush SELECTOR\n"
190//usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n" 168//usage: "iproute get ADDRESS [from ADDRESS iif STRING]\n"
191//usage: " [oif STRING] [tos TOS]\n" 169//usage: " [oif STRING] [tos TOS]\n"
192//usage: "iproute { add | del | change | append | replace | test } ROUTE\n" 170//usage: "iproute add|del|change|append|replace|test ROUTE\n"
193//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" 171//usage: " SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n"
194//usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]" 172//usage: " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO] [metric METRIC]"
195//usage: 173//usage:
196//usage:#define iprule_trivial_usage 174//usage:#define iprule_trivial_usage
197//usage: "{[list | add | del] RULE}" 175//usage: "[list] | add|del SELECTOR ACTION"
198//usage:#define iprule_full_usage "\n\n" 176//usage:#define iprule_full_usage "\n\n"
199//usage: "iprule [list | add | del] SELECTOR ACTION\n"
200//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n" 177//usage: " SELECTOR := [from PREFIX] [to PREFIX] [tos TOS] [fwmark FWMARK]\n"
201//usage: " [dev STRING] [pref NUMBER]\n" 178//usage: " [dev IFACE] [pref NUMBER]\n"
202//usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n" 179//usage: " ACTION := [table TABLE_ID] [nat ADDRESS]\n"
203//usage: " [prohibit | reject | unreachable]\n" 180//usage: " [prohibit|reject|unreachable]\n"
204//usage: " [realms [SRCREALM/]DSTREALM]\n" 181//usage: " [realms [SRCREALM/]DSTREALM]\n"
205//usage: " TABLE_ID := [local | main | default | NUMBER]" 182//usage: " TABLE_ID := [local|main|default|NUMBER]"
206//usage: 183//usage:
207//usage:#define iptunnel_trivial_usage 184//usage:#define iptunnel_trivial_usage
208//usage: "{ add | change | del | show } [NAME]\n" 185//usage: "add|change|del|show [NAME]\n"
209//usage: " [mode { ipip | gre | sit }]\n" 186//usage: " [mode ipip|gre|sit]\n"
210//usage: " [remote ADDR] [local ADDR] [ttl TTL]" 187//usage: " [remote ADDR] [local ADDR] [ttl TTL]"
211//usage:#define iptunnel_full_usage "\n\n" 188//usage:#define iptunnel_full_usage "\n\n"
212//usage: "iptunnel { add | change | del | show } [NAME]\n" 189//usage: "iptunnel add|change|del|show [NAME]\n"
213//usage: " [mode { ipip | gre | sit }] [remote ADDR] [local ADDR]\n" 190//usage: " [mode ipip|gre|sit] [remote ADDR] [local ADDR]\n"
214//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n" 191//usage: " [[i|o]seq] [[i|o]key KEY] [[i|o]csum]\n"
215//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]" 192//usage: " [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]"
216//usage: 193//usage:
217//usage:#define ipneigh_trivial_usage 194//usage:#define ipneigh_trivial_usage
218//usage: "{ show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" 195//usage: "show|flush [to PREFIX] [dev DEV] [nud STATE]"
219//usage:#define ipneigh_full_usage "\n\n" 196//usage:#define ipneigh_full_usage ""
220//usage: "ipneigh { show | flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]" 197//usage:
198//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE
199//usage:# define IP_BAR_LINK "|"
200//usage:#else
201//usage:# define IP_BAR_LINK ""
202//usage:#endif
203//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK
204//usage:# define IP_BAR_TUNNEL "|"
205//usage:#else
206//usage:# define IP_BAR_TUNNEL ""
207//usage:#endif
208//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL
209//usage:# define IP_BAR_NEIGH "|"
210//usage:#else
211//usage:# define IP_BAR_NEIGH ""
212//usage:#endif
213//usage:#if ENABLE_FEATURE_IP_ADDRESS || ENABLE_FEATURE_IP_ROUTE || ENABLE_FEATURE_IP_LINK || ENABLE_FEATURE_IP_TUNNEL || ENABLE_FEATURE_IP_NEIGH
214//usage:# define IP_BAR_RULE "|"
215//usage:#else
216//usage:# define IP_BAR_RULE ""
217//usage:#endif
218//usage:
219//usage:#define ip_trivial_usage
220//usage: "[OPTIONS] "
221//usage: IF_FEATURE_IP_ADDRESS("address")
222//usage: IF_FEATURE_IP_ROUTE( IF_FEATURE_IP_ADDRESS("|")"route")
223//usage: IF_FEATURE_IP_LINK( IP_BAR_LINK "link")
224//usage: IF_FEATURE_IP_TUNNEL( IP_BAR_TUNNEL"tunnel")
225//usage: IF_FEATURE_IP_NEIGH( IP_BAR_NEIGH "neigh")
226//usage: IF_FEATURE_IP_RULE( IP_BAR_RULE "rule")
227//usage: " [COMMAND]"
228//usage:#define ip_full_usage "\n\n"
229//usage: "OPTIONS := -f[amily] inet|inet6|link | -o[neline]\n"
230//usage: "COMMAND :="
231//usage: IF_FEATURE_IP_ADDRESS("\n"
232//usage: "ip addr "ipaddr_trivial_usage)
233//usage: IF_FEATURE_IP_ROUTE("\n"
234//usage: "ip route "iproute_trivial_usage)
235//usage: IF_FEATURE_IP_LINK("\n"
236//usage: "ip link "iplink_trivial_usage)
237//usage: IF_FEATURE_IP_TUNNEL("\n"
238//usage: "ip tunnel "iptunnel_trivial_usage)
239//usage: IF_FEATURE_IP_NEIGH("\n"
240//usage: "ip neigh "ipneigh_trivial_usage)
241//usage: IF_FEATURE_IP_RULE("\n"
242//usage: "ip rule "iprule_trivial_usage)
221 243
222#include "libbb.h" 244#include "libbb.h"
223 245
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 @@
18//config: ipcalc takes an IP address and netmask and calculates the 18//config: ipcalc takes an IP address and netmask and calculates the
19//config: resulting broadcast, network, and host range. 19//config: resulting broadcast, network, and host range.
20//config: 20//config:
21//config:config FEATURE_IPCALC_LONG_OPTIONS
22//config: bool "Enable long options"
23//config: default y
24//config: depends on IPCALC && LONG_OPTS
25//config:
21//config:config FEATURE_IPCALC_FANCY 26//config:config FEATURE_IPCALC_FANCY
22//config: bool "Fancy IPCALC, more options, adds 1 kbyte" 27//config: bool "Fancy IPCALC, more options, adds 1 kbyte"
23//config: default y 28//config: default y
@@ -25,13 +30,6 @@
25//config: help 30//config: help
26//config: Adds the options hostname, prefix and silent to the output of 31//config: Adds the options hostname, prefix and silent to the output of
27//config: "ipcalc". 32//config: "ipcalc".
28//config:
29//config:config FEATURE_IPCALC_LONG_OPTIONS
30//config: bool "Enable long options"
31//config: default y
32//config: depends on IPCALC && LONG_OPTS
33//config: help
34//config: Support long options for the ipcalc applet.
35 33
36//applet:IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP)) 34//applet:IF_IPCALC(APPLET(ipcalc, BB_DIR_BIN, BB_SUID_DROP))
37 35
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 @@
21//config: netstat prints information about the Linux networking subsystem. 21//config: netstat prints information about the Linux networking subsystem.
22//config: 22//config:
23//config:config FEATURE_NETSTAT_WIDE 23//config:config FEATURE_NETSTAT_WIDE
24//config: bool "Enable wide netstat output" 24//config: bool "Enable wide output"
25//config: default y 25//config: default y
26//config: depends on NETSTAT 26//config: depends on NETSTAT
27//config: help 27//config: help
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)
757 * and clear reachable bits, but this proved to be too agressive: 757 * and clear reachable bits, but this proved to be too agressive:
758 * after step (tested with suspending laptop for ~30 secs), 758 * after step (tested with suspending laptop for ~30 secs),
759 * this caused all previous data to be considered invalid, 759 * this caused all previous data to be considered invalid,
760 * making us needing to collect full ~8 datapoins per peer 760 * making us needing to collect full ~8 datapoints per peer
761 * after step in order to start trusting them. 761 * after step in order to start trusting them.
762 * In turn, this was making poll interval decrease even after 762 * In turn, this was making poll interval decrease even after
763 * step was done. (Poll interval decreases already before step 763 * step was done. (Poll interval decreases already before step
@@ -800,6 +800,8 @@ resolve_peer_hostname(peer_t *p)
800 free(p->p_dotted); 800 free(p->p_dotted);
801 p->p_lsa = lsa; 801 p->p_lsa = lsa;
802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); 802 p->p_dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
803 VERB1 if (strcmp(p->p_hostname, p->p_dotted) != 0)
804 bb_error_msg("'%s' is %s", p->p_hostname, p->p_dotted);
803 } else { 805 } else {
804 /* error message is emitted by host2sockaddr() */ 806 /* error message is emitted by host2sockaddr() */
805 set_next(p, HOSTNAME_INTERVAL); 807 set_next(p, HOSTNAME_INTERVAL);
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 @@
94//usage: "\n -4,-6 Force IP or IPv6 name resolution" 94//usage: "\n -4,-6 Force IP or IPv6 name resolution"
95//usage: ) 95//usage: )
96//usage: "\n -c CNT Send only CNT pings" 96//usage: "\n -c CNT Send only CNT pings"
97//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" 97//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
98//usage: "\n -t TTL Set TTL" 98//usage: "\n -t TTL Set TTL"
99//usage: "\n -I IFACE/IP Use interface or IP address as source" 99//usage: "\n -I IFACE/IP Source interface or IP address"
100//usage: "\n -W SEC Seconds to wait for the first response (default:10)" 100//usage: "\n -W SEC Seconds to wait for the first response (default 10)"
101//usage: "\n (after all -c CNT packets are sent)" 101//usage: "\n (after all -c CNT packets are sent)"
102//usage: "\n -w SEC Seconds until ping exits (default:infinite)" 102//usage: "\n -w SEC Seconds until ping exits (default:infinite)"
103//usage: "\n (can exit earlier with -c CNT)" 103//usage: "\n (can exit earlier with -c CNT)"
@@ -110,8 +110,8 @@
110//usage:# define ping6_full_usage "\n\n" 110//usage:# define ping6_full_usage "\n\n"
111//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n" 111//usage: "Send ICMP ECHO_REQUEST packets to network hosts\n"
112//usage: "\n -c CNT Send only CNT pings" 112//usage: "\n -c CNT Send only CNT pings"
113//usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" 113//usage: "\n -s SIZE Send SIZE data bytes in packets (default 56)"
114//usage: "\n -I IFACE/IP Use interface or IP address as source" 114//usage: "\n -I IFACE/IP Source interface or IP address"
115//usage: "\n -q Quiet, only display output at start" 115//usage: "\n -q Quiet, only display output at start"
116//usage: "\n and when finished" 116//usage: "\n and when finished"
117//usage: "\n -p Pattern to use for payload" 117//usage: "\n -p Pattern to use for payload"
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 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//config:config SSL_CLIENT
7//config: bool "ssl_client"
8//config: default y
9//config: select TLS
10//config: help
11//config: This tool pipes data to/from a socket, TLS-encrypting it.
12
13//applet:IF_SSL_CLIENT(APPLET(ssl_client, BB_DIR_USR_BIN, BB_SUID_DROP))
14
15//kbuild:lib-$(CONFIG_SSL_CLIENT) += ssl_client.o
16
17//usage:#define ssl_client_trivial_usage
18//usage: "-s FD [-r FD] [-n SNI]"
19//usage:#define ssl_client_full_usage ""
20
21#include "libbb.h"
22
23int ssl_client_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int ssl_client_main(int argc UNUSED_PARAM, char **argv)
25{
26 tls_state_t *tls;
27 const char *sni = NULL;
28 int opt;
29
30 // INIT_G();
31
32 tls = new_tls_state();
33 opt = getopt32(argv, "s:#r:#n:", &tls->ofd, &tls->ifd, &sni);
34 if (!(opt & 2)) {
35 /* -r N defaults to -s N */
36 tls->ifd = tls->ofd;
37 }
38
39 if (!(opt & 3)) {
40 if (!argv[1])
41 bb_show_usage();
42 /* Undocumented debug feature: without -s and -r, takes HOST arg and connects to it */
43 //
44 // Talk to kernel.org:
45 // printf "GET / HTTP/1.1\r\nHost: kernel.org\r\n\r\n" | ./busybox ssl_client kernel.org
46 if (!sni)
47 sni = argv[1];
48 tls->ifd = tls->ofd = create_and_connect_stream_or_die(argv[1], 443);
49 }
50
51 tls_handshake(tls, sni);
52 tls_run_copy_loop(tls);
53
54 return EXIT_SUCCESS;
55}
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 @@
27/* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */ 27/* //usage: "[OPTIONS] OBJECT CMD [dev STRING]" */
28//usage: "OBJECT CMD [dev STRING]" 28//usage: "OBJECT CMD [dev STRING]"
29//usage:#define tc_full_usage "\n\n" 29//usage:#define tc_full_usage "\n\n"
30//usage: "OBJECT: {qdisc|class|filter}\n" 30//usage: "OBJECT: qdisc|class|filter\n"
31//usage: "CMD: {add|del|change|replace|show}\n" 31//usage: "CMD: add|del|change|replace|show\n"
32//usage: "\n" 32//usage: "\n"
33//usage: "qdisc [ handle QHANDLE ] [ root |"IF_FEATURE_TC_INGRESS(" ingress |")" parent CLASSID ]\n" 33//usage: "qdisc [handle QHANDLE] [root|"IF_FEATURE_TC_INGRESS("ingress|")"parent CLASSID]\n"
34/* //usage: "[ estimator INTERVAL TIME_CONSTANT ]\n" */ 34/* //usage: "[estimator INTERVAL TIME_CONSTANT]\n" */
35//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" 35//usage: " [[QDISC_KIND] [help|OPTIONS]]\n"
36//usage: " QDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n" 36//usage: " QDISC_KIND := [p|b]fifo|tbf|prio|cbq|red|etc.\n"
37//usage: "qdisc show [ dev STRING ]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n" 37//usage: "qdisc show [dev STRING]"IF_FEATURE_TC_INGRESS(" [ingress]")"\n"
38//usage: "class [ classid CLASSID ] [ root | parent CLASSID ]\n" 38//usage: "class [classid CLASSID] [root|parent CLASSID]\n"
39//usage: " [ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" 39//usage: " [[QDISC_KIND] [help|OPTIONS] ]\n"
40//usage: "class show [ dev STRING ] [ root | parent CLASSID ]\n" 40//usage: "class show [ dev STRING ] [root|parent CLASSID]\n"
41//usage: "filter [ pref PRIO ] [ protocol PROTO ]\n" 41//usage: "filter [pref PRIO] [protocol PROTO]\n"
42/* //usage: "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */ 42/* //usage: "\t[estimator INTERVAL TIME_CONSTANT]\n" */
43//usage: " [ root | classid CLASSID ] [ handle FILTERID ]\n" 43//usage: " [root|classid CLASSID] [handle FILTERID]\n"
44//usage: " [ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n" 44//usage: " [[FILTER_TYPE] [help|OPTIONS]]\n"
45//usage: "filter show [ dev STRING ] [ root | parent CLASSID ]" 45//usage: "filter show [dev STRING] [root|parent CLASSID]"
46 46
47#include "libbb.h" 47#include "libbb.h"
48#include "common_bufsiz.h" 48#include "common_bufsiz.h"
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 @@
45//config: remote host you are connecting to. This is useful when you need to 45//config: remote host you are connecting to. This is useful when you need to
46//config: log into a machine without telling the username (autologin). This 46//config: log into a machine without telling the username (autologin). This
47//config: option enables `-a' and `-l USER' arguments. 47//config: option enables `-a' and `-l USER' arguments.
48//config:
49//config:config FEATURE_TELNET_WIDTH
50//config: bool "Enable window size autodetection"
51//config: default y
52//config: depends on TELNET
48 53
49//applet:IF_TELNET(APPLET(telnet, BB_DIR_USR_BIN, BB_SUID_DROP)) 54//applet:IF_TELNET(APPLET(telnet, BB_DIR_USR_BIN, BB_SUID_DROP))
50 55
@@ -128,7 +133,7 @@ struct globals {
128#if ENABLE_FEATURE_TELNET_AUTOLOGIN 133#if ENABLE_FEATURE_TELNET_AUTOLOGIN
129 const char *autologin; 134 const char *autologin;
130#endif 135#endif
131#if ENABLE_FEATURE_AUTOWIDTH 136#if ENABLE_FEATURE_TELNET_WIDTH
132 unsigned win_width, win_height; 137 unsigned win_width, win_height;
133#endif 138#endif
134 /* same buffer used both for network and console read/write */ 139 /* same buffer used both for network and console read/write */
@@ -401,7 +406,7 @@ static void put_iac_subopt_autologin(void)
401} 406}
402#endif 407#endif
403 408
404#if ENABLE_FEATURE_AUTOWIDTH 409#if ENABLE_FEATURE_TELNET_WIDTH
405static void put_iac_naws(byte c, int x, int y) 410static void put_iac_naws(byte c, int x, int y)
406{ 411{
407 if (G.iaclen + 9 > IACBUFSIZE) 412 if (G.iaclen + 9 > IACBUFSIZE)
@@ -538,7 +543,7 @@ static void to_new_environ(void)
538} 543}
539#endif 544#endif
540 545
541#if ENABLE_FEATURE_AUTOWIDTH 546#if ENABLE_FEATURE_TELNET_WIDTH
542static void to_naws(void) 547static void to_naws(void)
543{ 548{
544 /* Tell server we will do NAWS */ 549 /* Tell server we will do NAWS */
@@ -561,7 +566,7 @@ static void telopt(byte c)
561 case TELOPT_NEW_ENVIRON: 566 case TELOPT_NEW_ENVIRON:
562 to_new_environ(); break; 567 to_new_environ(); break;
563#endif 568#endif
564#if ENABLE_FEATURE_AUTOWIDTH 569#if ENABLE_FEATURE_TELNET_WIDTH
565 case TELOPT_NAWS: 570 case TELOPT_NAWS:
566 to_naws(); 571 to_naws();
567 put_iac_naws(c, G.win_width, G.win_height); 572 put_iac_naws(c, G.win_width, G.win_height);
@@ -623,7 +628,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
623 628
624 INIT_G(); 629 INIT_G();
625 630
626#if ENABLE_FEATURE_AUTOWIDTH 631#if ENABLE_FEATURE_TELNET_WIDTH
627 get_terminal_width_height(0, &G.win_width, &G.win_height); 632 get_terminal_width_height(0, &G.win_width, &G.win_height);
628#endif 633#endif
629 634
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 @@
69//config: "blksize" and "tsize" options. 69//config: "blksize" and "tsize" options.
70//config: 70//config:
71//config:config FEATURE_TFTP_PROGRESS_BAR 71//config:config FEATURE_TFTP_PROGRESS_BAR
72//config: bool "Enable tftp progress meter" 72//config: bool "Enable progress bar"
73//config: default y 73//config: default y
74//config: depends on TFTP && FEATURE_TFTP_BLOCKSIZE 74//config: depends on TFTP && FEATURE_TFTP_BLOCKSIZE
75//config: help
76//config: Show progress bar.
77//config: 75//config:
78//config:config TFTP_DEBUG 76//config:config TFTP_DEBUG
79//config: bool "Enable debug" 77//config: bool "Enable debug"
diff --git a/networking/tls.c b/networking/tls.c
new file mode 100644
index 000000000..30afd9ea9
--- /dev/null
+++ b/networking/tls.c
@@ -0,0 +1,1815 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6//config:config TLS
7//config: bool #No description makes it a hidden option
8//config: default n
9
10//kbuild:lib-$(CONFIG_TLS) += tls.o
11//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o
12//kbuild:lib-$(CONFIG_TLS) += tls_pstm_montgomery_reduce.o
13//kbuild:lib-$(CONFIG_TLS) += tls_pstm_mul_comba.o
14//kbuild:lib-$(CONFIG_TLS) += tls_pstm_sqr_comba.o
15//kbuild:lib-$(CONFIG_TLS) += tls_rsa.o
16//kbuild:lib-$(CONFIG_TLS) += tls_aes.o
17////kbuild:lib-$(CONFIG_TLS) += tls_aes_gcm.o
18
19#include "tls.h"
20
21//Tested against kernel.org:
22//TLS 1.2
23#define TLS_MAJ 3
24#define TLS_MIN 3
25//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA // ok, recvs SERVER_KEY_EXCHANGE *** matrixssl uses this on my box
26//#define CIPHER_ID TLS_RSA_WITH_AES_256_CBC_SHA256 // ok, no SERVER_KEY_EXCHANGE
27//#define CIPHER_ID TLS_DH_anon_WITH_AES_256_CBC_SHA // SSL_ALERT_HANDSHAKE_FAILURE
28//^^^^^^^^^^^^^^^^^^^^^^^ (tested b/c this one doesn't req server certs... no luck, server refuses it)
29//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 // SSL_ALERT_HANDSHAKE_FAILURE
30//#define CIPHER_ID TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
31//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // ok, recvs SERVER_KEY_EXCHANGE
32//#define CIPHER_ID TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
33//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
34//#define CIPHER_ID TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
35//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
36//#define CIPHER_ID TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 // SSL_ALERT_HANDSHAKE_FAILURE
37//#define CIPHER_ID TLS_RSA_WITH_AES_256_GCM_SHA384 // ok, no SERVER_KEY_EXCHANGE
38//#define CIPHER_ID TLS_RSA_WITH_AES_128_GCM_SHA256 // ok, no SERVER_KEY_EXCHANGE *** select this?
39
40// works against "openssl s_server -cipher NULL"
41// and against wolfssl-3.9.10-stable/examples/server/server.c:
42//#define CIPHER_ID TLS_RSA_WITH_NULL_SHA256 // for testing (does everything except encrypting)
43
44// works against wolfssl-3.9.10-stable/examples/server/server.c
45// works for kernel.org
46// does not work for cdn.kernel.org (e.g. downloading an actual tarball, not a web page)
47// getting alert 40 "handshake failure" at once
48// with GNU Wget 1.18, they agree on TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xC02F) cipher
49// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-SHA256
50// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES256-GCM-SHA384
51// fail: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA256
52// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-GCM-SHA256
53// ok: openssl s_client -connect cdn.kernel.org:443 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher AES128-SHA
54// (TLS_RSA_WITH_AES_128_CBC_SHA - in TLS 1.2 it's mandated to be always supported)
55#define CIPHER_ID1 TLS_RSA_WITH_AES_256_CBC_SHA256 // no SERVER_KEY_EXCHANGE from peer
56// Works with "wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.9.5.tar.xz"
57#define CIPHER_ID2 TLS_RSA_WITH_AES_128_CBC_SHA
58
59
60#define TLS_DEBUG 0
61#define TLS_DEBUG_HASH 0
62#define TLS_DEBUG_DER 0
63#define TLS_DEBUG_FIXED_SECRETS 0
64#if 0
65# define dump_raw_out(...) dump_hex(__VA_ARGS__)
66#else
67# define dump_raw_out(...) ((void)0)
68#endif
69#if 0
70# define dump_raw_in(...) dump_hex(__VA_ARGS__)
71#else
72# define dump_raw_in(...) ((void)0)
73#endif
74
75#if TLS_DEBUG
76# define dbg(...) fprintf(stderr, __VA_ARGS__)
77#else
78# define dbg(...) ((void)0)
79#endif
80
81#if TLS_DEBUG_DER
82# define dbg_der(...) fprintf(stderr, __VA_ARGS__)
83#else
84# define dbg_der(...) ((void)0)
85#endif
86
87#define RECORD_TYPE_CHANGE_CIPHER_SPEC 20
88#define RECORD_TYPE_ALERT 21
89#define RECORD_TYPE_HANDSHAKE 22
90#define RECORD_TYPE_APPLICATION_DATA 23
91
92#define HANDSHAKE_HELLO_REQUEST 0
93#define HANDSHAKE_CLIENT_HELLO 1
94#define HANDSHAKE_SERVER_HELLO 2
95#define HANDSHAKE_HELLO_VERIFY_REQUEST 3
96#define HANDSHAKE_NEW_SESSION_TICKET 4
97#define HANDSHAKE_CERTIFICATE 11
98#define HANDSHAKE_SERVER_KEY_EXCHANGE 12
99#define HANDSHAKE_CERTIFICATE_REQUEST 13
100#define HANDSHAKE_SERVER_HELLO_DONE 14
101#define HANDSHAKE_CERTIFICATE_VERIFY 15
102#define HANDSHAKE_CLIENT_KEY_EXCHANGE 16
103#define HANDSHAKE_FINISHED 20
104
105#define SSL_NULL_WITH_NULL_NULL 0x0000
106#define SSL_RSA_WITH_NULL_MD5 0x0001
107#define SSL_RSA_WITH_NULL_SHA 0x0002
108#define SSL_RSA_WITH_RC4_128_MD5 0x0004
109#define SSL_RSA_WITH_RC4_128_SHA 0x0005
110#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* 10 */
111#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* 47 */
112#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* 53 */
113#define TLS_RSA_WITH_NULL_SHA256 0x003B /* 59 */
114
115#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
116
117#define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* 7 */
118#define SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* 22 */
119#define SSL_DH_anon_WITH_RC4_128_MD5 0x0018 /* 24 */
120#define SSL_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* 27 */
121#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* 51 */
122#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* 57 */
123#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 /* 103 */
124#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B /* 107 */
125#define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* 52 */
126#define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* 58 */
127#define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C /* 60 */
128#define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D /* 61 */
129#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096 /* 150 */
130#define TLS_PSK_WITH_AES_128_CBC_SHA 0x008C /* 140 */
131#define TLS_PSK_WITH_AES_128_CBC_SHA256 0x00AE /* 174 */
132#define TLS_PSK_WITH_AES_256_CBC_SHA384 0x00AF /* 175 */
133#define TLS_PSK_WITH_AES_256_CBC_SHA 0x008D /* 141 */
134#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x0090 /* 144 */
135#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */
136#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /* 49156 */
137#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /* 49157 */
138#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /* 49161 */
139#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /* 49162 */
140#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /* 49170 */
141#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /* 49171 */
142#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /* 49172 */
143#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /* 49166 */
144#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /* 49167 */
145#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /* 49187 */
146#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /* 49188 */
147#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /* 49189 */
148#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /* 49190 */
149#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /* 49191 */
150#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /* 49192 */
151#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /* 49193 */
152#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /* 49194 */
153
154/* RFC 5288 "AES Galois Counter Mode (GCM) Cipher Suites for TLS" */
155#define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */
156#define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */
157#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /* 49195 */
158#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /* 49196 */
159#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /* 49197 */
160#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /* 49198 */
161#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /* 49199 */
162#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /* 49200 */
163#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /* 49201 */
164#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /* 49202 */
165
166/* Might go to libbb.h */
167#define TLS_MAX_CRYPTBLOCK_SIZE 16
168#define TLS_MAX_OUTBUF (1 << 14)
169
170enum {
171 SHA_INSIZE = 64,
172 SHA1_OUTSIZE = 20,
173 SHA256_OUTSIZE = 32,
174
175 AES_BLOCKSIZE = 16,
176 AES128_KEYSIZE = 16,
177 AES256_KEYSIZE = 32,
178
179 RSA_PREMASTER_SIZE = 48,
180
181 RECHDR_LEN = 5,
182
183 /* 8 = 3+5. 3 extra bytes result in record data being 32-bit aligned */
184 OUTBUF_PFX = 8 + AES_BLOCKSIZE, /* header + IV */
185 OUTBUF_SFX = TLS_MAX_MAC_SIZE + TLS_MAX_CRYPTBLOCK_SIZE, /* MAC + padding */
186
187 // RFC 5246
188 // | 6.2.1. Fragmentation
189 // | The record layer fragments information blocks into TLSPlaintext
190 // | records carrying data in chunks of 2^14 bytes or less. Client
191 // | message boundaries are not preserved in the record layer (i.e.,
192 // | multiple client messages of the same ContentType MAY be coalesced
193 // | into a single TLSPlaintext record, or a single message MAY be
194 // | fragmented across several records)
195 // |...
196 // | length
197 // | The length (in bytes) of the following TLSPlaintext.fragment.
198 // | The length MUST NOT exceed 2^14.
199 // |...
200 // | 6.2.2. Record Compression and Decompression
201 // |...
202 // | Compression must be lossless and may not increase the content length
203 // | by more than 1024 bytes. If the decompression function encounters a
204 // | TLSCompressed.fragment that would decompress to a length in excess of
205 // | 2^14 bytes, it MUST report a fatal decompression failure error.
206 // |...
207 // | length
208 // | The length (in bytes) of the following TLSCompressed.fragment.
209 // | The length MUST NOT exceed 2^14 + 1024.
210 // |...
211 // | 6.2.3. Record Payload Protection
212 // | The encryption and MAC functions translate a TLSCompressed
213 // | structure into a TLSCiphertext. The decryption functions reverse
214 // | the process. The MAC of the record also includes a sequence
215 // | number so that missing, extra, or repeated messages are
216 // | detectable.
217 // |...
218 // | length
219 // | The length (in bytes) of the following TLSCiphertext.fragment.
220 // | The length MUST NOT exceed 2^14 + 2048.
221 MAX_INBUF = RECHDR_LEN + (1 << 14) + 2048,
222};
223
224struct record_hdr {
225 uint8_t type;
226 uint8_t proto_maj, proto_min;
227 uint8_t len16_hi, len16_lo;
228};
229
230struct tls_handshake_data {
231 /* In bbox, md5/sha1/sha256 ctx's are the same structure */
232 md5sha_ctx_t handshake_hash_ctx;
233
234 uint8_t client_and_server_rand32[2 * 32];
235 uint8_t master_secret[48];
236//TODO: store just the DER key here, parse/use/delete it when sending client key
237//this way it will stay key type agnostic here.
238 psRsaKey_t server_rsa_pub_key;
239
240 unsigned saved_client_hello_size;
241 uint8_t saved_client_hello[1];
242};
243
244
245static unsigned get24be(const uint8_t *p)
246{
247 return 0x100*(0x100*p[0] + p[1]) + p[2];
248}
249
250#if TLS_DEBUG
251static void dump_hex(const char *fmt, const void *vp, int len)
252{
253 char hexbuf[32 * 1024 + 4];
254 const uint8_t *p = vp;
255
256 bin2hex(hexbuf, (void*)p, len)[0] = '\0';
257 dbg(fmt, hexbuf);
258}
259
260static void dump_tls_record(const void *vp, int len)
261{
262 const uint8_t *p = vp;
263
264 while (len > 0) {
265 unsigned xhdr_len;
266 if (len < RECHDR_LEN) {
267 dump_hex("< |%s|\n", p, len);
268 return;
269 }
270 xhdr_len = 0x100*p[3] + p[4];
271 dbg("< hdr_type:%u ver:%u.%u len:%u", p[0], p[1], p[2], xhdr_len);
272 p += RECHDR_LEN;
273 len -= RECHDR_LEN;
274 if (len >= 4 && p[-RECHDR_LEN] == RECORD_TYPE_HANDSHAKE) {
275 unsigned len24 = get24be(p + 1);
276 dbg(" type:%u len24:%u", p[0], len24);
277 }
278 if (xhdr_len > len)
279 xhdr_len = len;
280 dump_hex(" |%s|\n", p, xhdr_len);
281 p += xhdr_len;
282 len -= xhdr_len;
283 }
284}
285#else
286# define dump_hex(...) ((void)0)
287# define dump_tls_record(...) ((void)0)
288#endif
289
290void tls_get_random(void *buf, unsigned len)
291{
292 if (len != open_read_close("/dev/urandom", buf, len))
293 xfunc_die();
294}
295
296/* Nondestructively see the current hash value */
297static unsigned sha_peek(md5sha_ctx_t *ctx, void *buffer)
298{
299 md5sha_ctx_t ctx_copy = *ctx; /* struct copy */
300 return sha_end(&ctx_copy, buffer);
301}
302
303static ALWAYS_INLINE unsigned get_handshake_hash(tls_state_t *tls, void *buffer)
304{
305 return sha_peek(&tls->hsd->handshake_hash_ctx, buffer);
306}
307
308#if !TLS_DEBUG_HASH
309# define hash_handshake(tls, fmt, buffer, len) \
310 hash_handshake(tls, buffer, len)
311#endif
312static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer, unsigned len)
313{
314 md5sha_hash(&tls->hsd->handshake_hash_ctx, buffer, len);
315#if TLS_DEBUG_HASH
316 {
317 uint8_t h[TLS_MAX_MAC_SIZE];
318 dump_hex(fmt, buffer, len);
319 dbg(" (%u bytes) ", (int)len);
320 len = sha_peek(&tls->hsd->handshake_hash_ctx, h);
321 if (len == SHA1_OUTSIZE)
322 dump_hex("sha1:%s\n", h, len);
323 else
324 if (len == SHA256_OUTSIZE)
325 dump_hex("sha256:%s\n", h, len);
326 else
327 dump_hex("sha???:%s\n", h, len);
328 }
329#endif
330}
331
332// RFC 2104
333// HMAC(key, text) based on a hash H (say, sha256) is:
334// ipad = [0x36 x INSIZE]
335// opad = [0x5c x INSIZE]
336// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
337//
338// H(key XOR opad) and H(key XOR ipad) can be precomputed
339// if we often need HMAC hmac with the same key.
340//
341// text is often given in disjoint pieces.
342typedef struct hmac_precomputed {
343 md5sha_ctx_t hashed_key_xor_ipad;
344 md5sha_ctx_t hashed_key_xor_opad;
345} hmac_precomputed_t;
346
347static unsigned hmac_sha_precomputed_v(
348 hmac_precomputed_t *pre,
349 uint8_t *out,
350 va_list va)
351{
352 uint8_t *text;
353 unsigned len;
354
355 /* pre->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
356 /* pre->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
357
358 /* calculate out = H((key XOR ipad) + text) */
359 while ((text = va_arg(va, uint8_t*)) != NULL) {
360 unsigned text_size = va_arg(va, unsigned);
361 md5sha_hash(&pre->hashed_key_xor_ipad, text, text_size);
362 }
363 len = sha_end(&pre->hashed_key_xor_ipad, out);
364
365 /* out = H((key XOR opad) + out) */
366 md5sha_hash(&pre->hashed_key_xor_opad, out, len);
367 return sha_end(&pre->hashed_key_xor_opad, out);
368}
369
370static void hmac_sha256_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size)
371{
372 uint8_t key_xor_ipad[SHA_INSIZE];
373 uint8_t key_xor_opad[SHA_INSIZE];
374 uint8_t tempkey[SHA256_OUTSIZE];
375 unsigned i;
376
377 // "The authentication key can be of any length up to INSIZE, the
378 // block length of the hash function. Applications that use keys longer
379 // than INSIZE bytes will first hash the key using H and then use the
380 // resultant OUTSIZE byte string as the actual key to HMAC."
381 if (key_size > SHA_INSIZE) {
382 md5sha_ctx_t ctx;
383 sha256_begin(&ctx);
384 md5sha_hash(&ctx, key, key_size);
385 key_size = sha_end(&ctx, tempkey);
386 }
387
388 for (i = 0; i < key_size; i++) {
389 key_xor_ipad[i] = key[i] ^ 0x36;
390 key_xor_opad[i] = key[i] ^ 0x5c;
391 }
392 for (; i < SHA_INSIZE; i++) {
393 key_xor_ipad[i] = 0x36;
394 key_xor_opad[i] = 0x5c;
395 }
396
397 sha256_begin(&pre->hashed_key_xor_ipad);
398 sha256_begin(&pre->hashed_key_xor_opad);
399 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
400 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
401}
402// TODO: ^^^ vvv merge?
403static void hmac_sha1_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size)
404{
405 uint8_t key_xor_ipad[SHA_INSIZE];
406 uint8_t key_xor_opad[SHA_INSIZE];
407 uint8_t tempkey[SHA1_OUTSIZE];
408 unsigned i;
409
410 // "The authentication key can be of any length up to INSIZE, the
411 // block length of the hash function. Applications that use keys longer
412 // than INSIZE bytes will first hash the key using H and then use the
413 // resultant OUTSIZE byte string as the actual key to HMAC."
414 if (key_size > SHA_INSIZE) {
415 md5sha_ctx_t ctx;
416 sha1_begin(&ctx);
417 md5sha_hash(&ctx, key, key_size);
418 key_size = sha_end(&ctx, tempkey);
419 }
420
421 for (i = 0; i < key_size; i++) {
422 key_xor_ipad[i] = key[i] ^ 0x36;
423 key_xor_opad[i] = key[i] ^ 0x5c;
424 }
425 for (; i < SHA_INSIZE; i++) {
426 key_xor_ipad[i] = 0x36;
427 key_xor_opad[i] = 0x5c;
428 }
429
430 sha1_begin(&pre->hashed_key_xor_ipad);
431 sha1_begin(&pre->hashed_key_xor_opad);
432 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
433 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
434}
435
436static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
437{
438 hmac_precomputed_t pre;
439 va_list va;
440 unsigned len;
441
442 va_start(va, key_size);
443
444 if (tls->MAC_size == SHA256_OUTSIZE)
445 hmac_sha256_begin(&pre, key, key_size);
446 else
447 hmac_sha1_begin(&pre, key, key_size);
448
449 len = hmac_sha_precomputed_v(&pre, out, va);
450
451 va_end(va);
452 return len;
453}
454
455static unsigned hmac_sha256(/*tls_state_t *tls,*/ uint8_t *out, uint8_t *key, unsigned key_size, ...)
456{
457 hmac_precomputed_t pre;
458 va_list va;
459 unsigned len;
460
461 va_start(va, key_size);
462
463 hmac_sha256_begin(&pre, key, key_size);
464 len = hmac_sha_precomputed_v(&pre, out, va);
465
466 va_end(va);
467 return len;
468}
469
470// RFC 5246:
471// 5. HMAC and the Pseudorandom Function
472//...
473// In this section, we define one PRF, based on HMAC. This PRF with the
474// SHA-256 hash function is used for all cipher suites defined in this
475// document and in TLS documents published prior to this document when
476// TLS 1.2 is negotiated.
477// ^^^^^^^^^^^^^ IMPORTANT!
478// PRF uses sha256 regardless of cipher (at least for all ciphers
479// defined by RFC5246). It's not sha1 for AES_128_CBC_SHA!
480//...
481// P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
482// HMAC_hash(secret, A(2) + seed) +
483// HMAC_hash(secret, A(3) + seed) + ...
484// where + indicates concatenation.
485// A() is defined as:
486// A(0) = seed
487// A(1) = HMAC_hash(secret, A(0)) = HMAC_hash(secret, seed)
488// A(i) = HMAC_hash(secret, A(i-1))
489// P_hash can be iterated as many times as necessary to produce the
490// required quantity of data. For example, if P_SHA256 is being used to
491// create 80 bytes of data, it will have to be iterated three times
492// (through A(3)), creating 96 bytes of output data; the last 16 bytes
493// of the final iteration will then be discarded, leaving 80 bytes of
494// output data.
495//
496// TLS's PRF is created by applying P_hash to the secret as:
497//
498// PRF(secret, label, seed) = P_<hash>(secret, label + seed)
499//
500// The label is an ASCII string.
501static void prf_hmac_sha256(/*tls_state_t *tls,*/
502 uint8_t *outbuf, unsigned outbuf_size,
503 uint8_t *secret, unsigned secret_size,
504 const char *label,
505 uint8_t *seed, unsigned seed_size)
506{
507 uint8_t a[TLS_MAX_MAC_SIZE];
508 uint8_t *out_p = outbuf;
509 unsigned label_size = strlen(label);
510 unsigned MAC_size = SHA256_OUTSIZE;///tls->MAC_size;
511
512 /* In P_hash() calculation, "seed" is "label + seed": */
513#define SEED label, label_size, seed, seed_size
514#define SECRET secret, secret_size
515#define A a, MAC_size
516
517 /* A(1) = HMAC_hash(secret, seed) */
518 hmac_sha256(/*tls,*/ a, SECRET, SEED, NULL);
519//TODO: convert hmac to precomputed
520
521 for(;;) {
522 /* HMAC_hash(secret, A(1) + seed) */
523 if (outbuf_size <= MAC_size) {
524 /* Last, possibly incomplete, block */
525 /* (use a[] as temp buffer) */
526 hmac_sha256(/*tls,*/ a, SECRET, A, SEED, NULL);
527 memcpy(out_p, a, outbuf_size);
528 return;
529 }
530 /* Not last block. Store directly to result buffer */
531 hmac_sha256(/*tls,*/ out_p, SECRET, A, SEED, NULL);
532 out_p += MAC_size;
533 outbuf_size -= MAC_size;
534 /* A(2) = HMAC_hash(secret, A(1)) */
535 hmac_sha256(/*tls,*/ a, SECRET, A, NULL);
536 }
537#undef A
538#undef SECRET
539#undef SEED
540}
541
542static void bad_record_die(tls_state_t *tls, const char *expected, int len)
543{
544 bb_error_msg("got bad TLS record (len:%d) while expecting %s", len, expected);
545 if (len > 0) {
546 uint8_t *p = tls->inbuf;
547 while (len > 0) {
548 fprintf(stderr, " %02x", *p++);
549 len--;
550 }
551 fputc('\n', stderr);
552 }
553 xfunc_die();
554}
555
556static void tls_error_die(tls_state_t *tls, int line)
557{
558 dump_tls_record(tls->inbuf, tls->ofs_to_buffered + tls->buffered_size);
559 bb_error_msg_and_die("tls error at line %d cipher:%04x", line, tls->cipher_id);
560}
561#define tls_error_die(tls) tls_error_die(tls, __LINE__)
562
563#if 0 //UNUSED
564static void tls_free_inbuf(tls_state_t *tls)
565{
566 if (tls->buffered_size == 0) {
567 free(tls->inbuf);
568 tls->inbuf_size = 0;
569 tls->inbuf = NULL;
570 }
571}
572#endif
573
574static void tls_free_outbuf(tls_state_t *tls)
575{
576 free(tls->outbuf);
577 tls->outbuf_size = 0;
578 tls->outbuf = NULL;
579}
580
581static void *tls_get_outbuf(tls_state_t *tls, int len)
582{
583 if (len > TLS_MAX_OUTBUF)
584 xfunc_die();
585 len += OUTBUF_PFX + OUTBUF_SFX;
586 if (tls->outbuf_size < len) {
587 tls->outbuf_size = len;
588 tls->outbuf = xrealloc(tls->outbuf, len);
589 }
590 return tls->outbuf + OUTBUF_PFX;
591}
592
593static void xwrite_encrypted(tls_state_t *tls, unsigned size, unsigned type)
594{
595 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
596 struct record_hdr *xhdr;
597 uint8_t padding_length;
598
599 xhdr = (void*)(buf - RECHDR_LEN);
600 if (tls->cipher_id != TLS_RSA_WITH_NULL_SHA256)
601 xhdr = (void*)(buf - RECHDR_LEN - AES_BLOCKSIZE); /* place for IV */
602
603 xhdr->type = type;
604 xhdr->proto_maj = TLS_MAJ;
605 xhdr->proto_min = TLS_MIN;
606 /* fake unencrypted record len for MAC calculation */
607 xhdr->len16_hi = size >> 8;
608 xhdr->len16_lo = size & 0xff;
609
610 /* Calculate MAC signature */
611 hmac(tls, buf + size, /* result */
612 tls->client_write_MAC_key, tls->MAC_size,
613 &tls->write_seq64_be, sizeof(tls->write_seq64_be),
614 xhdr, RECHDR_LEN,
615 buf, size,
616 NULL
617 );
618 tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
619
620 size += tls->MAC_size;
621
622 // RFC 5246
623 // 6.2.3.1. Null or Standard Stream Cipher
624 //
625 // Stream ciphers (including BulkCipherAlgorithm.null; see Appendix A.6)
626 // convert TLSCompressed.fragment structures to and from stream
627 // TLSCiphertext.fragment structures.
628 //
629 // stream-ciphered struct {
630 // opaque content[TLSCompressed.length];
631 // opaque MAC[SecurityParameters.mac_length];
632 // } GenericStreamCipher;
633 //
634 // The MAC is generated as:
635 // MAC(MAC_write_key, seq_num +
636 // TLSCompressed.type +
637 // TLSCompressed.version +
638 // TLSCompressed.length +
639 // TLSCompressed.fragment);
640 // where "+" denotes concatenation.
641 // seq_num
642 // The sequence number for this record.
643 // MAC
644 // The MAC algorithm specified by SecurityParameters.mac_algorithm.
645 //
646 // Note that the MAC is computed before encryption. The stream cipher
647 // encrypts the entire block, including the MAC.
648 //...
649 // Appendix C. Cipher Suite Definitions
650 //...
651 // MAC Algorithm mac_length mac_key_length
652 // -------- ----------- ---------- --------------
653 // SHA HMAC-SHA1 20 20
654 // SHA256 HMAC-SHA256 32 32
655 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256) {
656 /* No encryption, only signing */
657 xhdr->len16_hi = size >> 8;
658 xhdr->len16_lo = size & 0xff;
659 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
660 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
661 dbg("wrote %u bytes (NULL crypt, SHA256 hash)\n", size);
662 return;
663 }
664
665 // 6.2.3.2. CBC Block Cipher
666 // For block ciphers (such as 3DES or AES), the encryption and MAC
667 // functions convert TLSCompressed.fragment structures to and from block
668 // TLSCiphertext.fragment structures.
669 // struct {
670 // opaque IV[SecurityParameters.record_iv_length];
671 // block-ciphered struct {
672 // opaque content[TLSCompressed.length];
673 // opaque MAC[SecurityParameters.mac_length];
674 // uint8 padding[GenericBlockCipher.padding_length];
675 // uint8 padding_length;
676 // };
677 // } GenericBlockCipher;
678 //...
679 // IV
680 // The Initialization Vector (IV) SHOULD be chosen at random, and
681 // MUST be unpredictable. Note that in versions of TLS prior to 1.1,
682 // there was no IV field (...). For block ciphers, the IV length is
683 // of length SecurityParameters.record_iv_length, which is equal to the
684 // SecurityParameters.block_size.
685 // padding
686 // Padding that is added to force the length of the plaintext to be
687 // an integral multiple of the block cipher's block length.
688 // padding_length
689 // The padding length MUST be such that the total size of the
690 // GenericBlockCipher structure is a multiple of the cipher's block
691 // length. Legal values range from zero to 255, inclusive.
692 //...
693 // Appendix C. Cipher Suite Definitions
694 //...
695 // Key IV Block
696 // Cipher Type Material Size Size
697 // ------------ ------ -------- ---- -----
698 // AES_128_CBC Block 16 16 16
699 // AES_256_CBC Block 32 16 16
700
701 /* Fill IV and padding in outbuf */
702 tls_get_random(buf - AES_BLOCKSIZE, AES_BLOCKSIZE); /* IV */
703 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", size, tls->MAC_size);
704 // RFC is talking nonsense:
705 // "Padding that is added to force the length of the plaintext to be
706 // an integral multiple of the block cipher's block length."
707 // WRONG. _padding+padding_length_, not just _padding_,
708 // pads the data.
709 // IOW: padding_length is the last byte of padding[] array,
710 // contrary to what RFC depicts.
711 //
712 // What actually happens is that there is always padding.
713 // If you need one byte to reach BLOCKSIZE, this byte is 0x00.
714 // If you need two bytes, they are both 0x01.
715 // If you need three, they are 0x02,0x02,0x02. And so on.
716 // If you need no bytes to reach BLOCKSIZE, you have to pad a full
717 // BLOCKSIZE with bytes of value (BLOCKSIZE-1).
718 // It's ok to have more than minimum padding, but we do minimum.
719 padding_length = (~size) & (AES_BLOCKSIZE - 1);
720 do {
721 buf[size++] = padding_length; /* padding */
722 } while ((size & (AES_BLOCKSIZE - 1)) != 0);
723
724 /* Encrypt content+MAC+padding in place */
725 aes_cbc_encrypt(
726 tls->client_write_key, tls->key_size, /* selects 128/256 */
727 buf - AES_BLOCKSIZE, /* IV */
728 buf, size, /* plaintext */
729 buf /* ciphertext */
730 );
731
732 /* Write out */
733 dbg("writing 5 + %u IV + %u encrypted bytes, padding_length:0x%02x\n",
734 AES_BLOCKSIZE, size, padding_length);
735 size += AES_BLOCKSIZE; /* + IV */
736 xhdr->len16_hi = size >> 8;
737 xhdr->len16_lo = size & 0xff;
738 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
739 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
740 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
741}
742
743static void xwrite_handshake_record(tls_state_t *tls, unsigned size)
744{
745 //if (!tls->encrypt_on_write) {
746 uint8_t *buf = tls->outbuf + OUTBUF_PFX;
747 struct record_hdr *xhdr = (void*)(buf - RECHDR_LEN);
748
749 xhdr->type = RECORD_TYPE_HANDSHAKE;
750 xhdr->proto_maj = TLS_MAJ;
751 xhdr->proto_min = TLS_MIN;
752 xhdr->len16_hi = size >> 8;
753 xhdr->len16_lo = size & 0xff;
754 dump_raw_out(">> %s\n", xhdr, RECHDR_LEN + size);
755 xwrite(tls->ofd, xhdr, RECHDR_LEN + size);
756 dbg("wrote %u bytes\n", (int)RECHDR_LEN + size);
757 // return;
758 //}
759 //xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
760}
761
762static void xwrite_and_update_handshake_hash(tls_state_t *tls, unsigned size)
763{
764 if (!tls->encrypt_on_write) {
765 uint8_t *buf;
766
767 xwrite_handshake_record(tls, size);
768 /* Handshake hash does not include record headers */
769 buf = tls->outbuf + OUTBUF_PFX;
770 hash_handshake(tls, ">> hash:%s", buf, size);
771 return;
772 }
773 xwrite_encrypted(tls, size, RECORD_TYPE_HANDSHAKE);
774}
775
776static int tls_has_buffered_record(tls_state_t *tls)
777{
778 int buffered = tls->buffered_size;
779 struct record_hdr *xhdr;
780 int rec_size;
781
782 if (buffered < RECHDR_LEN)
783 return 0;
784 xhdr = (void*)(tls->inbuf + tls->ofs_to_buffered);
785 rec_size = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo);
786 if (buffered < rec_size)
787 return 0;
788 return rec_size;
789}
790
791static const char *alert_text(int code)
792{
793 switch (code) {
794 case 20: return "bad MAC";
795 case 50: return "decode error";
796 case 51: return "decrypt error";
797 case 40: return "handshake failure";
798 case 112: return "unrecognized name";
799 }
800 return itoa(code);
801}
802
803static int tls_xread_record(tls_state_t *tls)
804{
805 struct record_hdr *xhdr;
806 int sz;
807 int total;
808 int target;
809
810 again:
811 dbg("ofs_to_buffered:%u buffered_size:%u\n", tls->ofs_to_buffered, tls->buffered_size);
812 total = tls->buffered_size;
813 if (total != 0) {
814 memmove(tls->inbuf, tls->inbuf + tls->ofs_to_buffered, total);
815 //dbg("<< remaining at %d [%d] ", tls->ofs_to_buffered, total);
816 //dump_raw_in("<< %s\n", tls->inbuf, total);
817 }
818 errno = 0;
819 target = MAX_INBUF;
820 for (;;) {
821 int rem;
822
823 if (total >= RECHDR_LEN && target == MAX_INBUF) {
824 xhdr = (void*)tls->inbuf;
825 target = RECHDR_LEN + (0x100 * xhdr->len16_hi + xhdr->len16_lo);
826 if (target > MAX_INBUF) {
827 /* malformed input (too long): yell and die */
828 tls->buffered_size = 0;
829 tls->ofs_to_buffered = total;
830 tls_error_die(tls);
831 }
832 /* can also check type/proto_maj/proto_min here */
833 dbg("xhdr type:%d ver:%d.%d len:%d\n",
834 xhdr->type, xhdr->proto_maj, xhdr->proto_min,
835 0x100 * xhdr->len16_hi + xhdr->len16_lo
836 );
837 }
838 /* if total >= target, we have a full packet (and possibly more)... */
839 if (total - target >= 0)
840 break;
841 /* input buffer is grown only as needed */
842 rem = tls->inbuf_size - total;
843 if (rem == 0) {
844 tls->inbuf_size += MAX_INBUF / 8;
845 if (tls->inbuf_size > MAX_INBUF)
846 tls->inbuf_size = MAX_INBUF;
847 dbg("inbuf_size:%d\n", tls->inbuf_size);
848 rem = tls->inbuf_size - total;
849 tls->inbuf = xrealloc(tls->inbuf, tls->inbuf_size);
850 }
851 sz = safe_read(tls->ifd, tls->inbuf + total, rem);
852 if (sz <= 0) {
853 if (sz == 0 && total == 0) {
854 /* "Abrupt" EOF, no TLS shutdown (seen from kernel.org) */
855 dbg("EOF (without TLS shutdown) from peer\n");
856 tls->buffered_size = 0;
857 goto end;
858 }
859 bb_perror_msg_and_die("short read, have only %d", total);
860 }
861 dump_raw_in("<< %s\n", tls->inbuf + total, sz);
862 total += sz;
863 }
864 tls->buffered_size = total - target;
865 tls->ofs_to_buffered = target;
866 //dbg("<< stashing at %d [%d] ", tls->ofs_to_buffered, tls->buffered_size);
867 //dump_hex("<< %s\n", tls->inbuf + tls->ofs_to_buffered, tls->buffered_size);
868
869 sz = target - RECHDR_LEN;
870
871 /* Needs to be decrypted? */
872 if (tls->min_encrypted_len_on_read > tls->MAC_size) {
873 uint8_t *p = tls->inbuf + RECHDR_LEN;
874 int padding_len;
875
876 if (sz & (AES_BLOCKSIZE-1)
877 || sz < (int)tls->min_encrypted_len_on_read
878 ) {
879 bb_error_msg_and_die("bad encrypted len:%u < %u",
880 sz, tls->min_encrypted_len_on_read);
881 }
882 /* Decrypt content+MAC+padding, moving it over IV in the process */
883 sz -= AES_BLOCKSIZE; /* we will overwrite IV now */
884 aes_cbc_decrypt(
885 tls->server_write_key, tls->key_size, /* selects 128/256 */
886 p, /* IV */
887 p + AES_BLOCKSIZE, sz, /* ciphertext */
888 p /* plaintext */
889 );
890 padding_len = p[sz - 1];
891 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len);
892 padding_len++;
893 sz -= tls->MAC_size + padding_len; /* drop MAC and padding */
894 //if (sz < 0)
895 // bb_error_msg_and_die("bad padding size:%u", padding_len);
896 } else {
897 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */
898 /* else: no encryption yet on input, subtract zero = NOP */
899 sz -= tls->min_encrypted_len_on_read;
900 }
901 if (sz < 0)
902 bb_error_msg_and_die("encrypted data too short");
903
904 //dump_hex("<< %s\n", tls->inbuf, RECHDR_LEN + sz);
905
906 xhdr = (void*)tls->inbuf;
907 if (xhdr->type == RECORD_TYPE_ALERT && sz >= 2) {
908 uint8_t *p = tls->inbuf + RECHDR_LEN;
909 dbg("ALERT size:%d level:%d description:%d\n", sz, p[0], p[1]);
910 if (p[0] == 2) { /* fatal */
911 bb_error_msg_and_die("TLS %s from peer (alert code %d): %s",
912 "error",
913 p[1], alert_text(p[1])
914 );
915 }
916 if (p[0] == 1) { /* warning */
917 if (p[1] == 0) { /* "close_notify" warning: it's EOF */
918 dbg("EOF (TLS encoded) from peer\n");
919 sz = 0;
920 goto end;
921 }
922//This possibly needs to be cached and shown only if
923//a fatal alert follows
924// bb_error_msg("TLS %s from peer (alert code %d): %s",
925// "warning",
926// p[1], alert_text(p[1])
927// );
928 /* discard it, get next record */
929 goto again;
930 }
931 /* p[0] not 1 or 2: not defined in protocol */
932 sz = 0;
933 goto end;
934 }
935
936 /* RFC 5246 is not saying it explicitly, but sha256 hash
937 * in our FINISHED record must include data of incoming packets too!
938 */
939 if (tls->inbuf[0] == RECORD_TYPE_HANDSHAKE
940 && tls->MAC_size != 0 /* do we know which hash to use? (server_hello() does not!) */
941 ) {
942 hash_handshake(tls, "<< hash:%s", tls->inbuf + RECHDR_LEN, sz);
943 }
944 end:
945 dbg("got block len:%u\n", sz);
946 return sz;
947}
948
949/*
950 * DER parsing routines
951 */
952static unsigned get_der_len(uint8_t **bodyp, uint8_t *der, uint8_t *end)
953{
954 unsigned len, len1;
955
956 if (end - der < 2)
957 xfunc_die();
958// if ((der[0] & 0x1f) == 0x1f) /* not single-byte item code? */
959// xfunc_die();
960
961 len = der[1]; /* maybe it's short len */
962 if (len >= 0x80) {
963 /* no, it's long */
964
965 if (len == 0x80 || end - der < (int)(len - 0x7e)) {
966 /* 0x80 is "0 bytes of len", invalid DER: must use short len if can */
967 /* need 3 or 4 bytes for 81, 82 */
968 xfunc_die();
969 }
970
971 len1 = der[2]; /* if (len == 0x81) it's "ii 81 xx", fetch xx */
972 if (len > 0x82) {
973 /* >0x82 is "3+ bytes of len", should not happen realistically */
974 xfunc_die();
975 }
976 if (len == 0x82) { /* it's "ii 82 xx yy" */
977 len1 = 0x100*len1 + der[3];
978 der += 1; /* skip [yy] */
979 }
980 der += 1; /* skip [xx] */
981 len = len1;
982// if (len < 0x80)
983// xfunc_die(); /* invalid DER: must use short len if can */
984 }
985 der += 2; /* skip [code]+[1byte] */
986
987 if (end - der < (int)len)
988 xfunc_die();
989 *bodyp = der;
990
991 return len;
992}
993
994static uint8_t *enter_der_item(uint8_t *der, uint8_t **endp)
995{
996 uint8_t *new_der;
997 unsigned len = get_der_len(&new_der, der, *endp);
998 dbg_der("entered der @%p:0x%02x len:%u inner_byte @%p:0x%02x\n", der, der[0], len, new_der, new_der[0]);
999 /* Move "end" position to cover only this item */
1000 *endp = new_der + len;
1001 return new_der;
1002}
1003
1004static uint8_t *skip_der_item(uint8_t *der, uint8_t *end)
1005{
1006 uint8_t *new_der;
1007 unsigned len = get_der_len(&new_der, der, end);
1008 /* Skip body */
1009 new_der += len;
1010 dbg_der("skipped der 0x%02x, next byte 0x%02x\n", der[0], new_der[0]);
1011 return new_der;
1012}
1013
1014static void der_binary_to_pstm(pstm_int *pstm_n, uint8_t *der, uint8_t *end)
1015{
1016 uint8_t *bin_ptr;
1017 unsigned len = get_der_len(&bin_ptr, der, end);
1018
1019 dbg_der("binary bytes:%u, first:0x%02x\n", len, bin_ptr[0]);
1020 pstm_init_for_read_unsigned_bin(/*pool:*/ NULL, pstm_n, len);
1021 pstm_read_unsigned_bin(pstm_n, bin_ptr, len);
1022 //return bin + len;
1023}
1024
1025static void find_key_in_der_cert(tls_state_t *tls, uint8_t *der, int len)
1026{
1027/* Certificate is a DER-encoded data structure. Each DER element has a length,
1028 * which makes it easy to skip over large compound elements of any complexity
1029 * without parsing them. Example: partial decode of kernel.org certificate:
1030 * SEQ 0x05ac/1452 bytes (Certificate): 308205ac
1031 * SEQ 0x0494/1172 bytes (tbsCertificate): 30820494
1032 * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0] 3 bytes: a003
1033 * INTEGER (version): 0201 02
1034 * INTEGER 0x11 bytes (serialNumber): 0211 00 9f85bf664b0cddafca508679501b2be4
1035 * //^^^^^^note: matrixSSL also allows [ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2] = 0x82 type
1036 * SEQ 0x0d bytes (signatureAlgo): 300d
1037 * OID 9 bytes: 0609 2a864886f70d01010b (OID_SHA256_RSA_SIG 42.134.72.134.247.13.1.1.11)
1038 * NULL: 0500
1039 * SEQ 0x5f bytes (issuer): 305f
1040 * SET 11 bytes: 310b
1041 * SEQ 9 bytes: 3009
1042 * OID 3 bytes: 0603 550406
1043 * Printable string "FR": 1302 4652
1044 * SET 14 bytes: 310e
1045 * SEQ 12 bytes: 300c
1046 * OID 3 bytes: 0603 550408
1047 * Printable string "Paris": 1305 5061726973
1048 * SET 14 bytes: 310e
1049 * SEQ 12 bytes: 300c
1050 * OID 3 bytes: 0603 550407
1051 * Printable string "Paris": 1305 5061726973
1052 * SET 14 bytes: 310e
1053 * SEQ 12 bytes: 300c
1054 * OID 3 bytes: 0603 55040a
1055 * Printable string "Gandi": 1305 47616e6469
1056 * SET 32 bytes: 3120
1057 * SEQ 30 bytes: 301e
1058 * OID 3 bytes: 0603 550403
1059 * Printable string "Gandi Standard SSL CA 2": 1317 47616e6469205374616e646172642053534c2043412032
1060 * SEQ 30 bytes (validity): 301e
1061 * TIME "161011000000Z": 170d 3136313031313030303030305a
1062 * TIME "191011235959Z": 170d 3139313031313233353935395a
1063 * SEQ 0x5b/91 bytes (subject): 305b //I did not decode this
1064 * 3121301f060355040b1318446f6d61696e20436f
1065 * 6e74726f6c2056616c6964617465643121301f06
1066 * 0355040b1318506f73697469766553534c204d75
1067 * 6c74692d446f6d61696e31133011060355040313
1068 * 0a6b65726e656c2e6f7267
1069 * SEQ 0x01a2/418 bytes (subjectPublicKeyInfo): 308201a2
1070 * SEQ 13 bytes (algorithm): 300d
1071 * OID 9 bytes: 0609 2a864886f70d010101 (OID_RSA_KEY_ALG 42.134.72.134.247.13.1.1.1)
1072 * NULL: 0500
1073 * BITSTRING 0x018f/399 bytes (publicKey): 0382018f
1074 * ????: 00
1075 * //after the zero byte, it appears key itself uses DER encoding:
1076 * SEQ 0x018a/394 bytes: 3082018a
1077 * INTEGER 0x0181/385 bytes (modulus): 02820181
1078 * 00b1ab2fc727a3bef76780c9349bf3
1079 * ...24 more blocks of 15 bytes each...
1080 * 90e895291c6bc8693b65
1081 * INTEGER 3 bytes (exponent): 0203 010001
1082 * [ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0x3] 0x01e5 bytes (X509v3 extensions): a38201e5
1083 * SEQ 0x01e1 bytes: 308201e1
1084 * ...
1085 * Certificate is a sequence of three elements:
1086 * tbsCertificate (SEQ)
1087 * signatureAlgorithm (AlgorithmIdentifier)
1088 * signatureValue (BIT STRING)
1089 *
1090 * In turn, tbsCertificate is a sequence of:
1091 * version
1092 * serialNumber
1093 * signatureAlgo (AlgorithmIdentifier)
1094 * issuer (Name, has complex structure)
1095 * validity (Validity, SEQ of two Times)
1096 * subject (Name)
1097 * subjectPublicKeyInfo (SEQ)
1098 * ...
1099 *
1100 * subjectPublicKeyInfo is a sequence of:
1101 * algorithm (AlgorithmIdentifier)
1102 * publicKey (BIT STRING)
1103 *
1104 * We need Certificate.tbsCertificate.subjectPublicKeyInfo.publicKey
1105 */
1106 uint8_t *end = der + len;
1107
1108 /* enter "Certificate" item: [der, end) will be only Cert */
1109 der = enter_der_item(der, &end);
1110
1111 /* enter "tbsCertificate" item: [der, end) will be only tbsCert */
1112 der = enter_der_item(der, &end);
1113
1114 /* skip up to subjectPublicKeyInfo */
1115 der = skip_der_item(der, end); /* version */
1116 der = skip_der_item(der, end); /* serialNumber */
1117 der = skip_der_item(der, end); /* signatureAlgo */
1118 der = skip_der_item(der, end); /* issuer */
1119 der = skip_der_item(der, end); /* validity */
1120 der = skip_der_item(der, end); /* subject */
1121
1122 /* enter subjectPublicKeyInfo */
1123 der = enter_der_item(der, &end);
1124 { /* check subjectPublicKeyInfo.algorithm */
1125 static const uint8_t expected[] = {
1126 0x30,0x0d, // SEQ 13 bytes
1127 0x06,0x09, 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01, // OID RSA_KEY_ALG 42.134.72.134.247.13.1.1.1
1128 //0x05,0x00, // NULL
1129 };
1130 if (memcmp(der, expected, sizeof(expected)) != 0)
1131 bb_error_msg_and_die("not RSA key");
1132 }
1133 /* skip subjectPublicKeyInfo.algorithm */
1134 der = skip_der_item(der, end);
1135 /* enter subjectPublicKeyInfo.publicKey */
1136// die_if_not_this_der_type(der, end, 0x03); /* must be BITSTRING */
1137 der = enter_der_item(der, &end);
1138
1139 /* parse RSA key: */
1140//based on getAsnRsaPubKey(), pkcs1ParsePrivBin() is also of note
1141 dbg("key bytes:%u, first:0x%02x\n", (int)(end - der), der[0]);
1142 if (end - der < 14) xfunc_die();
1143 /* example format:
1144 * ignore bits: 00
1145 * SEQ 0x018a/394 bytes: 3082018a
1146 * INTEGER 0x0181/385 bytes (modulus): 02820181 XX...XXX
1147 * INTEGER 3 bytes (exponent): 0203 010001
1148 */
1149 if (*der != 0) /* "ignore bits", should be 0 */
1150 xfunc_die();
1151 der++;
1152 der = enter_der_item(der, &end); /* enter SEQ */
1153 /* memset(tls->hsd->server_rsa_pub_key, 0, sizeof(tls->hsd->server_rsa_pub_key)); - already is */
1154 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.N, der, end); /* modulus */
1155 der = skip_der_item(der, end);
1156 der_binary_to_pstm(&tls->hsd->server_rsa_pub_key.e, der, end); /* exponent */
1157 tls->hsd->server_rsa_pub_key.size = pstm_unsigned_bin_size(&tls->hsd->server_rsa_pub_key.N);
1158 dbg("server_rsa_pub_key.size:%d\n", tls->hsd->server_rsa_pub_key.size);
1159}
1160
1161/*
1162 * TLS Handshake routines
1163 */
1164static int tls_xread_handshake_block(tls_state_t *tls, int min_len)
1165{
1166 struct record_hdr *xhdr;
1167 int len = tls_xread_record(tls);
1168
1169 xhdr = (void*)tls->inbuf;
1170 if (len < min_len
1171 || xhdr->type != RECORD_TYPE_HANDSHAKE
1172 || xhdr->proto_maj != TLS_MAJ
1173 || xhdr->proto_min != TLS_MIN
1174 ) {
1175 bad_record_die(tls, "handshake record", len);
1176 }
1177 dbg("got HANDSHAKE\n");
1178 return len;
1179}
1180
1181static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, unsigned len)
1182{
1183 struct handshake_hdr {
1184 uint8_t type;
1185 uint8_t len24_hi, len24_mid, len24_lo;
1186 } *h = buf;
1187
1188 len -= 4;
1189 h->type = type;
1190 h->len24_hi = len >> 16;
1191 h->len24_mid = len >> 8;
1192 h->len24_lo = len & 0xff;
1193}
1194
1195static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1196{
1197 struct client_hello {
1198 uint8_t type;
1199 uint8_t len24_hi, len24_mid, len24_lo;
1200 uint8_t proto_maj, proto_min;
1201 uint8_t rand32[32];
1202 uint8_t session_id_len;
1203 /* uint8_t session_id[]; */
1204 uint8_t cipherid_len16_hi, cipherid_len16_lo;
1205 uint8_t cipherid[2 * (2 + !!CIPHER_ID2)]; /* actually variable */
1206 uint8_t comprtypes_len;
1207 uint8_t comprtypes[1]; /* actually variable */
1208 /* Extensions (SNI shown):
1209 * hi,lo // len of all extensions
1210 * 00,00 // extension_type: "Server Name"
1211 * 00,0e // list len (there can be more than one SNI)
1212 * 00,0c // len of 1st Server Name Indication
1213 * 00 // name type: host_name
1214 * 00,09 // name len
1215 * "localhost" // name
1216 */
1217// GNU Wget 1.18 to cdn.kernel.org sends these extensions:
1218// 0055
1219// 0005 0005 0100000000 - status_request
1220// 0000 0013 0011 00 000e 63646e 2e 6b65726e656c 2e 6f7267 - server_name
1221// ff01 0001 00 - renegotiation_info
1222// 0023 0000 - session_ticket
1223// 000a 0008 0006001700180019 - supported_groups
1224// 000b 0002 0100 - ec_point_formats
1225// 000d 0016 00140401040305010503060106030301030302010203 - signature_algorithms
1226 };
1227 struct client_hello *record;
1228 int len;
1229 int sni_len = sni ? strnlen(sni, 127) : 0;
1230
1231 len = sizeof(*record);
1232 if (sni_len)
1233 len += 11 + strlen(sni);
1234 record = tls_get_outbuf(tls, len);
1235 memset(record, 0, len);
1236
1237 fill_handshake_record_hdr(record, HANDSHAKE_CLIENT_HELLO, len);
1238 record->proto_maj = TLS_MAJ; /* the "requested" version of the protocol, */
1239 record->proto_min = TLS_MIN; /* can be higher than one in record headers */
1240 tls_get_random(record->rand32, sizeof(record->rand32));
1241 if (TLS_DEBUG_FIXED_SECRETS)
1242 memset(record->rand32, 0x11, sizeof(record->rand32));
1243 /* record->session_id_len = 0; - already is */
1244
1245 /* record->cipherid_len16_hi = 0; */
1246 record->cipherid_len16_lo = sizeof(record->cipherid);
1247 /* RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1248 /*record->cipherid[0] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV >> 8; - zero */
1249 record->cipherid[1] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xff;
1250 if ((CIPHER_ID1 >> 8) != 0) record->cipherid[2] = CIPHER_ID1 >> 8;
1251 /*************************/ record->cipherid[3] = CIPHER_ID1 & 0xff;
1252#if CIPHER_ID2
1253 if ((CIPHER_ID2 >> 8) != 0) record->cipherid[4] = CIPHER_ID2 >> 8;
1254 /*************************/ record->cipherid[5] = CIPHER_ID2 & 0xff;
1255#endif
1256
1257 record->comprtypes_len = 1;
1258 /* record->comprtypes[0] = 0; */
1259
1260 if (sni_len) {
1261 uint8_t *p = (void*)(record + 1);
1262 //p[0] = 0; //
1263 p[1] = sni_len + 9; //ext_len
1264 //p[2] = 0; //
1265 //p[3] = 0; //extension_type
1266 //p[4] = 0; //
1267 p[5] = sni_len + 5; //list len
1268 //p[6] = 0; //
1269 p[7] = sni_len + 3; //len of 1st SNI
1270 //p[8] = 0; //name type
1271 //p[9] = 0; //
1272 p[10] = sni_len; //name len
1273 memcpy(&p[11], sni, sni_len);
1274 }
1275
1276 dbg(">> CLIENT_HELLO\n");
1277 /* Can hash it only when we know which MAC hash to use */
1278 /*xwrite_and_update_handshake_hash(tls, len); - WRONG! */
1279 xwrite_handshake_record(tls, len);
1280
1281 tls->hsd = xzalloc(sizeof(*tls->hsd) + len);
1282 tls->hsd->saved_client_hello_size = len;
1283 memcpy(tls->hsd->saved_client_hello, record, len);
1284 memcpy(tls->hsd->client_and_server_rand32, record->rand32, sizeof(record->rand32));
1285}
1286
1287static void get_server_hello(tls_state_t *tls)
1288{
1289 struct server_hello {
1290 struct record_hdr xhdr;
1291 uint8_t type;
1292 uint8_t len24_hi, len24_mid, len24_lo;
1293 uint8_t proto_maj, proto_min;
1294 uint8_t rand32[32]; /* first 4 bytes are unix time in BE format */
1295 uint8_t session_id_len;
1296 uint8_t session_id[32];
1297 uint8_t cipherid_hi, cipherid_lo;
1298 uint8_t comprtype;
1299 /* extensions may follow, but only those which client offered in its Hello */
1300 };
1301
1302 struct server_hello *hp;
1303 uint8_t *cipherid;
1304 unsigned cipher;
1305 int len, len24;
1306
1307 len = tls_xread_handshake_block(tls, 74 - 32);
1308
1309 hp = (void*)tls->inbuf;
1310 // 74 bytes:
1311 // 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|
1312 //SvHl len=70 maj.min unixtime^^^ 28randbytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^_^^^ slen sid32bytes^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cipSel comprSel
1313 if (hp->type != HANDSHAKE_SERVER_HELLO
1314 || hp->len24_hi != 0
1315 || hp->len24_mid != 0
1316 /* hp->len24_lo checked later */
1317 || hp->proto_maj != TLS_MAJ
1318 || hp->proto_min != TLS_MIN
1319 ) {
1320 bad_record_die(tls, "'server hello'", len);
1321 }
1322
1323 cipherid = &hp->cipherid_hi;
1324 len24 = hp->len24_lo;
1325 if (hp->session_id_len != 32) {
1326 if (hp->session_id_len != 0)
1327 bad_record_die(tls, "'server hello'", len);
1328
1329 // session_id_len == 0: no session id
1330 // "The server
1331 // may return an empty session_id to indicate that the session will
1332 // not be cached and therefore cannot be resumed."
1333 cipherid -= 32;
1334 len24 += 32; /* what len would be if session id would be present */
1335 }
1336
1337 if (len24 < 70
1338// || cipherid[0] != (CIPHER_ID >> 8)
1339// || cipherid[1] != (CIPHER_ID & 0xff)
1340// || cipherid[2] != 0 /* comprtype */
1341 ) {
1342 bad_record_die(tls, "'server hello'", len);
1343 }
1344 dbg("<< SERVER_HELLO\n");
1345
1346 memcpy(tls->hsd->client_and_server_rand32 + 32, hp->rand32, sizeof(hp->rand32));
1347
1348 tls->cipher_id = cipher = 0x100 * cipherid[0] + cipherid[1];
1349 dbg("server chose cipher %04x\n", cipher);
1350
1351 if (cipher == TLS_RSA_WITH_AES_128_CBC_SHA) {
1352 tls->key_size = AES128_KEYSIZE;
1353 tls->MAC_size = SHA1_OUTSIZE;
1354 }
1355 else { /* TLS_RSA_WITH_AES_256_CBC_SHA256 */
1356 tls->key_size = AES256_KEYSIZE;
1357 tls->MAC_size = SHA256_OUTSIZE;
1358 }
1359 /* Handshake hash eventually destined to FINISHED record
1360 * is sha256 regardless of cipher
1361 * (at least for all ciphers defined by RFC5246).
1362 * It's not sha1 for AES_128_CBC_SHA - only MAC is sha1, not this hash.
1363 */
1364 sha256_begin(&tls->hsd->handshake_hash_ctx);
1365 hash_handshake(tls, ">> client hello hash:%s",
1366 tls->hsd->saved_client_hello, tls->hsd->saved_client_hello_size
1367 );
1368 hash_handshake(tls, "<< server hello hash:%s",
1369 tls->inbuf + RECHDR_LEN, len
1370 );
1371}
1372
1373static void get_server_cert(tls_state_t *tls)
1374{
1375 struct record_hdr *xhdr;
1376 uint8_t *certbuf;
1377 int len, len1;
1378
1379 len = tls_xread_handshake_block(tls, 10);
1380
1381 xhdr = (void*)tls->inbuf;
1382 certbuf = (void*)(xhdr + 1);
1383 if (certbuf[0] != HANDSHAKE_CERTIFICATE)
1384 tls_error_die(tls);
1385 dbg("<< CERTIFICATE\n");
1386 // 4392 bytes:
1387 // 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...
1388 //Cert len=4388 ChainLen CertLen^ DER encoded X509 starts here. openssl x509 -in FILE -inform DER -noout -text
1389 len1 = get24be(certbuf + 1);
1390 if (len1 > len - 4) tls_error_die(tls);
1391 len = len1;
1392 len1 = get24be(certbuf + 4);
1393 if (len1 > len - 3) tls_error_die(tls);
1394 len = len1;
1395 len1 = get24be(certbuf + 7);
1396 if (len1 > len - 3) tls_error_die(tls);
1397 len = len1;
1398
1399 if (len)
1400 find_key_in_der_cert(tls, certbuf + 10, len);
1401}
1402
1403static void send_empty_client_cert(tls_state_t *tls)
1404{
1405 struct client_empty_cert {
1406 uint8_t type;
1407 uint8_t len24_hi, len24_mid, len24_lo;
1408 uint8_t cert_chain_len24_hi, cert_chain_len24_mid, cert_chain_len24_lo;
1409 };
1410 struct client_empty_cert *record;
1411
1412 record = tls_get_outbuf(tls, sizeof(*record));
1413//FIXME: can just memcpy a ready-made one.
1414 fill_handshake_record_hdr(record, HANDSHAKE_CERTIFICATE, sizeof(*record));
1415 record->cert_chain_len24_hi = 0;
1416 record->cert_chain_len24_mid = 0;
1417 record->cert_chain_len24_lo = 0;
1418
1419 dbg(">> CERTIFICATE\n");
1420 xwrite_and_update_handshake_hash(tls, sizeof(*record));
1421}
1422
1423static void send_client_key_exchange(tls_state_t *tls)
1424{
1425 struct client_key_exchange {
1426 uint8_t type;
1427 uint8_t len24_hi, len24_mid, len24_lo;
1428 /* keylen16 exists for RSA (in TLS, not in SSL), but not for some other key types */
1429 uint8_t keylen16_hi, keylen16_lo;
1430 uint8_t key[4 * 1024]; // size??
1431 };
1432//FIXME: better size estimate
1433 struct client_key_exchange *record = tls_get_outbuf(tls, sizeof(*record));
1434 uint8_t rsa_premaster[RSA_PREMASTER_SIZE];
1435 int len;
1436
1437 tls_get_random(rsa_premaster, sizeof(rsa_premaster));
1438 if (TLS_DEBUG_FIXED_SECRETS)
1439 memset(rsa_premaster, 0x44, sizeof(rsa_premaster));
1440 // RFC 5246
1441 // "Note: The version number in the PreMasterSecret is the version
1442 // offered by the client in the ClientHello.client_version, not the
1443 // version negotiated for the connection."
1444 rsa_premaster[0] = TLS_MAJ;
1445 rsa_premaster[1] = TLS_MIN;
1446 dump_hex("premaster:%s\n", rsa_premaster, sizeof(rsa_premaster));
1447 len = psRsaEncryptPub(/*pool:*/ NULL,
1448 /* psRsaKey_t* */ &tls->hsd->server_rsa_pub_key,
1449 rsa_premaster, /*inlen:*/ sizeof(rsa_premaster),
1450 record->key, sizeof(record->key),
1451 data_param_ignored
1452 );
1453 record->keylen16_hi = len >> 8;
1454 record->keylen16_lo = len & 0xff;
1455 len += 2;
1456 record->type = HANDSHAKE_CLIENT_KEY_EXCHANGE;
1457 record->len24_hi = 0;
1458 record->len24_mid = len >> 8;
1459 record->len24_lo = len & 0xff;
1460 len += 4;
1461
1462 dbg(">> CLIENT_KEY_EXCHANGE\n");
1463 xwrite_and_update_handshake_hash(tls, len);
1464
1465 // RFC 5246
1466 // For all key exchange methods, the same algorithm is used to convert
1467 // the pre_master_secret into the master_secret. The pre_master_secret
1468 // should be deleted from memory once the master_secret has been
1469 // computed.
1470 // master_secret = PRF(pre_master_secret, "master secret",
1471 // ClientHello.random + ServerHello.random)
1472 // [0..47];
1473 // The master secret is always exactly 48 bytes in length. The length
1474 // of the premaster secret will vary depending on key exchange method.
1475 prf_hmac_sha256(/*tls,*/
1476 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1477 rsa_premaster, sizeof(rsa_premaster),
1478 "master secret",
1479 tls->hsd->client_and_server_rand32, sizeof(tls->hsd->client_and_server_rand32)
1480 );
1481 dump_hex("master secret:%s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
1482
1483 // RFC 5246
1484 // 6.3. Key Calculation
1485 //
1486 // The Record Protocol requires an algorithm to generate keys required
1487 // by the current connection state (see Appendix A.6) from the security
1488 // parameters provided by the handshake protocol.
1489 //
1490 // The master secret is expanded into a sequence of secure bytes, which
1491 // is then split to a client write MAC key, a server write MAC key, a
1492 // client write encryption key, and a server write encryption key. Each
1493 // of these is generated from the byte sequence in that order. Unused
1494 // values are empty. Some AEAD ciphers may additionally require a
1495 // client write IV and a server write IV (see Section 6.2.3.3).
1496 //
1497 // When keys and MAC keys are generated, the master secret is used as an
1498 // entropy source.
1499 //
1500 // To generate the key material, compute
1501 //
1502 // key_block = PRF(SecurityParameters.master_secret,
1503 // "key expansion",
1504 // SecurityParameters.server_random +
1505 // SecurityParameters.client_random);
1506 //
1507 // until enough output has been generated. Then, the key_block is
1508 // partitioned as follows:
1509 //
1510 // client_write_MAC_key[SecurityParameters.mac_key_length]
1511 // server_write_MAC_key[SecurityParameters.mac_key_length]
1512 // client_write_key[SecurityParameters.enc_key_length]
1513 // server_write_key[SecurityParameters.enc_key_length]
1514 // client_write_IV[SecurityParameters.fixed_iv_length]
1515 // server_write_IV[SecurityParameters.fixed_iv_length]
1516 {
1517 uint8_t tmp64[64];
1518
1519 /* make "server_rand32 + client_rand32" */
1520 memcpy(&tmp64[0] , &tls->hsd->client_and_server_rand32[32], 32);
1521 memcpy(&tmp64[32], &tls->hsd->client_and_server_rand32[0] , 32);
1522
1523 prf_hmac_sha256(/*tls,*/
1524 tls->client_write_MAC_key, 2 * (tls->MAC_size + tls->key_size),
1525 // also fills:
1526 // server_write_MAC_key[]
1527 // client_write_key[]
1528 // server_write_key[]
1529 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1530 "key expansion",
1531 tmp64, 64
1532 );
1533 tls->client_write_key = tls->client_write_MAC_key + (2 * tls->MAC_size);
1534 tls->server_write_key = tls->client_write_key + tls->key_size;
1535 dump_hex("client_write_MAC_key:%s\n",
1536 tls->client_write_MAC_key, tls->MAC_size
1537 );
1538 dump_hex("client_write_key:%s\n",
1539 tls->client_write_key, tls->key_size
1540 );
1541 }
1542}
1543
1544static const uint8_t rec_CHANGE_CIPHER_SPEC[] = {
1545 RECORD_TYPE_CHANGE_CIPHER_SPEC, TLS_MAJ, TLS_MIN, 00, 01,
1546 01
1547};
1548
1549static void send_change_cipher_spec(tls_state_t *tls)
1550{
1551 dbg(">> CHANGE_CIPHER_SPEC\n");
1552 xwrite(tls->ofd, rec_CHANGE_CIPHER_SPEC, sizeof(rec_CHANGE_CIPHER_SPEC));
1553}
1554
1555// 7.4.9. Finished
1556// A Finished message is always sent immediately after a change
1557// cipher spec message to verify that the key exchange and
1558// authentication processes were successful. It is essential that a
1559// change cipher spec message be received between the other handshake
1560// messages and the Finished message.
1561//...
1562// The Finished message is the first one protected with the just
1563// negotiated algorithms, keys, and secrets. Recipients of Finished
1564// messages MUST verify that the contents are correct. Once a side
1565// has sent its Finished message and received and validated the
1566// Finished message from its peer, it may begin to send and receive
1567// application data over the connection.
1568//...
1569// struct {
1570// opaque verify_data[verify_data_length];
1571// } Finished;
1572//
1573// verify_data
1574// PRF(master_secret, finished_label, Hash(handshake_messages))
1575// [0..verify_data_length-1];
1576//
1577// finished_label
1578// For Finished messages sent by the client, the string
1579// "client finished". For Finished messages sent by the server,
1580// the string "server finished".
1581//
1582// Hash denotes a Hash of the handshake messages. For the PRF
1583// defined in Section 5, the Hash MUST be the Hash used as the basis
1584// for the PRF. Any cipher suite which defines a different PRF MUST
1585// also define the Hash to use in the Finished computation.
1586//
1587// In previous versions of TLS, the verify_data was always 12 octets
1588// long. In the current version of TLS, it depends on the cipher
1589// suite. Any cipher suite which does not explicitly specify
1590// verify_data_length has a verify_data_length equal to 12. This
1591// includes all existing cipher suites.
1592static void send_client_finished(tls_state_t *tls)
1593{
1594 struct finished {
1595 uint8_t type;
1596 uint8_t len24_hi, len24_mid, len24_lo;
1597 uint8_t prf_result[12];
1598 };
1599 struct finished *record = tls_get_outbuf(tls, sizeof(*record));
1600 uint8_t handshake_hash[TLS_MAX_MAC_SIZE];
1601 unsigned len;
1602
1603 fill_handshake_record_hdr(record, HANDSHAKE_FINISHED, sizeof(*record));
1604
1605 len = get_handshake_hash(tls, handshake_hash);
1606 prf_hmac_sha256(/*tls,*/
1607 record->prf_result, sizeof(record->prf_result),
1608 tls->hsd->master_secret, sizeof(tls->hsd->master_secret),
1609 "client finished",
1610 handshake_hash, len
1611 );
1612 dump_hex("from secret: %s\n", tls->hsd->master_secret, sizeof(tls->hsd->master_secret));
1613 dump_hex("from labelSeed: %s", "client finished", sizeof("client finished")-1);
1614 dump_hex("%s\n", handshake_hash, sizeof(handshake_hash));
1615 dump_hex("=> digest: %s\n", record->prf_result, sizeof(record->prf_result));
1616
1617 dbg(">> FINISHED\n");
1618 xwrite_encrypted(tls, sizeof(*record), RECORD_TYPE_HANDSHAKE);
1619}
1620
1621void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
1622{
1623 // Client RFC 5246 Server
1624 // (*) - optional messages, not always sent
1625 //
1626 // ClientHello ------->
1627 // ServerHello
1628 // Certificate*
1629 // ServerKeyExchange*
1630 // CertificateRequest*
1631 // <------- ServerHelloDone
1632 // Certificate*
1633 // ClientKeyExchange
1634 // CertificateVerify*
1635 // [ChangeCipherSpec]
1636 // Finished ------->
1637 // [ChangeCipherSpec]
1638 // <------- Finished
1639 // Application Data <------> Application Data
1640 int len;
1641
1642 send_client_hello_and_alloc_hsd(tls, sni);
1643 get_server_hello(tls);
1644
1645 // RFC 5246
1646 // The server MUST send a Certificate message whenever the agreed-
1647 // upon key exchange method uses certificates for authentication
1648 // (this includes all key exchange methods defined in this document
1649 // except DH_anon). This message will always immediately follow the
1650 // ServerHello message.
1651 //
1652 // IOW: in practice, Certificate *always* follows.
1653 // (for example, kernel.org does not even accept DH_anon cipher id)
1654 get_server_cert(tls);
1655
1656 len = tls_xread_handshake_block(tls, 4);
1657 if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_SERVER_KEY_EXCHANGE) {
1658 // 459 bytes:
1659 // 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...
1660 //SvKey len=455^
1661 // with TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: 461 bytes:
1662 // 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...
1663 dbg("<< SERVER_KEY_EXCHANGE len:%u\n", len);
1664//probably need to save it
1665 len = tls_xread_handshake_block(tls, 4);
1666 }
1667
1668 if (tls->inbuf[RECHDR_LEN] == HANDSHAKE_CERTIFICATE_REQUEST) {
1669 dbg("<< CERTIFICATE_REQUEST\n");
1670 // RFC 5246: "If no suitable certificate is available,
1671 // the client MUST send a certificate message containing no
1672 // certificates. That is, the certificate_list structure has a
1673 // length of zero. ...
1674 // Client certificates are sent using the Certificate structure
1675 // defined in Section 7.4.2."
1676 // (i.e. the same format as server certs)
1677 send_empty_client_cert(tls);
1678 len = tls_xread_handshake_block(tls, 4);
1679 }
1680
1681 if (tls->inbuf[RECHDR_LEN] != HANDSHAKE_SERVER_HELLO_DONE) {
1682 bad_record_die(tls, "'server hello done'", len);
1683 }
1684 // 0e 000000 (len:0)
1685 dbg("<< SERVER_HELLO_DONE\n");
1686
1687 send_client_key_exchange(tls);
1688
1689 send_change_cipher_spec(tls);
1690 /* from now on we should send encrypted */
1691 /* tls->write_seq64_be = 0; - already is */
1692 tls->encrypt_on_write = 1;
1693
1694 send_client_finished(tls);
1695
1696 /* Get CHANGE_CIPHER_SPEC */
1697 len = tls_xread_record(tls);
1698 if (len != 1 || memcmp(tls->inbuf, rec_CHANGE_CIPHER_SPEC, 6) != 0)
1699 bad_record_die(tls, "switch to encrypted traffic", len);
1700 dbg("<< CHANGE_CIPHER_SPEC\n");
1701 if (tls->cipher_id == TLS_RSA_WITH_NULL_SHA256)
1702 tls->min_encrypted_len_on_read = tls->MAC_size;
1703 else {
1704 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCKSIZE-1) / AES_BLOCKSIZE;
1705 /* all incoming packets now should be encrypted and have
1706 * at least IV + (MAC padded to blocksize):
1707 */
1708 tls->min_encrypted_len_on_read = AES_BLOCKSIZE + (mac_blocks * AES_BLOCKSIZE);
1709 dbg("min_encrypted_len_on_read: %u", tls->min_encrypted_len_on_read);
1710 }
1711
1712 /* Get (encrypted) FINISHED from the server */
1713 len = tls_xread_record(tls);
1714 if (len < 4 || tls->inbuf[RECHDR_LEN] != HANDSHAKE_FINISHED)
1715 tls_error_die(tls);
1716 dbg("<< FINISHED\n");
1717 /* application data can be sent/received */
1718
1719 /* free handshake data */
1720// if (PARANOIA)
1721// memset(tls->hsd, 0, tls->hsd->hsd_size);
1722 free(tls->hsd);
1723 tls->hsd = NULL;
1724}
1725
1726static void tls_xwrite(tls_state_t *tls, int len)
1727{
1728 dbg(">> DATA\n");
1729 xwrite_encrypted(tls, len, RECORD_TYPE_APPLICATION_DATA);
1730}
1731
1732// To run a test server using openssl:
1733// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1734// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1
1735//
1736// Unencryped SHA256 example:
1737// openssl req -x509 -newkey rsa:$((4096/4*3)) -keyout key.pem -out server.pem -nodes -days 99999 -subj '/CN=localhost'
1738// openssl s_server -key key.pem -cert server.pem -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL
1739// openssl s_client -connect 127.0.0.1:4433 -debug -tls1_2 -no_tls1 -no_tls1_1 -cipher NULL-SHA256
1740
1741void FAST_FUNC tls_run_copy_loop(tls_state_t *tls)
1742{
1743 fd_set readfds;
1744 int inbuf_size;
1745 const int INBUF_STEP = 4 * 1024;
1746
1747//TODO: convert to poll
1748 /* Select loop copying stdin to ofd, and ifd to stdout */
1749 FD_ZERO(&readfds);
1750 FD_SET(tls->ifd, &readfds);
1751 FD_SET(STDIN_FILENO, &readfds);
1752
1753 inbuf_size = INBUF_STEP;
1754 for (;;) {
1755 fd_set testfds;
1756 int nread;
1757
1758 testfds = readfds;
1759 if (select(tls->ifd + 1, &testfds, NULL, NULL, NULL) < 0)
1760 bb_perror_msg_and_die("select");
1761
1762 if (FD_ISSET(STDIN_FILENO, &testfds)) {
1763 void *buf;
1764
1765 dbg("STDIN HAS DATA\n");
1766 buf = tls_get_outbuf(tls, inbuf_size);
1767 nread = safe_read(STDIN_FILENO, buf, inbuf_size);
1768 if (nread < 1) {
1769 /* We'd want to do this: */
1770 /* Close outgoing half-connection so they get EOF,
1771 * but leave incoming alone so we can see response
1772 */
1773 //shutdown(tls->ofd, SHUT_WR);
1774 /* But TLS has no way to encode this,
1775 * doubt it's ok to do it "raw"
1776 */
1777 FD_CLR(STDIN_FILENO, &readfds);
1778 tls_free_outbuf(tls); /* mem usage optimization */
1779 } else {
1780 if (nread == inbuf_size) {
1781 /* TLS has per record overhead, if input comes fast,
1782 * read, encrypt and send bigger chunks
1783 */
1784 inbuf_size += INBUF_STEP;
1785 if (inbuf_size > TLS_MAX_OUTBUF)
1786 inbuf_size = TLS_MAX_OUTBUF;
1787 }
1788 tls_xwrite(tls, nread);
1789 }
1790 }
1791 if (FD_ISSET(tls->ifd, &testfds)) {
1792 dbg("NETWORK HAS DATA\n");
1793 read_record:
1794 nread = tls_xread_record(tls);
1795 if (nread < 1) {
1796 /* TLS protocol has no real concept of one-sided shutdowns:
1797 * if we get "TLS EOF" from the peer, writes will fail too
1798 */
1799 //FD_CLR(tls->ifd, &readfds);
1800 //close(STDOUT_FILENO);
1801 //tls_free_inbuf(tls); /* mem usage optimization */
1802 //continue;
1803 break;
1804 }
1805 if (tls->inbuf[0] != RECORD_TYPE_APPLICATION_DATA)
1806 bb_error_msg_and_die("unexpected record type %d", tls->inbuf[0]);
1807 xwrite(STDOUT_FILENO, tls->inbuf + RECHDR_LEN, nread);
1808 /* We may already have a complete next record buffered,
1809 * can process it without network reads (and possible blocking)
1810 */
1811 if (tls_has_buffered_record(tls))
1812 goto read_record;
1813 }
1814 }
1815}
diff --git a/networking/tls.h b/networking/tls.h
new file mode 100644
index 000000000..d487f3810
--- /dev/null
+++ b/networking/tls.h
@@ -0,0 +1,99 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6/* Interface glue between bbox code and minimally tweaked matrixssl
7 * code. All C files (matrixssl and bbox (ones which need TLS))
8 * include this file, and guaranteed to see a consistent API,
9 * defines, types, etc.
10 */
11#include "libbb.h"
12
13
14/* Config tweaks */
15#define HAVE_NATIVE_INT64
16#undef USE_1024_KEY_SPEED_OPTIMIZATIONS
17#undef USE_2048_KEY_SPEED_OPTIMIZATIONS
18#define USE_AES
19#undef USE_AES_CBC_EXTERNAL
20#undef USE_AES_CCM
21#undef USE_AES_GCM
22#undef USE_3DES
23#undef USE_ARC4
24#undef USE_IDEA
25#undef USE_RC2
26#undef USE_SEED
27/* pstm: multiprecision numbers */
28#undef DISABLE_PSTM
29#if defined(__GNUC__) && defined(__i386__)
30 /* PSTM_X86 works correctly. +25 bytes. */
31# define PSTM_32BIT
32# define PSTM_X86
33#endif
34//#if defined(__GNUC__) && defined(__x86_64__)
35// /* PSTM_X86_64 works correctly, but +782 bytes. */
36// /* Looks like most of the growth is because of PSTM_64BIT. */
37//# define PSTM_64BIT
38//# define PSTM_X86_64
39//#endif
40//#if SOME_COND #define PSTM_MIPS, #define PSTM_32BIT
41//#if SOME_COND #define PSTM_ARM, #define PSTM_32BIT
42
43
44#define PS_SUCCESS 0
45#define PS_FAILURE -1
46#define PS_ARG_FAIL -6 /* Failure due to bad function param */
47#define PS_PLATFORM_FAIL -7 /* Failure as a result of system call error */
48#define PS_MEM_FAIL -8 /* Failure to allocate requested memory */
49#define PS_LIMIT_FAIL -9 /* Failure on sanity/limit tests */
50
51#define PS_TRUE 1
52#define PS_FALSE 0
53
54#if BB_BIG_ENDIAN
55# define ENDIAN_BIG 1
56# undef ENDIAN_LITTLE
57//#???? ENDIAN_32BITWORD
58// controls only STORE32L, which we don't use
59#else
60# define ENDIAN_LITTLE 1
61# undef ENDIAN_BIG
62#endif
63
64typedef uint64_t uint64;
65typedef int64_t int64;
66typedef uint32_t uint32;
67typedef int32_t int32;
68typedef uint16_t uint16;
69typedef int16_t int16;
70
71//typedef char psPool_t;
72
73//#ifdef PS_PUBKEY_OPTIMIZE_FOR_SMALLER_RAM
74#define PS_EXPTMOD_WINSIZE 3
75//#ifdef PS_PUBKEY_OPTIMIZE_FOR_FASTER_SPEED
76//#define PS_EXPTMOD_WINSIZE 5
77
78#define PUBKEY_TYPE 0x01
79#define PRIVKEY_TYPE 0x02
80
81void tls_get_random(void *buf, unsigned len);
82
83#define matrixCryptoGetPrngData(buf, len, userPtr) (tls_get_random(buf, len), PS_SUCCESS)
84
85#define psFree(p, pool) free(p)
86#define psTraceCrypto(...) bb_error_msg_and_die(__VA_ARGS__)
87
88/* Secure zerofill */
89#define memset_s(A,B,C,D) memset((A),(C),(D))
90/* Constant time memory comparison */
91#define memcmpct(s1, s2, len) memcmp((s1), (s2), (len))
92#undef min
93#define min(x, y) ((x) < (y) ? (x) : (y))
94
95
96#include "tls_pstm.h"
97#include "tls_rsa.h"
98#include "tls_symmetric.h"
99#include "tls_aes.h"
diff --git a/networking/tls_aes.c b/networking/tls_aes.c
new file mode 100644
index 000000000..ebaab15b1
--- /dev/null
+++ b/networking/tls_aes.c
@@ -0,0 +1,1776 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8static
9int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey);
10static
11void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
12 psAesKey_t *skey);
13static
14void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
15 psAesKey_t *skey);
16static
17int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV,
18 const unsigned char *key, uint32 keylen);
19static
20int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt,
21 unsigned char *ct, uint32 len);
22static
23int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct,
24 unsigned char *pt, uint32 len);
25
26void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
27{
28 psCipherContext_t ctx;
29 psAesInit(&ctx, iv, key, klen);
30 psAesEncrypt(&ctx,
31 data, /* plaintext */
32 dst, /* ciphertext */
33 len
34 );
35}
36
37void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst)
38{
39 psCipherContext_t ctx;
40 psAesInit(&ctx, iv, key, klen);
41 psAesDecrypt(&ctx,
42 data, /* ciphertext */
43 dst, /* plaintext */
44 len
45 );
46}
47
48/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/.
49 * Changes are flagged with //bbox
50 */
51
52/**
53 * @file aes.c
54 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
55 *
56 * AES CBC block cipher implementation.
57 */
58/*
59 * Copyright (c) 2013-2015 INSIDE Secure Corporation
60 * Copyright (c) PeerSec Networks, 2002-2011
61 * All Rights Reserved
62 *
63 * The latest version of this code is available at http://www.matrixssl.org
64 *
65 * This software is open source; you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
67 * the Free Software Foundation; either version 2 of the License, or
68 * (at your option) any later version.
69 *
70 * This General Public License does NOT permit incorporating this software
71 * into proprietary programs. If you are unable to comply with the GPL, a
72 * commercial license for this software may be purchased from INSIDE at
73 * http://www.insidesecure.com/eng/Company/Locations
74 *
75 * This program is distributed in WITHOUT ANY WARRANTY; without even the
76 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 * See the GNU General Public License for more details.
78 *
79 * You should have received a copy of the GNU General Public License
80 * along with this program; if not, write to the Free Software
81 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
82 * http://www.gnu.org/copyleft/gpl.html
83 */
84/******************************************************************************/
85
86//bbox
87//#include "../cryptoApi.h"
88
89#ifdef USE_AES
90#ifndef USE_AES_CBC_EXTERNAL
91/******************************************************************************/
92
93/* The precomputed tables for AES */
94/*
95Te0[x] = S [x].[02, 01, 01, 03];
96Te1[x] = S [x].[03, 02, 01, 01];
97Te2[x] = S [x].[01, 03, 02, 01];
98Te3[x] = S [x].[01, 01, 03, 02];
99Te4[x] = S [x].[01, 01, 01, 01];
100
101Td0[x] = Si[x].[0e, 09, 0d, 0b];
102Td1[x] = Si[x].[0b, 0e, 09, 0d];
103Td2[x] = Si[x].[0d, 0b, 0e, 09];
104Td3[x] = Si[x].[09, 0d, 0b, 0e];
105Td4[x] = Si[x].[01, 01, 01, 01];
106*/
107
108static const uint32 TE0[] = {
109 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
110 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
111 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
112 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
113 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
114 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
115 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
116 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
117 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
118 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
119 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
120 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
121 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
122 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
123 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
124 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
125 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
126 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
127 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
128 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
129 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
130 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
131 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
132 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
133 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
134 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
135 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
136 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
137 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
138 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
139 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
140 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
141 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
142 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
143 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
144 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
145 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
146 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
147 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
148 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
149 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
150 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
151 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
152 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
153 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
154 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
155 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
156 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
157 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
158 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
159 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
160 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
161 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
162 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
163 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
164 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
165 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
166 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
167 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
168 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
169 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
170 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
171 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
172 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
173};
174
175static const uint32 Te4[] = {
176 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
177 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
178 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
179 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
180 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
181 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
182 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
183 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
184 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
185 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
186 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
187 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
188 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
189 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
190 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
191 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
192 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
193 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
194 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
195 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
196 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
197 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
198 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
199 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
200 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
201 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
202 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
203 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
204 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
205 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
206 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
207 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
208 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
209 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
210 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
211 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
212 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
213 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
214 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
215 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
216 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
217 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
218 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
219 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
220 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
221 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
222 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
223 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
224 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
225 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
226 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
227 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
228 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
229 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
230 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
231 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
232 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
233 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
234 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
235 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
236 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
237 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
238 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
239 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
240};
241
242static const uint32 TD0[] = {
243 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
244 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
245 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
246 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
247 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
248 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
249 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
250 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
251 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
252 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
253 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
254 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
255 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
256 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
257 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
258 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
259 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
260 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
261 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
262 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
263 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
264 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
265 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
266 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
267 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
268 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
269 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
270 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
271 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
272 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
273 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
274 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
275 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
276 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
277 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
278 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
279 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
280 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
281 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
282 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
283 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
284 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
285 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
286 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
287 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
288 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
289 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
290 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
291 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
292 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
293 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
294 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
295 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
296 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
297 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
298 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
299 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
300 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
301 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
302 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
303 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
304 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
305 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
306 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
307};
308
309static const uint32 Td4[] = {
310 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
311 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
312 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
313 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
314 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
315 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
316 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
317 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
318 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
319 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
320 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
321 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
322 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
323 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
324 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
325 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
326 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
327 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
328 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
329 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
330 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
331 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
332 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
333 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
334 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
335 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
336 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
337 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
338 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
339 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
340 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
341 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
342 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
343 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
344 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
345 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
346 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
347 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
348 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
349 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
350 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
351 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
352 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
353 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
354 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
355 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
356 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
357 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
358 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
359 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
360 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
361 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
362 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
363 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
364 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
365 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
366 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
367 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
368 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
369 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
370 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
371 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
372 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
373 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
374 0xe1f27f3aUL, 0xf5710fb0UL, 0xada0e5c4UL, 0x98e4c919UL
375};
376
377#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
378
379#define Te0(x) TE0[x]
380#define Te1(x) ROR(TE0[x], 8)
381#define Te2(x) ROR(TE0[x], 16)
382#define Te3(x) ROR(TE0[x], 24)
383
384#define Td0(x) TD0[x]
385#define Td1(x) ROR(TD0[x], 8)
386#define Td2(x) ROR(TD0[x], 16)
387#define Td3(x) ROR(TD0[x], 24)
388
389#define Te4_0 0x000000FF & Te4
390#define Te4_1 0x0000FF00 & Te4
391#define Te4_2 0x00FF0000 & Te4
392#define Te4_3 0xFF000000 & Te4
393
394#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
395
396#define Te0(x) TE0[x]
397#define Te1(x) TE1[x]
398#define Te2(x) TE2[x]
399#define Te3(x) TE3[x]
400
401#define Td0(x) TD0[x]
402#define Td1(x) TD1[x]
403#define Td2(x) TD2[x]
404#define Td3(x) TD3[x]
405
406static const uint32 TE1[256] = {
407 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
408 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
409 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
410 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
411 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
412 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
413 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
414 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
415 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
416 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
417 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
418 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
419 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
420 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
421 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
422 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
423 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
424 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
425 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
426 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
427 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
428 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
429 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
430 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
431 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
432 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
433 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
434 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
435 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
436 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
437 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
438 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
439 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
440 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
441 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
442 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
443 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
444 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
445 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
446 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
447 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
448 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
449 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
450 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
451 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
452 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
453 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
454 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
455 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
456 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
457 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
458 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
459 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
460 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
461 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
462 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
463 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
464 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
465 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
466 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
467 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
468 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
469 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
470 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,
471};
472static const uint32 TE2[256] = {
473 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
474 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
475 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
476 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
477 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
478 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
479 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
480 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
481 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
482 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
483 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
484 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
485 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
486 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
487 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
488 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
489 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
490 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
491 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
492 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
493 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
494 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
495 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
496 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
497 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
498 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
499 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
500 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
501 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
502 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
503 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
504 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
505 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
506 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
507 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
508 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
509 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
510 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
511 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
512 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
513 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
514 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
515 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
516 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
517 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
518 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
519 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
520 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
521 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
522 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
523 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
524 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
525 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
526 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
527 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
528 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
529 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
530 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
531 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
532 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
533 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
534 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
535 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
536 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,
537};
538static const uint32 TE3[256] = {
539
540 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
541 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
542 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
543 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
544 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
545 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
546 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
547 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
548 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
549 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
550 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
551 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
552 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
553 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
554 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
555 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
556 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
557 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
558 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
559 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
560 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
561 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
562 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
563 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
564 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
565 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
566 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
567 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
568 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
569 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
570 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
571 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
572 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
573 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
574 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
575 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
576 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
577 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
578 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
579 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
580 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
581 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
582 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
583 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
584 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
585 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
586 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
587 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
588 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
589 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
590 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
591 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
592 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
593 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
594 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
595 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
596 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
597 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
598 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
599 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
600 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
601 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
602 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
603 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,
604};
605
606static const uint32 Te4_0[] = {
6070x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL,
6080x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL,
6090x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL,
6100x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL,
6110x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL,
6120x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL,
6130x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL,
6140x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL,
6150x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL,
6160x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL,
6170x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL,
6180x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL,
6190x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL,
6200x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL,
6210x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL,
6220x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL,
6230x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL,
6240x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL,
6250x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL,
6260x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL,
6270x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL,
6280x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL,
6290x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL,
6300x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL,
6310x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL,
6320x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL,
6330x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL,
6340x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL,
6350x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL,
6360x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL,
6370x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL,
6380x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL
639};
640
641static const uint32 Te4_1[] = {
6420x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL,
6430x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL,
6440x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL,
6450x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL,
6460x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL,
6470x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL,
6480x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL,
6490x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL,
6500x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL,
6510x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL,
6520x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL,
6530x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL,
6540x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL,
6550x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL,
6560x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL,
6570x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL,
6580x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL,
6590x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL,
6600x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL,
6610x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL,
6620x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL,
6630x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL,
6640x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL,
6650x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL,
6660x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL,
6670x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL,
6680x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL,
6690x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL,
6700x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL,
6710x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL,
6720x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL,
6730x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL
674};
675
676static const uint32 Te4_2[] = {
6770x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL,
6780x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL,
6790x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL,
6800x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL,
6810x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL,
6820x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL,
6830x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL,
6840x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL,
6850x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL,
6860x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL,
6870x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL,
6880x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL,
6890x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL,
6900x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL,
6910x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL,
6920x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL,
6930x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL,
6940x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL,
6950x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL,
6960x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL,
6970x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL,
6980x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL,
6990x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL,
7000x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL,
7010x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL,
7020x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL,
7030x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL,
7040x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL,
7050x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL,
7060x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL,
7070x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL,
7080x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL
709};
710
711static const uint32 Te4_3[] = {
7120x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL,
7130x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL,
7140xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL,
7150xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL,
7160xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL,
7170x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL,
7180x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL,
7190x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL,
7200x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL,
7210x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL,
7220x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL,
7230x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL,
7240xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL,
7250x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL,
7260x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL,
7270xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL,
7280xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL,
7290xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL,
7300x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL,
7310x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL,
7320xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL,
7330xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL,
7340xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL,
7350x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL,
7360xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL,
7370xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL,
7380x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL,
7390x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL,
7400xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL,
7410x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL,
7420x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL,
7430x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
744};
745
746static const uint32 TD1[256] = {
747 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
748 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
749 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
750 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
751 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
752 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
753 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
754 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
755 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
756 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
757 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
758 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
759 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
760 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
761 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
762 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
763 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
764 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
765 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
766 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
767 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
768 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
769 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
770 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
771 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
772 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
773 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
774 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
775 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
776 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
777 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
778 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
779 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
780 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
781 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
782 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
783 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
784 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
785 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
786 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
787 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
788 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
789 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
790 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
791 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
792 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
793 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
794 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
795 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
796 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
797 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
798 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
799 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
800 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
801 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
802 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
803 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
804 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
805 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
806 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
807 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
808 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
809 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
810 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,
811};
812static const uint32 TD2[256] = {
813 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
814 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
815 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
816 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
817 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
818 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
819 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
820 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
821 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
822 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
823 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
824 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
825 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
826 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
827 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
828 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
829 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
830 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
831 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
832 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
833 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
834 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
835 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
836 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
837 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
838 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
839 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
840 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
841 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
842 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
843 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
844 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
845 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
846 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
847 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
848 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
849 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
850 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
851 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
852 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
853 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
854 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
855 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
856 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
857 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
858 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
859 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
860 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
861 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
862 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
863 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
864 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
865 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
866 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
867 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
868 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
869 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
870 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
871 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
872 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
873 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
874 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
875 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
876 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,
877};
878static const uint32 TD3[256] = {
879 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
880 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
881 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
882 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
883 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
884 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
885 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
886 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
887 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
888 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
889 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
890 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
891 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
892 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
893 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
894 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
895 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
896 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
897 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
898 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
899 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
900 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
901 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
902 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
903 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
904 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
905 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
906 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
907 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
908 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
909 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
910 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
911 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
912 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
913 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
914 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
915 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
916 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
917 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
918 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
919 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
920 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
921 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
922 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
923 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
924 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
925 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
926 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
927 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
928 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
929 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
930 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
931 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
932 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
933 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
934 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
935 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
936 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
937 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
938 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
939 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
940 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
941 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
942 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,
943};
944
945static const uint32 Tks0[] = {
9460x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL,
9470x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL,
9480xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL,
9490x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL,
9500xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL,
9510xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL,
9520x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL,
9530x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL,
9540xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL,
9550xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL,
9560x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL,
9570x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL,
9580x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL,
9590x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL,
9600x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL,
9610xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL,
9620x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL,
9630x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL,
9640xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL,
9650xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL,
9660x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL,
9670xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL,
9680x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL,
9690x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL,
9700xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL,
9710x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL,
9720x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL,
9730x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL,
9740x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL,
9750x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL,
9760xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL,
9770xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
978};
979
980static const uint32 Tks1[] = {
9810x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL,
9820x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL,
9830xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL,
9840xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL,
9850x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL,
9860x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL,
9870xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL,
9880x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL,
9890xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL,
9900xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL,
9910x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL,
9920x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL,
9930x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL,
9940xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL,
9950x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL,
9960x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL,
9970xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL,
9980xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL,
9990x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL,
10000x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL,
10010x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL,
10020xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL,
10030x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL,
10040x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL,
10050x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL,
10060x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL,
10070xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL,
10080xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL,
10090x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL,
10100x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL,
10110xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL,
10120x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
1013};
1014
1015static const uint32 Tks2[] = {
10160x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL,
10170x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL,
10180xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL,
10190xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL,
10200xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL,
10210xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL,
10220x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL,
10230x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL,
10240x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL,
10250x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL,
10260xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL,
10270xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL,
10280xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL,
10290xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL,
10300x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL,
10310x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL,
10320xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL,
10330xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL,
10340x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL,
10350x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL,
10360x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL,
10370x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL,
10380xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL,
10390xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL,
10400xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL,
10410xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL,
10420x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL,
10430x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL,
10440x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL,
10450x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL,
10460xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL,
10470xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
1048};
1049
1050static const uint32 Tks3[] = {
10510x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL,
10520x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL,
10530x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL,
10540xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL,
10550x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL,
10560x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL,
10570xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL,
10580xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL,
10590x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL,
10600x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL,
10610xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL,
10620xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL,
10630x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL,
10640x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL,
10650xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL,
10660x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL,
10670xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL,
10680xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL,
10690x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL,
10700x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL,
10710xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL,
10720x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL,
10730x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL,
10740x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL,
10750x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL,
10760xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL,
10770x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL,
10780x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL,
10790xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL,
10800xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL,
10810x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL,
10820x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
1083};
1084
1085#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1086
1087static const uint32 rcon[] = {
1088 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
1089 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
1090 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, AES never uses more than 10 rcon values */
1091};
1092
1093#ifdef USE_BURN_STACK
1094static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
1095 psAesKey_t *skey);
1096static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
1097 psAesKey_t *skey);
1098#endif
1099
1100static uint32 setup_mix(uint32 temp)
1101{
1102 return (Te4_3[byte(temp, 2)]) ^
1103 (Te4_2[byte(temp, 1)]) ^
1104 (Te4_1[byte(temp, 0)]) ^
1105 (Te4_0[byte(temp, 3)]);
1106}
1107
1108#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1109static uint32 setup_mix2(uint32 temp)
1110{
1111 return Td0(255 & Te4[byte(temp, 3)]) ^
1112 Td1(255 & Te4[byte(temp, 2)]) ^
1113 Td2(255 & Te4[byte(temp, 1)]) ^
1114 Td3(255 & Te4[byte(temp, 0)]);
1115}
1116#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1117
1118/*
1119 Software implementation of AES CBC APIs
1120 */
1121#ifndef USE_AES_CBC_EXTERNAL
1122static //bbox
1123int32 psAesInit(psCipherContext_t *ctx, unsigned char *IV,
1124 const unsigned char *key, uint32 keylen)
1125{
1126 int32 x, err;
1127
1128//bbox
1129// if (IV == NULL || key == NULL || ctx == NULL) {
1130// psTraceCrypto("psAesInit arg fail\n");
1131// return PS_ARG_FAIL;
1132// }
1133 memset(ctx, 0x0, sizeof(psCipherContext_t));
1134/*
1135 setup cipher
1136 */
1137 if ((err = psAesInitKey(key, keylen, &ctx->aes.key)) != PS_SUCCESS) {
1138 return err;
1139 }
1140/*
1141 copy IV
1142 */
1143 ctx->aes.blocklen = 16;
1144 for (x = 0; x < ctx->aes.blocklen; x++) {
1145 ctx->aes.IV[x] = IV[x];
1146 }
1147 return PS_SUCCESS;
1148}
1149
1150static //bbox
1151int32 psAesEncrypt(psCipherContext_t *ctx, const unsigned char *pt,
1152 unsigned char *ct, uint32 len)
1153{
1154 int32 x;
1155 uint32 i;
1156 unsigned char tmp[MAXBLOCKSIZE];
1157
1158//bbox
1159// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
1160// psTraceCrypto("Bad parameters to psAesEncrypt\n");
1161// return PS_ARG_FAIL;
1162// }
1163 if ((len & 0x7) != 0)
1164 bb_error_msg_and_die("AES len:%d", len);
1165
1166/*
1167 is blocklen valid?
1168 */
1169 if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen >
1170 (int32)sizeof(ctx->aes.IV))) {
1171 psTraceCrypto("Bad blocklen in psAesEncrypt\n");
1172 return PS_LIMIT_FAIL;
1173 }
1174
1175 for (i = 0; i < len; i += ctx->aes.blocklen) {
1176/*
1177 xor IV against plaintext
1178 */
1179 for (x = 0; x < ctx->aes.blocklen; x++) {
1180 tmp[x] = pt[x] ^ ctx->aes.IV[x];
1181 }
1182/*
1183 encrypt
1184 */
1185 psAesEncryptBlock(tmp, ct, &ctx->aes.key);
1186
1187/*
1188 store IV [ciphertext] for a future block
1189 */
1190 for (x = 0; x < ctx->aes.blocklen; x++) {
1191 ctx->aes.IV[x] = ct[x];
1192 }
1193 ct += ctx->aes.blocklen;
1194 pt += ctx->aes.blocklen;
1195 }
1196
1197 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp));
1198 return len;
1199}
1200
1201static //bbox
1202int32 psAesDecrypt(psCipherContext_t *ctx, const unsigned char *ct,
1203 unsigned char *pt, uint32 len)
1204{
1205 int32 x;
1206 uint32 i;
1207 unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
1208
1209//bbox
1210// if (pt == NULL || ct == NULL || ctx == NULL || (len & 0x7) != 0) {
1211// psTraceCrypto("Bad parameters to psAesDecrypt\n");
1212// return PS_ARG_FAIL;
1213// }
1214 if ((len & 0x7) != 0)
1215 bb_error_msg_and_die("AES len:%d", len);
1216
1217/*
1218 is blocklen valid?
1219 */
1220 if (ctx->aes.blocklen < 0 || (ctx->aes.blocklen >
1221 (int32)sizeof(ctx->aes.IV))) {
1222 psTraceCrypto("Bad blocklen in psAesDecrypt\n");
1223 return PS_LIMIT_FAIL;
1224 }
1225 for (i = 0; i < len; i += ctx->aes.blocklen) {
1226/*
1227 decrypt the block from ct into tmp
1228 */
1229 psAesDecryptBlock(ct, tmp, &ctx->aes.key);
1230/*
1231 xor IV against the plaintext of the previous step
1232 */
1233 for (x = 0; x < ctx->aes.blocklen; x++) {
1234/*
1235 copy CT in case ct == pt
1236 */
1237 tmp2[x] = ct[x];
1238/*
1239 actually decrypt the byte
1240 */
1241 pt[x] = tmp[x] ^ ctx->aes.IV[x];
1242 }
1243/*
1244 replace IV with this current ciphertext
1245 */
1246 for (x = 0; x < ctx->aes.blocklen; x++) {
1247 ctx->aes.IV[x] = tmp2[x];
1248 }
1249 ct += ctx->aes.blocklen;
1250 pt += ctx->aes.blocklen;
1251 }
1252 memset_s(tmp, sizeof(tmp), 0x0, sizeof(tmp));
1253 memset_s(tmp2, sizeof(tmp2), 0x0, sizeof(tmp2));
1254
1255 return len;
1256}
1257
1258#endif /* USE_AES_CBC_EXTERNAL */
1259
1260/******************************************************************************/
1261/*
1262 Initialize the AES (Rijndael) block cipher
1263
1264 key: The symmetric key you wish to pass
1265 keylen: The key length in bytes
1266 skey: The key in as scheduled by this function.
1267*/
1268
1269static //bbox
1270int32 psAesInitKey(const unsigned char *key, uint32 keylen, psAesKey_t *skey)
1271{
1272 int32 i, j;
1273 uint32 temp, *rk, *rrk;
1274
1275//bbox
1276// if (key == NULL || skey == NULL) {
1277// psTraceCrypto("Bad args to psAesInitKey\n");
1278// return PS_ARG_FAIL;
1279// }
1280
1281 if (keylen != 16 && keylen != 24 && keylen != 32) {
1282 psTraceCrypto("Invalid AES key length\n");
1283 //bbox return CRYPT_INVALID_KEYSIZE;
1284 //unreachable anyway
1285 return PS_ARG_FAIL;
1286 }
1287
1288 memset(skey, 0x0, sizeof(psAesKey_t));
1289 skey->Nr = 10 + ((keylen/8)-2)*2;
1290
1291/*
1292 setup the forward key
1293 */
1294 i = 0;
1295 rk = skey->eK;
1296 LOAD32H(rk[0], key );
1297 LOAD32H(rk[1], key + 4);
1298 LOAD32H(rk[2], key + 8);
1299 LOAD32H(rk[3], key + 12);
1300 if (keylen == 16) {
1301 j = 44;
1302 for (;;) {
1303 temp = rk[3];
1304 rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
1305 rk[5] = rk[1] ^ rk[4];
1306 rk[6] = rk[2] ^ rk[5];
1307 rk[7] = rk[3] ^ rk[6];
1308 if (++i == 10) {
1309 break;
1310 }
1311 rk += 4;
1312 }
1313 } else if (keylen == 24) {
1314 j = 52;
1315 LOAD32H(rk[4], key + 16);
1316 LOAD32H(rk[5], key + 20);
1317 for (;;) {
1318 #ifdef _MSC_VER
1319 temp = skey->eK[rk - skey->eK + 5];
1320 #else
1321 temp = rk[5];
1322 #endif /* _MSC_VER */
1323 rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
1324 rk[ 7] = rk[ 1] ^ rk[ 6];
1325 rk[ 8] = rk[ 2] ^ rk[ 7];
1326 rk[ 9] = rk[ 3] ^ rk[ 8];
1327 if (++i == 8) {
1328 break;
1329 }
1330 rk[10] = rk[ 4] ^ rk[ 9];
1331 rk[11] = rk[ 5] ^ rk[10];
1332 rk += 6;
1333 }
1334 } else if (keylen == 32) {
1335 j = 60;
1336 LOAD32H(rk[4], key + 16);
1337 LOAD32H(rk[5], key + 20);
1338 LOAD32H(rk[6], key + 24);
1339 LOAD32H(rk[7], key + 28);
1340 for (;;) {
1341 #ifdef _MSC_VER
1342 temp = skey->eK[rk - skey->eK + 7];
1343 #else
1344 temp = rk[7];
1345 #endif /* _MSC_VER */
1346 rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
1347 rk[ 9] = rk[ 1] ^ rk[ 8];
1348 rk[10] = rk[ 2] ^ rk[ 9];
1349 rk[11] = rk[ 3] ^ rk[10];
1350 if (++i == 7) {
1351 break;
1352 }
1353 temp = rk[11];
1354 rk[12] = rk[ 4] ^ setup_mix(ROR(temp, 8));
1355 rk[13] = rk[ 5] ^ rk[12];
1356 rk[14] = rk[ 6] ^ rk[13];
1357 rk[15] = rk[ 7] ^ rk[14];
1358 rk += 8;
1359 }
1360 } else {
1361/*
1362 this can't happen
1363 */
1364 return PS_FAILURE;
1365 }
1366
1367/*
1368 setup the inverse key now
1369 */
1370 rk = skey->dK;
1371 rrk = skey->eK + j - 4;
1372
1373/*
1374 apply the inverse MixColumn transform to all round keys but
1375 the first and the last:
1376 */
1377 /* copy first */
1378 *rk++ = *rrk++;
1379 *rk++ = *rrk++;
1380 *rk++ = *rrk++;
1381 *rk = *rrk;
1382 rk -= 3; rrk -= 3;
1383
1384 for (i = 1; i < skey->Nr; i++) {
1385 rrk -= 4;
1386 rk += 4;
1387#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1388 temp = rrk[0];
1389 rk[0] = setup_mix2(temp);
1390 temp = rrk[1];
1391 rk[1] = setup_mix2(temp);
1392 temp = rrk[2];
1393 rk[2] = setup_mix2(temp);
1394 temp = rrk[3];
1395 rk[3] = setup_mix2(temp);
1396#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1397 temp = rrk[0];
1398 rk[0] =
1399 Tks0[byte(temp, 3)] ^
1400 Tks1[byte(temp, 2)] ^
1401 Tks2[byte(temp, 1)] ^
1402 Tks3[byte(temp, 0)];
1403 temp = rrk[1];
1404 rk[1] =
1405 Tks0[byte(temp, 3)] ^
1406 Tks1[byte(temp, 2)] ^
1407 Tks2[byte(temp, 1)] ^
1408 Tks3[byte(temp, 0)];
1409 temp = rrk[2];
1410 rk[2] =
1411 Tks0[byte(temp, 3)] ^
1412 Tks1[byte(temp, 2)] ^
1413 Tks2[byte(temp, 1)] ^
1414 Tks3[byte(temp, 0)];
1415 temp = rrk[3];
1416 rk[3] =
1417 Tks0[byte(temp, 3)] ^
1418 Tks1[byte(temp, 2)] ^
1419 Tks2[byte(temp, 1)] ^
1420 Tks3[byte(temp, 0)];
1421#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1422 }
1423
1424 /* copy last */
1425 rrk -= 4;
1426 rk += 4;
1427 *rk++ = *rrk++;
1428 *rk++ = *rrk++;
1429 *rk++ = *rrk++;
1430 *rk = *rrk;
1431
1432 return PS_SUCCESS;
1433}
1434
1435
1436#ifdef USE_BURN_STACK
1437static //bbox
1438void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
1439 psAesKey_t *skey)
1440{
1441 _aes_ecb_encrypt(pt, ct, skey);
1442 psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2);
1443}
1444static void _aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct,
1445 psAesKey_t *skey)
1446#else
1447static //bbox
1448void psAesEncryptBlock(const unsigned char *pt, unsigned char *ct,
1449 psAesKey_t *skey)
1450#endif /* USE_BURN_STACK */
1451{
1452 uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
1453 int32 Nr, r;
1454
1455//bbox
1456// if (pt == NULL || ct == NULL || skey == NULL) {
1457// return;
1458// }
1459
1460 Nr = skey->Nr;
1461 rk = skey->eK;
1462
1463/*
1464 map byte array block to cipher state
1465 and add initial round key:
1466 */
1467 LOAD32H(s0, pt ); s0 ^= rk[0];
1468 LOAD32H(s1, pt + 4); s1 ^= rk[1];
1469 LOAD32H(s2, pt + 8); s2 ^= rk[2];
1470 LOAD32H(s3, pt + 12); s3 ^= rk[3];
1471
1472#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1473 for (r = 0; ; r++) {
1474 rk += 4;
1475 t0 =
1476 Te0(byte(s0, 3)) ^
1477 Te1(byte(s1, 2)) ^
1478 Te2(byte(s2, 1)) ^
1479 Te3(byte(s3, 0)) ^
1480 rk[0];
1481 t1 =
1482 Te0(byte(s1, 3)) ^
1483 Te1(byte(s2, 2)) ^
1484 Te2(byte(s3, 1)) ^
1485 Te3(byte(s0, 0)) ^
1486 rk[1];
1487 t2 =
1488 Te0(byte(s2, 3)) ^
1489 Te1(byte(s3, 2)) ^
1490 Te2(byte(s0, 1)) ^
1491 Te3(byte(s1, 0)) ^
1492 rk[2];
1493 t3 =
1494 Te0(byte(s3, 3)) ^
1495 Te1(byte(s0, 2)) ^
1496 Te2(byte(s1, 1)) ^
1497 Te3(byte(s2, 0)) ^
1498 rk[3];
1499 if (r == Nr-2) {
1500 break;
1501 }
1502 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1503 }
1504 rk += 4;
1505#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1506
1507/*
1508 Nr - 1 full rounds:
1509 */
1510 r = Nr >> 1;
1511 for (;;) {
1512
1513 t0 =
1514 Te0(byte(s0, 3)) ^
1515 Te1(byte(s1, 2)) ^
1516 Te2(byte(s2, 1)) ^
1517 Te3(byte(s3, 0)) ^
1518 rk[4];
1519 t1 =
1520 Te0(byte(s1, 3)) ^
1521 Te1(byte(s2, 2)) ^
1522 Te2(byte(s3, 1)) ^
1523 Te3(byte(s0, 0)) ^
1524 rk[5];
1525 t2 =
1526 Te0(byte(s2, 3)) ^
1527 Te1(byte(s3, 2)) ^
1528 Te2(byte(s0, 1)) ^
1529 Te3(byte(s1, 0)) ^
1530 rk[6];
1531 t3 =
1532 Te0(byte(s3, 3)) ^
1533 Te1(byte(s0, 2)) ^
1534 Te2(byte(s1, 1)) ^
1535 Te3(byte(s2, 0)) ^
1536 rk[7];
1537
1538 rk += 8;
1539 if (--r == 0) {
1540 break;
1541 }
1542
1543 s0 =
1544 Te0(byte(t0, 3)) ^
1545 Te1(byte(t1, 2)) ^
1546 Te2(byte(t2, 1)) ^
1547 Te3(byte(t3, 0)) ^
1548 rk[0];
1549 s1 =
1550 Te0(byte(t1, 3)) ^
1551 Te1(byte(t2, 2)) ^
1552 Te2(byte(t3, 1)) ^
1553 Te3(byte(t0, 0)) ^
1554 rk[1];
1555 s2 =
1556 Te0(byte(t2, 3)) ^
1557 Te1(byte(t3, 2)) ^
1558 Te2(byte(t0, 1)) ^
1559 Te3(byte(t1, 0)) ^
1560 rk[2];
1561 s3 =
1562 Te0(byte(t3, 3)) ^
1563 Te1(byte(t0, 2)) ^
1564 Te2(byte(t1, 1)) ^
1565 Te3(byte(t2, 0)) ^
1566 rk[3];
1567 }
1568#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1569
1570/*
1571 apply last round and map cipher state to byte array block:
1572 */
1573 s0 =
1574 (Te4_3[byte(t0, 3)]) ^
1575 (Te4_2[byte(t1, 2)]) ^
1576 (Te4_1[byte(t2, 1)]) ^
1577 (Te4_0[byte(t3, 0)]) ^
1578 rk[0];
1579 STORE32H(s0, ct);
1580 s1 =
1581 (Te4_3[byte(t1, 3)]) ^
1582 (Te4_2[byte(t2, 2)]) ^
1583 (Te4_1[byte(t3, 1)]) ^
1584 (Te4_0[byte(t0, 0)]) ^
1585 rk[1];
1586 STORE32H(s1, ct+4);
1587 s2 =
1588 (Te4_3[byte(t2, 3)]) ^
1589 (Te4_2[byte(t3, 2)]) ^
1590 (Te4_1[byte(t0, 1)]) ^
1591 (Te4_0[byte(t1, 0)]) ^
1592 rk[2];
1593 STORE32H(s2, ct+8);
1594 s3 =
1595 (Te4_3[byte(t3, 3)]) ^
1596 (Te4_2[byte(t0, 2)]) ^
1597 (Te4_1[byte(t1, 1)]) ^
1598 (Te4_0[byte(t2, 0)]) ^
1599 rk[3];
1600 STORE32H(s3, ct+12);
1601}
1602
1603#ifdef USE_BURN_STACK
1604static //bbox
1605void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
1606 psAesKey_t *skey)
1607{
1608 _aes_ecb_decrypt(ct, pt, skey);
1609 psBurnStack(sizeof(uint32)*8 + sizeof(uint32*) + sizeof(int32)*2);
1610}
1611static void _aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt,
1612 psAesKey_t *skey)
1613#else
1614static //bbox
1615void psAesDecryptBlock(const unsigned char *ct, unsigned char *pt,
1616 psAesKey_t *skey)
1617#endif /* USE_BURN_STACK */
1618{
1619 uint32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
1620 int32 Nr, r;
1621
1622//bbox
1623// if (pt == NULL || ct == NULL || skey == NULL) {
1624// return;
1625// }
1626
1627 Nr = skey->Nr;
1628 rk = skey->dK;
1629
1630/*
1631 map byte array block to cipher state and add initial round key:
1632 */
1633 LOAD32H(s0, ct ); s0 ^= rk[0];
1634 LOAD32H(s1, ct + 4); s1 ^= rk[1];
1635 LOAD32H(s2, ct + 8); s2 ^= rk[2];
1636 LOAD32H(s3, ct + 12); s3 ^= rk[3];
1637
1638#ifndef PS_AES_IMPROVE_PERF_INCREASE_CODESIZE
1639 for (r = 0; ; r++) {
1640 rk += 4;
1641 t0 =
1642 Td0(byte(s0, 3)) ^
1643 Td1(byte(s3, 2)) ^
1644 Td2(byte(s2, 1)) ^
1645 Td3(byte(s1, 0)) ^
1646 rk[0];
1647 t1 =
1648 Td0(byte(s1, 3)) ^
1649 Td1(byte(s0, 2)) ^
1650 Td2(byte(s3, 1)) ^
1651 Td3(byte(s2, 0)) ^
1652 rk[1];
1653 t2 =
1654 Td0(byte(s2, 3)) ^
1655 Td1(byte(s1, 2)) ^
1656 Td2(byte(s0, 1)) ^
1657 Td3(byte(s3, 0)) ^
1658 rk[2];
1659 t3 =
1660 Td0(byte(s3, 3)) ^
1661 Td1(byte(s2, 2)) ^
1662 Td2(byte(s1, 1)) ^
1663 Td3(byte(s0, 0)) ^
1664 rk[3];
1665 if (r == Nr-2) {
1666 break;
1667 }
1668 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
1669 }
1670 rk += 4;
1671
1672#else /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1673
1674/*
1675 Nr - 1 full rounds:
1676 */
1677 r = Nr >> 1;
1678 for (;;) {
1679
1680 t0 =
1681 Td0(byte(s0, 3)) ^
1682 Td1(byte(s3, 2)) ^
1683 Td2(byte(s2, 1)) ^
1684 Td3(byte(s1, 0)) ^
1685 rk[4];
1686 t1 =
1687 Td0(byte(s1, 3)) ^
1688 Td1(byte(s0, 2)) ^
1689 Td2(byte(s3, 1)) ^
1690 Td3(byte(s2, 0)) ^
1691 rk[5];
1692 t2 =
1693 Td0(byte(s2, 3)) ^
1694 Td1(byte(s1, 2)) ^
1695 Td2(byte(s0, 1)) ^
1696 Td3(byte(s3, 0)) ^
1697 rk[6];
1698 t3 =
1699 Td0(byte(s3, 3)) ^
1700 Td1(byte(s2, 2)) ^
1701 Td2(byte(s1, 1)) ^
1702 Td3(byte(s0, 0)) ^
1703 rk[7];
1704
1705 rk += 8;
1706 if (--r == 0) {
1707 break;
1708 }
1709
1710 s0 =
1711 Td0(byte(t0, 3)) ^
1712 Td1(byte(t3, 2)) ^
1713 Td2(byte(t2, 1)) ^
1714 Td3(byte(t1, 0)) ^
1715 rk[0];
1716 s1 =
1717 Td0(byte(t1, 3)) ^
1718 Td1(byte(t0, 2)) ^
1719 Td2(byte(t3, 1)) ^
1720 Td3(byte(t2, 0)) ^
1721 rk[1];
1722 s2 =
1723 Td0(byte(t2, 3)) ^
1724 Td1(byte(t1, 2)) ^
1725 Td2(byte(t0, 1)) ^
1726 Td3(byte(t3, 0)) ^
1727 rk[2];
1728 s3 =
1729 Td0(byte(t3, 3)) ^
1730 Td1(byte(t2, 2)) ^
1731 Td2(byte(t1, 1)) ^
1732 Td3(byte(t0, 0)) ^
1733 rk[3];
1734 }
1735#endif /* PS_AES_IMPROVE_PERF_INCREASE_CODESIZE */
1736
1737/*
1738 apply last round and map cipher state to byte array block:
1739 */
1740 s0 =
1741 (Td4[byte(t0, 3)] & 0xff000000) ^
1742 (Td4[byte(t3, 2)] & 0x00ff0000) ^
1743 (Td4[byte(t2, 1)] & 0x0000ff00) ^
1744 (Td4[byte(t1, 0)] & 0x000000ff) ^
1745 rk[0];
1746 STORE32H(s0, pt);
1747 s1 =
1748 (Td4[byte(t1, 3)] & 0xff000000) ^
1749 (Td4[byte(t0, 2)] & 0x00ff0000) ^
1750 (Td4[byte(t3, 1)] & 0x0000ff00) ^
1751 (Td4[byte(t2, 0)] & 0x000000ff) ^
1752 rk[1];
1753 STORE32H(s1, pt+4);
1754 s2 =
1755 (Td4[byte(t2, 3)] & 0xff000000) ^
1756 (Td4[byte(t1, 2)] & 0x00ff0000) ^
1757 (Td4[byte(t0, 1)] & 0x0000ff00) ^
1758 (Td4[byte(t3, 0)] & 0x000000ff) ^
1759 rk[2];
1760 STORE32H(s2, pt+8);
1761 s3 =
1762 (Td4[byte(t3, 3)] & 0xff000000) ^
1763 (Td4[byte(t2, 2)] & 0x00ff0000) ^
1764 (Td4[byte(t1, 1)] & 0x0000ff00) ^
1765 (Td4[byte(t0, 0)] & 0x000000ff) ^
1766 rk[3];
1767 STORE32H(s3, pt+12);
1768}
1769
1770
1771/******************************************************************************/
1772/******************************************************************************/
1773#endif /* !USE_AES_CBC_EXTERNAL */
1774#endif /* USE_AES */
1775/******************************************************************************/
1776
diff --git a/networking/tls_aes.h b/networking/tls_aes.h
new file mode 100644
index 000000000..c6791866a
--- /dev/null
+++ b/networking/tls_aes.h
@@ -0,0 +1,10 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 *
6 * Selected few declarations for AES.
7 */
8
9void aes_cbc_encrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst);
10void aes_cbc_decrypt(const void *key, int klen, void *iv, const void *data, size_t len, void *dst);
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
new file mode 100644
index 000000000..acd800307
--- /dev/null
+++ b/networking/tls_pstm.c
@@ -0,0 +1,2263 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision number implementation.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c);
51
52/******************************************************************************/
53/*
54 init an pstm_int for a given size
55 */
56int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
57{
58//bbox
59// uint16 x;
60
61/*
62 alloc mem
63 */
64 a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox
65//bbox a->pool = pool;
66 a->used = 0;
67 a->alloc = (int16)size;
68 a->sign = PSTM_ZPOS;
69/*
70 zero the digits
71 */
72//bbox
73// for (x = 0; x < size; x++) {
74// a->dp[x] = 0;
75// }
76 return PSTM_OKAY;
77}
78
79/******************************************************************************/
80/*
81 Init a new pstm_int.
82*/
83int32 pstm_init(psPool_t *pool, pstm_int * a)
84{
85//bbox
86// int32 i;
87/*
88 allocate memory required and clear it
89 */
90 a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);//bbox
91/*
92 set the digits to zero
93 */
94//bbox
95// for (i = 0; i < PSTM_DEFAULT_INIT; i++) {
96// a->dp[i] = 0;
97// }
98/*
99 set the used to zero, allocated digits to the default precision and sign
100 to positive
101 */
102//bbox a->pool = pool;
103 a->used = 0;
104 a->alloc = PSTM_DEFAULT_INIT;
105 a->sign = PSTM_ZPOS;
106
107 return PSTM_OKAY;
108}
109
110/******************************************************************************/
111/*
112 Grow as required
113 */
114int32 pstm_grow(pstm_int * a, int16 size)
115{
116 int16 i;
117 pstm_digit *tmp;
118
119/*
120 If the alloc size is smaller alloc more ram.
121 */
122 if (a->alloc < size) {
123/*
124 Reallocate the array a->dp
125
126 We store the return in a temporary variable in case the operation
127 failed we don't want to overwrite the dp member of a.
128*/
129 tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);//bbox
130/*
131 reallocation succeeded so set a->dp
132 */
133 a->dp = tmp;
134/*
135 zero excess digits
136 */
137 i = a->alloc;
138 a->alloc = size;
139 for (; i < a->alloc; i++) {
140 a->dp[i] = 0;
141 }
142 }
143 return PSTM_OKAY;
144}
145
146/******************************************************************************/
147/*
148 copy, b = a (b must be pre-allocated)
149 */
150int32 pstm_copy(pstm_int * a, pstm_int * b)
151{
152 int32 res, n;
153
154/*
155 If dst == src do nothing
156 */
157 if (a == b) {
158 return PSTM_OKAY;
159 }
160/*
161 Grow dest
162 */
163 if (b->alloc < a->used) {
164 if ((res = pstm_grow (b, a->used)) != PSTM_OKAY) {
165 return res;
166 }
167 }
168/*
169 Zero b and copy the parameters over
170 */
171 {
172 register pstm_digit *tmpa, *tmpb;
173
174 /* pointer aliases */
175 /* source */
176 tmpa = a->dp;
177
178 /* destination */
179 tmpb = b->dp;
180
181 /* copy all the digits */
182 for (n = 0; n < a->used; n++) {
183 *tmpb++ = *tmpa++;
184 }
185
186 /* clear high digits */
187 for (; n < b->used; n++) {
188 *tmpb++ = 0;
189 }
190 }
191/*
192 copy used count and sign
193 */
194 b->used = a->used;
195 b->sign = a->sign;
196 return PSTM_OKAY;
197}
198
199/******************************************************************************/
200/*
201 Trim unused digits
202
203 This is used to ensure that leading zero digits are trimed and the
204 leading "used" digit will be non-zero. Typically very fast. Also fixes
205 the sign if there are no more leading digits
206*/
207void pstm_clamp(pstm_int * a)
208{
209/* decrease used while the most significant digit is zero. */
210 while (a->used > 0 && a->dp[a->used - 1] == 0) {
211 --(a->used);
212 }
213/* reset the sign flag if used == 0 */
214 if (a->used == 0) {
215 a->sign = PSTM_ZPOS;
216 }
217}
218
219/******************************************************************************/
220/*
221 clear one (frees).
222 */
223void pstm_clear(pstm_int * a)
224{
225 int32 i;
226/*
227 only do anything if a hasn't been freed previously
228 */
229 if (a != NULL && a->dp != NULL) {
230/*
231 first zero the digits
232 */
233 for (i = 0; i < a->used; i++) {
234 a->dp[i] = 0;
235 }
236
237 psFree (a->dp, a->pool);
238/*
239 reset members to make debugging easier
240 */
241 a->dp = NULL;
242 a->alloc = a->used = 0;
243 a->sign = PSTM_ZPOS;
244 }
245}
246
247/******************************************************************************/
248/*
249 clear many (frees).
250 */
251void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
252 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5,
253 pstm_int *mp6, pstm_int *mp7)
254{
255 int32 n; /* Number of ok inits */
256
257 pstm_int *tempArray[9];
258
259 tempArray[0] = mp0;
260 tempArray[1] = mp1;
261 tempArray[2] = mp2;
262 tempArray[3] = mp3;
263 tempArray[4] = mp4;
264 tempArray[5] = mp5;
265 tempArray[6] = mp6;
266 tempArray[7] = mp7;
267 tempArray[8] = NULL;
268
269 for (n = 0; tempArray[n] != NULL; n++) {
270 if ((tempArray[n] != NULL) && (tempArray[n]->dp != NULL)) {
271 pstm_clear(tempArray[n]);
272 }
273 }
274}
275
276/******************************************************************************/
277/*
278 Set to zero.
279 */
280void pstm_zero(pstm_int * a)
281{
282 int32 n;
283 pstm_digit *tmp;
284
285 a->sign = PSTM_ZPOS;
286 a->used = 0;
287
288 tmp = a->dp;
289 for (n = 0; n < a->alloc; n++) {
290 *tmp++ = 0;
291 }
292}
293
294
295/******************************************************************************/
296/*
297 Compare maginitude of two ints (unsigned).
298 */
299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
300{
301 int16 n;
302 pstm_digit *tmpa, *tmpb;
303
304/*
305 compare based on # of non-zero digits
306 */
307 if (a->used > b->used) {
308 return PSTM_GT;
309 }
310
311 if (a->used < b->used) {
312 return PSTM_LT;
313 }
314
315 /* alias for a */
316 tmpa = a->dp + (a->used - 1);
317
318 /* alias for b */
319 tmpb = b->dp + (a->used - 1);
320
321/*
322 compare based on digits
323 */
324 for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
325 if (*tmpa > *tmpb) {
326 return PSTM_GT;
327 }
328 if (*tmpa < *tmpb) {
329 return PSTM_LT;
330 }
331 }
332 return PSTM_EQ;
333}
334
335/******************************************************************************/
336/*
337 Compare two ints (signed)
338 */
339int32 pstm_cmp(pstm_int * a, pstm_int * b)
340{
341/*
342 compare based on sign
343 */
344 if (a->sign != b->sign) {
345 if (a->sign == PSTM_NEG) {
346 return PSTM_LT;
347 } else {
348 return PSTM_GT;
349 }
350 }
351/*
352 compare digits
353 */
354 if (a->sign == PSTM_NEG) {
355 /* if negative compare opposite direction */
356 return pstm_cmp_mag(b, a);
357 } else {
358 return pstm_cmp_mag(a, b);
359 }
360}
361
362/******************************************************************************/
363/*
364 pstm_ints can be initialized more precisely when they will populated
365 using pstm_read_unsigned_bin since the length of the byte stream is known
366*/
367int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
368{
369 int32 size;
370/*
371 Need to set this based on how many words max it will take to store the bin.
372 The magic + 2:
373 1 to round up for the remainder of this integer math
374 1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8
375*/
376 size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
377 / DIGIT_BIT) + 2;
378 return pstm_init_size(pool, a, size);
379}
380
381
382/******************************************************************************/
383/*
384 Reads a unsigned char array into pstm_int format. User should have
385 called pstm_init_for_read_unsigned_bin first. There is some grow logic
386 here if the default pstm_init was used but we don't really want to hit it.
387*/
388int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
389{
390 /* zero the int */
391 pstm_zero (a);
392
393/*
394 If we know the endianness of this architecture, and we're using
395 32-bit pstm_digits, we can optimize this
396*/
397#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT)
398 /* But not for both simultaneously */
399#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
400#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
401#endif
402 {
403 unsigned char *pd;
404 if ((unsigned)c > (PSTM_MAX_SIZE * sizeof(pstm_digit))) {
405 uint32 excess = c - (PSTM_MAX_SIZE * sizeof(pstm_digit));
406 c -= excess;
407 b += excess;
408 }
409 a->used = (int16)((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit));
410 if (a->alloc < a->used) {
411 if (pstm_grow(a, a->used) != PSTM_OKAY) {
412 return PSTM_MEM;
413 }
414 }
415 pd = (unsigned char *)a->dp;
416 /* read the bytes in */
417#ifdef ENDIAN_BIG
418 {
419 /* Use Duff's device to unroll the loop. */
420 int32 idx = (c - 1) & ~3;
421 switch (c % 4) {
422 case 0: do { pd[idx+0] = *b++;
423 case 3: pd[idx+1] = *b++;
424 case 2: pd[idx+2] = *b++;
425 case 1: pd[idx+3] = *b++;
426 idx -= 4;
427 } while ((c -= 4) > 0);
428 }
429 }
430#else
431 for (c -= 1; c >= 0; c -= 1) {
432 pd[c] = *b++;
433 }
434#endif
435 }
436#else
437 /* Big enough based on the len? */
438 a->used = (((c / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
439 / DIGIT_BIT) + 2;
440
441 if (a->alloc < a->used) {
442 if (pstm_grow(a, a->used) != PSTM_OKAY) {
443 return PSTM_MEM;
444 }
445 }
446 /* read the bytes in */
447 for (; c > 0; c--) {
448 if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) {
449 return PS_MEM_FAIL;
450 }
451 a->dp[0] |= *b++;
452 a->used += 1;
453 }
454#endif
455
456 pstm_clamp (a);
457 return PS_SUCCESS;
458}
459
460/******************************************************************************/
461/*
462*/
463int16 pstm_count_bits (pstm_int * a)
464{
465 int16 r;
466 pstm_digit q;
467
468 if (a->used == 0) {
469 return 0;
470 }
471
472 /* get number of digits and add that */
473 r = (a->used - 1) * DIGIT_BIT;
474
475 /* take the last digit and count the bits in it */
476 q = a->dp[a->used - 1];
477 while (q > ((pstm_digit) 0)) {
478 ++r;
479 q >>= ((pstm_digit) 1);
480 }
481 return r;
482}
483
484/******************************************************************************/
485int32 pstm_unsigned_bin_size(pstm_int *a)
486{
487 int32 size = pstm_count_bits (a);
488 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
489}
490
491/******************************************************************************/
492void pstm_set(pstm_int *a, pstm_digit b)
493{
494 pstm_zero(a);
495 a->dp[0] = b;
496 a->used = a->dp[0] ? 1 : 0;
497}
498
499/******************************************************************************/
500/*
501 Right shift
502*/
503void pstm_rshd(pstm_int *a, int16 x)
504{
505 int16 y;
506
507 /* too many digits just zero and return */
508 if (x >= a->used) {
509 pstm_zero(a);
510 return;
511 }
512
513 /* shift */
514 for (y = 0; y < a->used - x; y++) {
515 a->dp[y] = a->dp[y+x];
516 }
517
518 /* zero rest */
519 for (; y < a->used; y++) {
520 a->dp[y] = 0;
521 }
522
523 /* decrement count */
524 a->used -= x;
525 pstm_clamp(a);
526}
527
528/******************************************************************************/
529/*
530 Shift left a certain amount of digits.
531 */
532int32 pstm_lshd(pstm_int * a, int16 b)
533{
534 int16 x;
535 int32 res;
536
537/*
538 If its less than zero return.
539 */
540 if (b <= 0) {
541 return PSTM_OKAY;
542 }
543/*
544 Grow to fit the new digits.
545 */
546 if (a->alloc < a->used + b) {
547 if ((res = pstm_grow (a, a->used + b)) != PSTM_OKAY) {
548 return res;
549 }
550 }
551
552 {
553 register pstm_digit *top, *bottom;
554/*
555 Increment the used by the shift amount then copy upwards.
556 */
557 a->used += b;
558
559 /* top */
560 top = a->dp + a->used - 1;
561
562 /* base */
563 bottom = a->dp + a->used - 1 - b;
564/*
565 This is implemented using a sliding window except the window goes the
566 other way around. Copying from the bottom to the top.
567 */
568 for (x = a->used - 1; x >= b; x--) {
569 *top-- = *bottom--;
570 }
571
572 /* zero the lower digits */
573 top = a->dp;
574 for (x = 0; x < b; x++) {
575 *top++ = 0;
576 }
577 }
578 return PSTM_OKAY;
579}
580
581/******************************************************************************/
582/*
583 computes a = 2**b
584*/
585int32 pstm_2expt(pstm_int *a, int16 b)
586{
587 int16 z;
588
589 /* zero a as per default */
590 pstm_zero (a);
591
592 if (b < 0) {
593 return PSTM_OKAY;
594 }
595
596 z = b / DIGIT_BIT;
597 if (z >= PSTM_MAX_SIZE) {
598 return PS_LIMIT_FAIL;
599 }
600
601 /* set the used count of where the bit will go */
602 a->used = z + 1;
603
604 if (a->used > a->alloc) {
605 if (pstm_grow(a, a->used) != PSTM_OKAY) {
606 return PS_MEM_FAIL;
607 }
608 }
609
610 /* put the single bit in its place */
611 a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT);
612 return PSTM_OKAY;
613}
614
615/******************************************************************************/
616/*
617
618*/
619int32 pstm_mul_2(pstm_int * a, pstm_int * b)
620{
621 int32 res;
622 int16 x, oldused;
623
624/*
625 grow to accomodate result
626 */
627 if (b->alloc < a->used + 1) {
628 if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) {
629 return res;
630 }
631 }
632 oldused = b->used;
633 b->used = a->used;
634
635 {
636 register pstm_digit r, rr, *tmpa, *tmpb;
637
638 /* alias for source */
639 tmpa = a->dp;
640
641 /* alias for dest */
642 tmpb = b->dp;
643
644 /* carry */
645 r = 0;
646 for (x = 0; x < a->used; x++) {
647/*
648 get what will be the *next* carry bit from the
649 MSB of the current digit
650*/
651 rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1));
652/*
653 now shift up this digit, add in the carry [from the previous]
654*/
655 *tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r);
656/*
657 copy the carry that would be from the source
658 digit into the next iteration
659*/
660 r = rr;
661 }
662
663 /* new leading digit? */
664 if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) {
665 /* add a MSB which is always 1 at this point */
666 *tmpb = 1;
667 ++(b->used);
668 }
669/*
670 now zero any excess digits on the destination that we didn't write to
671*/
672 tmpb = b->dp + b->used;
673 for (x = b->used; x < oldused; x++) {
674 *tmpb++ = 0;
675 }
676 }
677 b->sign = a->sign;
678 return PSTM_OKAY;
679}
680
681/******************************************************************************/
682/*
683 unsigned subtraction ||a|| >= ||b|| ALWAYS!
684*/
685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
686{
687 int16 oldbused, oldused;
688 int32 x;
689 pstm_word t;
690
691 if (b->used > a->used) {
692 return PS_LIMIT_FAIL;
693 }
694 if (c->alloc < a->used) {
695 if ((x = pstm_grow (c, a->used)) != PSTM_OKAY) {
696 return x;
697 }
698 }
699 oldused = c->used;
700 oldbused = b->used;
701 c->used = a->used;
702 t = 0;
703
704 for (x = 0; x < oldbused; x++) {
705 t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t);
706 c->dp[x] = (pstm_digit)t;
707 t = (t >> DIGIT_BIT)&1;
708 }
709 for (; x < a->used; x++) {
710 t = ((pstm_word)a->dp[x]) - t;
711 c->dp[x] = (pstm_digit)t;
712 t = (t >> DIGIT_BIT);
713 }
714 for (; x < oldused; x++) {
715 c->dp[x] = 0;
716 }
717 pstm_clamp(c);
718 return PSTM_OKAY;
719}
720
721/******************************************************************************/
722/*
723 unsigned addition
724*/
725static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
726{
727 int16 x, y, oldused;
728 register pstm_word t, adp, bdp;
729
730 y = a->used;
731 if (b->used > y) {
732 y = b->used;
733 }
734 oldused = c->used;
735 c->used = y;
736
737 if (c->used > c->alloc) {
738 if (pstm_grow(c, c->used) != PSTM_OKAY) {
739 return PS_MEM_FAIL;
740 }
741 }
742
743 t = 0;
744 for (x = 0; x < y; x++) {
745 if (a->used < x) {
746 adp = 0;
747 } else {
748 adp = (pstm_word)a->dp[x];
749 }
750 if (b->used < x) {
751 bdp = 0;
752 } else {
753 bdp = (pstm_word)b->dp[x];
754 }
755 t += (adp) + (bdp);
756 c->dp[x] = (pstm_digit)t;
757 t >>= DIGIT_BIT;
758 }
759 if (t != 0 && x < PSTM_MAX_SIZE) {
760 if (c->used == c->alloc) {
761 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
762 return PS_MEM_FAIL;
763 }
764 }
765 c->dp[c->used++] = (pstm_digit)t;
766 ++x;
767 }
768
769 c->used = x;
770 for (; x < oldused; x++) {
771 c->dp[x] = 0;
772 }
773 pstm_clamp(c);
774 return PSTM_OKAY;
775}
776
777
778/******************************************************************************/
779/*
780
781*/
782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
783{
784 int32 res;
785 int16 sa, sb;
786
787 sa = a->sign;
788 sb = b->sign;
789
790 if (sa != sb) {
791/*
792 subtract a negative from a positive, OR a positive from a negative.
793 For both, ADD their magnitudes, and use the sign of the first number.
794 */
795 c->sign = sa;
796 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
797 return res;
798 }
799 } else {
800/*
801 subtract a positive from a positive, OR a negative from a negative.
802 First, take the difference between their magnitudes, then...
803 */
804 if (pstm_cmp_mag (a, b) != PSTM_LT) {
805 /* Copy the sign from the first */
806 c->sign = sa;
807 /* The first has a larger or equal magnitude */
808 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
809 return res;
810 }
811 } else {
812 /* The result has the _opposite_ sign from the first number. */
813 c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS;
814 /* The second has a larger magnitude */
815 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
816 return res;
817 }
818 }
819 }
820 return PS_SUCCESS;
821}
822
823/******************************************************************************/
824/*
825 c = a - b
826*/
827int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
828{
829 pstm_int tmp;
830 int32 res;
831
832 if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) {
833 return PS_MEM_FAIL;
834 }
835 pstm_set(&tmp, b);
836 res = pstm_sub(a, &tmp, c);
837 pstm_clear(&tmp);
838 return res;
839}
840
841/******************************************************************************/
842/*
843 setups the montgomery reduction
844*/
845int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
846{
847 pstm_digit x, b;
848
849/*
850 fast inversion mod 2**k
851 Based on the fact that
852 XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
853 => 2*X*A - X*X*A*A = 1
854 => 2*(1) - (1) = 1
855 */
856 b = a->dp[0];
857
858 if ((b & 1) == 0) {
859 psTraceCrypto("pstm_montogomery_setup failure\n");
860 return PS_ARG_FAIL;
861 }
862
863 x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
864 x *= 2 - b * x; /* here x*a==1 mod 2**8 */
865 x *= 2 - b * x; /* here x*a==1 mod 2**16 */
866 x *= 2 - b * x; /* here x*a==1 mod 2**32 */
867#ifdef PSTM_64BIT
868 x *= 2 - b * x; /* here x*a==1 mod 2**64 */
869#endif
870 /* rho = -1/m mod b */
871 *rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) -
872 ((pstm_word)x));
873 return PSTM_OKAY;
874}
875
876/******************************************************************************/
877/*
878 * computes a = B**n mod b without division or multiplication useful for
879 * normalizing numbers in a Montgomery system.
880 */
881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
882{
883 int32 x;
884 int16 bits;
885
886 /* how many bits of last digit does b use */
887 bits = pstm_count_bits (b) % DIGIT_BIT;
888 if (!bits) bits = DIGIT_BIT;
889
890 /* compute A = B^(n-1) * 2^(bits-1) */
891 if (b->used > 1) {
892 if ((x = pstm_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) !=
893 PSTM_OKAY) {
894 return x;
895 }
896 } else {
897 pstm_set(a, 1);
898 bits = 1;
899 }
900
901 /* now compute C = A * B mod b */
902 for (x = bits - 1; x < (int32)DIGIT_BIT; x++) {
903 if (pstm_mul_2 (a, a) != PSTM_OKAY) {
904 return PS_MEM_FAIL;
905 }
906 if (pstm_cmp_mag (a, b) != PSTM_LT) {
907 if (s_pstm_sub (a, b, a) != PSTM_OKAY) {
908 return PS_MEM_FAIL;
909 }
910 }
911 }
912 return PSTM_OKAY;
913}
914
915/******************************************************************************/
916/*
917 c = a * 2**d
918*/
919static int32 pstm_mul_2d(pstm_int *a, int16 b, pstm_int *c)
920{
921 pstm_digit carry, carrytmp, shift;
922 int16 x;
923
924 /* copy it */
925 if (pstm_copy(a, c) != PSTM_OKAY) {
926 return PS_MEM_FAIL;
927 }
928
929 /* handle whole digits */
930 if (b >= DIGIT_BIT) {
931 if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) {
932 return PS_MEM_FAIL;
933 }
934 }
935 b %= DIGIT_BIT;
936
937 /* shift the digits */
938 if (b != 0) {
939 carry = 0;
940 shift = DIGIT_BIT - b;
941 for (x = 0; x < c->used; x++) {
942 carrytmp = c->dp[x] >> shift;
943 c->dp[x] = (c->dp[x] << b) + carry;
944 carry = carrytmp;
945 }
946 /* store last carry if room */
947 if (carry && x < PSTM_MAX_SIZE) {
948 if (c->used == c->alloc) {
949 if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
950 return PS_MEM_FAIL;
951 }
952 }
953 c->dp[c->used++] = carry;
954 }
955 }
956 pstm_clamp(c);
957 return PSTM_OKAY;
958}
959
960/******************************************************************************/
961/*
962 c = a mod 2**d
963*/
964static int32 pstm_mod_2d(pstm_int *a, int16 b, pstm_int *c)
965{
966 int16 x;
967
968 /* zero if count less than or equal to zero */
969 if (b <= 0) {
970 pstm_zero(c);
971 return PSTM_OKAY;
972 }
973
974 /* get copy of input */
975 if (pstm_copy(a, c) != PSTM_OKAY) {
976 return PS_MEM_FAIL;
977 }
978
979 /* if 2**d is larger than we just return */
980 if (b >= (DIGIT_BIT * a->used)) {
981 return PSTM_OKAY;
982 }
983
984 /* zero digits above the last digit of the modulus */
985 for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++)
986 {
987 c->dp[x] = 0;
988 }
989 /* clear the digit that is not completely outside/inside the modulus */
990 c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b);
991 pstm_clamp (c);
992 return PSTM_OKAY;
993}
994
995
996/******************************************************************************/
997/*
998 c = a * b
999*/
1000int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1001{
1002 pstm_word w;
1003 int32 res;
1004 int16 x, oldused;
1005
1006 if (c->alloc < a->used + 1) {
1007 if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) {
1008 return res;
1009 }
1010 }
1011 oldused = c->used;
1012 c->used = a->used;
1013 c->sign = a->sign;
1014 w = 0;
1015 for (x = 0; x < a->used; x++) {
1016 w = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w;
1017 c->dp[x] = (pstm_digit)w;
1018 w = w >> DIGIT_BIT;
1019 }
1020 if (w != 0 && (a->used != PSTM_MAX_SIZE)) {
1021 c->dp[c->used++] = (pstm_digit)w;
1022 ++x;
1023 }
1024 for (; x < oldused; x++) {
1025 c->dp[x] = 0;
1026 }
1027 pstm_clamp(c);
1028 return PSTM_OKAY;
1029}
1030
1031/******************************************************************************/
1032/*
1033 c = a / 2**b
1034*/
1035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c,
1036 pstm_int *d)
1037{
1038 pstm_digit D, r, rr;
1039 int32 res;
1040 int16 x;
1041 pstm_int t;
1042
1043 /* if the shift count is <= 0 then we do no work */
1044 if (b <= 0) {
1045 if (pstm_copy (a, c) != PSTM_OKAY) {
1046 return PS_MEM_FAIL;
1047 }
1048 if (d != NULL) {
1049 pstm_zero (d);
1050 }
1051 return PSTM_OKAY;
1052 }
1053
1054 /* get the remainder */
1055 if (d != NULL) {
1056 if (pstm_init(pool, &t) != PSTM_OKAY) {
1057 return PS_MEM_FAIL;
1058 }
1059 if (pstm_mod_2d (a, b, &t) != PSTM_OKAY) {
1060 res = PS_MEM_FAIL;
1061 goto LBL_DONE;
1062 }
1063 }
1064
1065 /* copy */
1066 if (pstm_copy(a, c) != PSTM_OKAY) {
1067 res = PS_MEM_FAIL;
1068 goto LBL_DONE;
1069 }
1070
1071 /* shift by as many digits in the bit count */
1072 if (b >= (int32)DIGIT_BIT) {
1073 pstm_rshd (c, b / DIGIT_BIT);
1074 }
1075
1076 /* shift any bit count < DIGIT_BIT */
1077 D = (pstm_digit) (b % DIGIT_BIT);
1078 if (D != 0) {
1079 register pstm_digit *tmpc, mask, shift;
1080
1081 /* mask */
1082 mask = (((pstm_digit)1) << D) - 1;
1083
1084 /* shift for lsb */
1085 shift = DIGIT_BIT - D;
1086
1087 /* alias */
1088 tmpc = c->dp + (c->used - 1);
1089
1090 /* carry */
1091 r = 0;
1092 for (x = c->used - 1; x >= 0; x--) {
1093 /* get the lower bits of this word in a temp */
1094 rr = *tmpc & mask;
1095
1096 /* shift the current word and mix in the carry bits from previous */
1097 *tmpc = (*tmpc >> D) | (r << shift);
1098 --tmpc;
1099
1100 /* set the carry to the carry bits of the current word above */
1101 r = rr;
1102 }
1103 }
1104 pstm_clamp (c);
1105
1106 res = PSTM_OKAY;
1107LBL_DONE:
1108 if (d != NULL) {
1109 if (pstm_copy(&t, d) != PSTM_OKAY) {
1110 res = PS_MEM_FAIL;
1111 }
1112 pstm_clear(&t);
1113 }
1114 return res;
1115}
1116
1117/******************************************************************************/
1118/*
1119 b = a/2
1120*/
1121int32 pstm_div_2(pstm_int * a, pstm_int * b)
1122{
1123 int16 x, oldused;
1124
1125 if (b->alloc < a->used) {
1126 if (pstm_grow(b, a->used) != PSTM_OKAY) {
1127 return PS_MEM_FAIL;
1128 }
1129 }
1130 oldused = b->used;
1131 b->used = a->used;
1132 {
1133 register pstm_digit r, rr, *tmpa, *tmpb;
1134
1135 /* source alias */
1136 tmpa = a->dp + b->used - 1;
1137
1138 /* dest alias */
1139 tmpb = b->dp + b->used - 1;
1140
1141 /* carry */
1142 r = 0;
1143 for (x = b->used - 1; x >= 0; x--) {
1144 /* get the carry for the next iteration */
1145 rr = *tmpa & 1;
1146
1147 /* shift the current digit, add in carry and store */
1148 *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
1149
1150 /* forward carry to next iteration */
1151 r = rr;
1152 }
1153
1154 /* zero excess digits */
1155 tmpb = b->dp + b->used;
1156 for (x = b->used; x < oldused; x++) {
1157 *tmpb++ = 0;
1158 }
1159 }
1160 b->sign = a->sign;
1161 pstm_clamp (b);
1162 return PSTM_OKAY;
1163}
1164
1165/******************************************************************************/
1166/*
1167 Creates "a" then copies b into it
1168 */
1169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int16 toSqr)
1170{
1171 int16 x;
1172 int32 res;
1173
1174 if (a == b) {
1175 return PSTM_OKAY;
1176 }
1177 x = b->alloc;
1178
1179 if (toSqr) {
1180/*
1181 Smart-size: Increasing size of a if b->used is roughly half
1182 of b->alloc because usage has shown that a lot of these copies
1183 go on to be squared and need these extra digits
1184*/
1185 if ((b->used * 2) + 2 >= x) {
1186 x = (b->used * 2) + 3;
1187 }
1188 }
1189 if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) {
1190 return res;
1191 }
1192 return pstm_copy(b, a);
1193}
1194
1195/******************************************************************************/
1196/*
1197 With some compilers, we have seen issues linking with the builtin
1198 64 bit division routine. The issues with either manifest in a failure
1199 to find 'udivdi3' at link time, or a runtime invalid instruction fault
1200 during an RSA operation.
1201 The routine below divides a 64 bit unsigned int by a 32 bit unsigned int
1202 explicitly, rather than using the division operation
1203 The 64 bit result is placed in the 'numerator' parameter
1204 The 32 bit mod (remainder) of the division is the return parameter
1205 Based on implementations by:
1206 Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
1207 Copyright (C) 1999 Hewlett-Packard Co
1208 Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
1209*/
1210#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1211static uint32 psDiv64(uint64 *numerator, uint32 denominator)
1212{
1213 uint64 rem = *numerator;
1214 uint64 b = denominator;
1215 uint64 res = 0;
1216 uint64 d = 1;
1217 uint32 high = rem >> 32;
1218
1219 if (high >= denominator) {
1220 high /= denominator;
1221 res = (uint64) high << 32;
1222 rem -= (uint64) (high * denominator) << 32;
1223 }
1224 while ((int64)b > 0 && b < rem) {
1225 b = b+b;
1226 d = d+d;
1227 }
1228 do {
1229 if (rem >= b) {
1230 rem -= b;
1231 res += d;
1232 }
1233 b >>= 1;
1234 d >>= 1;
1235 } while (d);
1236 *numerator = res;
1237 return rem;
1238}
1239#endif /* USE_MATRIX_DIV64 */
1240
1241#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1242typedef unsigned long uint128 __attribute__ ((mode(TI)));
1243static uint64 psDiv128(uint128 *numerator, uint64 denominator)
1244{
1245 uint128 rem = *numerator;
1246 uint128 b = denominator;
1247 uint128 res = 0;
1248 uint128 d = 1;
1249 uint64 high = rem >> 64;
1250
1251 if (high >= denominator) {
1252 high /= denominator;
1253 res = (uint128) high << 64;
1254 rem -= (uint128) (high * denominator) << 64;
1255 }
1256 while ((uint128)b > 0 && b < rem) {
1257 b = b+b;
1258 d = d+d;
1259 }
1260 do {
1261 if (rem >= b) {
1262 rem -= b;
1263 res += d;
1264 }
1265 b >>= 1;
1266 d >>= 1;
1267 } while (d);
1268 *numerator = res;
1269 return rem;
1270}
1271#endif /* USE_MATRIX_DIV128 */
1272
1273/******************************************************************************/
1274/*
1275 a/b => cb + d == a
1276*/
1277int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1278 pstm_int *d)
1279{
1280 pstm_int q, x, y, t1, t2;
1281 int32 res;
1282 int16 n, t, i, norm, neg;
1283
1284 /* is divisor zero ? */
1285 if (pstm_iszero (b) == 1) {
1286 return PS_LIMIT_FAIL;
1287 }
1288
1289 /* if a < b then q=0, r = a */
1290 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1291 if (d != NULL) {
1292 if (pstm_copy(a, d) != PSTM_OKAY) {
1293 return PS_MEM_FAIL;
1294 }
1295 }
1296 if (c != NULL) {
1297 pstm_zero (c);
1298 }
1299 return PSTM_OKAY;
1300 }
1301/*
1302 Smart-size inits
1303*/
1304 if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) {
1305 return res;
1306 }
1307 if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) {
1308 goto LBL_T1;
1309 }
1310 if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) {
1311 goto LBL_T2;
1312 }
1313/*
1314 Used to be an init_copy on b but pstm_grow was always hit with triple size
1315*/
1316 if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) {
1317 goto LBL_X;
1318 }
1319 if ((res = pstm_copy(b, &y)) != PSTM_OKAY) {
1320 goto LBL_Y;
1321 }
1322
1323 /* fix the sign */
1324 neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG;
1325 x.sign = y.sign = PSTM_ZPOS;
1326
1327 /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
1328 norm = pstm_count_bits(&y) % DIGIT_BIT;
1329 if (norm < (int32)(DIGIT_BIT-1)) {
1330 norm = (DIGIT_BIT-1) - norm;
1331 if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) {
1332 goto LBL_Y;
1333 }
1334 if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) {
1335 goto LBL_Y;
1336 }
1337 } else {
1338 norm = 0;
1339 }
1340
1341 /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1342 n = x.used - 1;
1343 t = y.used - 1;
1344
1345 if ((res = pstm_init_size(pool, &q, n - t + 1)) != PSTM_OKAY) {
1346 goto LBL_Y;
1347 }
1348 q.used = n - t + 1;
1349
1350 /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1351 if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */
1352 goto LBL_Q;
1353 }
1354
1355 while (pstm_cmp (&x, &y) != PSTM_LT) {
1356 ++(q.dp[n - t]);
1357 if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) {
1358 goto LBL_Q;
1359 }
1360 }
1361
1362 /* reset y by shifting it back down */
1363 pstm_rshd (&y, n - t);
1364
1365 /* step 3. for i from n down to (t + 1) */
1366 for (i = n; i >= (t + 1); i--) {
1367 if (i > x.used) {
1368 continue;
1369 }
1370
1371 /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
1372 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1373 if (x.dp[i] == y.dp[t]) {
1374 q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1);
1375 } else {
1376 pstm_word tmp;
1377 tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT);
1378 tmp |= ((pstm_word) x.dp[i - 1]);
1379#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
1380 psDiv64(&tmp, y.dp[t]);
1381#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
1382 psDiv128(&tmp, y.dp[t]);
1383#else
1384 tmp /= ((pstm_word) y.dp[t]);
1385#endif /* USE_MATRIX_DIV64 */
1386 q.dp[i - t - 1] = (pstm_digit) (tmp);
1387 }
1388
1389 /* while (q{i-t-1} * (yt * b + y{t-1})) >
1390 xi * b**2 + xi-1 * b + xi-2
1391
1392 do q{i-t-1} -= 1;
1393 */
1394 q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
1395 do {
1396 q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
1397
1398 /* find left hand */
1399 pstm_zero (&t1);
1400 t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
1401 t1.dp[1] = y.dp[t];
1402 t1.used = 2;
1403 if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1404 goto LBL_Q;
1405 }
1406
1407 /* find right hand */
1408 t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
1409 t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
1410 t2.dp[2] = x.dp[i];
1411 t2.used = 3;
1412 } while (pstm_cmp_mag(&t1, &t2) == PSTM_GT);
1413
1414 /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1415 if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
1416 goto LBL_Q;
1417 }
1418
1419 if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) {
1420 goto LBL_Q;
1421 }
1422
1423 if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) {
1424 goto LBL_Q;
1425 }
1426
1427 /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1428 if (x.sign == PSTM_NEG) {
1429 if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) {
1430 goto LBL_Q;
1431 }
1432 if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) {
1433 goto LBL_Q;
1434 }
1435 if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) {
1436 goto LBL_Q;
1437 }
1438 q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
1439 }
1440 }
1441/*
1442 now q is the quotient and x is the remainder (which we have to normalize)
1443*/
1444 /* get sign before writing to c */
1445 x.sign = x.used == 0 ? PSTM_ZPOS : a->sign;
1446
1447 if (c != NULL) {
1448 pstm_clamp (&q);
1449 if (pstm_copy (&q, c) != PSTM_OKAY) {
1450 res = PS_MEM_FAIL;
1451 goto LBL_Q;
1452 }
1453 c->sign = neg;
1454 }
1455
1456 if (d != NULL) {
1457 if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) {
1458 goto LBL_Q;
1459 }
1460/*
1461 the following is a kludge, essentially we were seeing the right
1462 remainder but with excess digits that should have been zero
1463 */
1464 for (i = b->used; i < x.used; i++) {
1465 x.dp[i] = 0;
1466 }
1467 pstm_clamp(&x);
1468 if (pstm_copy (&x, d) != PSTM_OKAY) {
1469 res = PS_MEM_FAIL;
1470 goto LBL_Q;
1471 }
1472 }
1473
1474 res = PSTM_OKAY;
1475
1476LBL_Q:pstm_clear (&q);
1477LBL_Y:pstm_clear (&y);
1478LBL_X:pstm_clear (&x);
1479LBL_T2:pstm_clear (&t2);
1480LBL_T1:pstm_clear (&t1);
1481
1482 return res;
1483}
1484
1485/******************************************************************************/
1486/*
1487 Swap the elements of two integers, for cases where you can't simply swap
1488 the pstm_int pointers around
1489*/
1490void pstm_exch(pstm_int * a, pstm_int * b)
1491{
1492 pstm_int t;
1493
1494 t = *a;
1495 *a = *b;
1496 *b = t;
1497}
1498
1499/******************************************************************************/
1500/*
1501 c = a mod b, 0 <= c < b
1502*/
1503int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
1504{
1505 pstm_int t;
1506 int32 err;
1507/*
1508 Smart-size
1509*/
1510 if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) {
1511 return err;
1512 }
1513 if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) {
1514 pstm_clear (&t);
1515 return err;
1516 }
1517 if (t.sign != b->sign) {
1518 err = pstm_add(&t, b, c);
1519 } else {
1520 pstm_exch (&t, c);
1521 }
1522 pstm_clear (&t);
1523 return err;
1524}
1525
1526/******************************************************************************/
1527/*
1528 d = a * b (mod c)
1529*/
1530int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1531 pstm_int *d)
1532{
1533 int32 res;
1534 int16 size;
1535 pstm_int tmp;
1536
1537/*
1538 Smart-size pstm_inits. d is an output that is influenced by this local 't'
1539 so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow
1540 in RSA operations
1541*/
1542 size = a->used + b->used + 1;
1543 if ((a == d) && (size < a->alloc)) {
1544 size = a->alloc;
1545 }
1546 if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) {
1547 return res;
1548 }
1549 if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) {
1550 pstm_clear(&tmp);
1551 return res;
1552 }
1553 res = pstm_mod(pool, &tmp, c, d);
1554 pstm_clear(&tmp);
1555 return res;
1556}
1557
1558/******************************************************************************/
1559/*
1560 * y = g**x (mod b)
1561 * Some restrictions... x must be positive and < b
1562 */
1563int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1564 pstm_int *Y)
1565{
1566 pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */
1567 pstm_digit buf, mp;
1568 pstm_digit *paD;
1569 int32 err, bitbuf;
1570 int16 bitcpy, bitcnt, mode, digidx, x, y, winsize;
1571 uint32 paDlen;
1572
1573 /* set window size from what user set as optimization */
1574 x = pstm_count_bits(X);
1575 if (x < 50) {
1576 winsize = 2;
1577 } else {
1578 winsize = PS_EXPTMOD_WINSIZE;
1579 }
1580
1581 /* now setup montgomery */
1582 if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) {
1583 return err;
1584 }
1585
1586 /* setup result */
1587 if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) {
1588 return err;
1589 }
1590/*
1591 create M table
1592 The M table contains powers of the input base, e.g. M[x] = G^x mod P
1593 The first half of the table is not computed though except for M[0] and M[1]
1594 */
1595 /* now we need R mod m */
1596 if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) {
1597 goto LBL_RES;
1598 }
1599/*
1600 init M array
1601 init first cell
1602 */
1603 if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) {
1604 goto LBL_RES;
1605 }
1606
1607 /* now set M[1] to G * R mod m */
1608 if (pstm_cmp_mag(P, G) != PSTM_GT) {
1609 /* G > P so we reduce it first */
1610 if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) {
1611 goto LBL_M;
1612 }
1613 } else {
1614 if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) {
1615 goto LBL_M;
1616 }
1617 }
1618 if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) {
1619 goto LBL_M;
1620 }
1621/*
1622 Pre-allocated digit. Used for mul, sqr, AND reduce
1623*/
1624 paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit);
1625 paD = xzalloc(paDlen);//bbox
1626/*
1627 compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
1628 */
1629 if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) {
1630 err = PS_MEM_FAIL;
1631 goto LBL_PAD;
1632 }
1633 for (x = 0; x < (winsize - 1); x++) {
1634 if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)],
1635 &M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) {
1636 goto LBL_PAD;
1637 }
1638 if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp,
1639 paD, paDlen)) != PSTM_OKAY) {
1640 goto LBL_PAD;
1641 }
1642 }
1643/*
1644 now init the second half of the array
1645*/
1646 for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) {
1647 if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1))
1648 != PSTM_OKAY) {
1649 for (y = 1<<(winsize-1); y < x; y++) {
1650 pstm_clear(&M[y]);
1651 }
1652 goto LBL_PAD;
1653 }
1654 }
1655
1656 /* create upper table */
1657 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
1658 if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen))
1659 != PSTM_OKAY) {
1660 goto LBL_MARRAY;
1661 }
1662 if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) !=
1663 PSTM_OKAY) {
1664 goto LBL_MARRAY;
1665 }
1666 }
1667
1668 /* set initial mode and bit cnt */
1669 mode = 0;
1670 bitcnt = 1;
1671 buf = 0;
1672 digidx = X->used - 1;
1673 bitcpy = 0;
1674 bitbuf = 0;
1675
1676 for (;;) {
1677 /* grab next digit as required */
1678 if (--bitcnt == 0) {
1679 /* if digidx == -1 we are out of digits so break */
1680 if (digidx == -1) {
1681 break;
1682 }
1683 /* read next digit and reset bitcnt */
1684 buf = X->dp[digidx--];
1685 bitcnt = (int32)DIGIT_BIT;
1686 }
1687
1688 /* grab the next msb from the exponent */
1689 y = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1;
1690 buf <<= (pstm_digit)1;
1691/*
1692 If the bit is zero and mode == 0 then we ignore it.
1693 These represent the leading zero bits before the first 1 bit
1694 in the exponent. Technically this opt is not required but it
1695 does lower the # of trivial squaring/reductions used
1696*/
1697 if (mode == 0 && y == 0) {
1698 continue;
1699 }
1700
1701 /* if the bit is zero and mode == 1 then we square */
1702 if (mode == 1 && y == 0) {
1703 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1704 PSTM_OKAY) {
1705 goto LBL_MARRAY;
1706 }
1707 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1708 != PSTM_OKAY) {
1709 goto LBL_MARRAY;
1710 }
1711 continue;
1712 }
1713
1714 /* else we add it to the window */
1715 bitbuf |= (y << (winsize - ++bitcpy));
1716 mode = 2;
1717
1718 if (bitcpy == winsize) {
1719 /* ok window is filled so square as required and mul square first */
1720 for (x = 0; x < winsize; x++) {
1721 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1722 PSTM_OKAY) {
1723 goto LBL_MARRAY;
1724 }
1725 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1726 paDlen)) != PSTM_OKAY) {
1727 goto LBL_MARRAY;
1728 }
1729 }
1730
1731 /* then multiply */
1732 if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD,
1733 paDlen)) != PSTM_OKAY) {
1734 goto LBL_MARRAY;
1735 }
1736 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1737 != PSTM_OKAY) {
1738 goto LBL_MARRAY;
1739 }
1740
1741 /* empty window and reset */
1742 bitcpy = 0;
1743 bitbuf = 0;
1744 mode = 1;
1745 }
1746 }
1747
1748 /* if bits remain then square/multiply */
1749 if (mode == 2 && bitcpy > 0) {
1750 /* square then multiply if the bit is set */
1751 for (x = 0; x < bitcpy; x++) {
1752 if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
1753 PSTM_OKAY) {
1754 goto LBL_MARRAY;
1755 }
1756 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
1757 != PSTM_OKAY) {
1758 goto LBL_MARRAY;
1759 }
1760
1761 /* get next bit of the window */
1762 bitbuf <<= 1;
1763 if ((bitbuf & (1 << winsize)) != 0) {
1764 /* then multiply */
1765 if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen))
1766 != PSTM_OKAY) {
1767 goto LBL_MARRAY;
1768 }
1769 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
1770 paDlen)) != PSTM_OKAY) {
1771 goto LBL_MARRAY;
1772 }
1773 }
1774 }
1775 }
1776/*
1777 Fix up result if Montgomery reduction is used recall that any value in a
1778 Montgomery system is actually multiplied by R mod n. So we have to reduce
1779 one more time to cancel out the factor of R.
1780*/
1781 if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) !=
1782 PSTM_OKAY) {
1783 goto LBL_MARRAY;
1784 }
1785 /* swap res with Y */
1786 if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) {
1787 goto LBL_MARRAY;
1788 }
1789 err = PSTM_OKAY;
1790LBL_MARRAY:
1791 for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
1792 pstm_clear(&M[x]);
1793 }
1794LBL_PAD:psFree(paD, pool);
1795LBL_M: pstm_clear(&M[1]);
1796LBL_RES:pstm_clear(&res);
1797 return err;
1798}
1799
1800/******************************************************************************/
1801/*
1802
1803*/
1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1805{
1806 int32 res;
1807 int16 sa, sb;
1808
1809 /* get sign of both inputs */
1810 sa = a->sign;
1811 sb = b->sign;
1812
1813 /* handle two cases, not four */
1814 if (sa == sb) {
1815 /* both positive or both negative, add their mags, copy the sign */
1816 c->sign = sa;
1817 if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
1818 return res;
1819 }
1820 } else {
1821/*
1822 one positive, the other negative
1823 subtract the one with the greater magnitude from the one of the lesser
1824 magnitude. The result gets the sign of the one with the greater mag.
1825 */
1826 if (pstm_cmp_mag (a, b) == PSTM_LT) {
1827 c->sign = sb;
1828 if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
1829 return res;
1830 }
1831 } else {
1832 c->sign = sa;
1833 if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
1834 return res;
1835 }
1836 }
1837 }
1838 return PS_SUCCESS;
1839}
1840
1841/******************************************************************************/
1842/*
1843 reverse an array, used for radix code
1844*/
1845static void pstm_reverse (unsigned char *s, int16 len)
1846{
1847 int32 ix, iy;
1848 unsigned char t;
1849
1850 ix = 0;
1851 iy = len - 1;
1852 while (ix < iy) {
1853 t = s[ix];
1854 s[ix] = s[iy];
1855 s[iy] = t;
1856 ++ix;
1857 --iy;
1858 }
1859}
1860/******************************************************************************/
1861/*
1862 No reverse. Useful in some of the EIP-154 PKA stuff where special byte
1863 order seems to come into play more often
1864*/
1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1866{
1867 int32 res;
1868 int16 x;
1869 pstm_int t = { 0 };
1870
1871 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1872 return res;
1873 }
1874
1875 x = 0;
1876 while (pstm_iszero (&t) == 0) {
1877 b[x++] = (unsigned char) (t.dp[0] & 255);
1878 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1879 pstm_clear(&t);
1880 return res;
1881 }
1882 }
1883 pstm_clear(&t);
1884 return PS_SUCCESS;
1885}
1886/******************************************************************************/
1887/*
1888
1889*/
1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1891{
1892 int32 res;
1893 int16 x;
1894 pstm_int t = { 0 };
1895
1896 if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
1897 return res;
1898 }
1899
1900 x = 0;
1901 while (pstm_iszero (&t) == 0) {
1902 b[x++] = (unsigned char) (t.dp[0] & 255);
1903 if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
1904 pstm_clear(&t);
1905 return res;
1906 }
1907 }
1908 pstm_reverse (b, x);
1909 pstm_clear(&t);
1910 return PS_SUCCESS;
1911}
1912
1913/******************************************************************************/
1914/*
1915 compare against a single digit
1916*/
1917int32 pstm_cmp_d(pstm_int *a, pstm_digit b)
1918{
1919 /* compare based on sign */
1920 if ((b && a->used == 0) || a->sign == PSTM_NEG) {
1921 return PSTM_LT;
1922 }
1923
1924 /* compare based on magnitude */
1925 if (a->used > 1) {
1926 return PSTM_GT;
1927 }
1928
1929 /* compare the only digit of a to b */
1930 if (a->dp[0] > b) {
1931 return PSTM_GT;
1932 } else if (a->dp[0] < b) {
1933 return PSTM_LT;
1934 } else {
1935 return PSTM_EQ;
1936 }
1937}
1938
1939/*
1940 Need invmod for ECC and also private key loading for hardware crypto
1941 in cases where dQ > dP. The values must be switched and a new qP must be
1942 calculated using this function
1943*/
1944//bbox: pool unused
1945#define pstm_invmod_slow(pool, a, b, c) \
1946 pstm_invmod_slow( a, b, c)
1947static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b,
1948 pstm_int * c)
1949{
1950 pstm_int x, y, u, v, A, B, C, D;
1951 int32 res;
1952
1953 /* b cannot be negative */
1954 if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) {
1955 return PS_LIMIT_FAIL;
1956 }
1957
1958 /* init temps */
1959 if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) {
1960 return PS_MEM_FAIL;
1961 }
1962
1963 /* x = a, y = b */
1964 if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) {
1965 goto LBL_X;
1966 }
1967
1968 if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) {
1969 goto LBL_X;
1970 }
1971
1972 /* 2. [modified] if x,y are both even then return an error! */
1973 if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) {
1974 res = PS_FAILURE;
1975 goto LBL_Y;
1976 }
1977
1978 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
1979 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
1980 goto LBL_Y;
1981 }
1982 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
1983 goto LBL_U;
1984 }
1985
1986 if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) {
1987 goto LBL_V;
1988 }
1989
1990 if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) {
1991 goto LBL_A;
1992 }
1993 pstm_set (&A, 1);
1994 pstm_set (&D, 1);
1995
1996 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
1997 goto LBL_D;
1998 }
1999 if ((res = pstm_init(pool, &C)) != PSTM_OKAY) {
2000 goto LBL_B;
2001 }
2002
2003top:
2004 /* 4. while u is even do */
2005 while (pstm_iseven (&u) == 1) {
2006 /* 4.1 u = u/2 */
2007 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2008 goto LBL_C;
2009 }
2010
2011 /* 4.2 if A or B is odd then */
2012 if (pstm_isodd (&A) == 1 || pstm_isodd (&B) == 1) {
2013 /* A = (A+y)/2, B = (B-x)/2 */
2014 if ((res = pstm_add (&A, &y, &A)) != PSTM_OKAY) {
2015 goto LBL_C;
2016 }
2017 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2018 goto LBL_C;
2019 }
2020 }
2021 /* A = A/2, B = B/2 */
2022 if ((res = pstm_div_2 (&A, &A)) != PSTM_OKAY) {
2023 goto LBL_C;
2024 }
2025 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2026 goto LBL_C;
2027 }
2028 }
2029
2030 /* 5. while v is even do */
2031 while (pstm_iseven (&v) == 1) {
2032 /* 5.1 v = v/2 */
2033 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2034 goto LBL_C;
2035 }
2036
2037 /* 5.2 if C or D is odd then */
2038 if (pstm_isodd (&C) == 1 || pstm_isodd (&D) == 1) {
2039 /* C = (C+y)/2, D = (D-x)/2 */
2040 if ((res = pstm_add (&C, &y, &C)) != PSTM_OKAY) {
2041 goto LBL_C;
2042 }
2043 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2044 goto LBL_C;
2045 }
2046 }
2047 /* C = C/2, D = D/2 */
2048 if ((res = pstm_div_2 (&C, &C)) != PSTM_OKAY) {
2049 goto LBL_C;
2050 }
2051 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2052 goto LBL_C;
2053 }
2054 }
2055
2056 /* 6. if u >= v then */
2057 if (pstm_cmp (&u, &v) != PSTM_LT) {
2058 /* u = u - v, A = A - C, B = B - D */
2059 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2060 goto LBL_C;
2061 }
2062 if ((res = pstm_sub (&A, &C, &A)) != PSTM_OKAY) {
2063 goto LBL_C;
2064 }
2065 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2066 goto LBL_C;
2067 }
2068 } else {
2069 /* v - v - u, C = C - A, D = D - B */
2070 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2071 goto LBL_C;
2072 }
2073 if ((res = pstm_sub (&C, &A, &C)) != PSTM_OKAY) {
2074 goto LBL_C;
2075 }
2076 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2077 goto LBL_C;
2078 }
2079 }
2080
2081 /* if not zero goto step 4 */
2082 if (pstm_iszero (&u) == 0)
2083 goto top;
2084
2085 /* now a = C, b = D, gcd == g*v */
2086
2087 /* if v != 1 then there is no inverse */
2088 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2089 res = PS_FAILURE;
2090 goto LBL_C;
2091 }
2092
2093 /* if its too low */
2094 while (pstm_cmp_d(&C, 0) == PSTM_LT) {
2095 if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) {
2096 goto LBL_C;
2097 }
2098 }
2099
2100 /* too big */
2101 while (pstm_cmp_mag(&C, b) != PSTM_LT) {
2102 if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) {
2103 goto LBL_C;
2104 }
2105 }
2106
2107 /* C is now the inverse */
2108 if ((res = pstm_copy(&C, c)) != PSTM_OKAY) {
2109 goto LBL_C;
2110 }
2111 res = PSTM_OKAY;
2112
2113LBL_C: pstm_clear(&C);
2114LBL_D: pstm_clear(&D);
2115LBL_B: pstm_clear(&B);
2116LBL_A: pstm_clear(&A);
2117LBL_V: pstm_clear(&v);
2118LBL_U: pstm_clear(&u);
2119LBL_Y: pstm_clear(&y);
2120LBL_X: pstm_clear(&x);
2121
2122 return res;
2123}
2124
2125/* c = 1/a (mod b) for odd b only */
2126int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
2127{
2128 pstm_int x, y, u, v, B, D;
2129 int32 res;
2130 uint16 neg, sanity;
2131
2132 /* 2. [modified] b must be odd */
2133 if (pstm_iseven (b) == 1) {
2134 return pstm_invmod_slow(pool, a,b,c);
2135 }
2136
2137 /* x == modulus, y == value to invert */
2138 if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) {
2139 return res;
2140 }
2141
2142 if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) {
2143 goto LBL_X;
2144 }
2145
2146 /* we need y = |a| */
2147 pstm_abs(a, &y);
2148
2149 /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
2150 if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
2151 goto LBL_Y;
2152 }
2153 if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
2154 goto LBL_U;
2155 }
2156 if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
2157 goto LBL_V;
2158 }
2159 if ((res = pstm_init(pool, &D)) != PSTM_OKAY) {
2160 goto LBL_B;
2161 }
2162
2163 pstm_set (&D, 1);
2164
2165 sanity = 0;
2166top:
2167 /* 4. while u is even do */
2168 while (pstm_iseven (&u) == 1) {
2169 /* 4.1 u = u/2 */
2170 if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
2171 goto LBL_D;
2172 }
2173
2174 /* 4.2 if B is odd then */
2175 if (pstm_isodd (&B) == 1) {
2176 if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
2177 goto LBL_D;
2178 }
2179 }
2180 /* B = B/2 */
2181 if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
2182 goto LBL_D;
2183 }
2184 }
2185
2186 /* 5. while v is even do */
2187 while (pstm_iseven (&v) == 1) {
2188 /* 5.1 v = v/2 */
2189 if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
2190 goto LBL_D;
2191 }
2192 /* 5.2 if D is odd then */
2193 if (pstm_isodd (&D) == 1) {
2194 /* D = (D-x)/2 */
2195 if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
2196 goto LBL_D;
2197 }
2198 }
2199 /* D = D/2 */
2200 if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
2201 goto LBL_D;
2202 }
2203 }
2204
2205 /* 6. if u >= v then */
2206 if (pstm_cmp (&u, &v) != PSTM_LT) {
2207 /* u = u - v, B = B - D */
2208 if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
2209 goto LBL_D;
2210 }
2211 if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
2212 goto LBL_D;
2213 }
2214 } else {
2215 /* v - v - u, D = D - B */
2216 if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
2217 goto LBL_D;
2218 }
2219 if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
2220 goto LBL_D;
2221 }
2222 }
2223
2224 /* if not zero goto step 4 */
2225 if (sanity++ > 1000) {
2226 res = PS_LIMIT_FAIL;
2227 goto LBL_D;
2228 }
2229 if (pstm_iszero (&u) == 0) {
2230 goto top;
2231 }
2232
2233 /* now a = C, b = D, gcd == g*v */
2234
2235 /* if v != 1 then there is no inverse */
2236 if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
2237 res = PS_FAILURE;
2238 goto LBL_D;
2239 }
2240
2241 /* b is now the inverse */
2242 neg = a->sign;
2243 while (D.sign == PSTM_NEG) {
2244 if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) {
2245 goto LBL_D;
2246 }
2247 }
2248 if ((res = pstm_copy (&D, c)) != PSTM_OKAY) {
2249 goto LBL_D;
2250 }
2251 c->sign = neg;
2252 res = PSTM_OKAY;
2253
2254LBL_D: pstm_clear(&D);
2255LBL_B: pstm_clear(&B);
2256LBL_V: pstm_clear(&v);
2257LBL_U: pstm_clear(&u);
2258LBL_Y: pstm_clear(&y);
2259LBL_X: pstm_clear(&x);
2260 return res;
2261}
2262#endif /* !DISABLE_PSTM */
2263/******************************************************************************/
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h
new file mode 100644
index 000000000..3a0fd8ce6
--- /dev/null
+++ b/networking/tls_pstm.h
@@ -0,0 +1,286 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
7 * Changes are flagged with //bbox
8 */
9
10/**
11 * @file pstm.h
12 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
13 *
14 * multiple-precision integer library.
15 */
16/*
17 * Copyright (c) 2013-2015 INSIDE Secure Corporation
18 * Copyright (c) PeerSec Networks, 2002-2011
19 * All Rights Reserved
20 *
21 * The latest version of this code is available at http://www.matrixssl.org
22 *
23 * This software is open source; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * This General Public License does NOT permit incorporating this software
29 * into proprietary programs. If you are unable to comply with the GPL, a
30 * commercial license for this software may be purchased from INSIDE at
31 * http://www.insidesecure.com/eng/Company/Locations
32 *
33 * This program is distributed in WITHOUT ANY WARRANTY; without even the
34 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
35 * See the GNU General Public License for more details.
36 *
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 * http://www.gnu.org/copyleft/gpl.html
41 */
42/******************************************************************************/
43
44#ifndef _h_PSTMATH
45#define _h_PSTMATH
46#ifndef DISABLE_PSTM
47
48/* Define this here to avoid including circular limits.h on some platforms */
49#ifndef CHAR_BIT
50#define CHAR_BIT 8
51#endif
52
53/******************************************************************************/
54/*
55 If native 64 bit integers are not supported, we do not support 32x32->64
56 in hardware, so we must set the 16 bit flag to produce 16x16->32 products.
57*/
58#ifndef HAVE_NATIVE_INT64
59 #define PSTM_16BIT
60#endif /* ! HAVE_NATIVE_INT64 */
61
62/******************************************************************************/
63/*
64 Some default configurations.
65
66 pstm_word should be the largest value the processor can hold as the product
67 of a multiplication. Most platforms support a 32x32->64 MAC instruction,
68 so 64bits is the default pstm_word size.
69 pstm_digit should be half the size of pstm_word
70 */
71#ifdef PSTM_8BIT
72/* 8-bit digits, 16-bit word products */
73 typedef unsigned char pstm_digit;
74 typedef unsigned short pstm_word;
75 #define DIGIT_BIT 8
76
77#elif defined(PSTM_16BIT)
78/* 16-bit digits, 32-bit word products */
79 typedef unsigned short pstm_digit;
80 typedef unsigned long pstm_word;
81 #define DIGIT_BIT 16
82
83#elif defined(PSTM_64BIT)
84/* 64-bit digits, 128-bit word products */
85 #ifndef __GNUC__
86 #error "64bit digits requires GCC"
87 #endif
88 typedef unsigned long pstm_digit;
89 typedef unsigned long pstm_word __attribute__ ((mode(TI)));
90 #define DIGIT_BIT 64
91
92#else
93/* This is the default case, 32-bit digits, 64-bit word products */
94 typedef uint32 pstm_digit;
95 typedef uint64 pstm_word;
96 #define DIGIT_BIT 32
97 #define PSTM_32BIT
98#endif /* digit and word size */
99
100#define PSTM_MASK (pstm_digit)(-1)
101#define PSTM_DIGIT_MAX PSTM_MASK
102
103/******************************************************************************/
104/*
105 equalities
106 */
107#define PSTM_LT -1 /* less than */
108#define PSTM_EQ 0 /* equal to */
109#define PSTM_GT 1 /* greater than */
110
111#define PSTM_ZPOS 0 /* positive integer */
112#define PSTM_NEG 1 /* negative */
113
114#define PSTM_OKAY PS_SUCCESS
115#define PSTM_MEM PS_MEM_FAIL
116
117/******************************************************************************/
118/*
119 Various build options
120 */
121#define PSTM_DEFAULT_INIT 64 /* default (64) digits of allocation */
122#define PSTM_MAX_SIZE 4096
123
124typedef struct {
125 int16 used, alloc, sign;
126 pstm_digit *dp;
127//bbox psPool_t *pool;
128} pstm_int;
129
130/******************************************************************************/
131/*
132 Operations on large integers
133 */
134#define pstm_iszero(a) (((a)->used == 0) ? PS_TRUE : PS_FALSE)
135#define pstm_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? PS_TRUE : PS_FALSE)
136#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE)
137#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; }
138
139extern void pstm_set(pstm_int *a, pstm_digit b);
140
141extern void pstm_zero(pstm_int * a);
142
143//bbox: pool unused
144#define pstm_init(pool, a) \
145 pstm_init( a)
146extern int32 pstm_init(psPool_t *pool, pstm_int * a);
147
148//bbox: pool unused
149#define pstm_init_size(pool, a, size) \
150 pstm_init_size( a, size)
151extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size);
152
153//bbox: pool unused
154#define pstm_init_copy(pool, a, b, toSqr) \
155 pstm_init_copy( a, b, toSqr)
156extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b,
157 int16 toSqr);
158
159extern int16 pstm_count_bits (pstm_int * a);
160
161//bbox: pool unused
162#define pstm_init_for_read_unsigned_bin(pool, a, len) \
163 pstm_init_for_read_unsigned_bin( a, len)
164extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a,
165 uint32 len);
166
167extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c);
168
169extern int32 pstm_unsigned_bin_size(pstm_int *a);
170
171extern int32 pstm_copy(pstm_int * a, pstm_int * b);
172
173extern void pstm_exch(pstm_int * a, pstm_int * b);
174
175extern void pstm_clear(pstm_int * a);
176
177extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
178 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6,
179 pstm_int *mp7);
180
181extern int32 pstm_grow(pstm_int * a, int16 size);
182
183extern void pstm_clamp(pstm_int * a);
184
185extern int32 pstm_cmp(pstm_int * a, pstm_int * b);
186
187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b);
188
189extern void pstm_rshd(pstm_int *a, int16 x);
190
191extern int32 pstm_lshd(pstm_int * a, int16 b);
192
193//bbox: pool unused
194#define pstm_div(pool, a, b, c, d) \
195 pstm_div( a, b, c, d)
196extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
197 pstm_int *d);
198
199//bbox: pool unused
200#define pstm_div_2d(pool, a, b, c, d) \
201 pstm_div_2d( a, b, c, d)
202extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int16 b, pstm_int *c,
203 pstm_int *d);
204
205extern int32 pstm_div_2(pstm_int * a, pstm_int * b);
206
207extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c);
208
209extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c);
210
211//bbox: pool unused
212#define pstm_sub_d(pool, a, b, c) \
213 pstm_sub_d( a, b, c)
214extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c);
215
216extern int32 pstm_mul_2(pstm_int * a, pstm_int * b);
217
218//bbox: pool unused
219#define pstm_mod(pool, a, b, c) \
220 pstm_mod( a, b, c)
221extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c);
222
223//bbox: pool unused
224#define pstm_mulmod(pool, a, b, c, d) \
225 pstm_mulmod( a, b, c, d)
226extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
227 pstm_int *d);
228
229//bbox: pool unused
230#define pstm_exptmod(pool, G, X, P, Y) \
231 pstm_exptmod( G, X, P, Y)
232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
233 pstm_int *Y);
234
235extern int32 pstm_2expt(pstm_int *a, int16 b);
236
237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c);
238
239//bbox: pool unused
240#define pstm_to_unsigned_bin(pool, a, b) \
241 pstm_to_unsigned_bin( a, b)
242extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a,
243 unsigned char *b);
244
245//bbox: pool unused
246#define pstm_to_unsigned_bin_nr(pool, a, b) \
247 pstm_to_unsigned_bin_nr( a, b)
248extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a,
249 unsigned char *b);
250
251extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho);
252
253//bbox: pool unused
254#define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \
255 pstm_montgomery_reduce( a, m, mp, paD, paDlen)
256extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
257 pstm_digit mp, pstm_digit *paD, uint32 paDlen);
258
259#define pstm_mul_comba(pool, A, B, C, paD, paDlen) \
260 pstm_mul_comba( A, B, C, paD, paDlen)
261extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
262 pstm_int *C, pstm_digit *paD, uint32 paDlen);
263
264//bbox: pool unused
265#define pstm_sqr_comba(pool, A, B, paD, paDlen) \
266 pstm_sqr_comba( A, B, paD, paDlen)
267extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
268 pstm_digit *paD, uint32 paDlen);
269
270extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b);
271
272extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b);
273
274extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c);
275
276//bbox: pool unused
277#define pstm_invmod(pool, a, b, c) \
278 pstm_invmod( a, b, c)
279extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b,
280 pstm_int * c);
281
282#else /* DISABLE_PSTM */
283 typedef int32 pstm_int;
284#endif /* !DISABLE_PSTM */
285#endif /* _h_PSTMATH */
286
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
new file mode 100644
index 000000000..dc2fe0a48
--- /dev/null
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -0,0 +1,427 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_montgomery_reduce.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision Montgomery Reduction.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51
52#if defined(PSTM_X86)
53/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
54#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
55#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
56#endif
57//#pragma message ("Using 32 bit x86 Assembly Optimizations")
58
59#define MONT_START
60#define MONT_FINI
61#define LOOP_END
62#define LOOP_START \
63 mu = c[x] * mp
64
65#define INNERMUL \
66asm( \
67 "movl %5,%%eax \n\t" \
68 "mull %4 \n\t" \
69 "addl %1,%%eax \n\t" \
70 "adcl $0,%%edx \n\t" \
71 "addl %%eax,%0 \n\t" \
72 "adcl $0,%%edx \n\t" \
73 "movl %%edx,%1 \n\t" \
74:"=g"(_c[LO]), "=r"(cy) \
75:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \
76: "%eax", "%edx", "%cc")
77
78#define PROPCARRY \
79asm( \
80 "addl %1,%0 \n\t" \
81 "setb %%al \n\t" \
82 "movzbl %%al,%1 \n\t" \
83:"=g"(_c[LO]), "=r"(cy) \
84:"0"(_c[LO]), "1"(cy) \
85: "%eax", "%cc")
86
87/******************************************************************************/
88#elif defined(PSTM_X86_64)
89/* x86-64 optimized */
90#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
91#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
92#endif
93//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
94
95#define MONT_START
96#define MONT_FINI
97#define LOOP_END
98#define LOOP_START \
99mu = c[x] * mp
100
101#define INNERMUL \
102asm( \
103 "movq %5,%%rax \n\t" \
104 "mulq %4 \n\t" \
105 "addq %1,%%rax \n\t" \
106 "adcq $0,%%rdx \n\t" \
107 "addq %%rax,%0 \n\t" \
108 "adcq $0,%%rdx \n\t" \
109 "movq %%rdx,%1 \n\t" \
110 :"=g"(_c[LO]), "=r"(cy) \
111 :"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
112 : "%rax", "%rdx", "cc")
113
114#define INNERMUL8 \
115asm( \
116 "movq 0(%5),%%rax \n\t" \
117 "movq 0(%2),%%r10 \n\t" \
118 "movq 0x8(%5),%%r11 \n\t" \
119 "mulq %4 \n\t" \
120 "addq %%r10,%%rax \n\t" \
121 "adcq $0,%%rdx \n\t" \
122 "movq 0x8(%2),%%r10 \n\t" \
123 "addq %3,%%rax \n\t" \
124 "adcq $0,%%rdx \n\t" \
125 "movq %%rax,0(%0) \n\t" \
126 "movq %%rdx,%1 \n\t" \
127 \
128 "movq %%r11,%%rax \n\t" \
129 "movq 0x10(%5),%%r11 \n\t" \
130 "mulq %4 \n\t" \
131 "addq %%r10,%%rax \n\t" \
132 "adcq $0,%%rdx \n\t" \
133 "movq 0x10(%2),%%r10 \n\t" \
134 "addq %3,%%rax \n\t" \
135 "adcq $0,%%rdx \n\t" \
136 "movq %%rax,0x8(%0) \n\t" \
137 "movq %%rdx,%1 \n\t" \
138 \
139 "movq %%r11,%%rax \n\t" \
140 "movq 0x18(%5),%%r11 \n\t" \
141 "mulq %4 \n\t" \
142 "addq %%r10,%%rax \n\t" \
143 "adcq $0,%%rdx \n\t" \
144 "movq 0x18(%2),%%r10 \n\t" \
145 "addq %3,%%rax \n\t" \
146 "adcq $0,%%rdx \n\t" \
147 "movq %%rax,0x10(%0) \n\t" \
148 "movq %%rdx,%1 \n\t" \
149 \
150 "movq %%r11,%%rax \n\t" \
151 "movq 0x20(%5),%%r11 \n\t" \
152 "mulq %4 \n\t" \
153 "addq %%r10,%%rax \n\t" \
154 "adcq $0,%%rdx \n\t" \
155 "movq 0x20(%2),%%r10 \n\t" \
156 "addq %3,%%rax \n\t" \
157 "adcq $0,%%rdx \n\t" \
158 "movq %%rax,0x18(%0) \n\t" \
159 "movq %%rdx,%1 \n\t" \
160 \
161 "movq %%r11,%%rax \n\t" \
162 "movq 0x28(%5),%%r11 \n\t" \
163 "mulq %4 \n\t" \
164 "addq %%r10,%%rax \n\t" \
165 "adcq $0,%%rdx \n\t" \
166 "movq 0x28(%2),%%r10 \n\t" \
167 "addq %3,%%rax \n\t" \
168 "adcq $0,%%rdx \n\t" \
169 "movq %%rax,0x20(%0) \n\t" \
170 "movq %%rdx,%1 \n\t" \
171 \
172 "movq %%r11,%%rax \n\t" \
173 "movq 0x30(%5),%%r11 \n\t" \
174 "mulq %4 \n\t" \
175 "addq %%r10,%%rax \n\t" \
176 "adcq $0,%%rdx \n\t" \
177 "movq 0x30(%2),%%r10 \n\t" \
178 "addq %3,%%rax \n\t" \
179 "adcq $0,%%rdx \n\t" \
180 "movq %%rax,0x28(%0) \n\t" \
181 "movq %%rdx,%1 \n\t" \
182 \
183 "movq %%r11,%%rax \n\t" \
184 "movq 0x38(%5),%%r11 \n\t" \
185 "mulq %4 \n\t" \
186 "addq %%r10,%%rax \n\t" \
187 "adcq $0,%%rdx \n\t" \
188 "movq 0x38(%2),%%r10 \n\t" \
189 "addq %3,%%rax \n\t" \
190 "adcq $0,%%rdx \n\t" \
191 "movq %%rax,0x30(%0) \n\t" \
192 "movq %%rdx,%1 \n\t" \
193 \
194 "movq %%r11,%%rax \n\t" \
195 "mulq %4 \n\t" \
196 "addq %%r10,%%rax \n\t" \
197 "adcq $0,%%rdx \n\t" \
198 "addq %3,%%rax \n\t" \
199 "adcq $0,%%rdx \n\t" \
200 "movq %%rax,0x38(%0) \n\t" \
201 "movq %%rdx,%1 \n\t" \
202 \
203 :"=r"(_c), "=r"(cy) \
204 : "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\
205 : "%rax", "%rdx", "%r10", "%r11", "cc")
206
207#define PROPCARRY \
208asm( \
209 "addq %1,%0 \n\t" \
210 "setb %%al \n\t" \
211 "movzbq %%al,%1 \n\t" \
212 :"=g"(_c[LO]), "=r"(cy) \
213 :"0"(_c[LO]), "1"(cy) \
214 : "%rax", "cc")
215
216/******************************************************************************/
217#elif defined(PSTM_ARM)
218
219#define MONT_START
220#define MONT_FINI
221#define LOOP_END
222#define LOOP_START \
223mu = c[x] * mp
224
225#ifdef __thumb2__
226//#pragma message ("Using 32 bit ARM Thumb2 Assembly Optimizations")
227#define INNERMUL \
228asm( \
229 " LDR r0,%1 \n\t" \
230 " ADDS r0,r0,%0 \n\t" \
231 " ITE CS \n\t" \
232 " MOVCS %0,#1 \n\t" \
233 " MOVCC %0,#0 \n\t" \
234 " UMLAL r0,%0,%3,%4 \n\t" \
235 " STR r0,%1 \n\t" \
236 :"=r"(cy),"=m"(_c[0])\
237 :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\
238 :"r0","%cc");
239#define PROPCARRY \
240asm( \
241 " LDR r0,%1 \n\t" \
242 " ADDS r0,r0,%0 \n\t" \
243 " STR r0,%1 \n\t" \
244 " ITE CS \n\t" \
245 " MOVCS %0,#1 \n\t" \
246 " MOVCC %0,#0 \n\t" \
247 :"=r"(cy),"=m"(_c[0])\
248 :"0"(cy),"m"(_c[0])\
249 :"r0","%cc");
250#else /* Non-Thumb2 code */
251//#pragma message ("Using 32 bit ARM Assembly Optimizations")
252#define INNERMUL \
253asm( \
254 " LDR r0,%1 \n\t" \
255 " ADDS r0,r0,%0 \n\t" \
256 " MOVCS %0,#1 \n\t" \
257 " MOVCC %0,#0 \n\t" \
258 " UMLAL r0,%0,%3,%4 \n\t" \
259 " STR r0,%1 \n\t" \
260 :"=r"(cy),"=m"(_c[0])\
261 :"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0])\
262 :"r0","%cc");
263#define PROPCARRY \
264asm( \
265 " LDR r0,%1 \n\t" \
266 " ADDS r0,r0,%0 \n\t" \
267 " STR r0,%1 \n\t" \
268 " MOVCS %0,#1 \n\t" \
269 " MOVCC %0,#0 \n\t" \
270 :"=r"(cy),"=m"(_c[0])\
271 :"0"(cy),"m"(_c[0])\
272 :"r0","%cc");
273#endif /* __thumb2__ */
274
275
276/******************************************************************************/
277#elif defined(PSTM_MIPS)
278/* MIPS32 */
279//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
280#define MONT_START
281#define MONT_FINI
282#define LOOP_END
283#define LOOP_START \
284mu = c[x] * mp
285
286#define INNERMUL \
287asm( \
288 " multu %3,%4 \n\t" \
289 " mflo $12 \n\t" \
290 " mfhi $13 \n\t" \
291 " addu $12,$12,%0 \n\t" \
292 " sltu $10,$12,%0 \n\t" \
293 " addu $13,$13,$10 \n\t" \
294 " lw $10,%1 \n\t" \
295 " addu $12,$12,$10 \n\t" \
296 " sltu $10,$12,$10 \n\t" \
297 " addu %0,$13,$10 \n\t" \
298 " sw $12,%1 \n\t" \
299 :"=r"(cy),"=m"(_c[0])\
300 :"r"(cy),"r"(mu),"r"(tmpm[0]),"r"(_c[0])\
301 :"$10","$12","$13")\
302; ++tmpm;
303
304#define PROPCARRY \
305asm( \
306 " lw $10,%1 \n\t" \
307 " addu $10,$10,%0 \n\t" \
308 " sw $10,%1 \n\t" \
309 " sltu %0,$10,%0 \n\t" \
310 :"=r"(cy),"=m"(_c[0])\
311 :"r"(cy),"r"(_c[0])\
312 :"$10");
313
314
315/******************************************************************************/
316#else
317
318/* ISO C code */
319#define MONT_START
320#define MONT_FINI
321#define LOOP_END
322#define LOOP_START \
323 mu = c[x] * mp
324
325#define INNERMUL \
326 do { pstm_word t; \
327 t = ((pstm_word)_c[0] + (pstm_word)cy) + \
328 (((pstm_word)mu) * ((pstm_word)*tmpm++)); \
329 _c[0] = (pstm_digit)t; \
330 cy = (pstm_digit)(t >> DIGIT_BIT); \
331 } while (0)
332
333#define PROPCARRY \
334 do { pstm_digit t = _c[0] += cy; cy = (t < cy); } while (0)
335
336#endif
337
338/******************************************************************************/
339
340#define LO 0
341
342/* computes x/R == x (mod N) via Montgomery Reduction */
343int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
344 pstm_digit mp, pstm_digit *paD, uint32 paDlen)
345{
346 pstm_digit *c, *_c, *tmpm, mu;
347 int32 oldused, x, y;
348 int16 pa;
349
350 pa = m->used;
351 if (pa > a->alloc) {
352 /* Sanity test for bad numbers. This will confirm no buffer overruns */
353 return PS_LIMIT_FAIL;
354 }
355
356 if (paD && paDlen >= (uint32)2*pa+1) {
357 c = paD;
358 memset(c, 0x0, paDlen);
359 } else {
360 c = xzalloc(2*pa+1);//bbox
361 }
362 /* copy the input */
363 oldused = a->used;
364 for (x = 0; x < oldused; x++) {
365 c[x] = a->dp[x];
366 }
367
368 MONT_START;
369
370 for (x = 0; x < pa; x++) {
371 pstm_digit cy = 0;
372 /* get Mu for this round */
373 LOOP_START;
374 _c = c + x;
375 tmpm = m->dp;
376 y = 0;
377#ifdef PSTM_X86_64
378 for (; y < (pa & ~7); y += 8) {
379 INNERMUL8;
380 _c += 8;
381 tmpm += 8;
382 }
383#endif /* PSTM_X86_64 */
384 for (; y < pa; y++) {
385 INNERMUL;
386 ++_c;
387 }
388 LOOP_END;
389 while (cy) {
390 PROPCARRY;
391 ++_c;
392 }
393 }
394
395 /* now copy out */
396 _c = c + pa;
397 tmpm = a->dp;
398 for (x = 0; x < pa+1; x++) {
399 *tmpm++ = *_c++;
400 }
401
402 for (; x < oldused; x++) {
403 *tmpm++ = 0;
404 }
405
406 MONT_FINI;
407
408 a->used = pa+1;
409 pstm_clamp(a);
410
411 /* reuse x as return code */
412 x = PSTM_OKAY;
413
414 /* if A >= m then A = A - m */
415 if (pstm_cmp_mag (a, m) != PSTM_LT) {
416 if (s_pstm_sub (a, m, a) != PSTM_OKAY) {
417 x = PS_MEM_FAIL;
418 }
419 }
420 if (paDlen < (uint32)2*pa+1) {
421 psFree(c, pool);
422 }
423 return x;
424}
425
426#endif /* !DISABLE_PSTM */
427/******************************************************************************/
diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c
new file mode 100644
index 000000000..47cbb9618
--- /dev/null
+++ b/networking/tls_pstm_mul_comba.c
@@ -0,0 +1,781 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_mul_comba.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision multiplication with Comba technique.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51#if defined(PSTM_X86)
52/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53#if !defined(__GNUC__) || !defined(__i386__) || !defined(PSTM_32BIT)
54#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55#endif
56//#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58/* anything you need at the start */
59#define COMBA_START
60
61/* clear the chaining variables */
62#define COMBA_CLEAR \
63 c0 = c1 = c2 = 0;
64
65/* forward the carry to the next digit */
66#define COMBA_FORWARD \
67 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
68
69/* store the first sum */
70#define COMBA_STORE(x) \
71 x = c0;
72
73/* store the second sum [carry] */
74#define COMBA_STORE2(x) \
75 x = c1;
76
77/* anything you need at the end */
78#define COMBA_FINI
79
80/* this should multiply i and j */
81#define MULADD(i, j) \
82asm( \
83 "movl %6,%%eax \n\t" \
84 "mull %7 \n\t" \
85 "addl %%eax,%0 \n\t" \
86 "adcl %%edx,%1 \n\t" \
87 "adcl $0,%2 \n\t" \
88 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
89
90/******************************************************************************/
91#elif defined(PSTM_X86_64)
92/* x86-64 optimized */
93#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
94#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
95#endif
96//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
97
98/* anything you need at the start */
99#define COMBA_START
100
101/* clear the chaining variables */
102#define COMBA_CLEAR \
103c0 = c1 = c2 = 0;
104
105/* forward the carry to the next digit */
106#define COMBA_FORWARD \
107do { c0 = c1; c1 = c2; c2 = 0; } while (0);
108
109/* store the first sum */
110#define COMBA_STORE(x) \
111x = c0;
112
113/* store the second sum [carry] */
114#define COMBA_STORE2(x) \
115x = c1;
116
117/* anything you need at the end */
118#define COMBA_FINI
119
120/* this should multiply i and j */
121#define MULADD(i, j) \
122asm ( \
123 "movq %6,%%rax \n\t" \
124 "mulq %7 \n\t" \
125 "addq %%rax,%0 \n\t" \
126 "adcq %%rdx,%1 \n\t" \
127 "adcq $0,%2 \n\t" \
128 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
129
130/******************************************************************************/
131#elif defined(PSTM_ARM)
132/* ARM code */
133//#pragma message ("Using 32 bit ARM Assembly Optimizations")
134
135#define COMBA_START
136
137#define COMBA_CLEAR \
138c0 = c1 = c2 = 0;
139
140#define COMBA_FORWARD \
141do { c0 = c1; c1 = c2; c2 = 0; } while (0);
142
143#define COMBA_STORE(x) \
144x = c0;
145
146#define COMBA_STORE2(x) \
147x = c1;
148
149#define COMBA_FINI
150
151#define MULADD(i, j) \
152asm( \
153 " UMULL r0,r1,%6,%7 \n\t" \
154 " ADDS %0,%0,r0 \n\t" \
155 " ADCS %1,%1,r1 \n\t" \
156 " ADC %2,%2,#0 \n\t" \
157 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
158
159/******************************************************************************/
160#elif defined(PSTM_MIPS)
161/* MIPS32 code */
162//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
163
164#define COMBA_START
165
166#define COMBA_CLEAR \
167c0 = c1 = c2 = 0;
168
169#define COMBA_FORWARD \
170do { c0 = c1; c1 = c2; c2 = 0; } while (0);
171
172#define COMBA_STORE(x) \
173x = c0;
174
175#define COMBA_STORE2(x) \
176x = c1;
177
178#define COMBA_FINI
179
180#define MULADD(i, j) \
181asm( \
182 " multu %6,%7 \n\t" \
183 " mflo $12 \n\t" \
184 " mfhi $13 \n\t" \
185 " addu %0,%0,$12 \n\t" \
186 " sltu $12,%0,$12 \n\t" \
187 " addu %1,%1,$13 \n\t" \
188 " sltu $13,%1,$13 \n\t" \
189 " addu %1,%1,$12 \n\t" \
190 " sltu $12,%1,$12 \n\t" \
191 " addu %2,%2,$13 \n\t" \
192 " addu %2,%2,$12 \n\t" \
193 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13");
194
195/******************************************************************************/
196#else
197
198#define COMBA_START
199
200#define COMBA_CLEAR \
201 c0 = c1 = c2 = 0;
202
203#define COMBA_FORWARD \
204 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
205
206#define COMBA_STORE(x) \
207 x = c0;
208
209#define COMBA_STORE2(x) \
210 x = c1;
211
212#define COMBA_FINI
213
214#define MULADD(i, j) \
215 do { pstm_word t; \
216 t = (pstm_word)c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
217 t = (pstm_word)c1 + (t >> DIGIT_BIT); \
218 c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
219 } while (0);
220
221#endif
222
223/******************************************************************************/
224/* generic PxQ multiplier */
225//bbox: pool unused
226#define pstm_mul_comba_gen(pool, A, B, C, paD, paDlen) \
227 pstm_mul_comba_gen( A, B, C, paD, paDlen)
228static int32 pstm_mul_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
229 pstm_int *C, pstm_digit *paD, uint32 paDlen)
230{
231 int16 paDfail, pa;
232 int32 ix, iy, iz, tx, ty;
233 pstm_digit c0, c1, c2, *tmpx, *tmpy, *dst;
234
235 COMBA_START;
236 COMBA_CLEAR;
237
238 paDfail = 0;
239 /* get size of output and trim */
240 pa = A->used + B->used;
241
242/*
243 If c is not large enough grow it and continue
244*/
245 if (C->alloc < pa) {
246 if (pstm_grow(C, pa) != PSTM_OKAY) {
247 return PS_MEM_FAIL;
248 }
249 }
250 if (paD != NULL) {
251 if (paDlen < (sizeof(pstm_digit) * pa)) {
252 paDfail = 1; /* have a paD but it's not large enough */
253 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
254 } else {
255 dst = paD;
256 memset(dst, 0x0, paDlen);
257 }
258 } else {
259 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
260 }
261
262 for (ix = 0; ix < pa; ix++) {
263 /* get offsets into the two bignums */
264 ty = min(ix, B->used-1);
265 tx = ix - ty;
266
267 /* setup temp aliases */
268 tmpx = A->dp + tx;
269 tmpy = B->dp + ty;
270/*
271 This is the number of times the loop will iterate, essentially it's
272 while (tx++ < a->used && ty-- >= 0) { ... }
273*/
274 iy = min(A->used-tx, ty+1);
275
276 /* execute loop */
277 COMBA_FORWARD;
278 for (iz = 0; iz < iy; ++iz) {
279 MULADD(*tmpx++, *tmpy--);
280 }
281
282 /* store term */
283 COMBA_STORE(dst[ix]);
284 }
285 COMBA_FINI;
286/*
287 setup dest
288 */
289 iy = C->used;
290 C->used = pa;
291 C->sign = A->sign ^ B->sign;
292 {
293 pstm_digit *tmpc;
294 tmpc = C->dp;
295 for (ix = 0; ix < pa; ix++) {
296 *tmpc++ = dst[ix];
297 }
298/*
299 clear unused digits [that existed in the old copy of c]
300 */
301 for (; ix < iy; ix++) {
302 *tmpc++ = 0;
303 }
304 }
305 pstm_clamp(C);
306
307 if ((paD == NULL) || (paDfail == 1)) {
308 psFree(dst, pool);
309 }
310
311 return PS_SUCCESS;
312}
313
314/******************************************************************************/
315#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
316static int32 pstm_mul_comba16(pstm_int *A, pstm_int *B, pstm_int *C)
317{
318 pstm_digit c0, c1, c2, at[32];
319
320 if (C->alloc < 32) {
321 if (pstm_grow(C, 32) != PSTM_OKAY) {
322 return PS_MEM_FAIL;
323 }
324 }
325 memcpy(at, A->dp, 16 * sizeof(pstm_digit));
326 memcpy(at+16, B->dp, 16 * sizeof(pstm_digit));
327
328 COMBA_START;
329
330 COMBA_CLEAR;
331 /* 0 */
332 MULADD(at[0], at[16]);
333 COMBA_STORE(C->dp[0]);
334 /* 1 */
335 COMBA_FORWARD;
336 MULADD(at[0], at[17]); MULADD(at[1], at[16]);
337 COMBA_STORE(C->dp[1]);
338 /* 2 */
339 COMBA_FORWARD;
340 MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]);
341 COMBA_STORE(C->dp[2]);
342 /* 3 */
343 COMBA_FORWARD;
344 MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]);
345 COMBA_STORE(C->dp[3]);
346 /* 4 */
347 COMBA_FORWARD;
348 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]);
349 COMBA_STORE(C->dp[4]);
350 /* 5 */
351 COMBA_FORWARD;
352 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]);
353 COMBA_STORE(C->dp[5]);
354 /* 6 */
355 COMBA_FORWARD;
356 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]);
357 COMBA_STORE(C->dp[6]);
358 /* 7 */
359 COMBA_FORWARD;
360 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]);
361 COMBA_STORE(C->dp[7]);
362 /* 8 */
363 COMBA_FORWARD;
364 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]);
365 COMBA_STORE(C->dp[8]);
366 /* 9 */
367 COMBA_FORWARD;
368 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]);
369 COMBA_STORE(C->dp[9]);
370 /* 10 */
371 COMBA_FORWARD;
372 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]);
373 COMBA_STORE(C->dp[10]);
374 /* 11 */
375 COMBA_FORWARD;
376 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]);
377 COMBA_STORE(C->dp[11]);
378 /* 12 */
379 COMBA_FORWARD;
380 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]);
381 COMBA_STORE(C->dp[12]);
382 /* 13 */
383 COMBA_FORWARD;
384 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]);
385 COMBA_STORE(C->dp[13]);
386 /* 14 */
387 COMBA_FORWARD;
388 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]);
389 COMBA_STORE(C->dp[14]);
390 /* 15 */
391 COMBA_FORWARD;
392 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]);
393 COMBA_STORE(C->dp[15]);
394 /* 16 */
395 COMBA_FORWARD;
396 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]);
397 COMBA_STORE(C->dp[16]);
398 /* 17 */
399 COMBA_FORWARD;
400 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]);
401 COMBA_STORE(C->dp[17]);
402 /* 18 */
403 COMBA_FORWARD;
404 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]);
405 COMBA_STORE(C->dp[18]);
406 /* 19 */
407 COMBA_FORWARD;
408 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]);
409 COMBA_STORE(C->dp[19]);
410 /* 20 */
411 COMBA_FORWARD;
412 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]);
413 COMBA_STORE(C->dp[20]);
414 /* 21 */
415 COMBA_FORWARD;
416 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]);
417 COMBA_STORE(C->dp[21]);
418 /* 22 */
419 COMBA_FORWARD;
420 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]);
421 COMBA_STORE(C->dp[22]);
422 /* 23 */
423 COMBA_FORWARD;
424 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]);
425 COMBA_STORE(C->dp[23]);
426 /* 24 */
427 COMBA_FORWARD;
428 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]);
429 COMBA_STORE(C->dp[24]);
430 /* 25 */
431 COMBA_FORWARD;
432 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]);
433 COMBA_STORE(C->dp[25]);
434 /* 26 */
435 COMBA_FORWARD;
436 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]);
437 COMBA_STORE(C->dp[26]);
438 /* 27 */
439 COMBA_FORWARD;
440 MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]);
441 COMBA_STORE(C->dp[27]);
442 /* 28 */
443 COMBA_FORWARD;
444 MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]);
445 COMBA_STORE(C->dp[28]);
446 /* 29 */
447 COMBA_FORWARD;
448 MULADD(at[14], at[31]); MULADD(at[15], at[30]);
449 COMBA_STORE(C->dp[29]);
450 /* 30 */
451 COMBA_FORWARD;
452 MULADD(at[15], at[31]);
453 COMBA_STORE(C->dp[30]);
454 COMBA_STORE2(C->dp[31]);
455 C->used = 32;
456 C->sign = A->sign ^ B->sign;
457 pstm_clamp(C);
458 COMBA_FINI;
459 return PSTM_OKAY;
460}
461#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
462
463
464#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
465static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C)
466{
467 pstm_digit c0, c1, c2, at[64];
468 int32 out_size;
469
470 if (C->alloc < 64) {
471 if (pstm_grow(C, 64) != PSTM_OKAY) {
472 return PS_MEM_FAIL;
473 }
474 }
475
476 out_size = A->used + B->used;
477 memcpy(at, A->dp, 32 * sizeof(pstm_digit));
478 memcpy(at+32, B->dp, 32 * sizeof(pstm_digit));
479 COMBA_START;
480
481 COMBA_CLEAR;
482 /* 0 */
483 MULADD(at[0], at[32]);
484 COMBA_STORE(C->dp[0]);
485 /* 1 */
486 COMBA_FORWARD;
487 MULADD(at[0], at[33]); MULADD(at[1], at[32]);
488 COMBA_STORE(C->dp[1]);
489 /* 2 */
490 COMBA_FORWARD;
491 MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]);
492 COMBA_STORE(C->dp[2]);
493 /* 3 */
494 COMBA_FORWARD;
495 MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]);
496 COMBA_STORE(C->dp[3]);
497 /* 4 */
498 COMBA_FORWARD;
499 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]);
500 COMBA_STORE(C->dp[4]);
501 /* 5 */
502 COMBA_FORWARD;
503 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]);
504 COMBA_STORE(C->dp[5]);
505 /* 6 */
506 COMBA_FORWARD;
507 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]);
508 COMBA_STORE(C->dp[6]);
509 /* 7 */
510 COMBA_FORWARD;
511 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]);
512 COMBA_STORE(C->dp[7]);
513 /* 8 */
514 COMBA_FORWARD;
515 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]);
516 COMBA_STORE(C->dp[8]);
517 /* 9 */
518 COMBA_FORWARD;
519 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]);
520 COMBA_STORE(C->dp[9]);
521 /* 10 */
522 COMBA_FORWARD;
523 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]);
524 COMBA_STORE(C->dp[10]);
525 /* 11 */
526 COMBA_FORWARD;
527 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]);
528 COMBA_STORE(C->dp[11]);
529 /* 12 */
530 COMBA_FORWARD;
531 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]);
532 COMBA_STORE(C->dp[12]);
533 /* 13 */
534 COMBA_FORWARD;
535 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]);
536 COMBA_STORE(C->dp[13]);
537 /* 14 */
538 COMBA_FORWARD;
539 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]);
540 COMBA_STORE(C->dp[14]);
541 /* 15 */
542 COMBA_FORWARD;
543 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]);
544 COMBA_STORE(C->dp[15]);
545 /* 16 */
546 COMBA_FORWARD;
547 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]);
548 COMBA_STORE(C->dp[16]);
549 /* 17 */
550 COMBA_FORWARD;
551 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]);
552 COMBA_STORE(C->dp[17]);
553 /* 18 */
554 COMBA_FORWARD;
555 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]);
556 COMBA_STORE(C->dp[18]);
557 /* 19 */
558 COMBA_FORWARD;
559 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]);
560 COMBA_STORE(C->dp[19]);
561 /* 20 */
562 COMBA_FORWARD;
563 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]);
564 COMBA_STORE(C->dp[20]);
565 /* 21 */
566 COMBA_FORWARD;
567 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]);
568 COMBA_STORE(C->dp[21]);
569 /* 22 */
570 COMBA_FORWARD;
571 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]);
572 COMBA_STORE(C->dp[22]);
573 /* 23 */
574 COMBA_FORWARD;
575 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]);
576 COMBA_STORE(C->dp[23]);
577 /* 24 */
578 COMBA_FORWARD;
579 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]);
580 COMBA_STORE(C->dp[24]);
581 /* 25 */
582 COMBA_FORWARD;
583 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]);
584 COMBA_STORE(C->dp[25]);
585 /* 26 */
586 COMBA_FORWARD;
587 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]);
588 COMBA_STORE(C->dp[26]);
589 /* 27 */
590 COMBA_FORWARD;
591 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]);
592 COMBA_STORE(C->dp[27]);
593 /* 28 */
594 COMBA_FORWARD;
595 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]);
596 COMBA_STORE(C->dp[28]);
597 /* 29 */
598 COMBA_FORWARD;
599 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]);
600 COMBA_STORE(C->dp[29]);
601 /* 30 */
602 COMBA_FORWARD;
603 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]);
604 COMBA_STORE(C->dp[30]);
605 /* 31 */
606 COMBA_FORWARD;
607 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]);
608 COMBA_STORE(C->dp[31]);
609 /* 32 */
610 COMBA_FORWARD;
611 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]);
612 COMBA_STORE(C->dp[32]);
613 /* 33 */
614 COMBA_FORWARD;
615 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]);
616 COMBA_STORE(C->dp[33]);
617 /* 34 */
618 COMBA_FORWARD;
619 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]);
620 COMBA_STORE(C->dp[34]);
621 /* 35 */
622 COMBA_FORWARD;
623 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]);
624 COMBA_STORE(C->dp[35]);
625 /* 36 */
626 COMBA_FORWARD;
627 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]);
628 COMBA_STORE(C->dp[36]);
629 /* 37 */
630 COMBA_FORWARD;
631 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]);
632 COMBA_STORE(C->dp[37]);
633 /* 38 */
634 COMBA_FORWARD;
635 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]);
636 COMBA_STORE(C->dp[38]);
637
638 /* early out at 40 digits, 40*32==1280, or two 640 bit operands */
639 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; }
640
641 /* 39 */
642 COMBA_FORWARD;
643 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]);
644 COMBA_STORE(C->dp[39]);
645 /* 40 */
646 COMBA_FORWARD;
647 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]);
648 COMBA_STORE(C->dp[40]);
649 /* 41 */
650 COMBA_FORWARD;
651 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]);
652 COMBA_STORE(C->dp[41]);
653 /* 42 */
654 COMBA_FORWARD;
655 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]);
656 COMBA_STORE(C->dp[42]);
657 /* 43 */
658 COMBA_FORWARD;
659 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]);
660 COMBA_STORE(C->dp[43]);
661 /* 44 */
662 COMBA_FORWARD;
663 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]);
664 COMBA_STORE(C->dp[44]);
665 /* 45 */
666 COMBA_FORWARD;
667 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]);
668 COMBA_STORE(C->dp[45]);
669 /* 46 */
670 COMBA_FORWARD;
671 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]);
672 COMBA_STORE(C->dp[46]);
673
674 /* early out at 48 digits, 48*32==1536, or two 768 bit operands */
675 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; }
676
677 /* 47 */
678 COMBA_FORWARD;
679 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]);
680 COMBA_STORE(C->dp[47]);
681 /* 48 */
682 COMBA_FORWARD;
683 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]);
684 COMBA_STORE(C->dp[48]);
685 /* 49 */
686 COMBA_FORWARD;
687 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]);
688 COMBA_STORE(C->dp[49]);
689 /* 50 */
690 COMBA_FORWARD;
691 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]);
692 COMBA_STORE(C->dp[50]);
693 /* 51 */
694 COMBA_FORWARD;
695 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]);
696 COMBA_STORE(C->dp[51]);
697 /* 52 */
698 COMBA_FORWARD;
699 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]);
700 COMBA_STORE(C->dp[52]);
701 /* 53 */
702 COMBA_FORWARD;
703 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]);
704 COMBA_STORE(C->dp[53]);
705 /* 54 */
706 COMBA_FORWARD;
707 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]);
708 COMBA_STORE(C->dp[54]);
709
710 /* early out at 56 digits, 56*32==1792, or two 896 bit operands */
711 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; }
712
713 /* 55 */
714 COMBA_FORWARD;
715 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]);
716 COMBA_STORE(C->dp[55]);
717 /* 56 */
718 COMBA_FORWARD;
719 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]);
720 COMBA_STORE(C->dp[56]);
721 /* 57 */
722 COMBA_FORWARD;
723 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]);
724 COMBA_STORE(C->dp[57]);
725 /* 58 */
726 COMBA_FORWARD;
727 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]);
728 COMBA_STORE(C->dp[58]);
729 /* 59 */
730 COMBA_FORWARD;
731 MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]);
732 COMBA_STORE(C->dp[59]);
733 /* 60 */
734 COMBA_FORWARD;
735 MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]);
736 COMBA_STORE(C->dp[60]);
737 /* 61 */
738 COMBA_FORWARD;
739 MULADD(at[30], at[63]); MULADD(at[31], at[62]);
740 COMBA_STORE(C->dp[61]);
741 /* 62 */
742 COMBA_FORWARD;
743 MULADD(at[31], at[63]);
744 COMBA_STORE(C->dp[62]);
745 COMBA_STORE2(C->dp[63]);
746 C->used = 64;
747 C->sign = A->sign ^ B->sign;
748 pstm_clamp(C);
749 COMBA_FINI;
750 return PSTM_OKAY;
751}
752#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
753
754/******************************************************************************/
755
756int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C,
757 pstm_digit *paD, uint32 paDlen)
758{
759#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
760 if (A->used == 16 && B->used == 16) {
761 return pstm_mul_comba16(A, B, C);
762 } else {
763#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
764 if (A->used == 32 && B->used == 32) {
765 return pstm_mul_comba32(A, B, C);
766 }
767#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
768 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
769 }
770#else
771#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
772 if (A->used == 32 && B->used == 32) {
773 return pstm_mul_comba32(A, B, C);
774 }
775#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
776 return pstm_mul_comba_gen(pool, A, B, C, paD, paDlen);
777#endif
778}
779
780#endif /* !DISABLE_PSTM */
781/******************************************************************************/
diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c
new file mode 100644
index 000000000..36cb9ea97
--- /dev/null
+++ b/networking/tls_pstm_sqr_comba.c
@@ -0,0 +1,1111 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
9 * Changes are flagged with //bbox
10 */
11
12/**
13 * @file pstm_sqr_comba.c
14 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
15 *
16 * Multiprecision Squaring with Comba technique.
17 */
18/*
19 * Copyright (c) 2013-2015 INSIDE Secure Corporation
20 * Copyright (c) PeerSec Networks, 2002-2011
21 * All Rights Reserved
22 *
23 * The latest version of this code is available at http://www.matrixssl.org
24 *
25 * This software is open source; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This General Public License does NOT permit incorporating this software
31 * into proprietary programs. If you are unable to comply with the GPL, a
32 * commercial license for this software may be purchased from INSIDE at
33 * http://www.insidesecure.com/eng/Company/Locations
34 *
35 * This program is distributed in WITHOUT ANY WARRANTY; without even the
36 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
37 * See the GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 * http://www.gnu.org/copyleft/gpl.html
43 */
44/******************************************************************************/
45
46//bbox
47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM
49
50/******************************************************************************/
51#if defined(PSTM_X86)
52/* x86-32 optimized for 32 bit platforms. For 64 bit mode use X86_64 instead */
53#if !defined(__GNUC__) || !defined(__i386__)
54#error "PSTM_X86 option requires GCC and 32 bit mode x86 processor"
55#endif
56//#pragma message ("Using 32 bit x86 Assembly Optimizations")
57
58#define COMBA_START
59
60#define CLEAR_CARRY \
61 c0 = c1 = c2 = 0;
62
63#define COMBA_STORE(x) \
64 x = c0;
65
66#define COMBA_STORE2(x) \
67 x = c1;
68
69#define CARRY_FORWARD \
70 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
71
72#define COMBA_FINI
73
74#define SQRADD(i, j) \
75asm( \
76 "movl %6,%%eax \n\t" \
77 "mull %%eax \n\t" \
78 "addl %%eax,%0 \n\t" \
79 "adcl %%edx,%1 \n\t" \
80 "adcl $0,%2 \n\t" \
81 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc");
82
83#define SQRADD2(i, j) \
84asm( \
85 "movl %6,%%eax \n\t" \
86 "mull %7 \n\t" \
87 "addl %%eax,%0 \n\t" \
88 "adcl %%edx,%1 \n\t" \
89 "adcl $0,%2 \n\t" \
90 "addl %%eax,%0 \n\t" \
91 "adcl %%edx,%1 \n\t" \
92 "adcl $0,%2 \n\t" \
93 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","%cc");
94
95#define SQRADDSC(i, j) \
96asm( \
97 "movl %6,%%eax \n\t" \
98 "mull %7 \n\t" \
99 "movl %%eax,%0 \n\t" \
100 "movl %%edx,%1 \n\t" \
101 "xorl %2,%2 \n\t" \
102 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
103
104#define SQRADDAC(i, j) \
105asm( \
106 "movl %6,%%eax \n\t" \
107 "mull %7 \n\t" \
108 "addl %%eax,%0 \n\t" \
109 "adcl %%edx,%1 \n\t" \
110 "adcl $0,%2 \n\t" \
111 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
112
113#define SQRADDDB \
114asm( \
115 "addl %6,%0 \n\t" \
116 "adcl %7,%1 \n\t" \
117 "adcl %8,%2 \n\t" \
118 "addl %6,%0 \n\t" \
119 "adcl %7,%1 \n\t" \
120 "adcl %8,%2 \n\t" \
121 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "%cc");
122
123/******************************************************************************/
124#elif defined(PSTM_X86_64)
125/* x86-64 optimized */
126#if !defined(__GNUC__) || !defined(__x86_64__) || !defined(PSTM_64BIT)
127#error "PSTM_X86_64 option requires PSTM_64BIT, GCC and 64 bit mode x86 processor"
128#endif
129//#pragma message ("Using 64 bit x86_64 Assembly Optimizations")
130
131#define COMBA_START
132
133#define CLEAR_CARRY \
134c0 = c1 = c2 = 0;
135
136#define COMBA_STORE(x) \
137x = c0;
138
139#define COMBA_STORE2(x) \
140x = c1;
141
142#define CARRY_FORWARD \
143do { c0 = c1; c1 = c2; c2 = 0; } while (0);
144
145#define COMBA_FINI
146
147#define SQRADD(i, j) \
148asm( \
149 "movq %6,%%rax \n\t" \
150 "mulq %%rax \n\t" \
151 "addq %%rax,%0 \n\t" \
152 "adcq %%rdx,%1 \n\t" \
153 "adcq $0,%2 \n\t" \
154 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc");
155
156#define SQRADD2(i, j) \
157asm( \
158 "movq %6,%%rax \n\t" \
159 "mulq %7 \n\t" \
160 "addq %%rax,%0 \n\t" \
161 "adcq %%rdx,%1 \n\t" \
162 "adcq $0,%2 \n\t" \
163 "addq %%rax,%0 \n\t" \
164 "adcq %%rdx,%1 \n\t" \
165 "adcq $0,%2 \n\t" \
166 :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc");
167
168#define SQRADDSC(i, j) \
169asm( \
170 "movq %6,%%rax \n\t" \
171 "mulq %7 \n\t" \
172 "movq %%rax,%0 \n\t" \
173 "movq %%rdx,%1 \n\t" \
174 "xorq %2,%2 \n\t" \
175 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
176
177#define SQRADDAC(i, j) \
178asm( \
179 "movq %6,%%rax \n\t" \
180 "mulq %7 \n\t" \
181 "addq %%rax,%0 \n\t" \
182 "adcq %%rdx,%1 \n\t" \
183 "adcq $0,%2 \n\t" \
184 :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc");
185
186#define SQRADDDB \
187asm( \
188 "addq %6,%0 \n\t" \
189 "adcq %7,%1 \n\t" \
190 "adcq %8,%2 \n\t" \
191 "addq %6,%0 \n\t" \
192 "adcq %7,%1 \n\t" \
193 "adcq %8,%2 \n\t" \
194 :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc");
195
196/******************************************************************************/
197#elif defined(PSTM_ARM)
198/* ARM code */
199//#pragma message ("Using 32 bit ARM Assembly Optimizations")
200
201#define COMBA_START
202
203#define CLEAR_CARRY \
204c0 = c1 = c2 = 0;
205
206#define COMBA_STORE(x) \
207x = c0;
208
209#define COMBA_STORE2(x) \
210x = c1;
211
212#define CARRY_FORWARD \
213do { c0 = c1; c1 = c2; c2 = 0; } while (0);
214
215#define COMBA_FINI
216
217/* multiplies point i and j, updates carry "c1" and digit c2 */
218#define SQRADD(i, j) \
219asm( \
220" UMULL r0,r1,%6,%6 \n\t" \
221" ADDS %0,%0,r0 \n\t" \
222" ADCS %1,%1,r1 \n\t" \
223" ADC %2,%2,#0 \n\t" \
224:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc");
225
226/* for squaring some of the terms are doubled... */
227#define SQRADD2(i, j) \
228asm( \
229" UMULL r0,r1,%6,%7 \n\t" \
230" ADDS %0,%0,r0 \n\t" \
231" ADCS %1,%1,r1 \n\t" \
232" ADC %2,%2,#0 \n\t" \
233" ADDS %0,%0,r0 \n\t" \
234" ADCS %1,%1,r1 \n\t" \
235" ADC %2,%2,#0 \n\t" \
236:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
237
238#define SQRADDSC(i, j) \
239asm( \
240" UMULL %0,%1,%6,%7 \n\t" \
241" SUB %2,%2,%2 \n\t" \
242:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc");
243
244#define SQRADDAC(i, j) \
245asm( \
246" UMULL r0,r1,%6,%7 \n\t" \
247" ADDS %0,%0,r0 \n\t" \
248" ADCS %1,%1,r1 \n\t" \
249" ADC %2,%2,#0 \n\t" \
250:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc");
251
252#define SQRADDDB \
253asm( \
254" ADDS %0,%0,%3 \n\t" \
255" ADCS %1,%1,%4 \n\t" \
256" ADC %2,%2,%5 \n\t" \
257" ADDS %0,%0,%3 \n\t" \
258" ADCS %1,%1,%4 \n\t" \
259" ADC %2,%2,%5 \n\t" \
260:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "%cc");
261
262/******************************************************************************/
263#elif defined(PSTM_MIPS)
264/* MIPS32 */
265//#pragma message ("Using 32 bit MIPS Assembly Optimizations")
266
267#define COMBA_START
268
269#define CLEAR_CARRY \
270c0 = c1 = c2 = 0;
271
272#define COMBA_STORE(x) \
273x = c0;
274
275#define COMBA_STORE2(x) \
276x = c1;
277
278#define CARRY_FORWARD \
279do { c0 = c1; c1 = c2; c2 = 0; } while (0);
280
281#define COMBA_FINI
282
283/* multiplies point i and j, updates carry "c1" and digit c2 */
284#define SQRADD(i, j) \
285asm( \
286 " multu %6,%6 \n\t" \
287 " mflo $12 \n\t" \
288 " mfhi $13 \n\t" \
289 " addu %0,%0,$12 \n\t" \
290 " sltu $12,%0,$12 \n\t" \
291 " addu %1,%1,$13 \n\t" \
292 " sltu $13,%1,$13 \n\t" \
293 " addu %1,%1,$12 \n\t" \
294 " sltu $12,%1,$12 \n\t" \
295 " addu %2,%2,$13 \n\t" \
296 " addu %2,%2,$12 \n\t" \
297 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13");
298
299/* for squaring some of the terms are doubled... */
300#define SQRADD2(i, j) \
301asm( \
302 " multu %6,%7 \n\t" \
303 " mflo $12 \n\t" \
304 " mfhi $13 \n\t" \
305 \
306 " addu %0,%0,$12 \n\t" \
307 " sltu $14,%0,$12 \n\t" \
308 " addu %1,%1,$13 \n\t" \
309 " sltu $15,%1,$13 \n\t" \
310 " addu %1,%1,$14 \n\t" \
311 " sltu $14,%1,$14 \n\t" \
312 " addu %2,%2,$15 \n\t" \
313 " addu %2,%2,$14 \n\t" \
314 \
315 " addu %0,%0,$12 \n\t" \
316 " sltu $14,%0,$12 \n\t" \
317 " addu %1,%1,$13 \n\t" \
318 " sltu $15,%1,$13 \n\t" \
319 " addu %1,%1,$14 \n\t" \
320 " sltu $14,%1,$14 \n\t" \
321 " addu %2,%2,$15 \n\t" \
322 " addu %2,%2,$14 \n\t" \
323 :"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15");
324
325#define SQRADDSC(i, j) \
326asm( \
327 " multu %6,%7 \n\t" \
328 " mflo %0 \n\t" \
329 " mfhi %1 \n\t" \
330 " xor %2,%2,%2 \n\t" \
331 :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "%cc");
332
333#define SQRADDAC(i, j) \
334asm( \
335 " multu %6,%7 \n\t" \
336 " mflo $12 \n\t" \
337 " mfhi $13 \n\t" \
338 " addu %0,%0,$12 \n\t" \
339 " sltu $12,%0,$12 \n\t" \
340 " addu %1,%1,$13 \n\t" \
341 " sltu $13,%1,$13 \n\t" \
342 " addu %1,%1,$12 \n\t" \
343 " sltu $12,%1,$12 \n\t" \
344 " addu %2,%2,$13 \n\t" \
345 " addu %2,%2,$12 \n\t" \
346 :"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14");
347
348#define SQRADDDB \
349asm( \
350 " addu %0,%0,%3 \n\t" \
351 " sltu $10,%0,%3 \n\t" \
352 " addu %1,%1,$10 \n\t" \
353 " sltu $10,%1,$10 \n\t" \
354 " addu %1,%1,%4 \n\t" \
355 " sltu $11,%1,%4 \n\t" \
356 " addu %2,%2,$10 \n\t" \
357 " addu %2,%2,$11 \n\t" \
358 " addu %2,%2,%5 \n\t" \
359 \
360 " addu %0,%0,%3 \n\t" \
361 " sltu $10,%0,%3 \n\t" \
362 " addu %1,%1,$10 \n\t" \
363 " sltu $10,%1,$10 \n\t" \
364 " addu %1,%1,%4 \n\t" \
365 " sltu $11,%1,%4 \n\t" \
366 " addu %2,%2,$10 \n\t" \
367 " addu %2,%2,$11 \n\t" \
368 " addu %2,%2,%5 \n\t" \
369 :"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11");
370
371#else
372/******************************************************************************/
373#define PSTM_ISO
374/* ISO C portable code */
375
376#define COMBA_START
377
378#define CLEAR_CARRY \
379 c0 = c1 = c2 = 0;
380
381#define COMBA_STORE(x) \
382 x = c0;
383
384#define COMBA_STORE2(x) \
385 x = c1;
386
387#define CARRY_FORWARD \
388 do { c0 = c1; c1 = c2; c2 = 0; } while (0);
389
390#define COMBA_FINI
391
392/* multiplies point i and j, updates carry "c1" and digit c2 */
393#define SQRADD(i, j) \
394 do { pstm_word t; \
395 t = c0 + ((pstm_word)i) * ((pstm_word)j); c0 = (pstm_digit)t; \
396 t = c1 + (t >> DIGIT_BIT); \
397 c1 = (pstm_digit)t; c2 += (pstm_digit)(t >> DIGIT_BIT); \
398 } while (0);
399
400
401/* for squaring some of the terms are doubled... */
402#define SQRADD2(i, j) \
403 do { pstm_word t; \
404 t = ((pstm_word)i) * ((pstm_word)j); \
405 tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \
406 tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \
407 c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \
408 tt = (pstm_word)c0 + t; c0 = (pstm_digit)tt; \
409 tt = (pstm_word)c1 + (tt >> DIGIT_BIT); \
410 c1 = (pstm_digit)tt; c2 += (pstm_digit)(tt >> DIGIT_BIT); \
411 } while (0);
412
413#define SQRADDSC(i, j) \
414 do { pstm_word t; \
415 t = ((pstm_word)i) * ((pstm_word)j); \
416 sc0 = (pstm_digit)t; sc1 = (pstm_digit)(t >> DIGIT_BIT); sc2 = 0; \
417 } while (0);
418
419#define SQRADDAC(i, j) \
420 do { pstm_word t; \
421 t = ((pstm_word)sc0) + ((pstm_word)i) * ((pstm_word)j); \
422 sc0 = (pstm_digit)t; \
423 t = ((pstm_word)sc1) + (t >> DIGIT_BIT); sc1 = (pstm_digit)t; \
424 sc2 += (pstm_digit)(t >> DIGIT_BIT); \
425 } while (0);
426
427#define SQRADDDB \
428 do { pstm_word t; \
429 t = ((pstm_word)sc0) + ((pstm_word)sc0) + ((pstm_word)c0); \
430 c0 = (pstm_digit)t; \
431 t = ((pstm_word)sc1) + ((pstm_word)sc1) + c1 + (t >> DIGIT_BIT); \
432 c1 = (pstm_digit)t; \
433 c2 = c2 + sc2 + sc2 + (pstm_digit)(t >> DIGIT_BIT); \
434 } while (0);
435
436#endif /* ISO_C */
437
438/******************************************************************************/
439/*
440 Non-unrolled comba squarer
441 */
442//bbox: pool unused
443#define pstm_sqr_comba_gen(pool, A, B, paD, paDlen) \
444 pstm_sqr_comba_gen( A, B, paD, paDlen)
445static int32 pstm_sqr_comba_gen(psPool_t *pool, pstm_int *A, pstm_int *B,
446 pstm_digit *paD, uint32 paDlen)
447{
448 int16 paDfail, pa;
449 int32 ix, iz;
450 pstm_digit c0, c1, c2, *dst;
451#ifdef PSTM_ISO
452 pstm_word tt;
453#endif
454
455 paDfail = 0;
456 /* get size of output and trim */
457 pa = A->used + A->used;
458
459 /* number of output digits to produce */
460 COMBA_START;
461 CLEAR_CARRY;
462/*
463 If b is not large enough grow it and continue
464*/
465 if (B->alloc < pa) {
466 if (pstm_grow(B, pa) != PSTM_OKAY) {
467 return PS_MEM_FAIL;
468 }
469 }
470 if (paD != NULL) {
471 if (paDlen < (sizeof(pstm_digit) * pa)) {
472 paDfail = 1; /* have a paD, but it's not big enough */
473 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
474 } else {
475 dst = paD;
476 memset(dst, 0x0, paDlen);
477 }
478 } else {
479 dst = xzalloc(sizeof(pstm_digit) * pa);//bbox
480 }
481
482 for (ix = 0; ix < pa; ix++) {
483 int32 tx, ty, iy;
484 pstm_digit *tmpy, *tmpx;
485
486 /* get offsets into the two bignums */
487 ty = min(A->used-1, ix);
488 tx = ix - ty;
489
490 /* setup temp aliases */
491 tmpx = A->dp + tx;
492 tmpy = A->dp + ty;
493
494/*
495 This is the number of times the loop will iterate,
496 while (tx++ < a->used && ty-- >= 0) { ... }
497*/
498 iy = min(A->used-tx, ty+1);
499
500/*
501 now for squaring tx can never equal ty. We halve the distance since
502 they approach at a rate of 2x and we have to round because odd cases
503 need to be executed
504*/
505 iy = min(iy, (ty-tx+1)>>1);
506
507 /* forward carries */
508 CARRY_FORWARD;
509
510 /* execute loop */
511 for (iz = 0; iz < iy; iz++) {
512 SQRADD2(*tmpx++, *tmpy--);
513 }
514
515 /* even columns have the square term in them */
516 if ((ix&1) == 0) {
517 SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
518 }
519
520 /* store it */
521 COMBA_STORE(dst[ix]);
522 }
523
524 COMBA_FINI;
525/*
526 setup dest
527 */
528 iz = B->used;
529 B->used = pa;
530 {
531 pstm_digit *tmpc;
532 tmpc = B->dp;
533 for (ix = 0; ix < pa; ix++) {
534 *tmpc++ = dst[ix];
535 }
536 /* clear unused digits (that existed in the old copy of c) */
537 for (; ix < iz; ix++) {
538 *tmpc++ = 0;
539 }
540 }
541 pstm_clamp(B);
542
543 if ((paD == NULL) || paDfail == 1) {
544 psFree(dst, pool);
545 }
546 return PS_SUCCESS;
547}
548
549/******************************************************************************/
550/*
551 Unrolled Comba loop for 1024 bit keys
552 */
553#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
554static int32 pstm_sqr_comba16(pstm_int *A, pstm_int *B)
555{
556 pstm_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2;
557#ifdef PSTM_ISO
558 pstm_word tt;
559#endif
560
561 if (B->alloc < 32) {
562 if (pstm_grow(B, 32) != PSTM_OKAY) {
563 return PS_MEM_FAIL;
564 }
565 }
566 a = A->dp;
567 sc0 = sc1 = sc2 = 0;
568
569 COMBA_START;
570
571 /* clear carries */
572 CLEAR_CARRY;
573
574 /* output 0 */
575 SQRADD(a[0],a[0]);
576 COMBA_STORE(b[0]);
577
578 /* output 1 */
579 CARRY_FORWARD;
580 SQRADD2(a[0], a[1]);
581 COMBA_STORE(b[1]);
582
583 /* output 2 */
584 CARRY_FORWARD;
585 SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
586 COMBA_STORE(b[2]);
587
588 /* output 3 */
589 CARRY_FORWARD;
590 SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
591 COMBA_STORE(b[3]);
592
593 /* output 4 */
594 CARRY_FORWARD;
595 SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
596 COMBA_STORE(b[4]);
597
598 /* output 5 */
599 CARRY_FORWARD;
600 SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
601 COMBA_STORE(b[5]);
602
603 /* output 6 */
604 CARRY_FORWARD;
605 SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
606 COMBA_STORE(b[6]);
607
608 /* output 7 */
609 CARRY_FORWARD;
610 SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
611 COMBA_STORE(b[7]);
612
613 /* output 8 */
614 CARRY_FORWARD;
615 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]);
616 COMBA_STORE(b[8]);
617
618 /* output 9 */
619 CARRY_FORWARD;
620 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;
621 COMBA_STORE(b[9]);
622
623 /* output 10 */
624 CARRY_FORWARD;
625 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]);
626 COMBA_STORE(b[10]);
627
628 /* output 11 */
629 CARRY_FORWARD;
630 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;
631 COMBA_STORE(b[11]);
632
633 /* output 12 */
634 CARRY_FORWARD;
635 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]);
636 COMBA_STORE(b[12]);
637
638 /* output 13 */
639 CARRY_FORWARD;
640 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;
641 COMBA_STORE(b[13]);
642
643 /* output 14 */
644 CARRY_FORWARD;
645 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]);
646 COMBA_STORE(b[14]);
647
648 /* output 15 */
649 CARRY_FORWARD;
650 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;
651 COMBA_STORE(b[15]);
652
653 /* output 16 */
654 CARRY_FORWARD;
655 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]);
656 COMBA_STORE(b[16]);
657
658 /* output 17 */
659 CARRY_FORWARD;
660 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;
661 COMBA_STORE(b[17]);
662
663 /* output 18 */
664 CARRY_FORWARD;
665 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]);
666 COMBA_STORE(b[18]);
667
668 /* output 19 */
669 CARRY_FORWARD;
670 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;
671 COMBA_STORE(b[19]);
672
673 /* output 20 */
674 CARRY_FORWARD;
675 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]);
676 COMBA_STORE(b[20]);
677
678 /* output 21 */
679 CARRY_FORWARD;
680 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;
681 COMBA_STORE(b[21]);
682
683 /* output 22 */
684 CARRY_FORWARD;
685 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]);
686 COMBA_STORE(b[22]);
687
688 /* output 23 */
689 CARRY_FORWARD;
690 SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
691 COMBA_STORE(b[23]);
692
693 /* output 24 */
694 CARRY_FORWARD;
695 SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
696 COMBA_STORE(b[24]);
697
698 /* output 25 */
699 CARRY_FORWARD;
700 SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
701 COMBA_STORE(b[25]);
702
703 /* output 26 */
704 CARRY_FORWARD;
705 SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]);
706 COMBA_STORE(b[26]);
707
708 /* output 27 */
709 CARRY_FORWARD;
710 SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]);
711 COMBA_STORE(b[27]);
712
713 /* output 28 */
714 CARRY_FORWARD;
715 SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]);
716 COMBA_STORE(b[28]);
717
718 /* output 29 */
719 CARRY_FORWARD;
720 SQRADD2(a[14], a[15]);
721 COMBA_STORE(b[29]);
722
723 /* output 30 */
724 CARRY_FORWARD;
725 SQRADD(a[15], a[15]);
726 COMBA_STORE(b[30]);
727 COMBA_STORE2(b[31]);
728 COMBA_FINI;
729
730 B->used = 32;
731 B->sign = PSTM_ZPOS;
732 memcpy(B->dp, b, 32 * sizeof(pstm_digit));
733 pstm_clamp(B);
734 return PSTM_OKAY;
735}
736#endif /* USE_1024_KEY_SPEED_OPTIMIZATIONS */
737
738
739#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
740static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B)
741{
742 pstm_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2;
743#ifdef PSTM_ISO
744 pstm_word tt;
745#endif
746
747 if (B->alloc < 64) {
748 if (pstm_grow(B, 64) != PSTM_OKAY) {
749 return PS_MEM_FAIL;
750 }
751 }
752 sc0 = sc1 = sc2 = 0;
753 a = A->dp;
754 COMBA_START;
755
756 /* clear carries */
757 CLEAR_CARRY;
758
759 /* output 0 */
760 SQRADD(a[0],a[0]);
761 COMBA_STORE(b[0]);
762
763 /* output 1 */
764 CARRY_FORWARD;
765 SQRADD2(a[0], a[1]);
766 COMBA_STORE(b[1]);
767
768 /* output 2 */
769 CARRY_FORWARD;
770 SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
771 COMBA_STORE(b[2]);
772
773 /* output 3 */
774 CARRY_FORWARD;
775 SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
776 COMBA_STORE(b[3]);
777
778 /* output 4 */
779 CARRY_FORWARD;
780 SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
781 COMBA_STORE(b[4]);
782
783 /* output 5 */
784 CARRY_FORWARD;
785 SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
786 COMBA_STORE(b[5]);
787
788 /* output 6 */
789 CARRY_FORWARD;
790 SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
791 COMBA_STORE(b[6]);
792
793 /* output 7 */
794 CARRY_FORWARD;
795 SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
796 COMBA_STORE(b[7]);
797
798 /* output 8 */
799 CARRY_FORWARD;
800 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]);
801 COMBA_STORE(b[8]);
802
803 /* output 9 */
804 CARRY_FORWARD;
805 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;
806 COMBA_STORE(b[9]);
807
808 /* output 10 */
809 CARRY_FORWARD;
810 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]);
811 COMBA_STORE(b[10]);
812
813 /* output 11 */
814 CARRY_FORWARD;
815 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;
816 COMBA_STORE(b[11]);
817
818 /* output 12 */
819 CARRY_FORWARD;
820 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]);
821 COMBA_STORE(b[12]);
822
823 /* output 13 */
824 CARRY_FORWARD;
825 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;
826 COMBA_STORE(b[13]);
827
828 /* output 14 */
829 CARRY_FORWARD;
830 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]);
831 COMBA_STORE(b[14]);
832
833 /* output 15 */
834 CARRY_FORWARD;
835 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;
836 COMBA_STORE(b[15]);
837
838 /* output 16 */
839 CARRY_FORWARD;
840 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]);
841 COMBA_STORE(b[16]);
842
843 /* output 17 */
844 CARRY_FORWARD;
845 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;
846 COMBA_STORE(b[17]);
847
848 /* output 18 */
849 CARRY_FORWARD;
850 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]);
851 COMBA_STORE(b[18]);
852
853 /* output 19 */
854 CARRY_FORWARD;
855 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;
856 COMBA_STORE(b[19]);
857
858 /* output 20 */
859 CARRY_FORWARD;
860 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]);
861 COMBA_STORE(b[20]);
862
863 /* output 21 */
864 CARRY_FORWARD;
865 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;
866 COMBA_STORE(b[21]);
867
868 /* output 22 */
869 CARRY_FORWARD;
870 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]);
871 COMBA_STORE(b[22]);
872
873 /* output 23 */
874 CARRY_FORWARD;
875 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;
876 COMBA_STORE(b[23]);
877
878 /* output 24 */
879 CARRY_FORWARD;
880 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]);
881 COMBA_STORE(b[24]);
882
883 /* output 25 */
884 CARRY_FORWARD;
885 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;
886 COMBA_STORE(b[25]);
887
888 /* output 26 */
889 CARRY_FORWARD;
890 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]);
891 COMBA_STORE(b[26]);
892
893 /* output 27 */
894 CARRY_FORWARD;
895 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;
896 COMBA_STORE(b[27]);
897
898 /* output 28 */
899 CARRY_FORWARD;
900 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]);
901 COMBA_STORE(b[28]);
902
903 /* output 29 */
904 CARRY_FORWARD;
905 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;
906 COMBA_STORE(b[29]);
907
908 /* output 30 */
909 CARRY_FORWARD;
910 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]);
911 COMBA_STORE(b[30]);
912
913 /* output 31 */
914 CARRY_FORWARD;
915 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;
916 COMBA_STORE(b[31]);
917
918 /* output 32 */
919 CARRY_FORWARD;
920 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]);
921 COMBA_STORE(b[32]);
922
923 /* output 33 */
924 CARRY_FORWARD;
925 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;
926 COMBA_STORE(b[33]);
927
928 /* output 34 */
929 CARRY_FORWARD;
930 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]);
931 COMBA_STORE(b[34]);
932
933 /* output 35 */
934 CARRY_FORWARD;
935 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;
936 COMBA_STORE(b[35]);
937
938 /* output 36 */
939 CARRY_FORWARD;
940 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]);
941 COMBA_STORE(b[36]);
942
943 /* output 37 */
944 CARRY_FORWARD;
945 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;
946 COMBA_STORE(b[37]);
947
948 /* output 38 */
949 CARRY_FORWARD;
950 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]);
951 COMBA_STORE(b[38]);
952
953 /* output 39 */
954 CARRY_FORWARD;
955 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;
956 COMBA_STORE(b[39]);
957
958 /* output 40 */
959 CARRY_FORWARD;
960 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]);
961 COMBA_STORE(b[40]);
962
963 /* output 41 */
964 CARRY_FORWARD;
965 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;
966 COMBA_STORE(b[41]);
967
968 /* output 42 */
969 CARRY_FORWARD;
970 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]);
971 COMBA_STORE(b[42]);
972
973 /* output 43 */
974 CARRY_FORWARD;
975 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;
976 COMBA_STORE(b[43]);
977
978 /* output 44 */
979 CARRY_FORWARD;
980 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]);
981 COMBA_STORE(b[44]);
982
983 /* output 45 */
984 CARRY_FORWARD;
985 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;
986 COMBA_STORE(b[45]);
987
988 /* output 46 */
989 CARRY_FORWARD;
990 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]);
991 COMBA_STORE(b[46]);
992
993 /* output 47 */
994 CARRY_FORWARD;
995 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;
996 COMBA_STORE(b[47]);
997
998 /* output 48 */
999 CARRY_FORWARD;
1000 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]);
1001 COMBA_STORE(b[48]);
1002
1003 /* output 49 */
1004 CARRY_FORWARD;
1005 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;
1006 COMBA_STORE(b[49]);
1007
1008 /* output 50 */
1009 CARRY_FORWARD;
1010 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]);
1011 COMBA_STORE(b[50]);
1012
1013 /* output 51 */
1014 CARRY_FORWARD;
1015 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;
1016 COMBA_STORE(b[51]);
1017
1018 /* output 52 */
1019 CARRY_FORWARD;
1020 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]);
1021 COMBA_STORE(b[52]);
1022
1023 /* output 53 */
1024 CARRY_FORWARD;
1025 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;
1026 COMBA_STORE(b[53]);
1027
1028 /* output 54 */
1029 CARRY_FORWARD;
1030 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]);
1031 COMBA_STORE(b[54]);
1032
1033 /* output 55 */
1034 CARRY_FORWARD;
1035 SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
1036 COMBA_STORE(b[55]);
1037
1038 /* output 56 */
1039 CARRY_FORWARD;
1040 SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
1041 COMBA_STORE(b[56]);
1042
1043 /* output 57 */
1044 CARRY_FORWARD;
1045 SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
1046 COMBA_STORE(b[57]);
1047
1048 /* output 58 */
1049 CARRY_FORWARD;
1050 SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]);
1051 COMBA_STORE(b[58]);
1052
1053 /* output 59 */
1054 CARRY_FORWARD;
1055 SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]);
1056 COMBA_STORE(b[59]);
1057
1058 /* output 60 */
1059 CARRY_FORWARD;
1060 SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]);
1061 COMBA_STORE(b[60]);
1062
1063 /* output 61 */
1064 CARRY_FORWARD;
1065 SQRADD2(a[30], a[31]);
1066 COMBA_STORE(b[61]);
1067
1068 /* output 62 */
1069 CARRY_FORWARD;
1070 SQRADD(a[31], a[31]);
1071 COMBA_STORE(b[62]);
1072 COMBA_STORE2(b[63]);
1073 COMBA_FINI;
1074
1075 B->used = 64;
1076 B->sign = PSTM_ZPOS;
1077 memcpy(B->dp, b, 64 * sizeof(pstm_digit));
1078 pstm_clamp(B);
1079 return PSTM_OKAY;
1080}
1081#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1082
1083/******************************************************************************/
1084/*
1085 */
1086int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD,
1087 uint32 paDlen)
1088{
1089#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
1090 if (A->used == 16) {
1091 return pstm_sqr_comba16(A, B);
1092 } else {
1093#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1094 if (A->used == 32) {
1095 return pstm_sqr_comba32(A, B);
1096 }
1097#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1098 return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1099 }
1100#else
1101#ifdef USE_2048_KEY_SPEED_OPTIMIZATIONS
1102 if (A->used == 32) {
1103 return pstm_sqr_comba32(A, B);
1104 }
1105#endif /* USE_2048_KEY_SPEED_OPTIMIZATIONS */
1106 return pstm_sqr_comba_gen(pool, A, B, paD, paDlen);
1107#endif
1108}
1109
1110#endif /* DISABLE_PSTM */
1111/******************************************************************************/
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
new file mode 100644
index 000000000..60c54248e
--- /dev/null
+++ b/networking/tls_rsa.c
@@ -0,0 +1,211 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6#include "tls.h"
7
8/* The code below is taken from parts of
9 * matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c
10 * matrixssl-3-7-2b-open/crypto/pubkey/rsa.c
11 * and (so far) almost not modified. Changes are flagged with //bbox
12 */
13
14#define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
15 pkcs1Pad(in, inlen, out, outlen, cryptType)
16static //bbox
17int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
18 uint32 outlen, int32 cryptType, void *userPtr)
19{
20 unsigned char *c;
21 int32 randomLen;
22
23 randomLen = outlen - 3 - inlen;
24 if (randomLen < 8) {
25 psTraceCrypto("pkcs1Pad failure\n");
26 return PS_LIMIT_FAIL;
27 }
28 c = out;
29 *c = 0x00;
30 c++;
31 *c = (unsigned char)cryptType;
32 c++;
33 if (cryptType == PUBKEY_TYPE) {
34 while (randomLen-- > 0) {
35 *c++ = 0xFF;
36 }
37 } else {
38 if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) {
39 return PS_PLATFORM_FAIL;
40 }
41/*
42 SECURITY: Read through the random data and change all 0x0 to 0x01.
43 This is per spec that no random bytes should be 0
44*/
45 while (randomLen-- > 0) {
46 if (*c == 0x0) {
47 *c = 0x01;
48 }
49 c++;
50 }
51 }
52 *c = 0x00;
53 c++;
54 memcpy(c, in, inlen);
55
56 return outlen;
57}
58
59#define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
60 psRsaCrypt( in, inlen, out, outlen, key, type)
61static //bbox
62int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
63 unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
64 void *data)
65{
66 pstm_int tmp, tmpa, tmpb;
67 int32 res;
68 uint32 x;
69
70//bbox
71// if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
72// psTraceCrypto("NULL parameter error in psRsaCrypt\n");
73// return PS_ARG_FAIL;
74// }
75
76 tmp.dp = tmpa.dp = tmpb.dp = NULL;
77
78 /* Init and copy into tmp */
79 if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
80 != PS_SUCCESS) {
81 return PS_FAILURE;
82 }
83 if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){
84 pstm_clear(&tmp);
85 return PS_FAILURE;
86 }
87 /* Sanity check on the input */
88 if (pstm_cmp(&key->N, &tmp) == PSTM_LT) {
89 res = PS_LIMIT_FAIL;
90 goto done;
91 }
92 if (type == PRIVKEY_TYPE) {
93 if (key->optimized) {
94 if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) {
95 res = PS_FAILURE;
96 goto done;
97 }
98 if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) {
99 pstm_clear(&tmpa);
100 res = PS_FAILURE;
101 goto done;
102 }
103 if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
104 PS_SUCCESS) {
105 psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
106 goto error;
107 }
108 if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
109 PS_SUCCESS) {
110 psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
111 goto error;
112 }
113 if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) {
114 psTraceCrypto("decrypt error: sub tmpb, tmp\n");
115 goto error;
116 }
117 if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) {
118 psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
119 goto error;
120 }
121 if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
122 != PS_SUCCESS){
123 psTraceCrypto("decrypt error: pstm_mul q \n");
124 goto error;
125 }
126 if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) {
127 psTraceCrypto("decrypt error: pstm_add tmp \n");
128 goto error;
129 }
130 } else {
131 if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
132 PS_SUCCESS) {
133 psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
134 goto error;
135 }
136 }
137 } else if (type == PUBKEY_TYPE) {
138 if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) {
139 psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
140 goto error;
141 }
142 } else {
143 psTraceCrypto("psRsaCrypt error: invalid type param\n");
144 goto error;
145 }
146 /* Read it back */
147 x = pstm_unsigned_bin_size(&key->N);
148
149 if ((uint32)x > *outlen) {
150 res = -1;
151 psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
152 goto done;
153 }
154 /* We want the encrypted value to always be the key size. Pad with 0x0 */
155 while ((uint32)x < (unsigned long)key->size) {
156 *out++ = 0x0;
157 x++;
158 }
159
160 *outlen = x;
161 /* Convert it */
162 memset(out, 0x0, x);
163
164 if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp)))
165 != PS_SUCCESS) {
166 psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
167 goto error;
168 }
169 /* Clean up and return */
170 res = PS_SUCCESS;
171 goto done;
172error:
173 res = PS_FAILURE;
174done:
175 if (type == PRIVKEY_TYPE && key->optimized) {
176 pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
177 }
178 pstm_clear(&tmp);
179 return res;
180}
181
182int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
183 unsigned char *in, uint32 inlen,
184 unsigned char *out, uint32 outlen, void *data)
185{
186 int32 err;
187 uint32 size;
188
189 size = key->size;
190 if (outlen < size) {
191//bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
192 bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
193 return PS_ARG_FAIL;
194 }
195
196 if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
197 < PS_SUCCESS) {
198 psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
199 return err;
200 }
201 if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
202 PUBKEY_TYPE, data)) < PS_SUCCESS) {
203 psTraceCrypto("Error performing psRsaEncryptPub\n");
204 return err;
205 }
206 if (outlen != size) {
207 psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
208 return PS_FAILURE;
209 }
210 return size;
211}
diff --git a/networking/tls_rsa.h b/networking/tls_rsa.h
new file mode 100644
index 000000000..c464ed552
--- /dev/null
+++ b/networking/tls_rsa.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 *
6 * Selected few declarations for RSA.
7 */
8
9typedef struct {
10 pstm_int e, d, N, qP, dP, dQ, p, q;
11 uint32 size; /* Size of the key in bytes */
12 int32 optimized; /* 1 for optimized */
13//bbox psPool_t *pool;
14} psRsaKey_t;
15
16#define psRsaEncryptPub(pool, key, in, inlen, out, outlen, data) \
17 psRsaEncryptPub( key, in, inlen, out, outlen)
18int32 psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
19 unsigned char *in, uint32 inlen,
20 unsigned char *out, uint32 outlen, void *data);
diff --git a/networking/tls_symmetric.h b/networking/tls_symmetric.h
new file mode 100644
index 000000000..5e0e4b6d8
--- /dev/null
+++ b/networking/tls_symmetric.h
@@ -0,0 +1,511 @@
1/*
2 * Copyright (C) 2017 Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7
8/* The part below is a section of matrixssl-3-7-2b-open/crypto/cryptolib.h
9 * Changes are flagged with //bbox
10 */
11
12/******************************************************************************/
13/* 32-bit Rotates */
14/******************************************************************************/
15#if defined(_MSC_VER)
16/******************************************************************************/
17
18/* instrinsic rotate */
19#include <stdlib.h>
20#pragma intrinsic(_lrotr,_lrotl)
21#define ROR(x,n) _lrotr(x,n)
22#define ROL(x,n) _lrotl(x,n)
23
24/******************************************************************************/
25#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && \
26 !defined(INTEL_CC) && !defined(PS_NO_ASM)
27
28static ALWAYS_INLINE unsigned ROL(unsigned word, int i)
29{
30 if (__builtin_constant_p(i)) { //box
31 // Rotates by constant use fewer registers,
32 // and on many Intel CPUs rotates by %cl take 2 cycles, not 1.
33 asm ("roll %2,%0"
34 :"=r" (word)
35 :"0" (word),"i" (i));
36 return word;
37 } //box
38 asm ("roll %%cl,%0"
39 :"=r" (word)
40 :"0" (word),"c" (i));
41 return word;
42}
43
44static ALWAYS_INLINE unsigned ROR(unsigned word, int i)
45{
46 if (__builtin_constant_p(i)) { //box
47 asm ("rorl %2,%0"
48 :"=r" (word)
49 :"0" (word),"i" (i));
50 return word;
51 } //box
52 asm ("rorl %%cl,%0"
53 :"=r" (word)
54 :"0" (word),"c" (i));
55 return word;
56}
57
58/******************************************************************************/
59#else
60
61/* rotates the hard way */
62#define ROL(x, y) \
63 ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | \
64 (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & \
65 0xFFFFFFFFUL)
66#define ROR(x, y) \
67 ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
68 ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
69
70#endif /* 32-bit Rotates */
71/******************************************************************************/
72
73#ifdef HAVE_NATIVE_INT64
74#ifdef _MSC_VER
75 #define CONST64(n) n ## ui64
76#else
77 #define CONST64(n) n ## ULL
78#endif
79#endif
80
81/******************************************************************************/
82/*
83 Endian helper macros
84 */
85#if defined (ENDIAN_NEUTRAL)
86#define STORE32L(x, y) { \
87(y)[3] = (unsigned char)(((x)>>24)&255); \
88(y)[2] = (unsigned char)(((x)>>16)&255); \
89(y)[1] = (unsigned char)(((x)>>8)&255); \
90(y)[0] = (unsigned char)((x)&255); \
91}
92
93#define LOAD32L(x, y) { \
94x = ((unsigned long)((y)[3] & 255)<<24) | \
95((unsigned long)((y)[2] & 255)<<16) | \
96((unsigned long)((y)[1] & 255)<<8) | \
97((unsigned long)((y)[0] & 255)); \
98}
99
100#define STORE64L(x, y) { \
101(y)[7] = (unsigned char)(((x)>>56)&255); \
102(y)[6] = (unsigned char)(((x)>>48)&255); \
103(y)[5] = (unsigned char)(((x)>>40)&255); \
104(y)[4] = (unsigned char)(((x)>>32)&255); \
105(y)[3] = (unsigned char)(((x)>>24)&255); \
106(y)[2] = (unsigned char)(((x)>>16)&255); \
107(y)[1] = (unsigned char)(((x)>>8)&255); \
108(y)[0] = (unsigned char)((x)&255); \
109}
110
111#define LOAD64L(x, y) { \
112x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
113(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
114(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
115(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
116}
117
118#define STORE32H(x, y) { \
119(y)[0] = (unsigned char)(((x)>>24)&255); \
120(y)[1] = (unsigned char)(((x)>>16)&255); \
121(y)[2] = (unsigned char)(((x)>>8)&255); \
122(y)[3] = (unsigned char)((x)&255); \
123}
124
125#define LOAD32H(x, y) { \
126x = ((unsigned long)((y)[0] & 255)<<24) | \
127((unsigned long)((y)[1] & 255)<<16) | \
128((unsigned long)((y)[2] & 255)<<8) | \
129((unsigned long)((y)[3] & 255)); \
130}
131
132#define STORE64H(x, y) { \
133(y)[0] = (unsigned char)(((x)>>56)&255); \
134(y)[1] = (unsigned char)(((x)>>48)&255); \
135(y)[2] = (unsigned char)(((x)>>40)&255); \
136(y)[3] = (unsigned char)(((x)>>32)&255); \
137(y)[4] = (unsigned char)(((x)>>24)&255); \
138(y)[5] = (unsigned char)(((x)>>16)&255); \
139(y)[6] = (unsigned char)(((x)>>8)&255); \
140(y)[7] = (unsigned char)((x)&255); \
141}
142
143#define LOAD64H(x, y) { \
144x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
145(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
146(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
147(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); \
148}
149
150#endif /* ENDIAN_NEUTRAL */
151
152#ifdef ENDIAN_LITTLE
153#define STORE32H(x, y) { \
154(y)[0] = (unsigned char)(((x)>>24)&255); \
155(y)[1] = (unsigned char)(((x)>>16)&255); \
156(y)[2] = (unsigned char)(((x)>>8)&255); \
157(y)[3] = (unsigned char)((x)&255); \
158}
159
160#define LOAD32H(x, y) { \
161x = ((unsigned long)((y)[0] & 255)<<24) | \
162((unsigned long)((y)[1] & 255)<<16) | \
163((unsigned long)((y)[2] & 255)<<8) | \
164((unsigned long)((y)[3] & 255)); \
165}
166
167#define STORE64H(x, y) { \
168(y)[0] = (unsigned char)(((x)>>56)&255); \
169(y)[1] = (unsigned char)(((x)>>48)&255); \
170(y)[2] = (unsigned char)(((x)>>40)&255); \
171(y)[3] = (unsigned char)(((x)>>32)&255); \
172(y)[4] = (unsigned char)(((x)>>24)&255); \
173(y)[5] = (unsigned char)(((x)>>16)&255); \
174(y)[6] = (unsigned char)(((x)>>8)&255); \
175(y)[7] = (unsigned char)((x)&255); \
176}
177
178#define LOAD64H(x, y) { \
179x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48) | \
180(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32) | \
181(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16) | \
182(((uint64)((y)[6] & 255))<<8)|(((uint64)((y)[7] & 255))); }
183
184#ifdef ENDIAN_32BITWORD
185#define STORE32L(x, y) { \
186unsigned long __t = (x); memcpy(y, &__t, 4); \
187}
188
189#define LOAD32L(x, y) memcpy(&(x), y, 4);
190
191#define STORE64L(x, y) { \
192(y)[7] = (unsigned char)(((x)>>56)&255); \
193(y)[6] = (unsigned char)(((x)>>48)&255); \
194(y)[5] = (unsigned char)(((x)>>40)&255); \
195(y)[4] = (unsigned char)(((x)>>32)&255); \
196(y)[3] = (unsigned char)(((x)>>24)&255); \
197(y)[2] = (unsigned char)(((x)>>16)&255); \
198(y)[1] = (unsigned char)(((x)>>8)&255); \
199(y)[0] = (unsigned char)((x)&255); \
200}
201
202#define LOAD64L(x, y) { \
203x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48)| \
204(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32)| \
205(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16)| \
206(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
207}
208
209#else /* 64-bit words then */
210#define STORE32L(x, y) \
211{ unsigned long __t = (x); memcpy(y, &__t, 4); }
212
213#define LOAD32L(x, y) \
214{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
215
216#define STORE64L(x, y) \
217{ uint64 __t = (x); memcpy(y, &__t, 8); }
218
219#define LOAD64L(x, y) \
220{ memcpy(&(x), y, 8); }
221
222#endif /* ENDIAN_64BITWORD */
223#endif /* ENDIAN_LITTLE */
224
225#ifdef ENDIAN_BIG
226#define STORE32L(x, y) { \
227(y)[3] = (unsigned char)(((x)>>24)&255); \
228(y)[2] = (unsigned char)(((x)>>16)&255); \
229(y)[1] = (unsigned char)(((x)>>8)&255); \
230(y)[0] = (unsigned char)((x)&255); \
231}
232
233#define LOAD32L(x, y) { \
234x = ((unsigned long)((y)[3] & 255)<<24) | \
235((unsigned long)((y)[2] & 255)<<16) | \
236((unsigned long)((y)[1] & 255)<<8) | \
237((unsigned long)((y)[0] & 255)); \
238}
239
240#define STORE64L(x, y) { \
241(y)[7] = (unsigned char)(((x)>>56)&255); \
242(y)[6] = (unsigned char)(((x)>>48)&255); \
243(y)[5] = (unsigned char)(((x)>>40)&255); \
244(y)[4] = (unsigned char)(((x)>>32)&255); \
245(y)[3] = (unsigned char)(((x)>>24)&255); \
246(y)[2] = (unsigned char)(((x)>>16)&255); \
247(y)[1] = (unsigned char)(((x)>>8)&255); \
248(y)[0] = (unsigned char)((x)&255); \
249}
250
251#define LOAD64L(x, y) { \
252x = (((uint64)((y)[7] & 255))<<56)|(((uint64)((y)[6] & 255))<<48) | \
253(((uint64)((y)[5] & 255))<<40)|(((uint64)((y)[4] & 255))<<32) | \
254(((uint64)((y)[3] & 255))<<24)|(((uint64)((y)[2] & 255))<<16) | \
255(((uint64)((y)[1] & 255))<<8)|(((uint64)((y)[0] & 255))); \
256}
257
258#ifdef ENDIAN_32BITWORD
259#define STORE32H(x, y) \
260{ unsigned int __t = (x); memcpy(y, &__t, 4); }
261
262#define LOAD32H(x, y) memcpy(&(x), y, 4);
263
264#define STORE64H(x, y) { \
265(y)[0] = (unsigned char)(((x)>>56)&255); \
266(y)[1] = (unsigned char)(((x)>>48)&255); \
267(y)[2] = (unsigned char)(((x)>>40)&255); \
268(y)[3] = (unsigned char)(((x)>>32)&255); \
269(y)[4] = (unsigned char)(((x)>>24)&255); \
270(y)[5] = (unsigned char)(((x)>>16)&255); \
271(y)[6] = (unsigned char)(((x)>>8)&255); \
272(y)[7] = (unsigned char)((x)&255); \
273}
274
275#define LOAD64H(x, y) { \
276x = (((uint64)((y)[0] & 255))<<56)|(((uint64)((y)[1] & 255))<<48)| \
277(((uint64)((y)[2] & 255))<<40)|(((uint64)((y)[3] & 255))<<32)| \
278(((uint64)((y)[4] & 255))<<24)|(((uint64)((y)[5] & 255))<<16)| \
279(((uint64)((y)[6] & 255))<<8)| (((uint64)((y)[7] & 255))); \
280}
281
282#else /* 64-bit words then */
283
284#define STORE32H(x, y) \
285{ unsigned long __t = (x); memcpy(y, &__t, 4); }
286
287#define LOAD32H(x, y) \
288{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
289
290#define STORE64H(x, y) \
291{ uint64 __t = (x); memcpy(y, &__t, 8); }
292
293#define LOAD64H(x, y) \
294{ memcpy(&(x), y, 8); }
295
296#endif /* ENDIAN_64BITWORD */
297#endif /* ENDIAN_BIG */
298
299#ifdef HAVE_NATIVE_INT64
300#define ROL64c(x, y) \
301( (((x)<<((uint64)(y)&63)) | \
302(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
303
304#define ROR64c(x, y) \
305( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((uint64)(y)&CONST64(63))) | \
306((x)<<((uint64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
307#endif /* HAVE_NATIVE_INT64 */
308/******************************************************************************/
309
310
311
312/* The part below is taken almost verbatim from matrixssl-3-7-2b-open/crypto/symmetric/.
313 * Changes are flagged with //bbox
314 */
315
316/**
317 * @file symmetric.h
318 * @version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
319 *
320 * Header for internal symmetric key cryptography support.
321 */
322/*
323 * Copyright (c) 2013-2015 INSIDE Secure Corporation
324 * Copyright (c) PeerSec Networks, 2002-2011
325 * All Rights Reserved
326 *
327 * The latest version of this code is available at http://www.matrixssl.org
328 *
329 * This software is open source; you can redistribute it and/or modify
330 * it under the terms of the GNU General Public License as published by
331 * the Free Software Foundation; either version 2 of the License, or
332 * (at your option) any later version.
333 *
334 * This General Public License does NOT permit incorporating this software
335 * into proprietary programs. If you are unable to comply with the GPL, a
336 * commercial license for this software may be purchased from INSIDE at
337 * http://www.insidesecure.com/eng/Company/Locations
338 *
339 * This program is distributed in WITHOUT ANY WARRANTY; without even the
340 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
341 * See the GNU General Public License for more details.
342 *
343 * You should have received a copy of the GNU General Public License
344 * along with this program; if not, write to the Free Software
345 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
346 * http://www.gnu.org/copyleft/gpl.html
347 */
348/******************************************************************************/
349
350#ifndef _h_PS_SYMMETRIC
351#define _h_PS_SYMMETRIC
352
353/******************************************************************************/
354#ifdef USE_AES
355/******************************************************************************/
356
357
358#ifndef USE_AES_CBC_EXTERNAL
359typedef struct {
360 uint32 eK[64], dK[64];
361 int32 Nr;
362} psAesKey_t;
363
364typedef struct {
365 int32 blocklen;
366 unsigned char IV[16];
367 psAesKey_t key;
368#if defined(USE_AES_GCM) || defined(USE_AES_CCM)
369 unsigned char EncCtr[16];
370 unsigned char CtrBlock[16];
371#endif
372#ifdef USE_AES_GCM
373 unsigned char gInit[16];
374 uint32 TagTemp[4];
375 unsigned char Hash_SubKey[16];
376 uint32 ProcessedBitCount[4];
377 uint32 InputBufferCount;
378 uint32 OutputBufferCount;
379 union
380 {
381 unsigned char Buffer[128];
382 uint32 BufferAlignment;
383 } Input;
384#endif /* USE_AES_GCM */
385#ifdef USE_AES_CCM
386 uint32_t ccmTagTemp[16 / sizeof(uint32_t)]; /* 32 */
387 union
388 {
389 /* Used for formatting IV. */
390 uint8_t Temporary[16];
391 /* Used for processing Mac. */
392 uint8_t Y0[16];
393 } u; /* 48 */
394#endif /* USE_AES_CCM */
395} psAesCipher_t;
396#endif /* USE_AES_CBC_EXTERNAL */
397
398#endif /* USE_AES */
399
400#ifdef USE_IDEA
401#define SSL_IDEA_KEY_LEN 16
402#define SSL_IDEA_IV_LEN 8
403#define SSL_IDEA_BLOCK_LEN 8
404
405typedef struct {
406 uint16 key_schedule[52];
407} psIdeaKey_t;
408
409typedef struct {
410 psIdeaKey_t key;
411 uint32 IV[2];
412 short for_encryption;
413 short inverted;
414} idea_CBC;
415#endif
416/******************************************************************************/
417
418/******************************************************************************/
419#ifdef USE_SEED
420/******************************************************************************/
421#define SSL_SEED_KEY_LEN 16
422#define SSL_SEED_IV_LEN 16
423
424
425typedef struct {
426 uint32 K[32], dK[32];
427} psSeedKey_t;
428
429typedef struct {
430 int32 blocklen;
431 unsigned char IV[16];
432 psSeedKey_t key;
433} seed_CBC;
434
435#endif /* USE_SEED */
436/******************************************************************************/
437
438/******************************************************************************/
439#if defined(USE_3DES) || defined(USE_DES)
440/******************************************************************************/
441#define DES3_KEY_LEN 24
442#define DES3_IV_LEN 8
443#define DES_KEY_LEN 8
444
445typedef struct {
446 uint32 ek[3][32], dk[3][32];
447} psDes3Key_t;
448
449/*
450 A block cipher CBC structure
451 */
452typedef struct {
453 int32 blocklen;
454 unsigned char IV[8];
455 psDes3Key_t key;
456} des3_CBC;
457
458#endif /* USE_3DES || USE_DES */
459/******************************************************************************/
460
461/******************************************************************************/
462#ifdef USE_ARC4
463typedef struct {
464 unsigned char state[256];
465 uint32 byteCount;
466 unsigned char x;
467 unsigned char y;
468} psRc4Key_t;
469#endif /* USE_ARC4 */
470/******************************************************************************/
471#ifdef USE_RC2
472typedef struct {
473 unsigned xkey[64];
474} psRc2Key_t;
475
476typedef struct {
477 int32 blocklen;
478 unsigned char IV[8];
479 psRc2Key_t key;
480} rc2_CBC;
481#endif /* USE_RC2 */
482/******************************************************************************/
483/* Universal types and defines */
484/******************************************************************************/
485#define MAXBLOCKSIZE 24
486
487typedef union {
488#ifdef USE_RC2
489 rc2_CBC rc2;
490#endif
491#ifdef USE_ARC4
492 psRc4Key_t arc4;
493#endif
494#ifdef USE_3DES
495 des3_CBC des3;
496#endif
497#ifdef USE_AES
498 psAesCipher_t aes;
499#endif
500#ifdef USE_SEED
501 seed_CBC seed;
502#endif
503#ifdef USE_IDEA
504 idea_CBC idea;
505#endif
506} psCipherContext_t;
507
508#define byte(x, n) (((x) >> (8 * (n))) & 255)
509
510#endif /* _h_PS_SYMMETRIC */
511/******************************************************************************/
diff --git a/networking/traceroute.c b/networking/traceroute.c
index a463b0faa..6817861ef 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -235,8 +235,6 @@
235//config: bool "Enable -I option (use ICMP instead of UDP)" 235//config: bool "Enable -I option (use ICMP instead of UDP)"
236//config: default y 236//config: default y
237//config: depends on TRACEROUTE || TRACEROUTE6 237//config: depends on TRACEROUTE || TRACEROUTE6
238//config: help
239//config: Add option -I to use ICMP ECHO instead of UDP datagrams.
240 238
241/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */ 239/* Needs socket(AF_INET, SOCK_RAW, IPPROTO_ICMP), therefore BB_SUID_MAYBE: */
242//applet:IF_TRACEROUTE(APPLET(traceroute, BB_DIR_USR_BIN, BB_SUID_MAYBE)) 240//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
123 are very verbose and useful for debugging only. 123 are very verbose and useful for debugging only.
124 124
125config FEATURE_UDHCP_RFC3397 125config FEATURE_UDHCP_RFC3397
126 bool "Support for RFC3397 domain search (experimental)" 126 bool "Support RFC3397 domain search (experimental)"
127 default y 127 default y
128 depends on UDHCPD || UDHCPC 128 depends on UDHCPD || UDHCPC
129 help 129 help
@@ -132,7 +132,7 @@ config FEATURE_UDHCP_RFC3397
132 and SIP servers option 120, specified in RFC 3361. 132 and SIP servers option 120, specified in RFC 3361.
133 133
134config FEATURE_UDHCP_8021Q 134config FEATURE_UDHCP_8021Q
135 bool "Support for 802.1Q VLAN parameters" 135 bool "Support 802.1Q VLAN parameters"
136 default y 136 default y
137 depends on UDHCPD || UDHCPC 137 depends on UDHCPD || UDHCPC
138 help 138 help
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[] = {
86}; 86};
87 87
88/* Used for converting options from incoming packets to env variables 88/* Used for converting options from incoming packets to env variables
89 * for udhcpc stript, and for setting options for udhcpd via 89 * for udhcpc script, and for setting options for udhcpd via
90 * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file. 90 * "opt OPTION_NAME OPTION_VALUE" directives in udhcpd.conf file.
91 */ 91 */
92/* Must match dhcp_optflags[] order */ 92/* Must match dhcp_optflags[] order */
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 @@
11//usage:#define dumpleases_full_usage "\n\n" 11//usage:#define dumpleases_full_usage "\n\n"
12//usage: "Display DHCP leases granted by udhcpd\n" 12//usage: "Display DHCP leases granted by udhcpd\n"
13//usage: IF_LONG_OPTS( 13//usage: IF_LONG_OPTS(
14//usage: "\n -f,--file=FILE Lease file" 14//usage: "\n -f,--file FILE Lease file"
15//usage: "\n -r,--remaining Show remaining time" 15//usage: "\n -r,--remaining Show remaining time"
16//usage: "\n -a,--absolute Show expiration time" 16//usage: "\n -a,--absolute Show expiration time"
17//usage: "\n -d,--decimal Show time in seconds" 17//usage: "\n -d,--decimal Show time in seconds"
diff --git a/networking/wget.c b/networking/wget.c
index 460b4b833..b9d840328 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -16,12 +16,15 @@
16//config: wget is a utility for non-interactive download of files from HTTP 16//config: wget is a utility for non-interactive download of files from HTTP
17//config: and FTP servers. 17//config: and FTP servers.
18//config: 18//config:
19//config:config FEATURE_WGET_LONG_OPTIONS
20//config: bool "Enable long options"
21//config: default y
22//config: depends on WGET && LONG_OPTS
23//config:
19//config:config FEATURE_WGET_STATUSBAR 24//config:config FEATURE_WGET_STATUSBAR
20//config: bool "Enable a nifty process meter (+2k)" 25//config: bool "Enable progress bar (+2k)"
21//config: default y 26//config: default y
22//config: depends on WGET 27//config: depends on WGET
23//config: help
24//config: Enable the transfer progress bar for wget transfers.
25//config: 28//config:
26//config:config FEATURE_WGET_AUTHENTICATION 29//config:config FEATURE_WGET_AUTHENTICATION
27//config: bool "Enable HTTP authentication" 30//config: bool "Enable HTTP authentication"
@@ -30,13 +33,6 @@
30//config: help 33//config: help
31//config: Support authenticated HTTP transfers. 34//config: Support authenticated HTTP transfers.
32//config: 35//config:
33//config:config FEATURE_WGET_LONG_OPTIONS
34//config: bool "Enable long options"
35//config: default y
36//config: depends on WGET && LONG_OPTS
37//config: help
38//config: Support long options for the wget applet.
39//config:
40//config:config FEATURE_WGET_TIMEOUT 36//config:config FEATURE_WGET_TIMEOUT
41//config: bool "Enable timeout option -T SEC" 37//config: bool "Enable timeout option -T SEC"
42//config: default y 38//config: default y
@@ -51,18 +47,59 @@
51//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option 47//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
52//config: will work in addition to -T. 48//config: will work in addition to -T.
53//config: 49//config:
50//config:config FEATURE_WGET_HTTPS
51//config: bool "Support HTTPS using internal TLS code"
52//config: default y
53//config: depends on WGET
54//config: select TLS
55//config: help
56//config: wget will use internal TLS code to connect to https:// URLs.
57//config: Note:
58//config: On NOMMU machines, ssl_helper applet should be available
59//config: in the $PATH for this to work. Make sure to select that applet.
60//config:
61//config: Note: currently, TLS code only makes TLS I/O work, it
62//config: does *not* check that the peer is who it claims to be, etc.
63//config: IOW: it uses peer-supplied public keys to establish encryption
64//config: and signing keys, then encrypts and signs outgoing data and
65//config: decrypts incoming data.
66//config: It does not check signature hashes on the incoming data:
67//config: this means that attackers manipulating TCP packets can
68//config: send altered data and we unknowingly receive garbage.
69//config: (This check might be relatively easy to add).
70//config: It does not check public key's certificate:
71//config: this means that the peer may be an attacker impersonating
72//config: the server we think we are talking to.
73//config:
74//config: If you think this is unacceptable, consider this. As more and more
75//config: servers switch to HTTPS-only operation, without such "crippled"
76//config: TLS code it is *impossible* to simply download a kernel source
77//config: from kernel.org. Which can in real world translate into
78//config: "my small automatic tooling to build cross-compilers from sources
79//config: no longer works, I need to additionally keep a local copy
80//config: of ~4 megabyte source tarball of a SSL library and ~2 megabyte
81//config: source of wget, need to compile and built both before I can
82//config: download anything. All this despite the fact that the build
83//config: is done in a QEMU sandbox on a machine with absolutely nothing
84//config: worth stealing, so I don't care if someone would go to a lot
85//config: of trouble to intercept my HTTPS download to send me an altered
86//config: kernel tarball".
87//config:
88//config: If you still think this is unacceptable, send patches.
89//config:
90//config: If you still think this is unacceptable, do not want to send
91//config: patches, but do want to waste bandwidth expaining how wrong
92//config: it is, you will be ignored.
93//config:
54//config:config FEATURE_WGET_OPENSSL 94//config:config FEATURE_WGET_OPENSSL
55//config: bool "Try to connect to HTTPS using openssl" 95//config: bool "Try to connect to HTTPS using openssl"
56//config: default y 96//config: default y
57//config: depends on WGET 97//config: depends on WGET
58//config: help 98//config: help
59//config: Choose how wget establishes SSL connection for https:// URLs. 99//config: Try to use openssl to handle HTTPS.
60//config:
61//config: Busybox itself contains no SSL code. wget will spawn
62//config: a helper program to talk over HTTPS.
63//config: 100//config:
64//config: OpenSSL has a simple SSL client for debug purposes. 101//config: OpenSSL has a simple SSL client for debug purposes.
65//config: If you select "openssl" helper, wget will effectively run: 102//config: If you select this option, wget will effectively run:
66//config: "openssl s_client -quiet -connect hostname:443 103//config: "openssl s_client -quiet -connect hostname:443
67//config: -servername hostname 2>/dev/null" and pipe its data 104//config: -servername hostname 2>/dev/null" and pipe its data
68//config: through it. -servername is not used if hostname is numeric. 105//config: through it. -servername is not used if hostname is numeric.
@@ -75,24 +112,9 @@
75//config: openssl is also a big binary, often dynamically linked 112//config: openssl is also a big binary, often dynamically linked
76//config: against ~15 libraries. 113//config: against ~15 libraries.
77//config: 114//config:
78//config:config FEATURE_WGET_SSL_HELPER 115//config: If openssl can't be executed, internal TLS code will be used
79//config: bool "Try to connect to HTTPS using ssl_helper" 116//config: (if you enabled it); if openssl can be executed but fails later,
80//config: default y 117//config: wget can't detect this, and download will fail.
81//config: depends on WGET
82//config: help
83//config: Choose how wget establishes SSL connection for https:// URLs.
84//config:
85//config: Busybox itself contains no SSL code. wget will spawn
86//config: a helper program to talk over HTTPS.
87//config:
88//config: ssl_helper is a tool which can be built statically
89//config: from busybox sources against a small embedded SSL library.
90//config: Please see networking/ssl_helper/README.
91//config: It does not require double host resolution and emits
92//config: error messages to stderr.
93//config:
94//config: Precompiled static binary may be available at
95//config: http://busybox.net/downloads/binaries/
96 118
97//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) 119//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
98 120
@@ -105,20 +127,21 @@
105/* Since we ignore these opts, we don't show them in --help */ 127/* Since we ignore these opts, we don't show them in --help */
106/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ 128/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
107/* //usage: " [-nv] [-nc] [-nH] [-np]" */ 129/* //usage: " [-nv] [-nc] [-nH] [-np]" */
108//usage: " [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 130//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
109//usage: ) 131//usage: )
110//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 132//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
111//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" 133//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]"
112//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 134//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
113//usage: ) 135//usage: )
114//usage:#define wget_full_usage "\n\n" 136//usage:#define wget_full_usage "\n\n"
115//usage: "Retrieve files via HTTP or FTP\n" 137//usage: "Retrieve files via HTTP or FTP\n"
116//usage: IF_FEATURE_WGET_LONG_OPTIONS( 138//usage: IF_FEATURE_WGET_LONG_OPTIONS(
117//usage: "\n --spider Spider mode - only check file existence" 139//usage: "\n --spider Only check URL existence: $? is 0 if exists"
118//usage: ) 140//usage: )
119//usage: "\n -c Continue retrieval of aborted transfer" 141//usage: "\n -c Continue retrieval of aborted transfer"
120//usage: "\n -q Quiet" 142//usage: "\n -q Quiet"
121//usage: "\n -P DIR Save to DIR (default .)" 143//usage: "\n -P DIR Save to DIR (default .)"
144//usage: "\n -S Show server response"
122//usage: IF_FEATURE_WGET_TIMEOUT( 145//usage: IF_FEATURE_WGET_TIMEOUT(
123//usage: "\n -T SEC Network read timeout is SEC seconds" 146//usage: "\n -T SEC Network read timeout is SEC seconds"
124//usage: ) 147//usage: )
@@ -141,6 +164,8 @@
141#endif 164#endif
142 165
143 166
167#define SSL_SUPPORTED (ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_HTTPS)
168
144struct host_info { 169struct host_info {
145 char *allocated; 170 char *allocated;
146 const char *path; 171 const char *path;
@@ -151,7 +176,7 @@ struct host_info {
151}; 176};
152static const char P_FTP[] ALIGN1 = "ftp"; 177static const char P_FTP[] ALIGN1 = "ftp";
153static const char P_HTTP[] ALIGN1 = "http"; 178static const char P_HTTP[] ALIGN1 = "http";
154#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 179#if SSL_SUPPORTED
155static const char P_HTTPS[] ALIGN1 = "https"; 180static const char P_HTTPS[] ALIGN1 = "https";
156#endif 181#endif
157 182
@@ -232,16 +257,17 @@ struct globals {
232enum { 257enum {
233 WGET_OPT_CONTINUE = (1 << 0), 258 WGET_OPT_CONTINUE = (1 << 0),
234 WGET_OPT_QUIET = (1 << 1), 259 WGET_OPT_QUIET = (1 << 1),
235 WGET_OPT_OUTNAME = (1 << 2), 260 WGET_OPT_SERVER_RESPONSE = (1 << 2),
236 WGET_OPT_PREFIX = (1 << 3), 261 WGET_OPT_OUTNAME = (1 << 3),
237 WGET_OPT_PROXY = (1 << 4), 262 WGET_OPT_PREFIX = (1 << 4),
238 WGET_OPT_USER_AGENT = (1 << 5), 263 WGET_OPT_PROXY = (1 << 5),
239 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 6), 264 WGET_OPT_USER_AGENT = (1 << 6),
240 WGET_OPT_RETRIES = (1 << 7), 265 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7),
241 WGET_OPT_nsomething = (1 << 8), 266 WGET_OPT_RETRIES = (1 << 8),
242 WGET_OPT_HEADER = (1 << 9) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 267 WGET_OPT_nsomething = (1 << 9),
243 WGET_OPT_POST_DATA = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 268 WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
244 WGET_OPT_SPIDER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 269 WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
270 WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
245}; 271};
246 272
247enum { 273enum {
@@ -395,7 +421,7 @@ static FILE *open_socket(len_and_sockaddr *lsa)
395} 421}
396 422
397/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ 423/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */
398static char fgets_and_trim(FILE *fp) 424static char fgets_and_trim(FILE *fp, const char *fmt)
399{ 425{
400 char c; 426 char c;
401 char *buf_ptr; 427 char *buf_ptr;
@@ -413,6 +439,9 @@ static char fgets_and_trim(FILE *fp)
413 439
414 log_io("< %s", G.wget_buf); 440 log_io("< %s", G.wget_buf);
415 441
442 if (fmt && (option_mask32 & WGET_OPT_SERVER_RESPONSE))
443 fprintf(stderr, fmt, G.wget_buf);
444
416 return c; 445 return c;
417} 446}
418 447
@@ -423,6 +452,9 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
423 if (!s2) 452 if (!s2)
424 s2 = ""; 453 s2 = "";
425 fprintf(fp, "%s%s\r\n", s1, s2); 454 fprintf(fp, "%s%s\r\n", s1, s2);
455 /* With --server-response, wget also shows its ftp commands */
456 if (option_mask32 & WGET_OPT_SERVER_RESPONSE)
457 fprintf(stderr, "--> %s%s\n\n", s1, s2);
426 fflush(fp); 458 fflush(fp);
427 log_io("> %s%s", s1, s2); 459 log_io("> %s%s", s1, s2);
428#if ENABLE_PLATFORM_MINGW32 460#if ENABLE_PLATFORM_MINGW32
@@ -431,7 +463,7 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
431 } 463 }
432 464
433 do { 465 do {
434 fgets_and_trim(fp); 466 fgets_and_trim(fp, "%s\n");
435 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); 467 } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' ');
436#if ENABLE_PLATFORM_MINGW32 468#if ENABLE_PLATFORM_MINGW32
437 fseek(fp, 0L, SEEK_CUR); 469 fseek(fp, 0L, SEEK_CUR);
@@ -458,7 +490,7 @@ static void parse_url(const char *src_url, struct host_info *h)
458 if (strcmp(url, P_FTP) == 0) { 490 if (strcmp(url, P_FTP) == 0) {
459 h->port = bb_lookup_port(P_FTP, "tcp", 21); 491 h->port = bb_lookup_port(P_FTP, "tcp", 21);
460 } else 492 } else
461#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER 493#if SSL_SUPPORTED
462 if (strcmp(url, P_HTTPS) == 0) { 494 if (strcmp(url, P_HTTPS) == 0) {
463 h->port = bb_lookup_port(P_HTTPS, "tcp", 443); 495 h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
464 h->protocol = P_HTTPS; 496 h->protocol = P_HTTPS;
@@ -480,7 +512,7 @@ static void parse_url(const char *src_url, struct host_info *h)
480 512
481 // FYI: 513 // FYI:
482 // "Real" wget 'http://busybox.net?var=a/b' sends this request: 514 // "Real" wget 'http://busybox.net?var=a/b' sends this request:
483 // 'GET /?var=a/b HTTP 1.0' 515 // 'GET /?var=a/b HTTP/1.0'
484 // and saves 'index.html?var=a%2Fb' (we save 'b') 516 // and saves 'index.html?var=a%2Fb' (we save 'b')
485 // wget 'http://busybox.net?login=john@doe': 517 // wget 'http://busybox.net?login=john@doe':
486 // request: 'GET /?login=john@doe HTTP/1.0' 518 // request: 'GET /?login=john@doe HTTP/1.0'
@@ -531,7 +563,7 @@ static char *gethdr(FILE *fp)
531 int c; 563 int c;
532 564
533 /* retrieve header line */ 565 /* retrieve header line */
534 c = fgets_and_trim(fp); 566 c = fgets_and_trim(fp, " %s\n");
535 567
536 /* end of the headers? */ 568 /* end of the headers? */
537 if (G.wget_buf[0] == '\0') 569 if (G.wget_buf[0] == '\0')
@@ -665,7 +697,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
665 char *servername; 697 char *servername;
666 int sp[2]; 698 int sp[2];
667 int pid; 699 int pid;
668 IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;) 700 IF_FEATURE_WGET_HTTPS(volatile int child_failed = 0;)
669 701
670 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 702 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
671 /* Kernel can have AF_UNIX support disabled */ 703 /* Kernel can have AF_UNIX support disabled */
@@ -710,7 +742,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
710 742
711 BB_EXECVP(argv[0], argv); 743 BB_EXECVP(argv[0], argv);
712 xmove_fd(3, 2); 744 xmove_fd(3, 2);
713# if ENABLE_FEATURE_WGET_SSL_HELPER 745# if ENABLE_FEATURE_WGET_HTTPS
714 child_failed = 1; 746 child_failed = 1;
715 xfunc_die(); 747 xfunc_die();
716# else 748# else
@@ -723,7 +755,7 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
723 free(servername); 755 free(servername);
724 free(allocated); 756 free(allocated);
725 close(sp[1]); 757 close(sp[1]);
726# if ENABLE_FEATURE_WGET_SSL_HELPER 758# if ENABLE_FEATURE_WGET_HTTPS
727 if (child_failed) { 759 if (child_failed) {
728 close(sp[0]); 760 close(sp[0]);
729 return -1; 761 return -1;
@@ -733,38 +765,51 @@ static int spawn_https_helper_openssl(const char *host, unsigned port)
733} 765}
734#endif 766#endif
735 767
736/* See networking/ssl_helper/README how to build one */ 768#if ENABLE_FEATURE_WGET_HTTPS
737#if ENABLE_FEATURE_WGET_SSL_HELPER 769static void spawn_ssl_client(const char *host, int network_fd)
738static void spawn_https_helper_small(int network_fd)
739{ 770{
740 int sp[2]; 771 int sp[2];
741 int pid; 772 int pid;
773 char *servername, *p;
774
775 servername = xstrdup(host);
776 p = strrchr(servername, ':');
777 if (p) *p = '\0';
742 778
743 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0) 779 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
744 /* Kernel can have AF_UNIX support disabled */ 780 /* Kernel can have AF_UNIX support disabled */
745 bb_perror_msg_and_die("socketpair"); 781 bb_perror_msg_and_die("socketpair");
746 782
783 fflush_all();
747 pid = BB_MMU ? xfork() : xvfork(); 784 pid = BB_MMU ? xfork() : xvfork();
748 if (pid == 0) { 785 if (pid == 0) {
749 /* Child */ 786 /* Child */
750 char *argv[3];
751
752 close(sp[0]); 787 close(sp[0]);
753 xmove_fd(sp[1], 0); 788 xmove_fd(sp[1], 0);
754 xdup2(0, 1); 789 xdup2(0, 1);
755 xmove_fd(network_fd, 3); 790 if (BB_MMU) {
756 /* 791 tls_state_t *tls = new_tls_state();
757 * A simple ssl/tls helper 792 tls->ifd = tls->ofd = network_fd;
758 */ 793 tls_handshake(tls, servername);
759 argv[0] = (char*)"ssl_helper"; 794 tls_run_copy_loop(tls);
760 argv[1] = (char*)"-d3"; 795 exit(0);
761 argv[2] = NULL; 796 } else {
762 BB_EXECVP(argv[0], argv); 797 char *argv[5];
763 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 798 xmove_fd(network_fd, 3);
799 argv[0] = (char*)"ssl_client";
800 argv[1] = (char*)"-s3";
801 //TODO: if (!is_ip_address(servername))...
802 argv[2] = (char*)"-n";
803 argv[3] = servername;
804 argv[4] = NULL;
805 BB_EXECVP(argv[0], argv);
806 bb_perror_msg_and_die("can't execute '%s'", argv[0]);
807 }
764 /* notreached */ 808 /* notreached */
765 } 809 }
766 810
767 /* Parent */ 811 /* Parent */
812 free(servername);
768 close(sp[1]); 813 close(sp[1]);
769 xmove_fd(sp[0], network_fd); 814 xmove_fd(sp[0], network_fd);
770} 815}
@@ -886,9 +931,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
886 if (!G.chunked) 931 if (!G.chunked)
887 break; 932 break;
888 933
889 fgets_and_trim(dfp); /* Eat empty line */ 934 fgets_and_trim(dfp, NULL); /* Eat empty line */
890 get_clen: 935 get_clen:
891 fgets_and_trim(dfp); 936 fgets_and_trim(dfp, NULL);
892 G.content_len = STRTOOFF(G.wget_buf, NULL, 16); 937 G.content_len = STRTOOFF(G.wget_buf, NULL, 16);
893 /* FIXME: error check? */ 938 /* FIXME: error check? */
894 if (G.content_len == 0) 939 if (G.content_len == 0)
@@ -1013,16 +1058,16 @@ static void download_one_url(const char *url)
1013 1058
1014 /* Open socket to http(s) server */ 1059 /* Open socket to http(s) server */
1015#if ENABLE_FEATURE_WGET_OPENSSL 1060#if ENABLE_FEATURE_WGET_OPENSSL
1016 /* openssl (and maybe ssl_helper) support is configured */ 1061 /* openssl (and maybe internal TLS) support is configured */
1017 if (target.protocol == P_HTTPS) { 1062 if (target.protocol == P_HTTPS) {
1018 /* openssl-based helper 1063 /* openssl-based helper
1019 * Inconvenient API since we can't give it an open fd 1064 * Inconvenient API since we can't give it an open fd
1020 */ 1065 */
1021 int fd = spawn_https_helper_openssl(server.host, server.port); 1066 int fd = spawn_https_helper_openssl(server.host, server.port);
1022# if ENABLE_FEATURE_WGET_SSL_HELPER 1067# if ENABLE_FEATURE_WGET_HTTPS
1023 if (fd < 0) { /* no openssl? try ssl_helper */ 1068 if (fd < 0) { /* no openssl? try internal */
1024 sfp = open_socket(lsa); 1069 sfp = open_socket(lsa);
1025 spawn_https_helper_small(fileno(sfp)); 1070 spawn_ssl_client(server.host, fileno(sfp));
1026 goto socket_opened; 1071 goto socket_opened;
1027 } 1072 }
1028# else 1073# else
@@ -1035,11 +1080,11 @@ static void download_one_url(const char *url)
1035 } 1080 }
1036 sfp = open_socket(lsa); 1081 sfp = open_socket(lsa);
1037 socket_opened: 1082 socket_opened:
1038#elif ENABLE_FEATURE_WGET_SSL_HELPER 1083#elif ENABLE_FEATURE_WGET_HTTPS
1039 /* Only ssl_helper support is configured */ 1084 /* Only internal TLS support is configured */
1040 sfp = open_socket(lsa); 1085 sfp = open_socket(lsa);
1041 if (target.protocol == P_HTTPS) 1086 if (target.protocol == P_HTTPS)
1042 spawn_https_helper_small(fileno(sfp)); 1087 spawn_ssl_client(server.host, fileno(sfp));
1043#else 1088#else
1044 /* ssl (https) support is not configured */ 1089 /* ssl (https) support is not configured */
1045 sfp = open_socket(lsa); 1090 sfp = open_socket(lsa);
@@ -1099,18 +1144,26 @@ static void download_one_url(const char *url)
1099 } 1144 }
1100 1145
1101 fflush(sfp); 1146 fflush(sfp);
1102 /* If we use SSL helper, keeping our end of the socket open for writing 1147
1103 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF) 1148/* Tried doing this unconditionally.
1104 * even after child closes its copy of the fd. 1149 * Cloudflare and nginx/1.11.5 are shocked to see SHUT_WR on non-HTTPS.
1105 * This helps: 1150 */
1106 */ 1151#if SSL_SUPPORTED
1107 shutdown(fileno(sfp), SHUT_WR); 1152 if (target.protocol == P_HTTPS) {
1153 /* If we use SSL helper, keeping our end of the socket open for writing
1154 * makes our end (i.e. the same fd!) readable (EAGAIN instead of EOF)
1155 * even after child closes its copy of the fd.
1156 * This helps:
1157 */
1158 shutdown(fileno(sfp), SHUT_WR);
1159 }
1160#endif
1108 1161
1109 /* 1162 /*
1110 * Retrieve HTTP response line and check for "200" status code. 1163 * Retrieve HTTP response line and check for "200" status code.
1111 */ 1164 */
1112 read_response: 1165 read_response:
1113 fgets_and_trim(sfp); 1166 fgets_and_trim(sfp, " %s\n");
1114 1167
1115 str = G.wget_buf; 1168 str = G.wget_buf;
1116 str = skip_non_whitespace(str); 1169 str = skip_non_whitespace(str);
@@ -1295,6 +1348,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1295 /* name, has_arg, val */ 1348 /* name, has_arg, val */
1296 "continue\0" No_argument "c" 1349 "continue\0" No_argument "c"
1297 "quiet\0" No_argument "q" 1350 "quiet\0" No_argument "q"
1351 "server-response\0" No_argument "S"
1298 "output-document\0" Required_argument "O" 1352 "output-document\0" Required_argument "O"
1299 "directory-prefix\0" Required_argument "P" 1353 "directory-prefix\0" Required_argument "P"
1300 "proxy\0" Required_argument "Y" 1354 "proxy\0" Required_argument "Y"
@@ -1337,7 +1391,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1337#endif 1391#endif
1338 opt_complementary = "-1" /* at least one URL */ 1392 opt_complementary = "-1" /* at least one URL */
1339 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */ 1393 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
1340 getopt32(argv, "cqO:P:Y:U:T:+" 1394 getopt32(argv, "cqSO:P:Y:U:T:+"
1341 /*ignored:*/ "t:" 1395 /*ignored:*/ "t:"
1342 /*ignored:*/ "n::" 1396 /*ignored:*/ "n::"
1343 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1397 /* wget has exactly four -n<letter> opts, all of which we can ignore: